单片机处理用串口接收频次较高的数据方式

来源:互联网 发布:重庆警方破获网络诈骗 编辑:程序博客网 时间:2024/06/06 03:30
    说出来都是泪,折腾了一个星期的串口接收并处理的程序,结果还经常出现数据丢失现象,结果是被老大骂了一顿,然后人家半天时就给搞定。除了恨自己无能以外,只有好好向高手学习。现在把人家的数据处理思路写出来,一块学习,一块成长。    本人是今年毕业的应届生,或许这个思路对于你们大神都已经是小儿科的玩意,也恳请你们传授点经验,小弟感激不尽、    闲话不多说,说说学到的东西吧。    这里主要介绍思路,适合所有的单片机,就以STC的15单片机的平台进行解说

**步骤一:串口的数据接收
关于串口的配置,和基础性的就不多说,自行看数据手册。直接看串口中断
“`
void Uart1() interrupt 4 using 1
{
if (RI)
{
RI = 0; //Çå³ýRIλ
Usart_RX1_buff[RX1_len++] = SBUF;
if(RX1_len >= buff_len)
{
RX1_len = 0;
}
}
if (TI)
{
TI = 0; //Çå³ýTIλ
busy = 0; //Çåæ±êÖ¾
}
}

在串口的中断里,只做接收,任何判断都不做,防止因为判断的方式不对,把一帧数据都给扔掉。就造成数据丢失。先不管三七二十一,先全盘接收。

步骤二:判断数据是否接收完成

  if(RX1_len >0)                {                               if(USART1_Rx_LastDateLength == RX1_len)                        {                                               uart1_rx_time ++;                            if(uart1_rx_time >10)                             {//数据接收完成                               USART1_Rx_Progress_DateLength = RX1_len;                                       memcpy(USART1_Rx_Progress_Buff,Usart_RX1_buff,USART1_Rx_Progress_DateLength);                                    RX1_len =0;                                    USART1_Rx_LastDateLength =0;                                    uart1_rx_time =0;                                               }                        }                        else if(USART1_Rx_Progress_DateLength ==0)                        {                                USART1_Rx_LastDateLength = RX1_len;                                uart1_rx_time =0;                        }                }   
    大体思路介绍,串口接收到一个字节的数据,在定时器的中断里进行扫描,   在一帧数据还没完全接收完成,每次的定时器中断扫描到的RX1_len都会+1,所以函数都会进入到  

else if (USART1_Rx_LastDateLength == RX1_len)里 当一帧数据接收完成后,每次扫描的结果就是
USART1_Rx_LastDateLength == RX1_len 所以函数就会进入到

if(USART1_Rx_LastDateLength == RX1_len)            {                                   uart1_rx_time ++;                if(uart1_rx_time >10)                 {//数据接收完成                        USART1_Rx_Progress_DateLength = RX1_len;                                                        memcpy(USART1_Rx_Progress_Buff,Usart_RX1_buff,USART1_Rx_Progress_DateLength);                        RX1_len =0;                        USART1_Rx_LastDateLength =0;                        uart1_rx_time =0;                                           }            }

先说下判断一帧数据接收完成的依据是在本次扫描串口接收数据个数与上次扫描个数一样,并且在10ms里都是这样,(这里可以根据自己实际情况而定)
一帧数据接收完成后进行复制,做处理,防止因为数据间隔时间过短而造成数据处理紊乱,或者数据丢失
数据接收完成,并且备份后,可以在主循环里进行处理。
步骤三 数据的甄别与处理
在主循环里进行数据的甄别与处理,这里的思路就直接在代码里写吧。为了更具有适配性,就用伪代码说明

        if (USART1_Rx_Progress_DateLength>0)   {                        while(USART1_Rx_Progress_DateLength >=自己定义的一帧数据的长度)        { /*由于数据的处理和接收不同步,如果串口的数据来源较多,并且数据的处理比较复杂,可能出现一次接收了好几帧的数据,所以要按照    数据帧长度进行截断提取,然后处理,  找到帧头才能处理,所以先找到帧头数据的位置*/            if(帧头的是否相等的判断,在这里也可以对数据帧的特殊位进行判断)//找到帧头            {                                               memcpy(cdata,USART1_Rx_Progress_Buff+datelength,一帧数据的长度);                   /*                    这里可以进行的数据的处理,尽量写成函数调用,方便阅读,(个人建议)              */       datelength +=一帧数据长度;                    USART1_Rx_Progress_DateLength -=一帧数据长度;    //找到帧头,就可以一次截取一帧的长度。进行下一次的处理        }    else   // 在接收到数据的数组里一一的进行扫面,不是的就扔掉。(针对于特殊标志在帧头,其他情况自行改动)    {            datelength +=1;            USART1_Rx_Progress_DateLength -=1;    }  }        USART1_Rx_Progress_DateLength =0;        datelength=0;   }    
    到此,大体的思路介绍完了  (刚开始博客生涯,编辑格式上可能处理的不太好,先将就吧)
原创粉丝点击