51 单片机分层架构的模块依赖关系图

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 扩散风险。
  • 模块化结构更符合大项目管理方式。

相关推荐
文心快码BaiduComate2 小时前
Comate 4.0新年全面焕新!底层重构、七大升级、复杂任务驾驭力跃升
前端·程序员·架构
DevnullCoffe3 小时前
基于 OpenClaw + Pangolinfo API 的 Amazon 价格监控系统:架构设计与最佳实践
人工智能·架构
Mintopia4 小时前
在深与广之间:产品、架构与开发如何为业务场景做权衡
架构
ray_liang1 天前
用六边形架构与整洁架构对比是伪命题?
java·架构
Java编程爱好者1 天前
字节二面:被问“大模型知识过时了怎么解?”,我答“微调”,面试官当场黑脸:“听说过 RAG 吗?”
架构
葫芦的运维日志1 天前
从手动部署到GitOps只需四步
架构
sumuve1 天前
从100行到1行:我是如何重构IoT设备实时数据通信的?
架构·响应式设计
koddnty1 天前
c++协程控制流深入剖析
后端·架构
Mintopia1 天前
Vite 与 Uni-App X 的协作原理:从前端开发到多端运行的桥梁
架构
louiX2 天前
深入理解 Android BLE GATT 回调机制:从“回调地狱”到高可靠 OTA 架构
架构