天天看点

IIC总线从零梳理(结合STM32平台)

时间:2017/06/07 22:01 IIC总线的EEPROM G15电装.王维鋆 常用的串行总线协议: 常用的微机与外设之间进行数据传输的串行总线主要有 I2C总线、SPI总线和SCI总线 。 其中I2C总线以 同步串行2线方式进行通信 (一条时钟线,一条数据线)。 SPI总线则以 同步串行3线方式进行通信 (一条时钟线,一条数据输入线,一条数据输出线)。 SCI总线是以 异步方式进行通信 (一条数据输入线,一条数据输出线)。 1-wire,即单线总线,又叫单总线。例如DS18B20温度传感器就是用的这种总线结构. 我们这里重点详解下I2C串行总线,我们这里以数据手册的IIC时序图为例讲起,看不懂时序图的小伙伴必须补上来了. 一.I2C串行总线的组成及工作原理. 1. I2C总线是PHLIPS公司推出的一种串行总线,它只有两根双向信号线。一根是数据线SDA(serial data I/O),另一根是时钟线SCL(serial clock)。 2. 如下图所示,IIC总线上可以挂多个器件,而每个器件都有唯一的地址,这样可以标识通信目标。数据的通信的方式采用主从方式,主机负责主动联系从机,而从机则被动回应数据。

IIC总线从零梳理(结合STM32平台)
IIC总线从零梳理(结合STM32平台)
IIC总线从零梳理(结合STM32平台)

二.I2C总线传输协议 1. 数据位的有效性规定: SCL为高电平期间,数据线上的数据必须保持稳定,只有SCL信号为低电平期间,SDA状态才允许变化。如图所示

IIC总线从零梳理(结合STM32平台)
IIC总线从零梳理(结合STM32平台)

2. I2C的起始和终止信号 SCL线为高电平期间,SDA线由高电平向低电平的变化表示起始信号;SCL线为高电平期间,SDA线由低电平向高电平的变化表示终止信号。如图所示

IIC总线从零梳理(结合STM32平台)
IIC总线从零梳理(结合STM32平台)

3. I2C字节的传送与应答 每一个字节必须保证是8位长度。数据传送时,先传送最高位(MSB),每一个被传送的字节后面都必须跟随一位应答位(即一帧共有9位).如图所示

IIC总线从零梳理(结合STM32平台)
IIC总线从零梳理(结合STM32平台)

4. 应答位的作用 主机在发送数据时,每次发送一字节数据,都需要读取从机应答位,当从机空闲可以接收该字节数据时,从机会发出应答(一帧数据的第9位为“0”),当从机正忙于其他工作的处理来不及接收主机发送的数据时,从机会发出非应答(一帧数据的第9位为“1”)主机则应发出终止信号以结束数据的继续传送,主机通过从机发出的应答位来判断从机是否成功接收数据.

当主机接收数据时,它收到最后一个数据字节后,必须向从机发出一个结束传送的信号。这个信号是由对从机的“非应答”来实现的。然后,从机释放SDA线,以允许主机产生终止信号。 贴个IIC总线在传送数据过程中信号 时序图.好好研究好时序图,一切都可以轻松解决.

IIC总线从零梳理(结合STM32平台)
IIC总线从零梳理(结合STM32平台)

三.IIC驱动代码理解(以51为例,模拟IIC) 这里,我用51单片机为例写下IIC 驱动代码,实现包括 IIC 的初始化( IO 口)、 IIC 开始、 IIC 结束、 ACK、 IIC 读写等功能.IIC驱动代码是根据时序图来编写的,结合着时序图看,感兴趣的小伙伴可以试着自己写一下底层驱动代码.由于是根据时序图来编写的,就没什么要说明的 I2C起始信号程序: void I2C_Start() { SCL = 1; _nop_(); //51的一个机器周期 1.08506us SDA = 1; delay_5us(); SDA = 0; delay_5us(); } I2C终止信号程序: void I2C_Stop() { SDA = 0; _nop_(); SCL = 1; delay_5us(); SDA = 1; delay_5us(); } I2C主机检测从机应答: bit Test_ACK() { SCL = 1; //在时钟总线为高电平期间可以读取应答信号 delay_5us(); if (SDA) { SCL = 0; I2C_Stop(); return(0); } else { SCL = 0; return(1); } } I2C主机发送应答: void Master_ACK(bit i) { SCL = 0; _nop_(); if (i) { SDA = 0; } else { SDA = 1; } _nop_(); SCL = 1;//数据保持稳定 _nop_(); SCL = 0; _nop_(); SDA = 1; _nop_(); } 根据这些IIC驱动代码编写自己的读写函数就可以和外部IIC器件通信了. 四.EEPROM—— AT24CXX梳理 1.I2C写数据流程

IIC总线从零梳理(结合STM32平台)

在起始信号后必须传送一个从机的地址(7位)我们开发板上的AT24C02器件地址为0xa0,第8位是数据的传送方向位(R/T),用“0”表示主机发送数据(T),“1”表示主机接收数据(R)

IIC总线从零梳理(结合STM32平台)

2.I2C读数据流程

IIC总线从零梳理(结合STM32平台)
IIC总线从零梳理(结合STM32平台)

在读数据时也要先发送器件地址,读写方向为写,因为我们下一帧需要发送从AT24C02内那个单元开始读,之后需在发一次器件地址这个时候读写方向就为读了,接着我们就可以从总线上读取数据

对IIC芯片外设的初始化,这里就不讲解了,很简单的配置过程。 初始化好I2C后,就可以使用I2C通讯了,我这里还是以51为例,配合火哥的模拟IIC通讯历程看,你会发现,发送数据流程和接收数据流程原理是一样的。 3. 下面放图 火哥的模拟IIC的写数据历程 bit I2C_TransmitData(uchar ADDR, DAT) { I2C_Start(); //I2C总线起始 I2C_send_byte(AT24C02_ADDR+0); //发送AT24C02地址加读写方向位0(写) if (!Test_ACK()) //检测是否发送成功(应答) { return(0); } I2C_send_byte(ADDR); //发送控制字节ADDR地址输出使能 if (!Test_ACK()) //检测是否发送成功(应答) { return(0); } I2C_send_byte(DAT); //发送数字量交由AT24C02转为模拟量AOUT脚输出 if (!Test_ACK()) //检测是否发送成功(应答) { return(0); } I2C_Stop(); //I2C停止信号 return(1); }

IIC总线从零梳理(结合STM32平台)
IIC总线从零梳理(结合STM32平台)

火哥的历程已经详细的说明了写数据的流程,这里,我就不多此一举了. 4. uchar I2C_ReceiveData(uchar ADDR) { uchar DAT; I2C_Start(); I2C_send_byte(AT24C02_ADDR+0); if (!Test_ACK()) { return(0); } I2C_send_byte(ADDR); //发送控制字节地址 Master_ACK(0); //发送非应答 I2C_Start(); //重发起始信号 I2C_send_byte(AT24C02_ADDR+1); //改变读写方向(读) if (!Test_ACK()) { return(0); } DAT = I2C_read_byte(); //把读取的值赋给形参 Master_ACK(0); //主机发送非应答 I2C_Stop(); //I2C停止信号 return(DAT); //成功返回1 }

IIC总线从零梳理(结合STM32平台)
IIC总线从零梳理(结合STM32平台)

通过上面的分析,IIC写数据,读数据的原理我就讲的这么多了,这是我自己的理解,仅供参考.

继续阅读