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

本文介绍了如何使用C51进行串口通讯,通过中断即时解析用户自定义协议,包含帧头检测、数据区存储、校验计算等步骤,实现了高效的数据接收和解析。在主函数中执行数据解析并控制LED和蜂鸣器工作,同时利用T0定时器中断服务函数处理计时。
摘要由CSDN通过智能技术生成

系列文章目录-串口通讯

/C51串口通讯调试目录:/
第5章:#C51串口通讯5-#一串数据#中断定时+超时接收+接收应答+CRC校验

第4章:#C51串口通讯4-#一串数据#中断即时解析用户自定义协议(握手接收应答)

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

第2章:#C51串口通讯2-#一串数据#定时中断实现超时接收(推荐)

第1章:#C51串口通讯1-#一串数据#接收与发送(基础概念)


提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

1.上一章(中断定时+超时接收)的逻辑,适用于协议较为复杂的情况,即中断判断接收结束,数据放置缓冲区,主函数中解析数据。
2.实际开发中,用户自定义协议的帧头是可预见的,包括数据长度等。
3.本章测试使用中断即时解析自定义协议


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

一、场景

示例一串数据:固定帧头区(AA 66 AA )+数据类型(01/02)+数据区+和校验+异或校验
其中,01LED,02蜂鸣器 ,数据区为工作时间,低位在前高位在后

二、编程实现

1.知识点

a.“状态机”的算法思想
状态机是有限状态自动机的简称,是现实事物运行规则抽象而成的一个数学模型。
包括:State(状态)、Event(事件)、Action(动作)、Transition(转换)
链接:什么是状态机
b.用户自定义协议一般格式:

帧头地址数据类型数据长度数据区校验帧尾
大多数无

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串口通讯2-#一串数据#定时中断实现超时接收(推荐)
下一章:#C51串口通讯4-#一串数据#中断即时解析用户自定义协议(握手接收应答,非固定长度)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值