#C51串口通讯3-#一串数据#中断即时解析用户自定义协议

发布者:mmsg3814最新更新时间:2022-09-16 来源: csdn关键字:C51  串口通讯  中断 手机看文章 扫描二维码
随时随地手机看文章

前言

1.上一章(中断定时+超时接收)的逻辑,适用于协议较为复杂的情况,即中断判断接收结束,数据放置缓冲区,主函数中解析数据。

2.实际开发中,用户自定义协议的帧头是可预见的,包括数据长度等。

3.本章测试使用中断即时解析自定义协议


提示:以下是本篇文章正文内容,下面案例可供参考

一、场景

示例一串数据:固定帧头区(AA 66 AA )+数据类型(01/02)+数据区+和校验+异或校验

其中,01LED,02蜂鸣器 ,数据区为工作时间,低位在前高位在后


二、编程实现

1.知识点

a.“状态机”的算法思想

状态机是有限状态自动机的简称,是现实事物运行规则抽象而成的一个数学模型。

包括:State(状态)、Event(事件)、Action(动作)、Transition(转换)

链接:什么是状态机

b.用户自定义协议一般格式:

image.png

eg:

数据类型包括外部负载,如led、继电器、蜂鸣器


2.代码设计

1.串口中断服务函数中判断数据有效性,仅保存数据区到缓冲区recv_buf[]

2.校验ok后清相关变量,置数据有效接收标志1


void uart_ISR() interrupt 4

{

if(RI)

{

RI = 0;

recv_data = SBUF;

switch(machine_step)

{

case 0:

if(0xAA == recv_data) //1.帧头符合,状态+1,下一次中断进入后继续检测,否则丢弃

{

machine_step = 1;

}

else

{

machine_step = 0;

}

break;

case 1:

if(0x66 == recv_data)

{

machine_step = 2;

}

else

{

machine_step = 0;

}

break;

case 2:

if(0xAA == recv_data)

{

machine_step = 3;

recv_Cnt = 0; //2.即将进入数据区,计数启动

}

else

{

machine_step = 0;

}

break;

case 3: //3.校验计算

sum_check += recv_data;

xor_check ^= recv_data;

recv_buf[recv_Cnt] = recv_data; //4.数据区存储到缓冲区

recv_Cnt++;

if(recv_Cnt >2)

{

machine_step = 4;

}

break;

case 4:

if(sum_check == recv_data) //5.校验判断 //recv_data已经是新的一个字节,

{

machine_step = 5;

}

else

{

machine_step = 0; //累加和错误,下次重新开始判断

sum_check = 0; //校验清0,否则下一串数据在状态3时出错

xor_check = 0;

}

break;

case 5:

if(xor_check == recv_data)

{

recv_flag = 1; //6.数据正确,标志置1

}

else

{

machine_step = 0; //异或校验错误,下次重新开始判断

}

sum_check = 0; //校验清0,否则下一串数据在状态3时出错

xor_check = 0;

machine_step = 0; //++的数都要记得在某个地方清0

recv_Cnt = 0; //不清也ok,养成习惯清除

break;

default:break;

}

}

}


3.主函数中执行数据解析:

数据类型01时LED工作,02时蜂鸣器工作,recv_buf[1]时间低位,recv_buf[2]数据高位,整合成unsigned int


void Convert(unsigned char *vbuf)

{

UC i;

if(recv_flag)

{

recv_flag = 0;

// timer_start = 0; //关掉定时器,防止T0一直在执行

for (i = 0; i < cRealLen; i++)

{

uart_Recv[i] = vbuf[i];

}

sendString(vbuf); //test

Exchange_Func();

clr_recvbuffer(vbuf);

}

}


void Exchange_Func(void)

{

// UC cSchIndex; //帧头不是指定特征帧头时,移位查找

// UC cErr_Info[] = {'e','r','r','o','r','n'};

// UC fvalid; //有效数据标志

switch(recv_buf[0])

{

case 1:

recv_Led_time = recv_buf[2];

recv_Led_time <<= 8;

recv_Led_time += recv_buf[1];

break;

case 2:

recv_Beep_time = recv_buf[2];

recv_Beep_time <<= 8;

recv_Beep_time += recv_buf[1];

break;

default:break;

}


4.T0定时器中断服务函数中将计数–处理,计时


void Timer0_ISR() interrupt 1

{

TR0 = 0; //进T0中断首先关闭定时器


if(recv_Led_time)

{

recv_Led_time--;

fLedShine = 1;

}

    else

    {

fLedShine = 0;

}

if(recv_Beep_time)

{

recv_Beep_time--;

set_buzz(BUZZ_TYPE1);

}

    else

    {

BUZZER = 1;

}


主函数数据解析开放性实现功能


总结

1.本章仅简单测试设计框架:“中断即时解析用户自定义数据”,较上一章而言,优点在于简易的协议情况下,处理速度更快。

2.引用“状态机”的编程思想

3.根据实际情况选择合适的代码方案。

关键字:C51  串口通讯  中断 引用地址:#C51串口通讯3-#一串数据#中断即时解析用户自定义协议

上一篇:#C51串口通讯4-#一串数据#中断即时解析用户自定义协议(握手接收应答)
下一篇:#C51串口通讯2-#一串数据#定时中断实现超时接收

小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved