新手被I2C总线弄得头疼 请大神帮忙分析下 下面两个同为应答函数代码区别
另问:在应答过程中当SCL为高电平时,SDA的电平是不是根据数据的接收情况自动决定是高电平还是低电平?
代码一中参数的作用是什么?
每次发送一个字节结束后,都要用这样的应答函数吗?
void Ack_I2c(bit a) //a作为应答标志
{
if(a==0)sda=0; /*在此发出应答或非应答信号 */
else sda=1; /*0为发出应答,1为非应答信号 */
_nop_();
_nop_();
_nop_();
scl=1;
_nop_();
_nop_(); /*时钟低电平周期大于4μs*/
_nop_();
_nop_();
_nop_();
scl=0; /*清时钟线,住I2C总线以便继续接收*/
_nop_();
_nop_();
}
bit Ask()
{
bit ack_bit;
SDA=1;
_nop_();
_nop_();
SCL=1;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
ack_bit=SDA;
SCL=0;
reurn ack_bit;
}
1.第一个函数是单片机是否要向设备产生IIC应答信号的函数,第二个函数是单片机判断设备是否产生了应答信号的函数。
应答信号的两种情况:
(1)主机等待应答,设备产生应答,这是第二个函数的功能。
这个时候,主机的SDA信号线拉高,SCL线拉高,主机等待设备的SDA信号线产生低电平信号,检测一段时间后,如果主机检测到了设备产生的低电平信号,那么主机SCL拉低,返回0,那么,我们就知道设备产生应答信号了,证明连接上了。
如果检测一段时间后,没有检测到设备产生低电平信号,那么主机SCL拉低,返回1,那么,我们就知道设备没有产生应答信号了。
(2)主机产生应答,设备等待应答,这是第一个函数的功能。
这个时候,设备的SDA信号线会拉高,SCL线拉低(这个过程我们不需要去管设备怎么操作的),这时候,函数中的参数a就是用来决定主机要不要产生应答信号的标志,如果a=0,证明我们需要主机产生应答信号,这时候主机的SDA线拉低,设备会检测到这个低电平信号,那么设备就知道,已经跟主机连接上了。如a=1,那么证明我们不需要主机产生应答信号,这时候主机的SDA线保持在高电平状态,那么设备检测不到低电平信号,设备就知道,主机没有反应了。
不知道这么说你明白吗?不明白的话,可以再问我。
2.可以这么说,SDA线上的信号如果是高电平,那么有低电平进来的时候,会自动拉低,就是你说的那样,由数据决定的。
3.第一个函数中的参数的功能在1里面已经说了,不清楚可以继续问我。
4.不是每发送一个字节,就需要产生一个应答信号。假如你的设备是8位数据的,那么发送一个数据,需要一次发送8个字节,在一次数据发送结束后,也就是在发送完8个字节之后,再进入等待应答或者产生应答的状态。
纯手打,欢迎你有不清楚的地方,继续问我。
你的回答我明白了,感谢解惑,我还有一个问题,也是关于应答信号的
Void responds()
{
uchar i=0;
SCL=1;
delay();
while((SDA==1)&&(i<255))
i++;
SCL=0;
delay();
}
这个应答函数没有返回值,是设备给主机的应答吗?这个函数,是不管从机有没有给出应答(while语句的作用),程序都会进行下去的意思吗?还有如果从机没有发出应答信号,主机会自动产生终止信号(不用代码)使传送结束吗?
哇, 这个函数我还真是没看懂,应该是主机等待应答的函数,但是不应该没有返回值呀。我觉得正确的代码应该是这样:
bit responds()
{
uchar i=0;
SDA=1
_nop_();
_nop_();
SCL=1;
_nop_();
_nop_();
delay();
while((SDA==1)&&(i<255))
i++;
if(i>=255)
return 1;
else
return 0
SCL=0;
delay();
}
这样只有从机在主机的255个机器时钟内应答了,就可以检测到。
你原来那个函数我也没看懂,如果运行的话,其实没有任何结果,只是延迟的作用。