1. GD32V通信协议概述:UART、SPI、I2C基础概念与GD32V外设特性

各位同学,咱们今天正式开篇。做嵌入式开发,说白了就是让芯片跟外界“说话”。不管是跟传感器要个温度数据,还是往显示屏上刷个画面,都离不开通信协议。GD32V这颗RISC-V内核的芯片,它的通信外设设计得挺扎实,但用好它,你得先理解这些协议到底在干什么。

我个人习惯,拿到一款新芯片,第一件事不是翻数据手册的寄存器列表,而是先看它的通信外设框图。为什么?因为通信是系统的“血管”,血管不通,CPU再强也没用。今天这一章,咱们就把UART、SPI、I2C这三个最常用的协议,结合GD32V的外设特性,掰开揉碎了讲清楚。

本章核心目标: 理解三大串行通信协议的本质差异,掌握GD32V对应外设的硬件特性与配置要点,为后续的驱动编写和调试打下基础。

1.1 为什么是串行通信?

你可能会问,为什么不用并行通信?一次传8位、16位,不是更快吗?嗯,这里要注意——并行通信在短距离、高频场景下,信号之间的串扰和时序偏差会让你头疼到怀疑人生。我早年做一款图像采集卡,8位并行数据线在50MHz下,布线稍微长一点,数据就全乱了。

串行通信的优势在于:

  • 引脚少——节省芯片封装成本和PCB面积
  • 抗干扰强——差分信号(如RS485)可以传几百米
  • 时序简单——时钟和数据的关系清晰,调试相对容易

GD32V系列芯片,根据型号不同,通常提供2~8个UART、2~3个SPI、1~2个I2C。数量不算多,但覆盖绝大多数嵌入式场景足够了。

1.2 UART:最通用的“老黄牛”

UART(Universal Asynchronous Receiver/Transmitter),通用异步收发器。注意“异步”这两个字——它没有独立的时钟线,收发双方靠约定的波特率来同步。

我刚开始学嵌入式时,总觉得异步通信不靠谱:两边时钟精度不一样,时间长了不就对不上了吗?其实UART在每个字节的开头都有一个起始位,相当于“我要开始发了,你准备好”,然后接收方用本地时钟采样。只要波特率误差在±2%以内,基本不会出错。

GD32V的UART特性

特性 说明
支持波特率 最高可达4.5Mbps(取决于系统时钟和分频配置)
数据位 7位、8位、9位可选
停止位 0.5、1、1.5、2位
校验位 无校验、奇校验、偶校验
硬件流控 支持RTS/CTS(部分型号)
FIFO深度 发送和接收各16字节
中断源 发送完成、接收非空、接收溢出、错误等
我的经验: 调试UART时,先用示波器看TX引脚的波形。如果波形幅度不对或者边沿不陡,先查电平转换芯片(如MAX3232)的供电和电容。我曾经被一颗虚焊的电容坑了整整半天,波形一直像“软脚虾”一样。

GD32V的UART还有一个很实用的特性——支持单线半双工模式。这意味着你可以用一根线既发又收,适合与某些单总线协议的传感器通信。不过要注意,半双工模式下需要软件控制收发切换,否则会冲突。

1.3 SPI:高速“同步”通道

SPI(Serial Peripheral Interface),串行外设接口。它跟UART最大的区别是:有独立的时钟线(SCK)。收发双方在时钟的上升沿或下降沿同步采样数据,所以速度可以做得非常高。

SPI总线通常有4根线:

  • SCK——时钟,由主机产生
  • MOSI——主机输出,从机输入
  • MISO——主机输入,从机输出
  • CS——片选,低电平有效,用于选择从机

你想想看,SPI的通信模型其实很简单:主机拉低某个从机的CS线,然后开始产生时钟,同时在MOSI上发送数据,从MISO上接收数据。一个时钟周期内,数据双向流动。

GD32V的SPI特性

特性 说明
最大速率 系统时钟的一半(如108MHz主频下可达54MHz)
数据帧格式 4~16位可编程
时钟极性/相位 CPOL和CPHA可配置,共4种模式
片选控制 硬件自动控制或软件手动控制
FIFO深度 发送和接收各16位(单级缓冲)
DMA支持 支持,可配合DMA实现高速连续传输
避坑指南: 我曾经在调试一款LCD显示屏时,SPI通信总是丢字节。查了半天发现是CPOL和CPHA配置错了。显示屏要求模式0(CPOL=0, CPHA=0),而我配成了模式3。记住:SPI的四种模式取决于从机的要求,不是你想用哪个就用哪个。先看从机数据手册的时序图!

GD32V的SPI还支持TI模式(与德州仪器的SPI兼容)和I2S模式(用于音频数据)。不过I2S模式在GD32V上属于“附加功能”,实际使用时要注意时钟精度,否则音频会有杂音。

1.4 I2C:两线制的“多面手”

I2C(Inter-Integrated Circuit),集成电路间总线。它只用两根线:SDA(数据线)和SCL(时钟线),但可以挂载多个设备,每个设备有唯一的地址。

I2C的通信过程有点像“打电话”:主机先拨号(发送起始条件和从机地址),从机应答(ACK),然后开始传输数据。传输结束后,主机挂断(发送停止条件)。

为什么I2C只有两根线却能实现多设备通信?因为它是开漏输出,加上上拉电阻。所有设备的SDA和SCL引脚都是“线与”关系——任何一个设备拉低,总线就是低电平。这就避免了多设备同时驱动总线导致的冲突。

GD32V的I2C特性

特性 说明
工作模式 标准模式(100kHz)、快速模式(400kHz)
地址长度 7位或10位
主从模式 支持主机和从机模式
多主机仲裁 硬件支持,自动检测总线冲突
FIFO深度 无独立FIFO,靠移位寄存器和中断
DMA支持 支持,但需注意时序配合
我的习惯: 调试I2C时,逻辑分析仪是必备工具。把SDA和SCL两根线挂上去,抓一段波形,对照数据手册的时序图,一眼就能看出问题。比如ACK位没有拉低,说明从机没响应——要么地址错了,要么从机没上电。

GD32V的I2C有一个容易忽略的细节:它的SCL时钟频率是通过APB时钟分频得到的,分频系数是一个整数。这意味着你无法得到任意精确的100kHz或400kHz,只能取近似值。比如APB时钟为54MHz时,要得到400kHz,分频系数为54M/400k=135,实际频率为54M/135=400kHz,刚好。但如果APB时钟是50MHz,分频系数125,实际频率就是400kHz,也刚好。但如果是48MHz,分频系数120,实际频率400kHz——嗯,还是刚好。但如果是72MHz,分频系数180,实际频率400kHz——你发现规律了吗?

其实我想说的是:只要分频后的实际频率不超过目标频率的±10%,大多数I2C从机都能正常工作。别太纠结那几kHz的偏差。

1.5 三大协议对比与选型建议

咱们用一张表来总结一下UART、SPI、I2C的核心差异:

特性 UART SPI I2C
信号线数量 2(TX/RX) 4(SCK/MOSI/MISO/CS) 2(SDA/SCL)
同步方式 异步(波特率约定) 同步(时钟线) 同步(时钟线)
最大速率 ~4.5Mbps ~54MHz 400kHz(快速模式)
多设备支持 点对点(或RS485多机) 一主多从(片选) 多主多从(地址)
硬件复杂度 低 中 中高(开漏+上拉)
典型应用 调试日志、GPS、蓝牙模块 Flash、LCD、SD卡、ADC 传感器、EEPROM、RTC

选型建议其实很简单:

  • 如果只是跟PC通信或者传日志,用UART,简单可靠。
  • 如果需要高速传输大量数据(比如刷屏、读写Flash),用SPI。
  • 如果引脚紧张且需要挂多个低速设备,用I2C。

但实际项目中,往往是三种协议混着用。比如一个智能家居网关,用UART接4G模块,用SPI接以太网芯片,用I2C接温湿度传感器。GD32V的外设资源刚好能覆盖这些需求。

1.6 GD32V通信外设的共性设计

最后,我想聊聊GD32V在通信外设设计上的一些共性特点。这些特点在你后续写驱动时会反复遇到:

  1. 寄存器映射清晰——每个外设的控制寄存器、状态寄存器、数据寄存器都有固定的偏移地址,且命名规范。比如UART的USART_STAT寄存器,bit0是TC(发送完成),bit5是RXNE(接收非空)。
  2. 中断向量独立——每个通信外设都有独立的中断向量,不像某些MCU多个外设共享一个中断号。这意味着你可以为每个外设单独写中断服务函数,代码更清晰。
  3. DMA支持完善——UART、SPI、I2C都支持DMA传输。我个人建议,只要数据量超过16字节,就用DMA。CPU可以腾出手来处理其他任务,系统整体吞吐量会明显提升。
  4. 时钟门控——每个外设的时钟都可以独立使能或关闭。不用的外设记得关掉时钟,能省不少功耗。我见过有人把所有外设时钟都开着,结果待机电流多了好几毫安。
核心要点: 理解GD32V通信外设的共性设计,比死记每个寄存器的位定义更重要。因为当你掌握了“时钟使能→复位→配置参数→使能外设→中断/DMA处理”这个通用流程后,换任何一个外设,你都能快速上手。
GD32V 通信协议知识体系 GD32V 通信外设 UART SPI I2C 异步/波特率 同步/时钟线 多从机/片选 多主机/地址 FIFO/中断 DMA支持 时钟门控 选型原则:速度要求高→SPI;引脚少→I2C;调试方便→UART GD32V外设共性:独立中断 + DMA + 时钟门控