51 单片机分层架构的模块依赖关系图,并配一份可直接套用的代码框架
一、51 单片机软件分层架构图
┌───────────────────────────────┐
│ 应用层(APP) │
│ - 产品业务逻辑(状态机) │
│ - 用户交互(按键、显示) │
│ - 流程控制(加热、保温等) │
└───────────────▲───────────────┘
│ 调用接口
┌───────────────┴───────────────┐
│ 服务层(Service) │
│ - 协议解析(Modbus、私有协议) │
│ - 数据处理(滤波、PID) │
│ - 按键扫描、显示缓存管理 │
└───────────────▲───────────────┘
│ 调用接口
┌───────────────┴───────────────┐
│ 硬件抽象层(HAL) │
│ - GPIO 接口化 │
│ - 串口收发接口化 │
│ - 定时器抽象接口 │
│ - 屏蔽不同 51 寄存器差异 │
└───────────────▲───────────────┘
│ 调用接口
┌───────────────┴───────────────┐
│ 硬件驱动层(Driver) │
│ - 直接操作寄存器 │
│ - 初始化、收发、配置 │
│ - 单片机特定寄存器访问 │
└───────────────────────────────┘
依赖规则:
- 上层只能调用下层,不允许跨层调用(例如 APP 不能直接用 Driver)。
- 硬件变化只改 Driver 和 HAL,业务变化只改 Service 和 APP。
二、代码文件组织结构
/project
│
├── app/
│ ├── app_main.c // 主循环、状态机
│ └── app_main.h
│
├── service/
│ ├── service_key.c // 按键扫描
│ ├── service_key.h
│ ├── service_display.c // 显示管理
│ └── service_display.h
│
├── hal/
│ ├── hal_gpio.c // GPIO 抽象
│ ├── hal_gpio.h
│ ├── hal_uart.c // 串口抽象
│ └── hal_uart.h
│
├── driver/
│ ├── driver_gpio.c // 直接操作 P0/P1/P2/P3
│ ├── driver_gpio.h
│ ├── driver_uart.c // 串口寄存器
│ └── driver_uart.h
│
└── main.c // 系统初始化入口
三、示例代码框架
driver_uart.c(硬件驱动层)
c
#include "driver_uart.h"
#include <REG51.H>
void UART0_Init(uint32_t baud) {
SCON = 0x50; // 串口模式1
TMOD |= 0x20; // 定时器1模式2
TH1 = 256 - (11059200UL / 12 / 32 / baud);
TL1 = TH1;
TR1 = 1;
}
void UART0_SendByte(uint8_t dat) {
SBUF = dat;
while (!TI);
TI = 0;
}
uint8_t UART0_RecvByte(void) {
while (!RI);
RI = 0;
return SBUF;
}
hal_uart.c(硬件抽象层)
c
#include "hal_uart.h"
#include "driver_uart.h"
void HAL_UART_Init(void) {
UART0_Init(9600);
}
void HAL_UART_SendString(const char *str) {
while (*str) {
UART0_SendByte(*str++);
}
}
service_key.c(服务层)
c
#include "service_key.h"
#include "hal_gpio.h"
#define KEY1_PIN P1_0
uint8_t Key_Scan(void) {
if (HAL_GPIO_ReadPin(KEY1_PIN) == 0) {
// 简单消抖
HAL_DelayMs(10);
if (HAL_GPIO_ReadPin(KEY1_PIN) == 0) {
return 1;
}
}
return 0;
}
app_main.c(应用层)
c
#include "service_key.h"
#include "hal_uart.h"
void APP_MainLoop(void) {
if (Key_Scan()) {
HAL_UART_SendString("Key Pressed\r\n");
}
}
main.c(系统入口)
c
#include "hal_uart.h"
#include "app_main.h"
void main(void) {
HAL_UART_Init();
while (1) {
APP_MainLoop();
}
}
四、这样分层的好处
- 换 51 型号,只改
driver_*
,不用改上层逻辑。 - 协议、算法、业务逻辑可直接移植到别的 MCU。
- 每层可独立调试,降低 bug 扩散风险。
- 模块化结构更符合大项目管理方式。