1. 从零理解软件模拟I2C的核心逻辑
第一次接触软件模拟I2C时,我盯着示波器上那些高低电平的变化波形看了整整一个下午。当时最困惑的是:为什么用GPIO口模拟的简单高低电平变化,就能实现设备间的可靠通信?后来在GD32F303上反复调试AT24C02的过程中,才真正理解了其中的门道。
I2C协议本质上是通过两根线(SCL时钟线和SDA数据线)的时序配合完成通信。软件模拟的关键在于精确控制这两根线的电平变化节奏。举个例子,起始信号的定义是SCL高电平时SDA从高到低的跳变,这个动作如果用代码表示就是:
void IIC_Start(void) {
SDA_OUT(); // 设置SDA为输出模式
IIC_SDA(1); // SDA拉高
IIC_SCL(1); // SCL拉高
delay_us(4); // 保持4us
IIC_SDA(0); // SDA拉低
delay_us(4); // 保持4us
IIC_SCL(0); // SCL拉低完成起始信号
}
这段代码中每个delay_us的数值都不是随便写的。AT24C02在标准模式下最高时钟频率400kHz,意味着每个时钟周期至少2.5us。实际调试时发现,当GD32F303主频在120MHz时,delay_us(4)能稳定工作,但降到2us以下就会出现数据错位。
2. 延时函数的精度陷阱与解决方案
很多初学者最容易栽在延时精度这个坑里。我曾遇到过用循环实现的延时函数在-O2优化等级下完全失效的情况。后来改用SysTick定时器才解决问题,关键代码如下:
void delay_us(uint32_t nus) {
uint32_t ticks = nus * (SystemCoreClock / 1000000);
uint32_t start = SysTick->VAL;
while(1) {
uint32_t current = SysTick->

1万+

被折叠的 条评论
为什么被折叠?



