I2C鬼怪的问题

2019-10-15 04:40发布

因为我一开始自己写的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时序连接不好,但怎么看都没有问题,望各位指点一下


友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。