打印
[STC单片机]

单片机串口如何接收上位机不断发送的数据帧,并将该帧的有效数据提取出来?

[复制链接]
2673|2
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
zfeng45|  楼主 | 2018-8-29 10:58 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

各位大虾:本人菜鸟请教一个问题,单片机如何接送串口不断发送的数据帧,并将该帧的有效数据提取出来,请赐教一个完整程序。
注:我用的是89C52,通信115200已经调试成功,我的思路是先接收一完整帧判断,然后再进行帧数分析,提取有效数据64
该帧为02 14 30 57 00 64 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 17 03
02                 //帧头
14                 //数据长度: 长度=命令+参数+效验
30 57 00        //命令
64 00  00 00 00 00 00 00 00 00 00 00 00 00 00 00 //有效数据
17                 //XOR :XOR=长度xor命令xor参数
03                 //帧尾  

相关帖子

沙发
zfeng45|  楼主 | 2018-8-29 11:04 | 只看该作者
我编写的主程序中LED无法点亮,硬件电路核查过没问题,void Data_anlysize()函数也没问题,Data_ok能收到,不清楚问题在哪?
#include "reg52.h"                         //此文件中定义了单片机的一些特殊功能寄存器

#define uint unsigned int         //对数据类型进行声明定义
#define uchar unsigned char


uchar Data_buf[22];          //串口接收数据缓存数组
uint  Data_recieve[22];      //串口接收到完整帧
uint  flag;                                         //串口接收结束标志
uint  Data_ok;                             //有效数据提取标志

sbit ticket=P1^0;                            //将单片机的P1.0端口定义为乘客购票检测
sbit voice=P1^4;                            //将单片机的P1.4端口定义为语音提示开关
sbit led=P0^0;                     //将单片机的P0.0端口定义bug检测

void UsartInit();            //串口初始化
void Data_anlysize();                 //数据分析

/*******************************************************************************
* 函 数 名       : main
* 函数功能                 : 主函数
* 输    入       : 无
* 输    出             : 无
*******************************************************************************/
void main()
{       
        UsartInit();                   //串口初始化
        while(1)
        {
                voice=0;
            Data_anlysize();            //数据分析
                if(Data_ok==1&&ticket==0)  //判断乘客有购票行为
                {
                         voice=1;              //开语音提示
                         led=0;
                }       
        }               
}
/*******************************************************************************
* 函数名         : Usart() interrupt 4
* 函数功能                 : 串口通信中断函数
* 输入           : 无
* 输出                  : 无
*******************************************************************************/
void Usart() interrupt 4
{
        static uchar count=0;                //静态计数变量
    RI=0;                                //接收中断请求标志位清0
    Data_buf[count]=SBUF;                //接收到的数据串保存在缓存数组
    if(Data_buf[0]==0x02)                //验证数据头(起始位)
    {
        count++;
        if(count>=23)
        {
            flag=1;                        //接收完成标志置1
            count=0;                        //计数变量清0
        }
     }
}
/*******************************************************************************
* 函数名         :UsartInit()
* 函数功能                 :串口初始化
* 输入           : 无
* 输出                  : 无
*******************************************************************************/
void UsartInit()
{
        SCON=0X50;                        //设置为串口工作方式1(SM0=0,SM0=1),允许接收 (REN=1)
        T2CON=0X34;                        //设置T2为波特率发生器工作方式(TCLK=1,RCLK=1,TR2=1),T2为定时器(C_T2=0 )
        //T2MOD=0X00;                        //设置T2为加法计数DCEN=0,时钟输出不使能T2OE=0
        TH2=0XFF;                    
        TL2=0XFD;
        RCAP2H=0XFF;
        RCAP2L=0XFD;            //计数器T2初始值设置,波特率115200
        EA=1;                                //打开总中断
        ES=1;                                //设置中断允许控制寄存器IE,允许串行中断   
}
/*******************************************************************************
* 函数名         :Data_anlysis()
* 函数功能                 :串口协议分析
* 输入           : 无
* 输出                  : 无
* 备注                  : 帧结构
                   02                 //帧头
                                   14                 //数据长度: 长度=命令+参数+效验
                                   30 57 00        //命令
                                   64 00        //找零箱内硬币数
                                   00 00 00 00 00 00 00 00 00 00 00 00 00 00
                                   17                 //XOR :XOR=长度xor命令xor参数
                                   03                 //帧尾      
*******************************************************************************/
void Data_anlysize()
{
        uchar i,j;                //临时变量
        if(flag==1)               //23位数据串接收完成
        {
            ES=0;                 //关串口中断
            flag=0;               //接收完成标志清0
            j=Data_buf[2]^Data_buf[3]^Data_buf[4]^Data_buf[5]^Data_buf[6]^Data_buf[7]^Data_buf[8]^Data_buf[9]^Data_buf[10]^Data_buf[11]^Data_buf[12]^Data_buf[13]^Data_buf[14]^Data_buf[15]^Data_buf[16]^Data_buf[17]^Data_buf[18]^Data_buf[19]^Data_buf[20];//XOR校验
            if(Data_buf[21]==j)  //校验通过
            {
               for(i=0;i<=22;i++)
                                   Data_recieve[i]=Data_buf[i];//接收完整帧
                           if(Data_recieve[5]==0x64)
                               Data_ok=1;
            }
            ES=1;                //开串口中断
          }
}

使用特权

评论回复
板凳
qishi00| | 2018-8-30 20:44 | 只看该作者
你要接收的数据长度是23字节,数组大小却是22,这样会造成接收数据溢出,篡改其他数据的隐患。
j=Data_buf[2]^Data_buf[3]^Data_buf[4]^Data_buf[5]^Data_buf[6]^Data_buf[7]^Data_buf[8]^Data_buf[9]^Data_buf[10]^Data_buf[11]^Data_buf[12]^Data_buf[13]^Data_buf[14]^Data_buf[15]^Data_buf[16]^Data_buf[17]^Data_buf[18]^Data_buf[19]^Data_buf[20];//XOR校验
这个异或,不是应该从Data_buf[1]开始吗?

使用特权

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

本版积分规则

4

主题

15

帖子

0

粉丝