I2C通讯协议详解:SDA/SCL时序与数据传输机制
创作时间:
作者:
@小白创作中心
I2C通讯协议详解:SDA/SCL时序与数据传输机制
引用
CSDN
1.
https://blog.csdn.net/weixin_44006573/article/details/105674761
I2C(Inter-Integrated Circuit)总线是一种两线式串行通信总线,广泛应用于微控制器(MCU)与外围设备之间的数据传输。它采用一主多从的总线结构,通过SDA(串行数据线)和SCL(串行时钟线)实现数据的发送和接收。本文将详细介绍I2C总线的基本概念、时序规则以及具体实现方式。
一、基础介绍
I2C总线的主要功能是实现主机和从机之间的数据传输,其核心机制包括起始信号、终止信号、应答信号、读字节、写字节、数据读取和数据写入等。I2C总线的基本架构如下:
Start_I2C
Stop_I2C
readack 读取应答信号
sendack and sendnack 输出应答或非应答
sendbyte
readbyte
write_I2C
read_I2C
二、I2C通信协议详解
1. 空闲状态
SDA和SCL通过上拉电阻保持高电平,表示总线处于空闲状态。
2. 主从设备
- 主设备负责控制通信,通过初始化/终止化数据传输,发送数据并产生同步时钟脉冲。
- 从设备等待主设备的命令并响应,同步时钟信号只能由主设备产生。
3. 起始信号和结束信号
(1) I2C的起始位
void I2C_sendStart() //开始位
{
SDA=1; /*发送起始条件的数据信号*/
SCL=1;
SDA=0; /*发送起始信号*/
Delay_us(1);
SCL=0;
}
(2)I2C的结束位
Void sendstop()
{
SCL=0;
SDA=0; /*发送结束条件的数据信号*/
SCL=1;
while(SCL!=1) { };
Delay_us(1);
SDA=1; Delay_us(1);
}
4. 数据有效性
I2C总线在SCL的每个时钟脉冲期间传输一个数据位。数据线SDA上的数据必须在SCL为高电平时保持稳定,只有在SCL为低电平时,SDA的状态才能发生变化。从机地址发送完成后,可能会发送一些指令,然后开始传输数据,每个数据为8位,数据的字节数没有限制。
5. 应答信号
- 当SDA是低电平表示有效应答(ACK),表示接收成功。
- 当SDA是高电平表示无效应答(NACK),表示接收失败。
(1)接收数据需向发送方发送应答:
void IIC_ack(u8 ack)
{
// 数据线设置为输出
SCL = 0;
delay_us(5);
if(ack)
SDA = 1; // 无效应答
else
SDA = 0; // 有效应答
delay_us(5);
SCL = 1;
// 保持数据稳定
delay_us(5);
// 拉低SCL开始传输数据
SCL = 0;
}
(2)发送数据需等待接收方的应答:
// 等待ACK 1-无效 0-有效
u8 IIC_wait_ack(void)
{
u8 ack = 0;
// 数据线设置为输入
// 拉高时钟线
SCL = 1;
delay_us(5);
// 获取数据线的电平
if(SDA)
{ // 无效应答
ack = 1;
IIC_stop();
}
else
{ // 有效应答
ack = 0;
// 拉低SCL开始传输数据
SCL = 0;
delay_us(5);
}
return ack;
}
三、I2C通信实现方式
1. 硬件I2C
使用芯片上的I2C外设,有专用的I2C引脚,通过调用I2C的控制函数实现通信,无需手动控制SCL、SDA的电平变化。
2. 模拟I2C
通过软件控制任意IO口模拟I2C协议的时序,实现I2C信号和数据传输。
3. 数据读取和写入的示例
- Write_I2C:start->slave address+0+ACK+数据包(byte+ack+…+byten+Nack)+stop
- Read_I2C:start->slave address+1+ACK+数据包(byte+ack+…+byten+Nack)+stop
注意:slave address是7位的一个字节,write是0位,read是1位。
示例:
- slave address为50H(1010000)
- 写地址:10100000(A0)
- 读地址:10100001(A1)
具体流程:
- 发送开始条件
- 发送从机地址和读写控制位
- 传输数据及数据传输结束时
- 发送停止条件
4. 应用示例
(1)读取I2C的应答标志位
Unsigned char readACK() //读取应答信号
{
SCL=0;
SDA=1; /*此处为释放SDA 总线,由从从机发出低电平应答*/
_nop_();
SCL=1;
_nop_();
if(SDA)
return 1; //no ACK
else
return 0; //ACK
}
(2)主控端送出应答信号
void sendACK() //输出应答信号
{
SCL=0;
SDA=0;
_nop_();
SCL=1;
}
void sendNOACK() //输出无应答信号
{
SCL=0;
SDA=1;
_nop_();
SCL=1;
}
(3)主控端写入一个字节到从机
void sendByte(uchar dat) //写一个字节
{
uchar i;
for(i=0;i<8;i++)
{
SCL=0; /*钳住I2C 总线,准备发送数据 */
if(dat&0x80)
SDA=1;
else
SDA=0;
_nop_();
_nop_();
SCL=1;
dat<<=1;
}
}
(4)主控端对从机读取一个字节
uchar readByte() //读一个字节
{
uchar i, dat=0;
for(i=0;i<8;i++)
{
SCL=0;
SDA=1;
_nop_();
dat<<=1;
SCL=1;
if(SDA==1)
dat|=0x01;
}
return dat;
}
(5)主控端数据写入
bit writeIIC(uchar addrW, uchar *writeData, uchar length)
{
uchar i;
bit ACK;
sendStart();
sendByte(addrW); //传送地址与写入标记
ACK = readACK();
if (ACK)
{
sendStop(); //地址不正确或装置未连接,送出停止信号
return ACK;
}
for(i = 0; i<length; i++)
{
sendByte(writeData[i]);
ACK = readACK();
if (ACK)
{
sendStop(); //未接收到ACK,送出停止信号
return ACK;
}
}
sendStop(); //资料写入完成,送出停止信号
return ACK;
}
(6)主控端对从机数据读取
bit readIIC(uchar addrR, uchar *readData, uchar length)
{
uchar i;
bit ACK;
sendStart();
sendByte(addrR); //传送地址与读取标记
ACK = readACK();
if (ACK)
{
sendStop(); //地址不正确或装置未连接,送出停止信号
return ACK;
}
for(i = 0; i<length; i++)
{
readData[i] = readByte();
if(i<length-1)
sendACK();
else
sendNOACK(); //读取最后一笔资料,送出No ACK
}
sendStop(); //资料读取完成,送出停止信号
return ACK;
}
(7)调用数据写入和读取
writeIIC(address_W, &Write_Buffer,4);
readIIC(address_R, &Read_Buffer, 5);
热门推荐
用B-P神经网络提升软件预测功能,你get了吗?
供应链预测新趋势:B-P神经网络 vs ARIMA
BP神经网络助力医疗诊断新突破
Vue照片卡点视频用什么音乐
百川智能Baichuan 3登顶国内AI大模型榜首,医疗场景应用成亮点
斯里兰卡旅游必看!如何合理兑换卢比?
郑益昕:从杭州亚运到巴黎奥运的排球奇兵
郑益昕率福建女排征战排超联赛,力争八强席位
滇藏线旅游攻略:从云南到西藏的绝美之旅
韭菜鸡蛋饺子馅调制全攻略:从基础到进阶的多种方法
韭菜鸡蛋饺子馅调制全攻略:从基础到特色,多种方法任你选
国家规定假期有哪些?如何计算年假天数?
中国科学院&NICE推荐:职业健康管理新策略
火电企业职业健康管理:挑战、政策与实践
这些出水文物见证甲午海战
骨刺的中医治疗方法是什么
自驾游10年总结:10条自驾游注意事项
当心!别中了“伪流水线直播”圈套
零基础也能轻松掌握!简笔画汽车教程
支付行业的移动支付技术发展趋势
日本消费者最爱用的支付方式有哪些?
日本交通卡中西瓜卡和ICOCA卡的区别
宜昌市疾控中心发布冬季防病小贴士:呼吸道和肠道传染病如何预防?
健康薯片:吃货的新宠儿!
自制酥脆泡泡薯片,亲子DIY新宠!
自制薯片成新宠!宅家必备追剧神器
小天使画室教你轻松画小汽车
亲子互动:一起学画小汽车简笔画
绵阳方特必打卡:神画、女娲补天、孟姜女
方特东方神画:《千里江山图》震撼来袭!