因为我一开始自己写的strar,wait_ACK,send函数,所以和原子哥的有一点不相同,归结的不相同就是原子哥每个函数末尾都释放总线即,SCL=0,而我不释放,在下一个函数开始在释放,结果大家看一下void IIC_Start(void)//和原子哥的一样,除了末尾没有释放总线
{
SDA_OUT();
IIC_SDA=1;//
IIC_SCL=1;
delay_us(4);//
IIC_SDA=0;
delay_us(4);//
}
void IIC_Stop(void)
{
delay_us(4);
IIC_SCL=0;
delay_us(4);
SDA_OUT();
IIC_SDA=0;
delay_us(4);
IIC_SCL=1;
delay_us(4);
IIC_SDA=1;//结束信号
delay_us(4);
}
u8 IIC_Wait_Ack(void)
{
int i=0;
IIC_SCL=0;//因为我没释放总线,所以我在这里释放
SDA_IN();
delay_us(5);
IIC_SDA=1; //这里是标记1,大家注意一下
delay_us(2);
IIC_SCL=1;
while(READ_SDA==1)
{
i++;
if(i>=250)
{
IIC_Stop();
return 1;
}
}
IIC_SCL=0; //这里是标记2,大家注意一下
return 0;
}
void IIC_Send_Byte(u8 txd)
{
u8 i;
SDA_OUT();
for(i=0;i<8;i++)
{
IIC_SCL=0;//这里释放总线
delay_us(2);
IIC_SDA=(txd&0x80)>>7;
txd<<=1;
delay_us(2);
IIC_SCL=1;
delay_us(4);
}
}
//AT24C02读一个字节
u8 AT24CXX_ReadOneByte(u16 ReadAddr)
{
u8 temp=0;
IIC_Start();
if(EE_TYPE>AT24C16)
{
IIC_Send_Byte(0XA0); //
IIC_Wait_Ack();
IIC_Send_Byte(ReadAddr>>8);
}else IIC_Send_Byte(0XA0+((ReadAddr/256)<<1)); //发送器件地址,写数据
IIC_Wait_Ack(); //第一个ACK
IIC_Send_Byte(ReadAddr%256); //发送低地址
IIC_Wait_Ack(); //第2个ACK //这里是标记3,大家注意一下
IIC_Start();
IIC_Send_Byte(0XA1); //接收模式
IIC_Wait_Ack();
temp=IIC_Read_Byte(0);
IIC_Stop();//结束
return temp;
}
现在我的I2C出了问题,标记2出我在函数末尾,释放了总线,但这和我一开始末尾不释放总线的写法是有背的,我的I2C能起作用有两个方法,第一个方法:标记1处SDA=1,改成SDA=0,那么标记2处不释放总线I2C也有效。第2个方法,标记1处写SDA=0,但必须在标记2处释放总线,否则I2C就会出错。
这2种必须要满足一种,才能使I2C有用,但我看数据手册,看时序图,看了好久也找不到我错误在哪里。手上缺少分析仪
(ST_LINK调试的时候)最后一个读字节函数,当满足方法时,(总共有3个ACK)进入任一ACK后,SDA读会变成低电平,即得到从机相应,但是当不满足我的两个方法时,进入第一个ACK会有从机相应,即SDA=0,但在进入第2个ACK的时候得不到相应了,SDA=1,进入ACK中的stop信号。因为这2个ACK中间只隔了一个发送函数,我觉得是发送函数和ACK时序连接不好,但怎么看都没有问题,望各位指点一下
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
恩恩,我看了好久以后写I2C也打算全部末尾加SCL=0,现在就是单纯纠结我的程序干嘛不行,如果是说IO切换的时候会有脉冲的话那我就有点明白了
一周热门 更多>