4. MCU端基础
在 MCU 与 Linux UI 协同开发中,MCU 端承担着“贴近硬件”的职责:读取按键、驱动指示灯、采集传感器、控制执行器,并通过串口或总线把状态上报给 Linux 主控。UI 层看到的每一个按钮响应、每一条状态刷新,背后都依赖 MCU 外设驱动的稳定运行。本节围绕 GPIO、UART、SPI、I2C 四类最常用外设,梳理其驱动开发的核心原理、配置方法与协同场景。
一、四类外设的定位与差异
GPIO 是最基础的离散信号接口,每个引脚只有高/低两种电平状态,适合按键输入、LED 输出、片选和复位控制。UART 是异步串行通信,双方按约定波特率收发字节,不需要时钟线,常用于 MCU 与 Linux 主控之间的命令与日志通道。SPI 是同步高速总线,依靠 SCLK、MOSI、MISO 和片选 CS 工作,适合屏幕、Flash、高速 ADC 等大数据量场景。I2C 是两线同步总线,SDA 与 SCL 上可挂多个从机,通过地址寻址,适合低速传感器和配置类器件。
二、GPIO 驱动:从寄存器到抽象接口
GPIO 驱动开发的第一步是明确引脚归属与复用功能。多数 MCU 的引脚通过复用寄存器在 GPIO、UART、SPI 等角色间切换,配置错误会导致外设完全无响应。第二步是设置方向与上下拉:输入按键通常启用内部上拉或下拉,避免悬空抖动;输出 LED 需确认灌电流与拉电流能力。第三步是读写与中断:轮询适合低频状态,边沿中断适合按键和脉冲计数。
// 以 STM32 HAL 为例:按键输入 + LED 输出
GPIO_InitTypeDef io = {0};
io.Pin = GPIO_PIN_0;
io.Mode = GPIO_MODE_IT_FALLING; // 下降沿中断
io.Pull = GPIO_PULLUP;
HAL_GPIO_Init(GPIOA, &io);
io.Pin = GPIO_PIN_5;
io.Mode = GPIO_MODE_OUTPUT_PP; // 推挽输出
io.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOB, &io);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, GPIO_PIN_SET);
在协同架构中,GPIO 事件通常不直接映射为 UI 动作,而是先进入 MCU 的事件队列,再由 UART 上报给 Linux 主控,避免 UI 线程被高频中断拖累。
三、UART、SPI、I2C 的驱动要点
UART 驱动关注波特率、数据位、停止位和校验位的一致性,以及收发缓冲与超时处理。MCU 与 Linux 之间常用“帧头 + 长度 + 命令 + 数据 + 校验”的协议,配合环形缓冲区实现非阻塞收发。SPI 驱动关注时钟极性 CPOL、时钟相位 CPHA、位序和片选管理,高速场景下建议使用 DMA 搬运数据。I2C 驱动关注从机地址、时钟频率、应答检测和总线仲裁,多从机系统中要防止地址冲突和总线锁死。
| 外设 | 典型速率 | 线数 | 适用场景 | 驱动关键点 |
|---|---|---|---|---|
| GPIO | — | 1 | 按键、LED、复位 | 复用、上下拉、中断 |
| UART | 9.6k~921.6k bps | 2 | 命令通道、日志 | 波特率、帧协议、缓冲 |
| SPI | 1~50 MHz | 4 | Flash、屏幕、高速 ADC | CPOL/CPHA、CS、DMA |
| I2C | 100k~400k Hz | 2 | 传感器、EEPROM | 地址、应答、总线恢复 |
四、协同场景:按键触发 UI 状态更新
以“按键切换工作模式”为例:MCU 检测到按键下降沿后,在中断中只置位标志,主循环完成消抖并更新本地状态;随后通过 UART 发送一帧状态数据,例如 0xAA 0x05 0x01 0x02 0x03 0x04 0x05 0xBB,其中包含命令字、模式值和校验。Linux 主控收到后解析并更新 UI 状态,界面上的模式指示随之变化。整个过程 MCU 不关心界面长什么样,只负责把硬件状态准确、及时地表达出来。
协同原则:MCU 端驱动负责“采集与执行”,Linux UI 负责“呈现与决策”。两者通过稳定的通信协议解耦,任何一方升级都不应破坏另一方的接口约定。
五、常见误区与复盘
- 忽略引脚复用:只配置 GPIO 模式,未切换复用功能,导致 UART/SPI 无输出。
- 中断中做耗时操作:在 GPIO 中断里直接发送 UART 数据,容易丢帧或阻塞其他中断。
- SPI 模式不匹配:CPOL/CPHA 与从机不一致,读回数据整体错位。
- I2C 无超时:从机掉线后总线被拉低,程序死等,UI 状态永久卡住。
- 协议无校验:偶发干扰导致 UI 显示错误状态,且难以定位。
调试建议:先用逻辑分析仪确认时序,再用串口打印关键状态,最后接入 Linux 端协议解析日志。分层排查能快速区分是硬件配置、驱动逻辑还是通信协议的问题。
注意:GPIO 中断服务函数应尽量短小,只做标志置位或数据入队;UART 收发建议使用 DMA 或环形缓冲,避免在中断中长时间占用 CPU,否则会直接影响 UI 状态上报的实时性。
掌握这四类外设的驱动开发,是 MCU 与 Linux UI 协同工作的基础。只有底层数据采集准确、通信稳定,上层界面才能呈现出可信、流畅的交互体验。