这篇详细介绍嵌入式的IIC总线,方便以后写该总线的器件驱动。
一、IIC总线讲解
IIC的硬件管脚为 VCC,GND,SDA,SCL。IIC的主要构成只有两个双向的信号线,一个是数据线SDA,一个是时钟线SCL。IIC总线有主从之分。
IIC总线实现的方式分为两种:硬件IIC & 软件模拟IIC。硬件IIC有主从之分;当然,软件I2C也是标准的I2C协议,当然有分主从,但一般情况下,软件IIC为主机模式,即发送请求接收响应信息。为什么要写从机呢?mcu 对 mcu ?)。由于每种MCU的硬件IIC总线配置各不相同,且有些芯片的IIC有Bug(Stm32),故接下来只讲 软件IIC。
- 由于实际应用上,IIC总线通讯速率本身就不高,因此,硬件IIC总线 & 软件IIC总线
本身速率方面就没多差大差距,不需要考虑IIC总线切换为软、硬件实现方式会给程序带来隐患。 - 无论是 硬件IIC 还是 软件IIC ,两种方式只是提供最基础的桥梁——提供了读、写1字节方式。如何调用IIC从器件,还是得查对应IIC从器件的datasheet。IIC总线好比中文的拼音,具体要怎么说话、说什么话,还是得看datasheet。
二、 (软件)IIC总线
2.1 基本知识
软件IIC,也能更好让我们了解IIC总线协议的实现方式。
I2C总线通过上拉电阻接正电源。即当总线空闲时,两根线均为高电平。如此,连在总线上的任一器件输出的低电平,都可以使得总线的信号变低,也就是说各器件的SDA和SCL都是线”与”关系。
数据位(1\0)有效性规定:I2C总线进行数据传送时,时钟信号为高电平期间,SDA线上的数据必须保持稳定;只有在SCL线的信号为低电平器件,SDA线的才可进行高低电平状态变化。
起始信号、终止信号、应答信号
- 起始信号:SCL线为高电平期间,SDA线由高电平向低电平跳变(下降沿)—-是一种电平跳变时序信号
- 终止信号:SCL线为高电平期间,SDA线由低电平向高电平跳变(上升沿)—-是一种电平跳变的时序信号
- 应答信号:在接收数据的IC(接收器)在接收到8bit数据后,向发送数据的IC(发送器)发出特定的低电平脉冲,表示已收到数据。即发送器在时钟脉冲9期间释放数据线,这样接收器就可以反馈一个应答信号。ACK(低电平)—-规定为有效应答位,NACK(高电平),规定为非应答位,表示接收器接收该字节咩有成功。
2.2 软件模拟IIC驱动程序函数编写
在IIC程序设计中,都是以8bit为基础进行数据的传输
- IO管教初始化
- 发出起始信号
- 发出终止信号
- 发出应答ACK
- 功能要求:由于IIC为双向数据通信,当从机发送完数据,主机也需要发送应答信号来说我接收到你的信息了,此时从机才可变为接收状态,接收来自主机的数据。
- 发出应答NACK
- 功能要求:当IIC程序运行到主机读取从机数据完成,需要停止此次数据传输时,主机发送一个发出主无应答信号,从机接收到后就停止发送数据,并释放SDA线;之后主机才可发送终止信号,停止此次数据的传输。
- 发送一个字节数据
- 基本思路:SCL在为0时,可以进行SDA数据的配置,当SCL为1时,SDA数据一定要锁定。其次为数据的移位,将待发送数据与0x80进行与运算,获得最高位的数据,通过8次循环完成1byte的数据发送。
- 读取一个字节,并发送ACK或NACK(发送NACK基通知从机发送器结束数据发送,释放SDA线(SDA接口置1)
- 功能要求:发送器每发送一个字节,就在时钟脉冲9期间释放数据线,由接收器反馈一个应答信号(故读取完需要发送 ACK 或 NACK )
- 等待ACK应答
- 功能要求:当IIC主机进行获取数值时,主机需要等待从机的应答信号,以此来判断从机是否完成了数据的接收。从主机方看,为IIC等待ASK函数。
- 基本思路:通过 延时等待从机的ACK是否发送出来,如果发送出来,则函数返回0,主机可继续发送数据,如果返回1,则从机没有应答,此时需要停止IIC数据传输。防止出现错误数据。
2.3 从具体I2C器件中读写数据
主机写(发送)从机数据
主机读(接收)从机数据
Ps:IIC器件往往是 器件地址+0 为写数据 ,器件地址+1 为读数据
主机读从机的情况分为两种:
- 读操作之前,都是需要进行一次写操作(写入读地址),表明你要读的是哪个地址的数据,然后在进行一次读操作(故有两个器件地址);(这是一般情况)
- 直接进行读操作,截取所需数据段
因为有些IIC器件(从机),例如24C02,当你需要读取它的数据,你要跟它说读取哪个地址数据,故先进行写操作;有些IIC器件,例如SD2403,它的时间日期地址是固定的(寄存器地址:00H-06H),因此读取该器件数据时,直接进行读操作,然后读出来7个数据,截取00H-06H的数据后,停止读取(这是特殊情况)
DEVICEADDRESS(器件地址)
器件地址的8位地址信息因器件而异;
三、软件IIC实例
3.1 EEPROM_24C02通信基础——IIC协议
24C02是一个可储存 256(8bit)字节数据的EEPROM,因此他的Word Address
为8bit(单字节);而他的器件地址如下:
据2.3.1图所示,主机对从机写操作如下:
1 | void AT24CXX_WriteOneByte(u16 WriteAddr, u8 DataToWrite) |
据2.3.1图所示,主机对从机读操作如下:
1 | u8 AT24CXX_ReadOneByte(u16 ReadAddr) |
3.2 24C02程序拓展——datasheet
1 | //在AT24CXX里面的指定地址开始写入长度为Len的数据 |
3.3 实时时钟_SD2403——IIC总线
SD2403是一个实时时钟,他的Word Address
为8bit(单字节);而他的器件地址如下:
据2.3图所示,主机对从机写操作如下:
1 | static uint8_t SD2403_WriteOneByte(uint8_t addr,uint8_t data) |
据2.3图所示,主机对从机读操作如下:
1 | uint8_t SD2403_ReakOneByte(uint8_t addr) |
3.4 SD2403程序拓展——datasheet
1 | uint8_t SD2403_ReadTimeDate(_strTimeDate *pstrTimeDate) |
四、拓展——软件IIC从机
要实现IIC从机功能,最核心的部分就是如何精确的抓住IIC_SCL,也就是IIC主机发出来的时钟信号。只有抓住精确的时钟SCL,才能正确的读取到SDA的数据,才能真正模拟出IIC时序。
但是要抓住SCL信号可不容易,IIC最高速度有400K,最小有效脉宽达到1.4us(数字0/1),最小脉冲是0.8us(应答和STOP信号产生的尖刺),采用中断来识别SCL是不可能的做到的,因为即使在最高主频72MHZ情况下,STM32最小指令周期是1/72(us),从SCL中断发生到STM32进入中断响应,至少要要40个指令周期,也就是40/72(us),加上堆栈操作及变量,很可能已经错过了SCL信号。
因此根据IIC主机的速度,从机实现方法分为两种:
- 采用中断方式识别SCL(适用于总线速度较慢)
- 采用查询方式识别SCL(适用于总线速度较快)
反过来言之,当你做成一个(从机)模块,实现软件模拟IIC,实际上还会因为IIC主机的因素来决定你这个模块的实际使用效果。如果是做模块化,还是推荐使用硬件IIC的方式实现。