本帖最后由 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); //打开串口接收中断
}
}
|