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

来源:互联网 发布:淘宝卖家买家一个账号 编辑:程序博客网 时间:2024/06/16 22:36
时间: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总线上可以挂多个器件,而每个器件都有唯一的地址,这样可以标识通信目标。数据的通信的方式采用主从方式,主机负责主动联系从机,而从机则被动回应数据。


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

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


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

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

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


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


2.I2C读数据流程

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

对IIC芯片外设的初始化,这里就不讲解了,很简单的配置过程。
初始化好I2C后,就可以使用I2C通讯了,我这里还是以51为例,配合火哥的模拟IIC通讯历程看,你会发现,发送数据流程和接收数据流程原理是一样的。
3./*I2C发送数据 I2C写数据流程*/下面放图 火哥的模拟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);
}

火哥的历程已经详细的说明了写数据的流程,这里,我就不多此一举了.
4. /*I2C接收数据 I2C读数据流程*/
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写数据,读数据的原理我就讲的这么多了,这是我自己的理解,仅供参考.
原创粉丝点击