串口接受固定格式的数据

开发时需要接受一串如下格式的数据

        0xAA    cmd     data        0x0D      0x0A

        其中头,和两个尾巴是固定的,cmd是区别不同的命令,data是数据域(数据长度是已知的)

 

#ifndef QUE_H
#define QUE_H
#include "stdio.h"
#define LEN 255//定义缓存队列的长度

typedef struct 
{
	unsigned char Rx_data[LEN];
	unsigned char front;
	unsigned char rear;
}Que;//定义缓存队列
typedef struct
{
	const unsigned char data_len;//数据域的长度
	const unsigned char TdeCmd;//指向命令的指针(数组的头)
	void(*Fun)();//当前命令需要执行的动作
}tde_t;
//判断队列是否为空
unsigned char IsEmpty(void);
//入队
void InQue(unsigned char val);
//出队
unsigned char OutQue(unsigned char *val);
void TDE(tde_t tde_arr[], unsigned char tde_num);
#endif
#include "que.h"
#define HEAD		0xAA
#define END1		0x0D
#define END2		0x0A




Que queue = {0};

//判断队列是否为空
unsigned char IsEmpty(void)
{
	if (queue.front == queue.rear)
	{
		return 1;
	}
	return 0;
}

//入队
void InQue(unsigned char val)
{
	if (queue.front == (queue.rear + 1) % LEN)
	{
		queue.Rx_data[queue.rear] = val;
		queue.rear = queue.front;
		queue.front = (queue.front + 1) % LEN;
	}
	else
	{
		queue.Rx_data[queue.rear] = val;
		queue.rear = (queue.rear + 1) % LEN;
	}
}
//出队
unsigned char OutQue(unsigned char *val)
{
	if (IsEmpty())
	{
		return 0;
	}
	else
	{
		*val = queue.Rx_data[queue.front];
		queue.front = (queue.front + 1) % LEN;
	}
	return 1;
}


//假设TDE命令每隔1ms轮询一次
void TDE(tde_t tde_arr[], unsigned char tde_num)
{
	static unsigned char stage = 0;
	static unsigned char delay_count = 0;//等待10ms,如果队列为空,则退出每次处理
	static unsigned char record_front = 0;//记录头指针的位置
	static unsigned char record_data_len = 0;//记录该指令数据域的长度
	static unsigned char record_cmd_index = 0;//记录命令在数组中的下标

	static unsigned char record_data[20] = {0};//记录数据域
	static unsigned char record_data_index = 0;

	unsigned char val = 0, i = 0;
	switch(stage)
	{
		case 0://头
			if(OutQue(&val) == 1)//出队成功
			{
				if(val == HEAD)
				{
					stage = 1;
				}
			}
			break;
		case 1://命令
			if(OutQue(&val) == 1)//出队成功
			{
				for(i = 0; i < tde_num; i++)//轮询tde中所有的命令
				{
					if(val == tde_arr[i].TdeCmd)
					{
						stage = 2;
						delay_count = 0;
						record_data_len = tde_arr[i].data_len;
						record_cmd_index = i;
						record_front = queue.front;//记录当前队尾位置
						return;
					}
					
				}
				if(val == HEAD)//如果找到头
				{
					stage = 1;
					delay_count = 0;
					break;
				}
				delay_count = 0;
				stage = 0;//未找到则复位
			}
			else
			{
				delay_count++;
				if(delay_count >= 10)
				{
					delay_count = 0;
					stage = 0;
				}
			}		
			break;
		case 2://数据域
			if(record_data_len == 0)
			{
				delay_count = 0;
				record_data_index = 0;
				stage = 3;
				break;
			}
			else
			{
				if(IsEmpty() == 0)//当前队列是否为空
				{
					OutQue(&val);
					//记录出队的数据
					record_data[record_data_index] = val;
					record_data_index++;
					record_data_len--;
				}
				else
				{
					delay_count++;
					if(delay_count >= 10)
					{
						delay_count = 0;
						record_data_index = 0;
						stage = 0;
					}
				}
			}		
			break;
		case 3://END1
			if(OutQue(&val) == 1)//出队成功
			{

				if(val == END1)
				{
					stage = 4;
					delay_count = 0;
					break;
				}
				else
				{
					queue.front = record_front;//指针复位,如果找到头和命令,但是END1错误,则要从数据域开始找头
					delay_count = 0;
					stage = 0;//未找到则复位
				}
			}
			else
			{
				delay_count++;
				if(delay_count >= 10)
				{
					delay_count = 0;
					stage = 0;
				}
			}
			break;
		case 4:
			if(OutQue(&val) == 1)//出队成功
			{

				if(val == END2)
				{
					stage = 0;
					delay_count = 0;
					tde_arr[record_cmd_index].Fun();
					break;
				}
				else
				{
					queue.front = record_front;//指针复位,如果找到头和命令,但是END2错误,则要从数据域开始找头
					stage = 0;//未找到则复位
					delay_count = 0;
				}
			}
			else
			{
				delay_count++;
				if(delay_count >= 10)
				{
					delay_count = 0;
					stage = 0;
				}
			}
			break;

	}
}

测试: 

#include "stdio.h"
#include "que.h"



void f1(void)
{
	printf("f1执行");
}
void f2(void)
{
	printf("f2执行");
}
tde_t tde_arr[] = 
{
	{1, 2, f1},
	{2, 3, f2},
};

int main()
{
	unsigned char temp = 0;
	InQue(0xAA);
	InQue(0xAA);
	InQue(0xAA);
	InQue(0x02);
	/*InQue(11);
	InQue(0x0d);*/
	InQue(0x0d);
	InQue(0xAA);
	InQue(0x03);
	InQue(11);
	InQue(11);
	InQue(0x0d);
	InQue(0x0a);


	while(1)
	{
		
		for(temp = 0; temp <22; temp++)
		{
			TDE(tde_arr, 2);
		}
		
	}

	return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

入门->放弃

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值