本帖最后由 SUPER_CRJ 于 2018-1-15 12:22 编辑
使用μc/OS-Ⅲ,其中串口4接收丢数据,但是在裸机上就没有这样的问题,同样的硬件,使用裸机的时候,正常,也就排除了是硬件问题,但是使用μc/OS-Ⅲ的时候,串口中断接收的数据就会丢失,而且有如下规律:
1:波特率越高,丢的越明显,大概的情况会是:2M波特率下,每40个数据,就会丢失一个。但是在1.5M的时候,就大概第100多个丢失。
但是想不明白的是:我觉得写的这个程序没有发现问题,之前使用460800的时候,也是同样的程序,没有发现问题(但是最近客户反应存在丢的情况),于是个人认为是软件问题!
怀疑的问题如下:是μc/OS-Ⅲ的任务切换导致任务调度的时候出现关中断行为~但是查找网上搜索资料,把:调度器使用上锁的方式,而不是关中断的方式,同样也是出现同样的问题!
本函数如下:就是串口接收到数据就把数据放到数组中,同时写指针+1,然后用信号量同步任务。
发现的问题是:每次发送40个字节,但是接收到有时候没有40个字节(波特率2M时,几乎每次都丢,1.5M的时候几百个丢一个!(不要怀疑波特率高!实测裸机没有问题!)),但是如果去掉操作系统相关的,就是只留下中断接收保留到数组就没有这样的问题!
#define COMBUF_MAXBUFF_SIZE 1024 // 1024个字节
#define COMMSG_MINLEN 40 // 40帧的报文
extern OS_MUTEX USART2_SendUseRight_Mutex;
extern OS_SEM USART2_HadReceiveData_Sem;
typedef struct
{
__IO u8 Buf[COMBUF_MAXBUFF_SIZE];
__IO u16 pRead;
__IO u16 pWrite;
}ComBuf;
ComBuf Com4; // 本函数使用了,串口4
/**
* @brief UART4 中断函数
*/
void UART4_IRQHandler()
{
OS_ERR err;
OSIntEnter(); // 使用μC/OS系统
if( UART4->SR.ReadDataRegisterNotEmpty_RCW0 == TRUE )
{
Com4.Buf[Com4.pWrite++] = UART4->DR.Data_RW;
Com4.pWrite %= COMBUF_MAXBUFF_SIZE;
}
OSSemPost ( (OS_SEM *)&USART2_HadReceiveData_Sem,
(OS_OPT )OS_OPT_POST_1,
(OS_ERR *)&err );
OSIntExit();
}
/**
* @brief 处理串口接收到命令的函数,显然需要用信号量同步处理
*/
void USARTDataProcess_Task( void *p_arg )
{
OS_ERR err;
CPU_TS ts;
while( DEF_ON )
{
OSSemPend( (OS_SEM *)&USART2_HadReceiveData_Sem, // 等待信号量用来同步
(OS_TICK )0,
(OS_OPT )OS_OPT_PEND_BLOCKING,
(CPU_TS *)&ts,
(OS_ERR *)&err);
if( err != OS_ERR_NONE ) { // 出错就卡住
while(1);
}
{
// 报文处理函数,大于报文开始处理,报文处理函数优先级是除了SWD函数的第二高的优先级
if( ((( Com4.pWrite + COMBUF_MAXBUFF_SIZE ) - Com4.pRead ) % COMBUF_MAXBUFF_SIZE ) >= COMMSG_MINLEN )
{
do {
for( u8 i=0;i<COMMSG_MINLEN;i++ )
{
dataBuf = Com4.Buf[(Com4.pRead+i)%COMBUF_MAXBUFF_SIZE];
}
if( (dataBuf[0] == 0x55)&&(dataBuf[1] == 0xAA)&&(dataBuf[COMMSG_MINLEN-1]==0x88) ) //报文开始和结束正确
{
if( GetSum((u8*)dataBuf,(u8)(COMMSG_MINLEN-2)) == dataBuf[COMMSG_MINLEN-2]) // 校验正确
{
switch( dataBuf[2] ) // 这样的方式,需要
{
case 0x00:
break;
case 0x01:
break;
case 0x02:
break;
case 0x03:
NVIC_SystemReset();
break;
default:
break;
}
Com4.pRead += COMMSG_MINLEN;
Com4.pRead %= COMBUF_MAXBUFF_SIZE;
}
else // 报文特征和不正确
{
Com4.pRead ++;
Com4.pRead %= COMBUF_MAXBUFF_SIZE;
}
}
else // 报文特征不正确,减少一位后
{
Com4.pRead ++;
Com4.pRead %= COMBUF_MAXBUFF_SIZE;
}
} while(((( Com4.pWrite + COMBUF_MAXBUFF_SIZE ) - Com4.pRead ) % COMBUF_MAXBUFF_SIZE ) >= COMMSG_MINLEN ); // 仍在报文长度内继续处理
}
}
}
}
}
2018-1-15 10:19:11编辑:
本人当前这样认为:使用2M的波特率,但是单片机本身也就:72M的运行频率,加上μc/OS-Ⅲ实际上这个2M的频率也就是:每次进入中断频率太高了,所以准备采用DMA的方式(本人是没用用过DMA~所以一开始设计的时候就没有考虑用。)。
2018年1月15日12:19:09编辑:
问题已经解决,串口接收使用了DMA的方式,这样可以减少中断频率,因为2M波特率,每秒200K次的中断,实在是太多了,现在改为40个字节一个帧,开启半传输中断,当前中断频率大约在:10K左右~,运行30min没有发现丢帧~
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
F4 fifo和双缓冲都有的,不过好像并不怎么好用
一周热门 更多>