51单片机自定义串口协议实现握手

搞了2整天的协议,查阅了很多博客,资料,对自定义数据传输大体都是这样:
帧头、地址信息、数据类型、数据长度、数据块、校验码、帧尾

那么首先说一下吧,之前我也不是很了解这个,直到我替人做了一个双机通讯的的例子后,发现接收端一直是丢数据或者显示错误数据,这时候,我才想到了定制自己的串口协议。本程序参考了坚哥的跟MODBUS。

接下来,我说一下自己定义的协议吧:
一帧数据总共有7个数据,分别为:
eb 01 30 xx xx 39 ed
eb 02 30 xx xx 39 ed

定义种类两种,如上面两行:
eb:数据头
01、02:功能位
30、39:校验和位
ed:数据尾
xx xx:数据位

我的程序实现功能是,当接收到数据串1时,执行LED1状态翻转
当接收到数据串2时,执行LED2状态翻转

首先来看个思维导图吧:
在这里插入图片描述
就是这么个思路,接下来自己看程序吧,很详细,简短:

#include "reg52.h"
typedef unsigned char  uchar;
typedef unsigned int   uint;
typedef unsigned long  ulong;

sbit LED1 = P1^0;
sbit LED2 = P1^2;

uchar BUF[10];		   //数据存储缓冲区
uchar Usart_Step;    //用来切换程序步
uchar Usart_Cnt;     //用来计数接收到数据的个数
uint  LED1_Date_Move;//用来了;累计计数
uint  LED2_Date_Move;

bit LED1_Flag;//LED状态
bit	LED2_Flag;

void Usart_Init(void)
{
	SCON = 0x50;
	TMOD |= 0x20;
	TL1 = TH1 = 0xfd;
	TR1 = 1;
	ES = 1;
	EA = 1;
}

void main(void)
{
	Usart_Init();
	while(1)
	{
		if(LED1_Flag)//标记位为1时执行状态翻转
		{
			LED1_Flag = 0;
			LED1 = !LED1;
		}
		if(LED2_Flag)//标记位为1时执行状态翻转
		{
			LED2_Flag = 0;
			LED2 = !LED2;
		}
	}
}

void USART_IRQ() interrupt 4
{
	if(RI)			 								//接收中断标记位
	{
		 RI = 0;	 								//清除中断标记
		 switch(Usart_Step)       
		 {
		 		case 0:						  //进入程序步0
				{
					 BUF[0] = SBUF;           //缓冲区接收第一个数
					 if(BUF[0] == 0xeb)       //判断是不是数据头
					 {
					 		BUF[0] = 0;		  //清除以便下次接收数据
							Usart_Cnt = 1;    //计数加1
							Usart_Step = 1;   //切换到程序步1
					 }
				}break;								
				case 1:						  //进入程序步1
				{
					 BUF[Usart_Cnt] = SBUF;   //将剩余的数据传送到缓冲区
					 Usart_Cnt++;			  //计数累加
					 if(Usart_Cnt >= 7)		  //当加到7个数时
					 {
					 		if(BUF[6] == 0xed) //判断数据尾是不是为0xed
							{
								 BUF[6] = 0;   //清零数据尾,方便下次接收
								 switch(BUF[1])	 //选择不同BUF【1】执行不同的功能
								 {
								 		case 0x01:	 //数据0x01时
										{
											LED1_Date_Move =  BUF[2];
											LED1_Date_Move =  LED1_Date_Move<<8;
											LED1_Date_Move += BUF[5];//上面的三个步骤负责累加数值 0x30<<8+0x39(十六进制)=12345(十进制)
											if(LED1_Date_Move == 12345)//判断累加数据是否为12345,进而准确接收数据位,当然我这没有写接收两个数据位实现什么
											{
												LED1_Flag = 1;//让标记位为1
											}
										}break;
										case 0x02:
										{
											LED2_Date_Move =  BUF[2];
											LED2_Date_Move =  LED2_Date_Move<<8;
											LED2_Date_Move += BUF[5];//上面的三个步骤负责累加数值 0x30<<8+0x39(十六进制)=12345(十进制)
											if(LED2_Date_Move == 12345)//判断累加数据是否为12345,进而准确接收数据位,当然我这没有写接收两个数据位实现什么
											{
												LED2_Flag = 1;//让标记位为1
											}
										}break;
								 }
							}Usart_Step = 0;//数据解析完后,返回程序步0,执行下一帧数据
					 }break;
				}
		 }
	}
	else 
	{
		TI = 0;
	}
}


  • 7
    点赞
  • 52
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值