嵌入式开发:GPIO、UART、SPI、I2C 驱动开发详解与实战案例

📍 本文为嵌入式学习系列第二篇,基于 GitHub 开源项目:0voice/EmbeddedSoftwareLearn

💬 作者:0voice

👀 适合对象:嵌入式初学者、STM32学习者、想搞明白外设驱动开发的C语言学习者


一、驱动是什么?为什么你必须学会写驱动?

在嵌入式系统中,驱动是连接 MCU 与外部世界的桥梁

你写的所有控制代码(点灯、收发数据、读取温度传感器等),最终都会通过底层驱动转换为硬件动作。

✅ 换句话说,驱动 = 让硬件动起来的 C 语言代码。


二、常用外设驱动概览

外设 功能 常见场景
GPIO 通用输入输出 点灯、按键、继电器
UART 串口通信 串口调试、模块通信
I2C 双线通信 OLED、EEPROM、MPU6050
SPI 高速通信 Flash、ADC、屏幕
ADC 模拟转数字 电压/光强/温度检测
TIM 定时/计数/PWM 电机控制、呼吸灯

这些模块几乎构成了嵌入式开发的大部分控制面。


三、GPIO 点灯裸机驱动代码(STM32为例)

下面是一个最经典的 GPIO 控制示例:点亮 LED 灯。

🔧 初始化流程

c 复制代码
#define RCC_APB2ENR   (*(volatile unsigned int *)0x40021018)
#define GPIOC_CRH     (*(volatile unsigned int *)0x40011004)
#define GPIOC_ODR     (*(volatile unsigned int *)0x4001100C)

void gpio_init() {
    RCC_APB2ENR |= (1 << 4);        // 开启 GPIOC 时钟
    GPIOC_CRH &= ~(0xF << 20);      // 配置 PC13 为推挽输出
    GPIOC_CRH |= (0x1 << 20);       
}

💡 控制 LED 灯亮灭

c 复制代码
void led_on() {
    GPIOC_ODR &= ~(1 << 13);  // 输出低电平
}

void led_off() {
    GPIOC_ODR |= (1 << 13);   // 输出高电平
}

四、UART 串口通信核心代码

串口通信是调试、通信、日志输出的核心。

✍️ 简化裸机收发过程

c 复制代码
void uart_send_char(char data) {
    while (!(USART1->SR & 0x80));  // 等待发送完成
    USART1->DR = data;
}

char uart_recv_char() {
    while (!(USART1->SR & 0x20));  // 等待接收完成
    return USART1->DR;
}

串口需要配置波特率、停止位、奇偶校验、GPIO复用等。

✅ 初学建议配合串口助手查看收发数据。


五、I2C 与 SPI:该如何选择?

比较项 SPI I2C
通信线数 4 2
通信速度 相对较慢
通信方式 全双工 半双工
应用场景 Flash、LCD、音频 OLED、温湿度传感器

💡 I2C 驱动 OLED 屏幕是一个非常好的练手项目!


六、驱动开发常见 Bug 与调试建议

问题 原因 解决建议
外设无响应 没开时钟 检查 RCC 设置
串口乱码 波特率不匹配 确认 MCU 与串口助手波特率一致
SPI 全是 0xFF 主从设置/时序错误 检查主设备 CS 管脚、电平时序
按键无效 引脚配置错误 检查 GPIO 模式是否为输入

✅ 调试技巧:善用 printf + 示波器 + 逻辑分析仪


七、推荐练习项目(从入门到进阶)

项目 涉及外设 难度
LED 跑马灯 GPIO
串口温度输出 UART + 模拟传感器 ⭐⭐
OLED 屏显示 I2C + 显存缓冲 ⭐⭐⭐
SPI 驱动 Flash SPI + 读写校验 ⭐⭐⭐⭐
电压采集与显示 ADC + OLED ⭐⭐⭐⭐

这些项目可作为你学习每个驱动模块的实战切入点。


八、学习建议与驱动能力成长路线

阶段 技能
入门 点灯、串口收发
提升 独立驱动 OLED、EEPROM
实战 多外设交互 + 数据逻辑
系统 模块化驱动架构 + RTOS驱动层封装

📌 建议配合芯片手册与 CubeMX 使用,逐步掌握寄存器与中间抽象层之间的转换。


九、结语与项目推荐

驱动开发不仅是连接软件和硬件的桥梁,也是你从"写代码"走向"做系统"的第一步。

💼 本文基于项目:0voice/EmbeddedSoftwareLearn

📂 项目内容涵盖:C语言基础、外设驱动、RTOS调度、系统移植等,适合系统性学习

欢迎点赞 👍、收藏 ⭐、评论区留言 📮 交流,持续更新「嵌入式系列实战」内容!

相关推荐
码界奇点35 分钟前
解密AI语言模型从原理到应用的全景解析
人工智能·语言模型·自然语言处理·架构
Msshu1231 小时前
PD快充诱骗芯片 XSP15 支持获取快充电压可与外部MCU共用D+D-网络与电脑传输数据
单片机·嵌入式硬件
brave and determined1 小时前
MCU学习Day24——STM32G030多路ADC DMA采集深度解析:完全可配置序列器与不完全可配置序列器的陷阱与抉择
stm32·单片机·嵌入式硬件·dma·adc·hal·多通道采集
d111111111d1 小时前
通过操作地址,来进行STM32的写入GPIO端口值
stm32·单片机·嵌入式硬件
奔跑吧邓邓子2 小时前
【C语言实战(77)】STM32实战:解锁传感器数据采集的C语言奥秘
c语言·stm32·开发实战·传感器数据采集
小刘爱玩单片机2 小时前
【stm32简单外设篇】- 土壤湿度传感器
c语言·stm32·单片机·嵌入式硬件
小龙报2 小时前
算法通关指南:数据结构和算法篇 --- 队列相关算法题》--- 1. 【模板】队列,2. 机器翻译
c语言·开发语言·数据结构·c++·算法·学习方法·visual studio
d111111111d2 小时前
STM32外设学习--TIM定时器--编码器接口
stm32·嵌入式硬件·学习
晨非辰2 小时前
【数据结构初阶】--从排序算法原理分析到代码实现操作,参透插入排序的奥秘!
c语言·开发语言·数据结构·c++·算法·面试·排序算法
2301_795167206 小时前
玩转Rust高级应用 如何避免对空指针做“解引用”操作,在C/C++ 里面就是未定义行为
c语言·c++·rust