求助:STM32F103RC 串口有时只能接收到前8个数据!

[复制链接]
3589|15
 楼主| Ryanhsiung 发表于 2013-6-22 16:46 | 显示全部楼层 |阅读模式
本帖最后由 Ryanhsiung 于 2013-6-22 16:58 编辑

环境:UC/OS-II  5个任务
          中有一个任务做I2C动力(操作屏,大概占CPU 50%)
          中有一个任务做串口的动作(间隔500ms)。
          其它3个任务都很小
          103RC没有FIFO,我也没有启用DMA
          串口使用中断进行收发
问题描述:
        1、在特定状态下,串口再有时只能接收到前8个数据  (概率基本几分钟就会出现1-2次)
             特定状态描述:在I2C不稳定时触发,触发后问题会一直出现,只有将设备断电重启后恢复正常。
        2、出现最多连续出现10次,未出现超过10次的
        3、串口接收到的是前面8个数据,后面都没有接收
        4、SPI操作也受到的相应的影响,有些时候写入到FLASH的数据为变与乱码
一些数据:
       1、UART外设的寄存器与 正常时无异常
       2、不管我将发送后等待接收的延时 调到多少,每次都只接收到8的数据
       3、设备CPU占用率高时,出现频率更高
       4、我将相关任务的堆栈放大的一倍,现象依旧
       5、2/10的设备有这个问题,但其它设备若人为将I2C处于非正常状态,也会触发这个问题
我的怀疑:
        1、I2C的不稳定引发 芯处及外设不稳定,在这个状态下SPI外设也出现有不正常的操作。
              先前有出现I2C死掉,导致芯片中断异常关闭的问题。(现增加了I2C及中断的自动复位)
              大家可能会说这个不就会引起接收不全的问题么,但是每次都是8个数据,且只要I2C一次不稳定,就会连续出现这个问题。
        2、I2C的不稳定引起,导致任务堆栈、OS不稳定引起。最后触发相应问题

附上代码:

  1. // 将uart3 的变量全部封装进去
  2. SlaveUartStruct slave_uart;

  3. // 由于采用结构体初始化不方便,一初始化就全部初始化,不想初始化的也会被初始化
  4. // 后续扩展较麻烦
  5. void sUart3_VariableInit(void)
  6. {                                                                                                                                 
  7.         slave_uart.p_uart3_sendbuffer = slave_uart.buart3_SendBuffer;        
  8.         slave_uart.p_uart3_recbuffer = slave_uart.buart3_RecBuffer;        
  9.         slave_uart.bUart3FeedbackCount = 0;
  10. }                 
  11. /*****************************************************************************************
  12. * Function name        : sUartWaitReciveOK().
  13. * Description          :
  14. * Input para(s)        : sstring 发送缓区
  15.                                                                         rstring 接收缓冲区
  16.                                                                         timeout 表示超时的时,20ms为一格.        
  17.                                                                         ack 暂无意思,本想留做是否需要回应处理
  18. * Output para(s): none.
  19. * Caller(s)                : USART1_IRQHandler().
  20. * Note(s)                : 等待接受数据完成
  21.                 sUart3SendData( slave_uart.buart3_SendBuffer,slave_uart.buart3_RecBuffer,timeout,TRUE)
  22. *****************************************************************************************/
  23. u8 sUart3SendData(const u8* sstring, u8* rstring,u8 timeout,bool ack)
  24. {
  25.         uint8_t temp_delay = 0 ;

  26.         slave_uart.bUart3FeedbackCount =0;                                                 // 回送个数清0         
  27.         slave_uart.bUartSendSlaveCount = 0;                                        // 发送个数先清0 ,
  28.         slave_uart.p_uart3_sendbuffer = sstring ;                // 确定指针
  29.         slave_uart.p_uart3_recbuffer        = rstring ;                        //
  30.         if(sstring[3]>90)                                                                                                                // 现发送缓冲区最大为100
  31.                 {
  32.                         return FALSE;
  33.                 }
  34.         slave_uart.bUartSendSlaveNum    =  sstring[3]+4 ;           // 要发送的个数 bUartSendSlaveNum  =  bUart4RxComandBuf[3]+4 ;
  35.         // USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);             //打开串口接收中断                         这个最好放到发送中断之后
  36.         USART_SendData(USART3, slave_uart.p_uart3_sendbuffer[slave_uart.bUartSendSlaveCount++]);         
  37.         USART_ITConfig(USART3, USART_IT_TXE , ENABLE);                                        //关闭串口中断        

  38.         while(temp_delay++ < timeout)                                                // 最长等待的时间,超时
  39.                 {
  40.                         OSTimeDly(10);                                                                        
  41.                         if(slave_uart.bUart3FeedbackCount >= 5)
  42.                                 {                                                                            //                                 
  43.                                         if(slave_uart.bUart3FeedbackCount > slave_uart.p_uart3_recbuffer[2]+4)
  44.                                                 {                 
  45.                                                         temp_delay = 99;
  46.                                                         break;                                                         // 提前退出
  47.                                                 }
  48.                                 }
  49.                 }
  50.        //  这里加入延时无做用
  51.         // receive                                                                                                                                                                                                               
  52.         USART_ITConfig(USART3, USART_IT_TXE , DISABLE);        //关闭串口中断        
  53.         USART_ITConfig(USART3, USART_IT_RXNE , DISABLE);        //关闭串口中断        
  54.         if(temp_delay == 99)
  55.                 {                        
  56.                         return TRUE;                        
  57.                 }else
  58.                         {
  59.                           return FALSE;               
  60.                         }

  61. }
  62. /*****************************************************************************************
  63. * Function name        : sUart3RxInterrupt().
  64. * Description        : USART1接收中断执行程序.
  65. * Input para(s)        : none.        
  66. * Output para(s): none.
  67. * Caller(s)                : USART1_IRQHandler().
  68. * Note(s)                : 中断接收数据,将数据放入到队列中
  69. *****************************************************************************************/               
  70. void sUart3RxInterrupt(void)
  71. {                                                                                                                                                                                                               
  72.         if(slave_uart.bUart3FeedbackCount>200)
  73.                 {        // 若大于200关中断                                         
  74.                         USART_ITConfig(USART3, USART_IT_RXNE , DISABLE);               
  75.                
  76.                         // 打开中断放置到发送完成处,以期望解决通道故障的问题                                                         
  77.                                        
  78.                 }
  79.         slave_uart.p_uart3_recbuffer[slave_uart.bUart3FeedbackCount++] = USART_ReceiveData(USART3);
  80. }

  81. /*****************************************************************************************
  82. * Function name        : sUart3TxInterrupt().
  83. * Description        : USART1发送中断执行程序(send the data from data buffer to FIFO).
  84. * Input para(s)        : none.        
  85. * Output para(s): none.
  86. * Caller(s)                : USART1_IRQHandler().
  87. * Note(s)                : 串口中断发送数据,根据wTxLength发送数据
  88. *****************************************************************************************/               
  89. void sUart3TxInterrupt(void)
  90. {                        
  91.         USART_SendData(USART3,slave_uart.p_uart3_sendbuffer[slave_uart.bUartSendSlaveCount++]);
  92.         if(slave_uart.bUartSendSlaveCount>slave_uart.bUartSendSlaveNum)
  93.                 {                                                                                                
  94.                         USART_ITConfig(USART3, USART_IT_TXE, DISABLE);         
  95.                         USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);        //打开串口接收中断                    

  96.                 }
  97. }


 楼主| Ryanhsiung 发表于 2013-6-22 16:51 | 显示全部楼层
本帖最后由 Ryanhsiung 于 2013-6-22 16:58 编辑

我现在入手的几个方向:
1、根据现有问题表象,提出假设、再针对性测试
   现在没有什么方向,求大家支持
2、继续断点,查看异常与正常时,寄存器及变量的微弱差异
   这个大家有没有 比较怀疑的寄存器及变量,让我有针对性的查看
3、查看I2C出现,问题后  对OS的影响
4、从相应外设查找

@yewuyi;
@香水城;
@grant_jx;
大家多多帮助一下。
zeluo 发表于 2013-6-22 18:34 | 显示全部楼层
不懂啊   楼主  帮你顶一个   看看别人的意见吧  
trumpxp 发表于 2013-6-23 10:10 | 显示全部楼层
帮楼主  好好顶一个   不错哦  
airwill 发表于 2013-6-23 10:34 | 显示全部楼层
可以肯定是软件 BUG. 但未必问题就在楼主提供的那段代码里
大方向:
利用调速器, 先捕捉不能继续接收的现成, 对现场还各个外设,寄存器状态分析, 寻找问题. 当然对于发生概率很低的缺陷, 怎么捕捉也是很有技巧的
分析软件和硬件导致 BUG 的冲突, 不需要去捕捉现场, 不过难度很大, 非 "高手" 难于胜任
liuzhongkai123 发表于 2013-6-23 11:25 | 显示全部楼层
香主在哪里
 楼主| Ryanhsiung 发表于 2013-6-23 11:41 | 显示全部楼层
airwill 发表于 2013-6-23 10:34
可以肯定是软件 BUG. 但未必问题就在楼主提供的那段代码里
大方向:
利用调速器, 先捕捉不能继续接收的现成, ...

这个有去捕捉 UART相关寄存器多次,但是无异常!
   其它寄存器等会准备看一下中断相关的
VW7788 发表于 2013-6-24 08:57 | 显示全部楼层
学习下。
hxb20122012 发表于 2013-6-24 09:15 | 显示全部楼层
单独各个模块独立运行是否正确,然后再一步步来排查到底是谁影响了USART接收数据,个人思路,具体也不清楚什么情况。飘过!!!!!!!!!!
Super_ 发表于 2013-6-24 20:05 | 显示全部楼层
 楼主| Ryanhsiung 发表于 2013-6-25 20:55 | 显示全部楼层
进展: 将APB2总线上的外设全部关闭,后再打开,再初始化!问题暂得到解决!
   若只重新初始化,是没有作用。
   若只重新关闭打开 I2C及UART 则只有一些改善。

还待继续测试!!
@香水城;
@airwill
 楼主| Ryanhsiung 发表于 2013-6-28 08:09 | 显示全部楼层
顶!!
IJK 发表于 2013-6-28 09:59 | 显示全部楼层
Ryanhsiung 发表于 2013-6-25 20:55
进展: 将APB2总线上的外设全部关闭,后再打开,再初始化!问题暂得到解决!
   若只重新初始化,是没有作 ...

将APB2总线上的外设全部关闭,后再打开,再初始化!问题暂得到解决!
这种情况不能接受。
可以接受的是:只对I2C关闭,再初始化,再打开,解决问题。
IJK 发表于 2013-6-28 10:01 | 显示全部楼层
STM32F1的I2C用起来很费劲,容易出问题,LZ是怎么用的?用了ST的所谓CPAL库吗?
 楼主| Ryanhsiung 发表于 2013-6-28 11:28 | 显示全部楼层
IJK 发表于 2013-6-28 09:59
将APB2总线上的外设全部关闭,后再打开,再初始化!问题暂得到解决!
这种情况不能接受。
可以接受的是: ...

关I2C做用不大,最后冒失TIMER4的影响较大一些!
 楼主| Ryanhsiung 发表于 2013-6-28 11:28 | 显示全部楼层
IJK 发表于 2013-6-28 10:01
STM32F1的I2C用起来很费劲,容易出问题,LZ是怎么用的?用了ST的所谓CPAL库吗? ...

恩,用的官方的库
您需要登录后才可以回帖 登录 | 注册

本版积分规则

认证:嵌入式技术专家
简介:道阻且长,行则将至!

64

主题

4653

帖子

14

粉丝
快速回复 在线客服 返回列表 返回顶部