单片机下串口(UART)协议包接收程序

该段代码仅仅是本人使用过的一段,非原创也不算抄袭,如果代码有什么不恰当、不优雅的地方,欢迎在评论留下宝贵的建议和意见。

 

代码编写在51单片机上,用于从接收缓冲区中提取有用数据(协议包)。基本逻辑亦可用于其他语言,其他情况下的接收程序。

数据的转移主要分了3步,接收缓冲区=》待处理数据=》有用数据。

接收缓冲区提取到待处理数据:由于可能下一个包马上就要过来,所以应把数据提取出来再做处理,以免直接处理的过程中收到新的数据造成混乱。

待处理数据提取到有用数据:例如在某些环境下,会收到其他协议的包(由其他程序处理),或者带有地址区分是否发给本机的包,所以需要设置一些条件来提取真正有用的数据。

 

单片机串口UART在接收中断程序中写入接收缓冲区,一定时间没有收到数据则标志为接收空闲(完成一个包的接收)。

本段代码先判断串口处于接收空闲状态,然后判断包太小则放弃,认为是错误包。

失能中断,把接收缓冲区提取出来后,重新使能中断,以尽快准备好接收下一次数据传输。

然后则开始搜索包头(帧头),然后把符合协议的部分提取出来,清空包头以免重复处理,最后解析该包。

int WaitingBuf(void)
{
    int return_err=5;
    uint8 bytecnt;
    uint8 i;    
    uint16 dest_p;
    uint16 ScanningAddr;
    uint8 buffer[RXBUFSIZE];//如果太小,收到数据CNT比他大,则程序崩溃    
    uint8 ReceiveBuf[20];
    
    if(rs_state==RS_IDLE)//uart中断接受处于空闲状态,表示一个包接受结束,利用一定时间内没有收到数据判断
    {        
        bytecnt=r_count;
        if(bytecnt<=5)//包太小,误传,错误包,电压不稳定等 
            return 3;
        UA_IER &= (~RDA_IEN | ~RLS_IEN);    //禁止中断,提取本次接收完成后,接受缓冲区的数据
        for(i=0;i)
        {
            buffer[i]=r_buf[i];
        }
        r_count=0;//让缓冲区重新从头开始储存
        UA_IER |= (RDA_IEN | RLS_IEN);   //使能中断,提取数据完毕,准备下一次接收数据
        for(ScanningAddr=0;ScanningAddr<(bytecnt-1);ScanningAddr++) //扫描数据
        {
            if(buffer[ScanningAddr] == 0xEF && buffer[ScanningAddr+1] == 0x01)//找到包头
            {
                for(dest_p=0;dest_p<(bytecnt-ScanningAddr);dest_p++)//从本次收到的数据中,提取有用的部分(符合协议的)
                {
                    ReceiveBuf[dest_p]=buffer[ScanningAddr+dest_p];    
                }
                buffer[ScanningAddr]=0;//清除包头,以免重复处理
                buffer[ScanningAddr+1]=0;
                return_err = ReceiveBufAnalysis(ReceiveBuf);//把收到的协议包送去处理
                break;//如果存在有1个以上数据包将快速发送过来的话,可能缓存区一次将包含2个有用的包,需要去掉该break;
            }
        }    
    }
    else 
        return_err = 2;
    return return_err;
}

转载于:https://www.cnblogs.com/nycko-blog/p/6697001.html

你可能感兴趣的:(单片机下串口(UART)协议包接收程序)