嵌入式开发必备:9个高效C语言代码技巧

在嵌入式系统开发过程中,开发者经常会面对资源受限、性能敏感的场景。为了提升开发效率、保证代码质量、避免重复造轮子,复用成熟的“工具级”代码片段成为一种高效的工程实践。

本文精选了9个在嵌入式开发中实用且常见的 C 语言技巧型代码片段(工具函数),并附带简要说明,助你构建更稳定、可维护的底层系统。

1. 循环队列(Circular Buffer)

循环队列是一种高效的数据结构,适用于串口通信、传感器数据缓冲等场景。
✅ 使用场景:

  • 串口接收缓冲

  • 音视频数据缓存

  • 生产者-消费者模型


2. 断言机制(Assertion)

断言机制有助于在开发阶段快速定位逻辑错误,提升调试效率。


✅ 使用场景:

  • 检查函数参数合法性

  • 保证状态机状态转移合法

  • 开发阶段防御性编程


3. 位反转操作(Bit Reversal)

位反转常用于数据编码、FFT预处理等底层算法中。


4. 固定点运算(Fixed-Point Arithmetic)

在无硬件FPU的系统上,使用固定点数可以有效模拟浮点计算。

✅ 使用场景:

  • 控制算法(如PID)

  • 数字滤波器

  • 图像处理(色彩运算等)


5. 字节序转换(Endianness Conversion)

在进行网络通信或外设协议交互时,字节序转换尤为重要。


6. 位掩码(Bit Masks)

构造位掩码,用于寄存器或位标志操作,是嵌入式中非常常见的技巧。


7. 硬件定时器读取(Timer Counter)

用于时间测量或精确的周期性操作。

  • ⚠️ 注意:该示例基于 AVR 平台,其他 MCU 需要参考对应的寄存器手册。

8. 二进制查找(Binary Search)

一个经典且高效的查找算法,适用于已排序数据。


9. 位集合(Bitset)

管理多个标志位时,使用位集合是一种高效且结构清晰的做法。


10. 嵌入式工具函数模块

✅ embedded_utils.h

#ifndef EMBEDDED_UTILS_H
#define EMBEDDED_UTILS_H

#include <stdint.h>
#include <stddef.h>

/* ========== 1. Circular Buffer ========== */
#define CBUF_SIZE 128

typedef struct {
    int buffer[CBUF_SIZE];
    int head;
    int tail;
    int count;
} CircularBuffer;

void cbuf_push(CircularBuffer *cb, int data);
int cbuf_pop(CircularBuffer *cb);

/* ========== 2. Assertion ========== */
void eu_assert_failed(const char *file, int line);

#ifndef NDEBUG
#define eu_assert(expr) ((expr) ? (void)0 : eu_assert_failed(__FILE__, __LINE__))
#else
#define eu_assert(expr) ((void)0)
#endif

/* ========== 3. Bit Reversal ========== */
uint32_t reverse_bits(uint32_t num);

/* ========== 4. Fixed-Point Arithmetic ========== */
typedef int16_t fixed_t;

#define FIXED_SHIFT         8
#define float_to_fixed(f)   ((fixed_t)((f) * (1 << FIXED_SHIFT)))
#define fixed_to_float(f)   ((float)(f) / (1 << FIXED_SHIFT))

fixed_t fixed_multiply(fixed_t a, fixed_t b);

/* ========== 5. Endianness Conversion ========== */
uint16_t swap_bytes16(uint16_t value);

/* ========== 6. Bit Mask ========== */
#define BIT_MASK(bit) (1U << (bit))

/* ========== 7. Timer Counting (AVR example) ========== */
#ifdef __AVR__
#include <avr/io.h>
void timer_setup(void);
uint16_t timer_read(void);
#endif

/* ========== 8. Binary Search ========== */
int binary_search(const int *arr, size_t size, int target);

/* ========== 9. Bitset ========== */
typedef struct {
    uint32_t bits;
} Bitset;

void bitset_set(Bitset *bitset, int bit);
int bitset_get(const Bitset *bitset, int bit);

#endif // EMBEDDED_UTILS_H

✅ embedded_utils.c

#include "embedded_utils.h"
#include <stdio.h>

/* ========== 1. Circular Buffer ========== */
void cbuf_push(CircularBuffer *cb, int data) {
    if (cb->count < CBUF_SIZE) {
        cb->buffer[cb->head] = data;
        cb->head = (cb->head + 1) % CBUF_SIZE;
        cb->count++;
    }
}

int cbuf_pop(CircularBuffer *cb) {
    if (cb->count > 0) {
        int data = cb->buffer[cb->tail];
        cb->tail = (cb->tail + 1) % CBUF_SIZE;
        cb->count--;
        return data;
    }
    return -1;
}

/* ========== 2. Assertion ========== */
void eu_assert_failed(const char *file, int line) {
    printf("Assertion failed at %s:%d\n", file, line);
}

/* ========== 3. Bit Reversal ========== */
uint32_t reverse_bits(uint32_t num) {
    uint32_t num_bits = sizeof(num) * 8;
    uint32_t result = 0;
    for (uint32_t i = 0; i < num_bits; ++i) {
        if (num & (1U << i)) {
            result |= (1U << (num_bits - 1 - i));
        }
    }
    return result;
}

/* ========== 4. Fixed-Point Arithmetic ========== */
fixed_t fixed_multiply(fixed_t a, fixed_t b) {
    return (fixed_t)(((int32_t)a * (int32_t)b) >> FIXED_SHIFT);
}

/* ========== 5. Endianness Conversion ========== */
uint16_t swap_bytes16(uint16_t value) {
    return (value >> 8) | (value << 8);
}

/* ========== 7. Timer Counting (AVR Only) ========== */
#ifdef __AVR__
void timer_setup(void) {
    // Configure timer (user-defined)
}

uint16_t timer_read(void) {
    return TCNT1;
}
#endif

/* ========== 8. Binary Search ========== */
int binary_search(const int *arr, size_t size, int target) {
    int left = 0;
    int right = (int)size - 1;

    while (left <= right) {
        int mid = left + (right - left) / 2;
        if (arr[mid] == target)
            return mid;
        else if (arr[mid] < target)
            left = mid + 1;
        else
            right = mid - 1;
    }
    return -1;
}

/* ========== 9. Bitset ========== */
void bitset_set(Bitset *bitset, int bit) {
    if (bit < 0 || bit >= 32) return; // 避免越界
    bitset->bits |= (1U << bit);
}

int bitset_get(const Bitset *bitset, int bit) {
    if (bit < 0 || bit >= 32) return 0;
    return (bitset->bits >> bit) & 1U;
}

✅ 示例用法 main.c

#include "embedded_utils.h"
#include <stdio.h>

int main() {
    CircularBuffer cb = {0};
    cbuf_push(&cb, 42);
    printf("Pop: %d\n", cbuf_pop(&cb));

    eu_assert(1 == 1);

    printf("Reversed bits: 0x%X\n", reverse_bits(0x00000001));

    fixed_t a = float_to_fixed(1.5f);
    fixed_t b = float_to_fixed(2.0f);
    printf("Fixed multiply: %.2f\n", fixed_to_float(fixed_multiply(a, b)));

    printf("Swap 0x1234: 0x%X\n", swap_bytes16(0x1234));

    Bitset bset = {0};
    bitset_set(&bset, 3);
    printf("Bit 3: %d\n", bitset_get(&bset, 3));

    int arr[] = {1, 3, 5, 7, 9};
    printf("Search 7: %d\n", binary_search(arr, 5, 7));

    return 0;
}

✅ Makefile

# === Project Configuration ===
TARGET     := embedded_demo
SRCS       := main.c embedded_utils.c
OBJS       := $(SRCS:.c=.o)
INCLUDES   := -I.
CFLAGS     := -Wall -Wextra -O2 $(INCLUDES)
LDFLAGS    := 

# === Cross Compile Support ===
# For native build, leave this empty.
# For ARM, you might use: arm-none-eabi-
CROSS_COMPILE ?= 

CC  := $(CROSS_COMPILE)gcc
LD  := $(CROSS_COMPILE)gcc

# === Rules ===
all: $(TARGET)

$(TARGET): $(OBJS)
	$(LD) -o $@ $^ $(LDFLAGS)

%.o: %.c
	$(CC) $(CFLAGS) -c $< -o $@

clean:
	rm -f $(OBJS) $(TARGET)

.PHONY: all clean

✅ 交叉编译

  • Linaro 提供的 AArch64 工具链:
下载地址:🔗 https://releases.linaro.org/components/toolchain/binaries/latest-7/aarch64-linux-gnu/
wget https://releases.linaro.org/components/toolchain/binaries/latest-7/aarch64-linux-gnu/gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu.tar.xz
mkdir ~/toolchains
cd ~/toolchains
tar -xvf gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu.tar.xz
export TOOLCHAIN_DIR=~/toolchains/gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu
export PATH=$TOOLCHAIN_DIR/bin:$PATH
export CROSS_COMPILE=aarch64-linux-gnu-
export ARCH=arm64

$ ls $TOOLCHAIN_DIR/bin/
aarch64-linux-gnu-gcc
aarch64-linux-gnu-g++
aarch64-linux-gnu-ld
aarch64-linux-gnu-strip
...

make CROSS_COMPILE=arm-none-eabi-

总结

这些工具级代码片段虽小,却极具威力,在嵌入式开发过程中扮演着“利剑”般的角色。掌握并善用这些技巧,不仅能提升开发效率,还能帮助你编写出更鲁棒、更易维护的底层系统。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值