在学习C51单片机中的I2C总线一部分时,对应答信号ACK很是疑惑,看了书上的写的以为仅仅是在程序中让SCL来个高脉冲就行了,
但实际操作中却不能正常工作。在请教老师后,终于明白,今天写博客跟初学的朋友们分享。
在EEROM芯片24C02技术手册上对于应答部分的解释如下:
你如果看不懂上面的标准说明,那你就听我这样说:
对于单片机和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模式下需要读应答。具体参考如下图:
好了,我能想到的也就这么多了,如果大家觉得有什么疑问或者问题,欢迎再下面讨论,或者发到邮箱15734445797@163.com
文章评论(0条评论)
登录后参与讨论