1.串口通信的缺点(与IIC协议的对比)
1. 串口通信通常需要至少三条线(TX、RX和GND),而 I2C 总线仅需要两条信号线(SDA和SCL);
2. 串口通信仅支持一对一通信,而 I2C 总线支持多机通信,允许单个主机与多个从机设备进行通信;
3. 串口通信通常无应答机制,而 I2C 必须有应答机制;
4. 串口通讯一般是异步通信,而 I2C 使用同步传输方式,数据在时钟信号(SCL)的控制下传输。
2.IIC协议概述
I2C总线,全称Inter-Integrated Circuit(互连集成电路),是一种由Philips(现NXP半导体)公司在1980年代初开发的同步 串行 半双工通信总线
·两个总线挂两个上拉电阻
·需要选择推挽输出和开漏输出的其中一种输出模式
·推挽输出只能输出一个高电平和一个低电平,开漏输出只能输出低电平,两个输出详解(http://t.csdnimg.cn/LOZt4)
输出怎么选择?
如果是推挽输出的话,一高一低电平,他们会相连会把硬件烧掉
所以一般用开漏输出,不过两个总线要各接一条上拉电阻,用来控制输出高电平
如果只有一个从机,一个主机的话配置开漏或推挽都可以,开漏的话要确保有上拉电阻
示例框图:
工作原理:
主从关系:主器件用于启动总线传送数据,并产生时钟以开放传送的器件,此时任何被寻址的器件均被认为是从器件。在总线上主和从、发和收的关系不是恒定的,而取决于此时数据传送方向。
数据传送:如果主机要发送数据给从器件,则主机首先寻址从器件,然后主动发送数据至从器件,最后由主机终止数据传送。如果主机要接收从器件的数据,首先由主器件寻址从器件,然后主机接收从器件发送的数据,最后由主机终止接收过程。
时钟同步:SCL用于数据的时钟同步,确保主从设备之间的数据传输同步进行。
主要特点:
硬件简单:I2C总线只需要一根数据线和一根时钟线两根线,总线接口已经集成在芯片内部,不需要特殊的接口电路。
多主机总线:I2C总线是一个真正的多主机总线,如果两个或多个主机同时初始化数据传输,可以通过冲突检测和仲裁防止数据破坏。
在线检测:I2C总线可以通过外部连线进行在线检测,便于系统故障诊断和调试。
数据传输与地址设定:数据传输和地址设定由软件设定,非常灵活。总线上的器件增加和删除不影响其他器件正常工作。
负载能力:由于线路中电容会影响总线传输速度,I2C总线的负载能力为400pF,因此可以估算出总线允许长度和所接器件数量。
应用领域
I2C总线广泛应用于各种设备和应用领域,例如传感器、存储器(如EEPROM)、显示屏、温度传感器、实时时钟(RTC)、扩展IO芯片等
2.IIC协议
IIC总线在传输数据的过程中一共有三种类型信号,分别为:开始信号、结束信号和应答信号。
//起始位,停止位,数据位,速度
这些信号中,起始信号是必需的,结束信号和应答信号
2.1 起始信号
2.2 终止信号
起始:当SCL为高电平时,SDA由高电平变成低电平(产生一个下降沿)
停止:当SCL为高电平时,SDA由低电平变成高点平(产生一个上升沿)
应答信号
发送器每发送一个字节(8个bit),就在时钟脉冲9期间释放数据线,由接收器反馈一个应答信号。应答信号为低电平时,规定为有效应答位(ACK,简称应答位),表示接收器已经成功地接收了该字节;
应答信号为高电平时,规定为非应答位(NACK),一般表示接收器接收该字节没有成功。
32篇读写时序:
发送一个字节:SCL低电平期间,主机将数据位依次放到SDA线上(高位先行),然后释放SCL,从机将在SCL高电平期间读取数据位,所以SCL高电平期间SDA不允许有数据变化,依次循环上述过程8次,即可发送一个字节
接收一个字节:SCL低电平期间,从机将数据位依次放到SDA线上(高位先行),然后释放SCL,主机将在SCL高电平期间读取数据位,所以SCL高电平期间SDA不允许有数据变化,依次循环上述过程8次,即可接收一个字节(主机在接收之前,需要释放SDA)
一个完整的时序:
1.SCL先发送一个高电平信号,SDA主机产生一个下降沿信号就开始发送信号了,每产生一个脉冲发送一个字节
2.发送高位在前,低位在后
3.当SCL处于高电平时,SDA的数据就不要再改变了(如果产生一个下降沿就是一个起始信号,如果产生一个上升沿,就是个停止信号)
4.如果接收到数据了就产生的应答信号,SDA拉低,主机就知道从机接收到了数据
5.停止信号,如果主机不行发送数据了,就来个停止的信号,SCL高电平,SDA产生一个上升沿
以下是51篇:
数据发送的时序
*
1. start()
2. 写入 b0111 1000 0x78
3. ACK
4. cotrol byte: (0)(0)000000 写入命令 (0)(1)000000写入数据
5. ACK
6. 写入指令/数据
7. ACK
8. STOP
#include "reg52.h"
sbit scl = P0^1;
sbit sda = P0^3;
void IIC_Start()
{
sda = 1;
scl = 1;
_nop_(); //耗时5个微妙
sda = 0;
_nop_();
}
void IIC_Start()
{
sda = 0;
scl = 1;
_nop_();
sda = 1;
_nop_();
}
char IIC_ACK()
{
char flag;
sda = 1; //就在时钟脉冲9期间释放数据线
_nop_();
scl = 1;
_nop_();
flag = sda;
_nop_();
scl = 0;
return flag;
}
void IIC_Send_Byte() //发送一个字节
{
int i;
for(i = 0 ;i<8;i++)
{
scl = 0;//scl 拉低,让sda做好数据准备
sda = dataSend & 0x80; // 1000 0000 获得datasend的最高位
_nop(); //发送数据建立的时间
scl = 1;//scl拉高开始发送
_nop(); //数据发送时间
scl = 0; // 发送完毕拉低
_nop();//
dataSend = dataSend <<1;
}
}
void main()
{
}
为什么要与高位0x80?
在这个表达式中,`sda = dataSend & 0x80;`,对 `dataSend` 和 `0x80` 进行按位与操作的目的是提取 `dataSend` 的最高位(即第 8 位)。在处理数据时,有时候需要提取数据的特定位,按位与操作是一种常见的方法。
具体来说,`0x80` 的二进制表示为 `10000000`,与一个字节的数据进行按位与操作,可以将该数据的最高位保留下来,其他位都置为 0。如果 `dataSend` 中最高位为 1,那么 `sda` 将会被设置为 `0x80`,否则为 0。
这样处理数据的目的可能是为了在具体的通信协议中,如 I2C 通信中,将数据的最高位作为特定控制信息或标志位,来控制数据的传输与处理。