OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 46|回复: 1

SMBus死机了,DR里面收到数但RxNE没有置位

[复制链接]

11

主题

59

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
497
金钱
497
注册时间
2016-9-5
在线时间
79 小时
发表于 5 天前 | 显示全部楼层 |阅读模式
5金钱
本帖最后由 猴子 于 2025-5-7 17:54 编辑

最近在调试SMBus时序,测试的时候发现跑一段时间后软件会死机,检查后发现在接收最后一个字节的时候IIC的DR寄存器收到数了,但是RxNE状态标志没有置位,导致卡在那个判断中了,现在加了超时计数,还在测试     但我不理解的是为什么会DR有数但是标志没置位,与固件库有关还是STM32F1芯片的缺陷?又或者是我理解错了?

局部截取_20250507_175304.png 局部截取_20250507_175225.png
  1. u16 readResult = 0;
  2.     u32 count = DF_I2C_WAITCHECK_TIME;
  3.     u8 PECData[6] = {0};  
  4.     u8 idx = 0;
  5.     u8 NumByteToRead = 3;
  6.     u8 PECResult = 0;  //校验码值

  7.     pObj->checkFlg = 0;  
  8.     PECData[0] = pObj->deviceAddress_Write;
  9.     PECData[1] = command;
  10.     PECData[2] = pObj->deviceAddress_Read;

  11.     //I2C_ClearFlag(pObj->I2Cx, I2C_FLAG_AF);

  12.     while(I2C_GetFlagStatus(pObj->I2Cx, I2C_FLAG_BUSY))
  13.     {
  14.         if(0 == (count--))
  15.         {
  16.             BSP_bq40z50_SmBusTimeOutHandle(pObj);
  17.             return 0;
  18.         }
  19.     }
  20.     count = DF_I2C_WAITCHECK_TIME;
  21.     //产生起始信号
  22.     I2C_GenerateSTART(pObj->I2Cx,ENABLE);
  23.     while(!I2C_CheckEvent(pObj->I2Cx, I2C_EVENT_MASTER_MODE_SELECT))        //  测试和清除EV5
  24.     {
  25.         if(0 == (count--))
  26.         {
  27.             BSP_bq40z50_SmBusTimeOutHandle(pObj);
  28.             return 0;
  29.         }
  30.     }
  31.     /*while (!I2C_GetFlagStatus(pObj->I2Cx,I2C_FLAG_SB))
  32.     {
  33.         if(0 == (count--))
  34.         {
  35.             BSP_bq40z50_SmBusTimeOutHandle(pObj);
  36.             return 0;
  37.         }
  38.     }*/
  39.     //发送从机地址,写
  40.     count = DF_I2C_WAITCHECK_TIME;
  41.     I2C_Send7bitAddress(pObj->I2Cx, pObj->deviceAddress, I2C_Direction_Transmitter);         
  42.     while(!I2C_CheckEvent(pObj->I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))     //  测试和清除EV6
  43.     {
  44.         if(0 == (count--))
  45.         {
  46.             BSP_bq40z50_SmBusTimeOutHandle(pObj);
  47.             return 0;
  48.         }
  49.     }  
  50.     //发送命令数据
  51.     count = DF_I2C_WAITCHECK_TIME;
  52.     I2C_SendData(pObj->I2Cx, command);     
  53.     //while(!I2C_CheckEvent(pObj->I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED))            //  测试和清除EV8
  54.     /*{
  55.         if(0 == (count--))
  56.         {
  57.             BSP_bq40z50_SmBusTimeOutHandle(pObj);
  58.             return 0;
  59.         }
  60.     }*/
  61.     while ((!I2C_GetFlagStatus(pObj->I2Cx,I2C_FLAG_TXE)) && (!I2C_GetFlagStatus(pObj->I2Cx,I2C_FLAG_BTF)))
  62.     {
  63.         if(0 == (count--))
  64.         {
  65.             BSP_bq40z50_SmBusTimeOutHandle(pObj);
  66.             return 0;
  67.         }
  68.     }
  69.     //产生起始信号
  70.     count = DF_I2C_WAITCHECK_TIME;
  71.     I2C_GenerateSTART(pObj->I2Cx,ENABLE);
  72.     while(!I2C_CheckEvent(pObj->I2Cx, I2C_EVENT_MASTER_MODE_SELECT))        //  测试和清除EV5
  73.     {
  74.         if(0 == (count--))
  75.         {
  76.             BSP_bq40z50_SmBusTimeOutHandle(pObj);
  77.             return 0;
  78.         }
  79.     }
  80.     /*while (!I2C_GetFlagStatus(pObj->I2Cx,I2C_FLAG_SB))
  81.     {
  82.         if(0 == (count--))
  83.         {
  84.             BSP_bq40z50_SmBusTimeOutHandle(pObj);
  85.             return 0;
  86.         }
  87.     }*/
  88.    
  89.     //发送从机地址,读
  90.     count = DF_I2C_WAITCHECK_TIME;
  91.     I2C_Send7bitAddress(pObj->I2Cx, pObj->deviceAddress, I2C_Direction_Receiver);         
  92.     while(!I2C_CheckEvent(pObj->I2Cx, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED))    //  测试和清除EV6
  93.     {
  94.         if(0 == (count--))
  95.         {
  96.             BSP_bq40z50_SmBusTimeOutHandle(pObj);
  97.             return 0;
  98.         }
  99.     }  
  100.    
  101.     I2C_AcknowledgeConfig(pObj->I2Cx, ENABLE);  //SMBus除了接收最后一个字节,其余字节接收后主机需要接收方需要发出应答

  102.     idx = 3;

  103.     count = DF_I2C_WAITCHECK_TIME;
  104.     if(NumByteToRead > 2)   //参考手册中接收方时序方式2,按字节数N>2,N=2,N=1分别处理
  105.     {
  106.         while(NumByteToRead)  
  107.         {
  108.             if(NumByteToRead <= 3)  //剩余3个字节接收时需要特殊处理
  109.             {
  110.                 if(NumByteToRead > 1)
  111.                 {
  112.                     if(I2C_GetFlagStatus(pObj->I2Cx,I2C_FLAG_BTF))  //移位寄存器和数据寄存器满了,BTF位被置1
  113.                     {
  114.                         I2C_AcknowledgeConfig(pObj->I2Cx, DISABLE);  //清除ACK位
  115.                         PECData[idx] = I2C_ReceiveData(pObj->I2Cx);           //读取第N-2个字节,移位寄存器接收第N个字节
  116.                         idx++;
  117.                         NumByteToRead--;
  118.                         I2C_GenerateSTOP(pObj->I2Cx, ENABLE);

  119.                         PECData[idx] = I2C_ReceiveData(pObj->I2Cx);           //读取第N-1个字节,
  120.                         idx++;
  121.                         NumByteToRead--;
  122.                     }
  123.                 }
  124.                 else if(1 == NumByteToRead)
  125.                 {
  126.                     count--;
  127.                     if(I2C_CheckEvent(pObj->I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED) || (0 == count))                                  // 测试和清除EV7
  128.                     {
  129.                         PECData[idx] = I2C_ReceiveData(pObj->I2Cx);           //读取第N个字节
  130.                         idx++;
  131.                         NumByteToRead--;
  132.                     }
  133.                 }
  134.             }
  135.             else
  136.             {
  137.                 if(I2C_CheckEvent(pObj->I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED))                                  // 测试和清除EV7
  138.                 {      
  139.                     PECData[idx] = I2C_ReceiveData(pObj->I2Cx);           //读取一个字节
  140.                     idx++;                                                                      //下一个读取的数据
  141.                     NumByteToRead--;                                             //递减字节计数
  142.                 }
  143.             }
  144.         }
  145.     }
  146.     else if(2 == NumByteToRead)
  147.     {
  148.         
  149.     }
  150.     else if(1 == NumByteToRead)
  151.     {

  152.     }
  153.     else
  154.     {

  155.     }
  156.    
  157.                                        
  158.     PECResult = calculate_crc8(PECData,(sizeof(PECData) - 1));

  159.     readResult = PECData[4];
  160.     readResult = (readResult << 8) | PECData[3];

  161.     if(PECData[5] != PECResult)  //校验码错误
  162.     {
  163.         pObj->checkFlg = 1;
  164.     }

  165.     return readResult;
复制代码

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

11

主题

59

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
497
金钱
497
注册时间
2016-9-5
在线时间
79 小时
 楼主| 发表于 5 天前 | 显示全部楼层
补充一下  我用单独的STM32核心板接库仑计测试时测了一下午都没卡死   但是在设备上测试的时候跑20分钟就卡死,加了超时计数之后目前跑了1个多小时没卡死
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-5-12 22:19

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表