为什么要模块化
嵌入式系统复杂度随功能增加而指数增长。模块化设计将系统拆分为独立模块,降低耦合度,提高可维护性和可扩展性。
复用性
通用模块可在多个项目中复用,减少重复开发。如 RS485 通讯模块、ADC 采集模块可复用于不同设备。
可维护性
模块独立修改不影响其他模块,降低维护成本。如更换 MCU 型号只需修改硬件抽象层,应用层代码不变。
可扩展性
新增功能通过添加模块实现,无需重构现有代码。如新增 CAN 通讯只需添加 CAN 模块。
团队协作
不同模块可由不同人员并行开发,提高开发效率。
硬件接口标准化设计
统一连接器
使用标准连接器定义模块接口,确保模块可插拔。
推荐连接器:
- 板间连接:2.54mm 排针排母
- 外部接口:航空插头、端子排
- 高速信号:板对板连接器
引脚定义规范
定义统一的引脚功能,避免混乱。
示例:通用 IO 模块接口定义
// 模块接口引脚定义
typedef struct {
uint8_t vcc_5v; // 5V 电源
uint8_t vcc_3v3; // 3.3V 电源
uint8_t gnd; // 地
uint8_t dio[4]; // 数字 IO
uint8_t aio[2]; // 模拟输入
uint8_t uart_tx; // UART 发送
uint8_t uart_rx; // UART 接收
uint8_t i2c_sda; // I2C 数据
uint8_t i2c_scl; // I2C 时钟
} Module_Interface_t;
电源规范
统一电源电压和电流规格:
- 主电源:24V DC(工业标准)
- 逻辑电源:5V DC(TTL 电平)
- 核心电源:3.3V DC(CMOS 电平)
- 电流限制:每个模块最大 500mA
信号规范
定义信号电平和时序标准:
- 数字输入:0-0.8V 为低,2.0-5.0V 为高
- 模拟输入:0-3.3V,12 位精度
- 通讯速率:UART 9600-115200bps,I2C 100kHz-400kHz
软件分层架构
软件分层将系统划分为硬件抽象层、驱动层、协议层、应用层,各层职责清晰。
硬件抽象层(HAL)
HAL 层屏蔽硬件差异,提供统一接口。
// GPIO 抽象接口
typedef struct {
void (*init)(uint8_t pin, uint8_t mode);
void (*write)(uint8_t pin, uint8_t value);
uint8_t (*read)(uint8_t pin);
} GPIO_Driver_t;
// STM32 实现
void STM32_GPIO_Init(uint8_t pin, uint8_t mode) {
// STM32 GPIO 初始化
}
void STM32_GPIO_Write(uint8_t pin, uint8_t value) {
// STM32 GPIO 写入
}
uint8_t STM32_GPIO_Read(uint8_t pin) {
// STM32 GPIO 读取
return 0;
}
GPIO_Driver_t gpio_driver = {
.init = STM32_GPIO_Init,
.write = STM32_GPIO_Write,
.read = STM32_GPIO_Read
};
驱动层
驱动层实现具体外设驱动,如 UART、SPI、I2C。
// UART 驱动接口
typedef struct {
int (*init)(uint32_t baudrate);
int (*send)(uint8_t *data, uint16_t len);
int (*recv)(uint8_t *data, uint16_t len);
} UART_Driver_t;
// UART 驱动实现
int UART_Init(uint32_t baudrate) {
// UART 初始化
return 0;
}
int UART_Send(uint8_t *data, uint16_t len) {
// UART 发送
return 0;
}
int UART_Recv(uint8_t *data, uint16_t len) {
// UART 接收
return 0;
}
协议层
协议层实现通讯协议,如 Modbus、CANopen。
// Modbus 协议接口
typedef struct {
int (*parse)(uint8_t *data, uint16_t len);
int (*build)(uint8_t *data, uint16_t *len);
} Modbus_Protocol_t;
int Modbus_Parse(uint8_t *data, uint16_t len) {
// Modbus 帧解析
return 0;
}
int Modbus_Build(uint8_t *data, uint16_t *len) {
// Modbus 帧构造
return 0;
}
应用层
应用层实现业务逻辑,调用下层接口。
void App_Task(void) {
uint8_t data[256];
uint16_t len;
// 接收数据
UART_Recv(data, &len);
// 解析协议
Modbus_Parse(data, len);
// 处理业务逻辑
Process_Data(data, len);
// 构造响应
Modbus_Build(data, &len);
// 发送响应
UART_Send(data, len);
}
回调函数模式实现解耦
回调函数实现模块间松耦合,驱动层通过回调通知应用层。
回调函数定义
// 定义回调函数类型
typedef void (*UART_RxCallback_t)(uint8_t *data, uint16_t len);
// UART 驱动
typedef struct {
UART_RxCallback_t rx_callback;
} UART_Driver_t;
// 注册回调函数
void UART_Register_Callback(UART_RxCallback_t callback) {
uart_driver.rx_callback = callback;
}
// UART 中断中调用回调
void UART_IRQHandler(void) {
if (UART_Get_Flag(UART_FLAG_RXNE)) {
uint8_t data = UART_Receive_Byte();
uart_rx_buffer[uart_rx_index++] = data;
if (uart_rx_index >= UART_RX_BUFFER_SIZE) {
if (uart_driver.rx_callback != NULL) {
uart_driver.rx_callback(uart_rx_buffer, uart_rx_index);
}
uart_rx_index = 0;
}
}
}
应用层实现回调
// 应用层回调函数
void UART_Rx_Handler(uint8_t *data, uint16_t len) {
// 处理接收到的数据
Modbus_Process(data, len);
}
// 注册回调
void App_Init(void) {
UART_Init(19200);
UART_Register_Callback(UART_Rx_Handler);
}
跨平台移植策略
条件编译
通过宏定义区分不同平台。
// 平台检测
#if defined(STM32F103)
#include "stm32f1xx_hal.h"
#define PLATFORM_STM32
#elif defined(ESP32)
#include "esp32_hal.h"
#define PLATFORM_ESP32
#elif defined(LINUX)
#include <linux/gpio.h>
#define PLATFORM_LINUX
#endif
// 平台相关实现
#if defined(PLATFORM_STM32)
void GPIO_Init(uint8_t pin, uint8_t mode) {
// STM32 实现
}
#elif defined(PLATFORM_ESP32)
void GPIO_Init(uint8_t pin, uint8_t mode) {
// ESP32 实现
}
#elif defined(PLATFORM_LINUX)
void GPIO_Init(uint8_t pin, uint8_t mode) {
// Linux 实现
}
#endif
弱引用
使用弱引用实现默认实现,平台可选择性覆盖。
// 默认实现(弱引用)
__attribute__((weak)) void Platform_Delay_ms(uint32_t ms) {
// 默认实现(空循环)
for (volatile uint32_t i = 0; i < ms * 1000; i++);
}
// 平台特定实现(覆盖弱引用)
void Platform_Delay_ms(uint32_t ms) {
HAL_Delay(ms);
}
硬件抽象层接口
定义统一 HAL 接口,各平台实现。
// HAL 接口定义
typedef struct {
void (*gpio_init)(uint8_t pin, uint8_t mode);
void (*gpio_write)(uint8_t pin, uint8_t value);
uint8_t (*gpio_read)(uint8_t pin);
void (*uart_init)(uint32_t baudrate);
void (*uart_send)(uint8_t *data, uint16_t len);
void (*delay_ms)(uint32_t ms);
} HAL_Interface_t;
// 平台实现
HAL_Interface_t stm32_hal = {
.gpio_init = STM32_GPIO_Init,
.gpio_write = STM32_GPIO_Write,
.gpio_read = STM32_GPIO_Read,
.uart_init = STM32_UART_Init,
.uart_send = STM32_UART_Send,
.delay_ms = HAL_Delay
};
// 使用 HAL 接口
HAL_Interface_t *hal = &stm32_hal;
hal->gpio_write(LED_PIN, 1);
配置管理
Flash 存储
使用 Flash 存储配置参数,掉电不丢失。
#include "stm32f1xx_hal_flash.h"
#define CONFIG_FLASH_ADDR 0x08080000 // Flash 最后 64KB
typedef struct {
uint32_t magic; // 魔数校验
uint8_t device_addr; // 设备地址
uint32_t baudrate; // 波特率
uint8_t parity; // 校验位
uint16_t crc; // CRC 校验
} Config_t;
Config_t config;
// 读取配置
int Config_Read(void) {
Config_t *flash_config = (Config_t *)CONFIG_FLASH_ADDR;
// 校验魔数
if (flash_config->magic != 0x5A5A5A5A) {
return -1; // 配置无效
}
// 校验 CRC
uint16_t crc_calc = CRC16((uint8_t *)flash_config, sizeof(Config_t) - 2);
if (crc_calc != flash_config->crc) {
return -1; // CRC 错误
}
memcpy(&config, flash_config, sizeof(Config_t));
return 0;
}
// 写入配置
int Config_Write(void) {
config.magic = 0x5A5A5A5A;
config.crc = CRC16((uint8_t *)&config, sizeof(Config_t) - 2);
HAL_FLASH_Unlock();
// 擦除 Flash
FLASH_ErasePage(CONFIG_FLASH_ADDR);
// 写入配置
uint32_t *data = (uint32_t *)&config;
for (int i = 0; i < sizeof(Config_t) / 4; i++) {
HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD,
CONFIG_FLASH_ADDR + i * 4,
data[i]);
}
HAL_FLASH_Lock();
return 0;
}
默认值管理
配置无效时加载默认值。
void Config_Load_Default(void) {
config.magic = 0x5A5A5A5A;
config.device_addr = 1;
config.baudrate = 19200;
config.parity = 0;
config.crc = CRC16((uint8_t *)&config, sizeof(Config_t) - 2);
}
void Config_Init(void) {
if (Config_Read() != 0) {
Config_Load_Default();
Config_Write();
}
}
版本兼容性处理
版本号管理
定义软件版本号和配置版本号。
#define SOFTWARE_VERSION "1.0.0"
#define CONFIG_VERSION 1
typedef struct {
uint32_t magic;
uint16_t config_version; // 配置版本
uint8_t device_addr;
uint32_t baudrate;
uint8_t parity;
// 保留字段用于扩展
uint8_t reserved[8];
uint16_t crc;
} Config_t;
向后兼容
新版本支持旧配置格式。
int Config_Read(void) {
Config_t *flash_config = (Config_t *)CONFIG_FLASH_ADDR;
if (flash_config->magic != 0x5A5A5A5A) {
return -1;
}
// 旧版本兼容处理
if (flash_config->config_version < CONFIG_VERSION) {
// 迁移旧配置到新格式
config.device_addr = flash_config->device_addr;
config.baudrate = flash_config->baudrate;
config.parity = flash_config->parity;
// 设置新字段默认值
config.config_version = CONFIG_VERSION;
Config_Write();
} else {
memcpy(&config, flash_config, sizeof(Config_t));
}
return 0;
}
完整模块示例
RS485 模块
硬件接口:
- VCC:5V
- GND:地
- A:RS485 A 线
- B:RS485 B 线
- DE/RE:收发控制
软件接口:
// rs485.h
#ifndef RS485_H
#define RS485_H
#include <stdint.h>
typedef struct {
void (*init)(uint32_t baudrate);
void (*send)(uint8_t *data, uint16_t len);
int (*recv)(uint8_t *data, uint16_t len, uint32_t timeout);
void (*set_mode_tx)(void);
void (*set_mode_rx)(void);
} RS485_Driver_t;
extern RS485_Driver_t rs485_driver;
#endif
// rs485.c
#include "rs485.h"
#include "stm32f1xx_hal.h"
UART_HandleTypeDef huart1;
void RS485_Init(uint32_t baudrate) {
huart1.Instance = USART1;
huart1.Init.BaudRate = baudrate;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
HAL_UART_Init(&huart1);
}
void RS485_Send(uint8_t *data, uint16_t len) {
RS485_Set_Mode_TX();
HAL_UART_Transmit(&huart1, data, len, 1000);
RS485_Set_Mode_RX();
}
int RS485_Recv(uint8_t *data, uint16_t len, uint32_t timeout) {
return HAL_UART_Receive(&huart1, data, len, timeout);
}
void RS485_Set_Mode_TX(void) {
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_SET);
HAL_Delay(1);
}
void RS485_Set_Mode_RX(void) {
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET);
HAL_Delay(1);
}
RS485_Driver_t rs485_driver = {
.init = RS485_Init,
.send = RS485_Send,
.recv = RS485_Recv,
.set_mode_tx = RS485_Set_Mode_TX,
.set_mode_rx = RS485_Set_Mode_RX
};
模块化设计检查清单
硬件设计
- 统一连接器型号
- 引脚定义文档化
- 电源电压和电流规格明确
- 信号电平和时序规范定义
- PCB 布局模块化,便于更换
软件设计
- 分层架构清晰(HAL、驱动、协议、应用)
- 接口统一,文档完善
- 回调函数实现解耦
- 条件编译支持跨平台
- 配置管理完善(Flash 存储、默认值、版本兼容)
测试验证
- 单模块独立测试
- 模块间接口测试
- 跨平台移植测试
- 版本兼容性测试
总结
模块化嵌入式系统设计关键点:
- 硬件接口标准化(统一连接器、引脚定义、电源规范)
- 软件分层架构(HAL、驱动、协议、应用层)
- 回调函数实现模块间解耦
- 条件编译和弱引用支持跨平台移植
- Flash 存储配置,支持默认值和版本兼容
- 完整的文档和测试验证
按此设计可构建高复用、易维护、可扩展的嵌入式系统。