原创 (c51)I2C总线应答信号

2017-5-6 09:52 1864 8 8 分类: MCU/ 嵌入式

在学习C51单片机中的I2C总线一部分时,对应答信号ACK很是疑惑,看了书上的写的以为仅仅是在程序中让SCL来个高脉冲就行了,

但实际操作中却不能正常工作。在请教老师后,终于明白,今天写博客跟初学的朋友们分享。

在EEROM芯片24C02技术手册上对于应答部分的解释如下:

ack

你如果看不懂上面的标准说明,那你就听我这样说:

对于单片机和I2C总线上的通讯分写数据和读数据两部。


第一步是写数据,也就是单片机把想要写的数据通过I2C总线写到24c02里面,这个过程中单片机是主机(发送器),它在总线上先让sda=1,这个过程是软件操作的,如果24c02发生应答了,sda就被拉低了变成了0,这个过程是24c02硬件完成的,我们不需要用软件拉低,如果想在程序里判断下应答了没有,可以在程序中做个判读while(sda==1);如果sda没有被拉低,就等在这儿,只有sda=0了才可以算是应答了,才可以继续下一步。具体的程序如下:

void ack_write() //写数据时的应答信号

{

scl=0;//为了保证在scl=1时sda必须稳定,所以让scl=0

delay();//延时个5us就行

sda=1;//这句就是我上面写的主句单片机在总线上先让sda=1,

//这个过程是软件操作的,至于sda=0是由24c02硬件自动拉低的,我们在程序中不用写,

//但可以在下面判断下是否sda被自动拉低了(是否有应答了)

delay();

while(sda==1);//如果没有24c02没有发应答信号sda=1就让程序在这等,直到sda=0有应答为止,

//这句最好写在下句scl=1;的前面,这样如果没应答信号的话,scl就不能变成1,

//也就形不成应答脉冲(scl由0变成1),这样如果sda=1就可形成应答脉冲了

scl=1;


delay();

}

第二部是读数据,就是让单片机从24c02里面读数据的过程,这个过程24c02是主机(发送器),因为总线上的数据是24c02提供的,单片机是从机(接收机),在24c02往IIC总线上写完一个字节数据后,会自动将sda拉高,这个不需要我们软件控制,以等待单片机来应答(把sda拉低),这个需要我们软件控制。记住这句话,我们写程序控制的是单片机和间接通过单片机控制的总线,单片机没有像24c02那样可以自动发出应答信号的功能(拉低sda),我们就需要控制单片机程序,拉低sda,以模拟IIC总线器件的应答功能。具体程序如下:

void ack_read()

{

scl=0;//为了保证在scl=1时sda必须稳定,所以让scl=0

delay();//延时个5us就行

sda=0;//在这句话执行之前,

24c02已经在IIC总线上自动发送了个sda=1的信号来让单片机应答,所以这句话是单片机的应答信号(拉低了sda)

scl=1;//形成应答脉冲(scl由0变成1第九个脉冲)


}


还有,我听老师说,仅仅像51单片机这种低端单片机没有IIC总线器件的自动应答功能,像一些高档的单片机如stm32等就具有IIC总线器件的自动应答功能,我们也就不需要用软件控制应答了,那就省事多了。

还有要注意,我说的写的时候的应答信号void ack_write()是在单片机往IIC总线上写器件地址,写内部存储地址和写数据时用,而不仅仅是在写的过程用,比如单片机从24c02里读数据的时候也得先写器件地址,写内部存储地址,这时候也是用的是void ack_write()这个应答信号。读时候的应答信号void ack_read()是针对于单片机从总线上读数据时,读完了如果需要应答才用,但有些读的方式如Random read 读完数据就不用应答,也就不需要void ack_read()。但在Sequential Read模式下需要读应答。具体参考如下图:

捕获1

捕获2

捕获3


好了,我能想到的也就这么多了,如果大家觉得有什么疑问或者问题,欢迎再下面讨论,或者发到邮箱15734445797@163.com


PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
8
关闭 站长推荐上一条 /3 下一条