找回密码
 立即注册

QQ登录

只需一步,快速开始

打印 上一主题 下一主题
开启左侧

[求助]M451的I2C通信问题

[复制链接]
跳转到指定楼层
楼主
cpf1232008 发表于 2016-7-8 10:34:59 | 只看该作者 回帖奖励 |正序浏览 |阅读模式
使用芯片:M452LG6AE
环境:通过I2C去读取电池管理芯片OZ9313,OZ9313支持SMBus。上拉电阻原为4.7K,因clock波形不好(tr时间长),后面改到1.2K。
故障现象:
M452芯片启动后能够正常通信获取电池信息,但是过一段时间(几小时)后就读取不到芯片上的信息,调试代码发现I2C读取超时,示波器抓取波形为SDA一直为高电平,SCL一直有正常的clock波形(波形还挺好~),


更改代码尝试在通信失败后调用I2C_STOP(I2C0)(代码如下),会卡死在while循环中,
static __INLINE void I2C_STOP(I2C_T *i2c)
{


    (i2c)->CTL |= (I2C_CTL_SI_Msk | I2C_CTL_STO_Msk);
    while(i2c->CTL & I2C_CTL_STO_Msk);
}

更改代码在通信失败后定时重新初始化I2C中断,结果还是读取超时,获取不到信息。
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 顶 踩
回复

使用道具 举报

板凳
 楼主| cpf1232008 发表于 2016-8-5 14:32:55 | 只看该作者
已测试一周,目前无死机现象出现,验证恢复状态良好,这个问题算解决了。。提供代码如下:
  1. void count_delay_us(uint32_t time_us)
  2. {   
  3.     uint32_t i;
  4.     uint32_t cons = 17;
  5.    
  6.     for(i=0; i<time_us; i++)
  7.     {
  8.         while(cons--) ;
  9.         cons = 22;
  10.     }
  11.    
  12.     return;
  13. }

  14. void I2C_recover(void)
  15. {
  16.     int i;
  17.     //first: changed the scl to gpio out
  18.     SYS->GPA_MFPL &= ~(SYS_GPA_MFPL_PA3MFP_Msk | SYS_GPA_MFPL_PA2MFP_Msk);
  19.     SYS->GPA_MFPL |= (SYS_GPA_MFPL_PA3MFP_GPIO | SYS_GPA_MFPL_PA2MFP_GPIO);


  20.     delayms(1);

  21.     GPIO_SetMode(PA, BIT3, GPIO_MODE_OUTPUT);
  22.     PA3=0;
  23.    
  24.     //second: send nine clock
  25.     delayms(1);
  26.     for(i=0; i<10; i++)
  27.         //while(1)
  28.     {
  29.         PA3=1;
  30.         count_delay_us(10);
  31.         PA3=0;
  32.         count_delay_us(10);
  33.     }
  34.     //PA3=1;
  35.     delayms(1);

  36.     return;   
  37. }


  38. int I2C_Conifiguration(void)
  39. {

  40.     //I2C_recover();


  41.     SYS->GPA_MFPL &= ~(SYS_GPA_MFPL_PA3MFP_Msk | SYS_GPA_MFPL_PA2MFP_Msk);
  42.     SYS->GPA_MFPL |= (SYS_GPA_MFPL_PA3MFP_I2C0_SCL | SYS_GPA_MFPL_PA2MFP_I2C0_SDA);


  43.     /* Reset I2C0 */
  44.        //SYS_ResetModule(I2C0_RST);
  45.    
  46.     /* Open I2C module and set bus clock */
  47.         I2C_Open(I2C0, 80000);
  48.    
  49.    

  50.    
  51.         /* Enable I2C interrupt */
  52.         I2C_EnableInt(I2C0);
  53.         NVIC_EnableIRQ(I2C0_IRQn);


  54.     I2C_SMBusOpen(I2C0, I2C_SMBH_ENABLE);
  55.     I2C_SMBusPECTxEnable(I2C0, I2C_PECTX_DISABLE);
  56.     //I2C_SMBUS_ACK_MANUAL(I2C0);
  57.     I2C_SMBUS_ACK_AUTO(I2C0);


  58.     //SYS_ResetModule(I2C0_RST);

  59.    
  60.         return 0;
  61. }

  62. void I2C_deinit(void)
  63. {
  64.     /* Disable I2C0 interrupt and clear corresponding NVIC bit */
  65.     I2C_DisableInt(I2C0);
  66.     NVIC_DisableIRQ(I2C0_IRQn);

  67.     /* Disable I2C0 and close I2C0 clock */
  68.     I2C_Close(I2C0);
  69.     //CLK_DisableModuleClock(I2C0_MODULE);

  70. //i2c all use ,donot close its clock


  71.    
  72. }
复制代码



回复 支持 反对

使用道具 举报

沙发
 楼主| cpf1232008 发表于 2016-7-22 09:53:05 | 只看该作者
自己回复一下吧,
经过调试,楼上问题确认是死锁问题,因电池侧不会掉电,总线busy,导致m451侧发送stop/软重启都无效。经过调试并优化后。i2c配置增加开启smbus的相关配置,自动ack等等。稳定性好了很多,不过偶尔还是会出现上一楼的死锁问题(主要是因充电器干扰,正常情况下i2c还是很稳定的),目前已添加通信失败后更改配置SCL为GPIO OUT,发送9个脉冲进行解锁。目前正进行烤机测试中,有结果再反馈~

PS:引用别人回复:

对于一个完整的I2C程序,起码应该具有三个标志

就是NoACK(无应答),Busy(器件忙)和BusFault(总线错误)。
1.当STA+SLA+R/W后,如果9th BIT=1,则置位NoACK,表示被寻址的I2C器件不存在。
2.当正处于访问一个I2C设备的过程中,程序应置位Busy。即STA和STO之间Busy=1.
3.如果初始化I2C(释放总线)后,SDA=0和(或)SCL=0,程序应置位BusFault。
根据以上三个条件合理控制程序的流程,才是一个完整的I2C程序。
当出现BusFault标志时,如果只有SDA=0,问题可能出现在主接收模式下的从发送数据等于0,这是可以通过附加SCL脉冲解决。如果不能解锁,应检查其它原因;如果只有SCL=0,应检查总线是否是多主系统。
当然以上条件是建立在硬件设计没有错误,器件没有损坏前提下进行的。
回复 支持 反对

使用道具 举报

高级模式
B Color Image Link Quote Code Smilies |上传

本版积分规则

新唐MCU