📝摘要:本文讲解I2C总线时序、读写流程,实战器件AT24C02 EEPROM、LM75温度传感器;讲解ADC模数转换原理、逐次逼近ADC、分辨率计算,多种数字滤波算法,附带时序示例与计算公式。
🔖标签:
#I2C#ADC#AT24C02#LM75#嵌入式裸机开发
1. I2C总线协议基础
I2C是半双工串行通信总线,两根信号线:SCL时钟线、SDA数据线。
- SCL:Serial Clock 串行时钟,由主机产生时钟信号;
- SDA:Serial Data 串行数据线,双向收发数据;>
I2C数据传输高位先行(MSB优先),先发bit7,最后发bit0。
设备地址格式
I2C总线上第一个字节格式:【7位从机设备地址】 + 1位读写方向位
- bit7~bit1:7位设备地址;
- bit0:读写位
0:主机写数据到从机;1:主机从从机读取数据。
示例:设备地址0x48
写操作:0x48 << 1 | 0 = 0x90
读操作:0x48 << 1 | 1 = 0x91
I2C标准速率:
- 标准模式:
100KHz - 快速模式:
400KHz - 高速模式:1.x MHz
- 超高速模式:3.x MHz
总线最多挂载127个不同7位地址的从机设备。
2. I2C时序:起始、停止、数据传输、ACK/NACK应答
硬件条件:SDA、SDA需要外接上拉电阻;空闲状态SCL、SDA都为高电平。
① 起始信号 START
SCL为高电平期间,SDA数据线由高电平向低电平跳变(下降沿),代表I2C通信启动。
② 停止信号 STOP
SCL为高电平期间,SDA数据线由低电平向高电平跳变(上升沿),代表通信结束。
③ 数据比特传输规则
- SCL高电平时:SDA电平必须保持稳定,接收方采样读取SDA上的数据比特;
- SCL低电平时:发送方才允许改变SDA数据线电平。>
❗不允许SCL为高的时候改变SDA,否则会被识别为START/STOP信号,破坏通信。
④ ACK / NACK应答信号
每传输完8bit(1字节),第9个时钟周期用来做应答:
- ACK应答:接收方把SDA拉为低电平 → 代表接收成功;
- NACK无应答:SDA保持高电平 → 代表接收失败,没有应答。
写流程:每发送1字节,主机释放SDA,等待从机回复ACK;
读流程:主机收到1字节之后,主机控制SDA发出ACK/NACK。
读取最后一个字节的时候,主机发送NACK告诉从机不再继续读数据,之后发出STOP停止信号。
3. I2C写时序、I2C读时序
I2C写流程(主机向从机寄存器写入1字节)
- 主机发送 START起始信号;
- 主机发送:
7位从机地址 + 写位(0),等待从机返回ACK; - 主机发送从机内部寄存器地址,等待从机ACK;
- 主机发送要写入的数据字节,等待从机ACK;
- 主机发送 STOP停止信号,通信结束。
I2C读流程(主机读取从机寄存器数据,组合起始信号)
I2C读之前,必须先写寄存器地址,使用重复起始信号 Repeated START,不发送停止信号。
- 主机发送START;
- 发送
从机地址+写位0,等待ACK; - 发送要读取的内部寄存器地址,等待ACK;
- 发送重复START信号(Repeated START,不发STOP);
- 发送
从机地址+读位1,等待从机ACK; - 主机接收从机发来的数据字节;
- 读完最后1字节,主机发出NACK,通知从机不再接收;
- 主机发送STOP停止信号。
易错坑:读取I2C不能直接上来就发读地址,必须先写寄存器编号;不能中间发STOP,要用重复起始。
软件I2C伪代码示例(模拟发送1字节)
// 发送一个字节,高位先行
void i2c_send_byte(unsigned char dat)
{
int i;
for(i = 0; i < 8; i++)
{
//SCL拉低,允许修改SDA
SCL = 0;
if(dat & 0x80)
SDA = 1;
else
SDA = 0;
dat <<= 1;
delay_us(5);
SCL = 1; //SCL高,从机采样SDA
delay_us(5);
}
SCL = 0;
//等待ACK应答
SDA = 1; //主机释放SDA
SCL = 1;
int ack = SDA;
SCL = 0;
}
4. I2C实战器件 AT24C02、LM75
AT24C02 EEPROM 电可擦除存储器
- 容量:
2Kbit,等价256字节; - I2C设备地址:
0x50; - 非易失存储,断电数据不会丢失;可以读写保存配置数据。
注意:EEPROM写入之后需要等待内部烧写时间,不能立刻连续写。
LM75 I2C数字温度传感器
| 参数 | 说明 |
|---|---|
| 工作电压 | 2.7V ~5.5V |
| 测量量程 | -55℃ ~ +125℃ |
| 测量精度 | ±2℃ ~ ±3℃ |
| 分辨率 | 9位,0.5℃ |
| I2C从机地址 | 0x48 |
| 温度寄存器地址 | 0x00 |
读取规则:读取2字节原始温度数据,低7位舍弃,有效数据为高9位,再换算摄氏度。
拓展:Cortex‑A7可以打开FPU(CP11协处理器),硬件浮点运算,处理温度浮点计算。
5. ADC模数转换原理
ADC:Analog‑to‑Digital Converter,模数转换器。
作用:把模拟信号(连续变化电压)转换成数字离散采样值 。
现实世界物理量(温度、液位、压力)属于模拟量;计算机只能处理数字。
示例高危液体储罐告警系统:
液位高度变化 → 传感器转换为连续变化电压;ADC采样电压,CPU读取数字值,判断液位是否超限,触发告警。
- 采样率(采样速度,单位HZ):每秒采集多少次模拟信号;采样率越高采样越密集。>
奈奎斯特采样定理:采样率必须大于信号最高频率2倍,才可以还原原始信号。
ADC关键概念
- Vref:参考基准电压,决定ADC量程。例如Vref=5V,则ADC输入电压范围0~5V。
- 模拟输入电压:外部待测量电压。
6. 逐次逼近型ADC工作原理
逐次逼近ADC,类似二分查找思想,从最高bit到最低bit逐位试探比较。
举例:Vref基准5V,待测电压3.2V
- 内部DAC输出中间值
2.5V,和待测3.2V比较;待测电压更大 → 当前bit置1; - 再向上试探:
2.5 +1.25 = 3.75V,比3.2V大,bit置0; - 继续二分
3.125V,小于3.2V,bit置1; - 逐位完成所有bit比较,最终输出数字采样结果。
优点:转换速度中等,硬件成本适中,嵌入式MCU大量使用逐次逼近ADC。
7. ADC分辨率与电压计算公式
分辨率代表ADC可以把参考电压切分成多少份。
| ADC位数 | 采样取值范围 | 份数 |
|---|---|---|
| 8bit | 0 ~ 255 | 256份 |
| 10bit | 0 ~1023 | 1024份 |
| 12bit | 0~4095 | 4096份 |
| 16bit | 0~65535 | 65536份 |
公式:
输入电压=采样数字值2分辨率位数−1×Vref输入电压 = \frac{采样数字值}{2^{分辨率位数}-1} \times V_{ref}输入电压=2分辨率位数−1采样数字值×Vref
示例:10bit ADC,Vref=5V,读到采样值650
U=6501023×5VU = \frac{650}{1023} \times5VU=1023650×5V
注意:ADC采样存在硬件噪声,会带来采样误差。
8. 数字滤波算法
ADC采样经常受外界干扰,原始数据跳动,软件使用滤波算法降低噪声。
-
均值滤波:多次采样求算术平均值;抑制随机白噪声;缺点:响应速度变慢。
//均值滤波示例,采样N次取平均
#define N 8
int adc_filter(void)
{
int sum = 0;
for(int i=0;i<N;i++)
{
sum += adc_read_sample();
}
return sum / N;
} -
低通滤波:滤除高频突变噪声,保留缓慢变化信号,适合温度、液位这类变化慢的物理量。
-
高通滤波:保留快速变化信号,滤除直流缓慢分量,适合脉冲检测。
-
卡尔曼滤波:预测式滤波算法,结合历史状态做最优估计,抗干扰强,算法复杂,机器人、姿态传感器大量使用。
9. 英文缩写全称对照表
| 缩写 | 英文全称 | 中文释义 |
|---|---|---|
| I2C | Inter‑Integrated Circuit | 集成电路间串行总线 |
| SCL | Serial Clock | I2C串行时钟线 |
| SDA | Serial Data | I2C串行数据线 |
| ACK | Acknowledge | 应答信号 |
| NACK | Not Acknowledge | 无应答信号 |
| EEPROM | Electrically Erasable Programmable Read‑Only Memory | 电可擦除只读存储器 |
| ADC | Analog‑to‑Digital Converter | 模数转换器 |
| DAC | Digital‑to‑Analog Converter | 数模转换器 |
| Vref | Reference Voltage | 参考基准电压 |
| FPU | Floating‑Point Unit | 浮点运算单元(CP11协处理器) |
| MSB | Most Significant Bit | 最高有效位 |
| LSB | Least Significant Bit | 最低有效位 |
💡复习要点总结
- I2C空闲SDA/SCL高电平;START/STOP都发生在SCL高电平;SCL高时SDA不能随便变;读最后一个字节主机发NACK。
- I2C读操作要先写寄存器地址,使用重复START,不能直接发读命令。
- LM75读取的2字节温度,丢弃低7位,使用高9位做温度换算。
- 逐次逼近ADC本质二分法逐位比较;电压计算公式:采样值/(2^N‑1)*Vref。
- ADC原始采样有噪声,软件可使用均值滤波、卡尔曼滤波等算法优化数据。