STM32_I2C,不稳定,死在I2C_CheckEvent解决办法

作者:153290557

转自:http://www.amobbs.com/thread-4786750-1-1.html


主设备:STM32F103C8T6
从设备:AT24C02
看见很多人用都出现死在I2C_CheckEvent,或经常不稳定
很多时候是死在AF标志上,在发送完后从设备如果一定时间内不返回ACK,STM32_I2C就置位AF不应答标志
用示波器测了下,带库时偶尔收到ACK,说明通讯有问题
例如
发送器件地址流程是:START->DEVICE_ADDRESS->ACK
因为用了固件库START跟DEVICE_ADDRESS时序会出现偏差,结果从设备偶尔能收到正确数据,偶尔返回ACK造成不稳定
如果ACK一段时间没返回主设备马上AF。。结果经常死在I2C_CheckEvent
解决办法:
一:不要用库,每一段START->ACK尽量写短,写简洁!
二:降低I2C速度!我测试在10KHZ时很稳定,20KHZ非常少,不稳定,50KHZ几乎不稳定

还有一种是中途传输字节,某些原因,主设备复位!结果I2C总线锁死,这种问题另外谈!

带库测试函数:
void I2C_EE_WaitEepromStandbyState(I2C_TypeDef *I2Cx,u8 EEPROM_Addr)
{
  vu16 SR1_Tmp = 0;
  while(1){
          do
          {          
    /* Send START condition */
    //I2C_GenerateSTART(I2Cx, ENABLE);
          
    /* Send EEPROM address for write */
    //I2C_Send7bitAddress(I2Cx, EEPROM_Addr, I2C_Direction_Transmitter);//EEPROM_Addr=0xA0
    }while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));//检查最近一次 I2C事件是否是输入的事件
   }         
  /* Clear AF flag */
  I2C_ClearFlag(I2Cx, I2C_FLAG_AF);
}

不带库测试:
void I2C_EE_WaitEepromStandbyState(I2C_TypeDef *I2Cx,u8 EEPROM_Addr)
{
  vu16 SR1_Tmp = 0;
  while(1){
          do
          {          
     /* Send START condition */
     I2Cx->CR1 |= 0x0100;

     /* Send EEPROM address for write */
     I2Cx->DR = EEPROM_Addr&0xFFFE;);//EEPROM_Addr=0xA0
    }while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));//检查最近一次 I2C事件是否是输入的事件
   }         
  /* Clear AF flag */
  I2C_ClearFlag(I2Cx, I2C_FLAG_AF);
}
下面是带库测试图:
细心看,发送器件地址0xA0,有时不能收到ACK,(长低最后那部分那尖刺就是ACK)

(原文件名:I2C-10KHZ带库.jpg)


(原文件名:I2C-50KHZ带库.jpg)


(原文件名:I2C-60KHZ带库.jpg)


(原文件名:I2C―50KHZ带库1.jpg)


(原文件名:I2C―50KHZ带库.jpg)


(原文件名:I2C―100KHZ带库1.jpg)


(原文件名:I2C―100KHZ带库2.jpg)


(原文件名:I2C―100KHZ带库3.jpg)


(原文件名:I2C―100KHZ带库4.jpg)


(原文件名:I2C―100KHZ带库.jpg)


不带库测试图:

(原文件名:I2C―50KHZ不带库.jpg)


(原文件名:I2C―100KHZ不带库1.jpg)


(原文件名:I2C―100KHZ不带库.jpg)


整个程序关键是那个SR2,官方的读SR2有些没关中断,我用的时候偶尔会出错,后来在读SR2前加关闭中断,读完再开启,暂时就没发现有问题!
附件有!
void I2C_EE_BufferRead(I2C_TypeDef *I2Cx ,vu8 EEPROM_Addr,vu16 ReadAddr,vu8 *pBuffer,vu16 NumByteToRead )//将EEPROM的数据读入缓冲器
{
        vu32 iErr,nErr;
       
        iErr = EE_TimeOut;
        nErr = EE_Error;
do{
       
//at24c02选择性读时序:START->DEVICE_ADDRESS_WRITE->ACK->BYTE_ADDRESS(n)->ACK----------------------------------------------------------------------------------------------------
        I2C_EE_WaitEepromStandbyState(I2Cx,EEPROM_Addr);//EEPROM设为待命状态
       
        iErr = EE_TimeOut;
        I2Cx->CR1 |= 0x0100;//Send START condition
        while((I2Cx->SR1&0x0001) != 0x0001){
                if(iErr-- == 0)
                goto EE_END;
        }

        iErr = EE_TimeOut;
        I2Cx->DR= EEPROM_Addr&0xFFFE;// Send EEPROM address for write
        /* Wait until ADDR is set: EV6 */
        while((I2Cx->SR1 &0x0002) != 0x0002){//Test on EV6 and clear it        
                if(iErr-- == 0)
                goto EE_END;
        }
        __disable_irq();
        /* Clear ADDR flag by reading SR2 register */
    Readtemp = I2Cx->SR2;        /*读SR2时,必须关闭中断,不关闭示波器看偶尔会发送9个CLK!,或者发送时,卡在EV8上!总之在读SR2时关闭中断读写就正常了!*/  
        /* Re-enable IRQs */
    __enable_irq();

连接原理图

(原文件名:24C64.jpg)
我这要接22PF,不然偶尔会通讯失败!想不明白!
点击此处下载 ourdev_721314E8GQ27.rar(文件大小:7K) (原文件名:EEPROM-I2C驱动.rar)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值