打印

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

[复制链接]
3027|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不稳定引起。最后触发相应问题

附上代码:

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

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

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

        while(temp_delay++ < timeout)                                                // 最长等待的时间,超时
                {
                        OSTimeDly(10);                                                                        
                        if(slave_uart.bUart3FeedbackCount >= 5)
                                {                                                                            //                                 
                                        if(slave_uart.bUart3FeedbackCount > slave_uart.p_uart3_recbuffer[2]+4)
                                                {                 
                                                        temp_delay = 99;
                                                        break;                                                         // 提前退出
                                                }
                                }
                }
       //  这里加入延时无做用
        // receive                                                                                                                                                                                                               
        USART_ITConfig(USART3, USART_IT_TXE , DISABLE);        //关闭串口中断        
        USART_ITConfig(USART3, USART_IT_RXNE , DISABLE);        //关闭串口中断        
        if(temp_delay == 99)
                {                        
                        return TRUE;                        
                }else
                        {
                          return FALSE;               
                        }

}
/*****************************************************************************************
* Function name        : sUart3RxInterrupt().
* Description        : USART1接收中断执行程序.
* Input para(s)        : none.        
* Output para(s): none.
* Caller(s)                : USART1_IRQHandler().
* Note(s)                : 中断接收数据,将数据放入到队列中
*****************************************************************************************/               
void sUart3RxInterrupt(void)
{                                                                                                                                                                                                               
        if(slave_uart.bUart3FeedbackCount>200)
                {        // 若大于200关中断                                         
                        USART_ITConfig(USART3, USART_IT_RXNE , DISABLE);               
               
                        // 打开中断放置到发送完成处,以期望解决通道故障的问题                                                         
                                       
                }
        slave_uart.p_uart3_recbuffer[slave_uart.bUart3FeedbackCount++] = USART_ReceiveData(USART3);
}

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

                }
}


沙发
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 | 只看该作者
帮楼主  好好顶一个   不错哦  

使用特权

评论回复
5
airwill| | 2013-6-23 10:34 | 只看该作者
可以肯定是软件 BUG. 但未必问题就在楼主提供的那段代码里
大方向:
利用调速器, 先捕捉不能继续接收的现成, 对现场还各个外设,寄存器状态分析, 寻找问题. 当然对于发生概率很低的缺陷, 怎么捕捉也是很有技巧的
分析软件和硬件导致 BUG 的冲突, 不需要去捕捉现场, 不过难度很大, 非 "高手" 难于胜任

使用特权

评论回复
6
liuzhongkai123| | 2013-6-23 11:25 | 只看该作者
香主在哪里

使用特权

评论回复
7
Ryanhsiung|  楼主 | 2013-6-23 11:41 | 只看该作者
airwill 发表于 2013-6-23 10:34
可以肯定是软件 BUG. 但未必问题就在楼主提供的那段代码里
大方向:
利用调速器, 先捕捉不能继续接收的现成, ...

这个有去捕捉 UART相关寄存器多次,但是无异常!
   其它寄存器等会准备看一下中断相关的

使用特权

评论回复
8
VW7788| | 2013-6-24 08:57 | 只看该作者
学习下。

使用特权

评论回复
9
hxb20122012| | 2013-6-24 09:15 | 只看该作者
单独各个模块独立运行是否正确,然后再一步步来排查到底是谁影响了USART接收数据,个人思路,具体也不清楚什么情况。飘过!!!!!!!!!!

使用特权

评论回复
10
Super_| | 2013-6-24 20:05 | 只看该作者
顶。

使用特权

评论回复
11
Ryanhsiung|  楼主 | 2013-6-25 20:55 | 只看该作者
进展: 将APB2总线上的外设全部关闭,后再打开,再初始化!问题暂得到解决!
   若只重新初始化,是没有作用。
   若只重新关闭打开 I2C及UART 则只有一些改善。

还待继续测试!!
@香水城;
@airwill

使用特权

评论回复
12
Ryanhsiung|  楼主 | 2013-6-28 08:09 | 只看该作者
顶!!

使用特权

评论回复
13
IJK| | 2013-6-28 09:59 | 只看该作者
Ryanhsiung 发表于 2013-6-25 20:55
进展: 将APB2总线上的外设全部关闭,后再打开,再初始化!问题暂得到解决!
   若只重新初始化,是没有作 ...

将APB2总线上的外设全部关闭,后再打开,再初始化!问题暂得到解决!
这种情况不能接受。
可以接受的是:只对I2C关闭,再初始化,再打开,解决问题。

使用特权

评论回复
14
IJK| | 2013-6-28 10:01 | 只看该作者
STM32F1的I2C用起来很费劲,容易出问题,LZ是怎么用的?用了ST的所谓CPAL库吗?

使用特权

评论回复
15
Ryanhsiung|  楼主 | 2013-6-28 11:28 | 只看该作者
IJK 发表于 2013-6-28 09:59
将APB2总线上的外设全部关闭,后再打开,再初始化!问题暂得到解决!
这种情况不能接受。
可以接受的是: ...

关I2C做用不大,最后冒失TIMER4的影响较大一些!

使用特权

评论回复
16
Ryanhsiung|  楼主 | 2013-6-28 11:28 | 只看该作者
IJK 发表于 2013-6-28 10:01
STM32F1的I2C用起来很费劲,容易出问题,LZ是怎么用的?用了ST的所谓CPAL库吗? ...

恩,用的官方的库

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

64

主题

4654

帖子

14

粉丝