做一个接收的缓冲,cup空闲时刻处理缓冲数据

功能简介: 

实现一个数据流(笔者用于串口)的接收缓冲,然后在cpu空闲的时候处理这些数据流,一般数据流有特定的格式,以便于程序分割命令和参数。


本文使用的是类似linxu shell的可见字符串。实际使用中也可以更改为16进制数据。


使用环境示例:

串口接收函数调用write_queue();插入上位机输入的数据。程序通过调用read_queue()获取数据。

/*
	queue.c
	--实现功能:定义一个环形消息队列,实现1.读一个字节 2.插入一个字节 3.取出一条命令。
	----------  命令格式定义:cmd prama\r    获取命令依照" "区分命令和参数,依照"\r"区分结尾。


	author:nome
	date  :2014/4/18


*/


#include "string.h"
#include "queue.h"


#define Q_LEN 100           //队列长度

#define TIMEOUT 900000       

char strqueue[Q_LEN];       //队列数组



int write = 0;               //写偏移
int read = 0;								//读偏移




/*
 * 功能:从队列中读取一个字节
 * 失败:返回-1
 * 成功:返回0
*/
char read_queue(char *pdata)
{
	if(write==read)
		return -1;		
	*pdata = strqueue[read];
	read = (read+1)%Q_LEN;
	return 0;
}
/*
 * 功能:往队列中写入一个字节
 * 失败:返回-1
 * 成功:返回0
*/
char write_queue(char data)
{
	if((write+1)%Q_LEN==read)
		return -1;
	strqueue[write] = data;
	write = (write+1)%Q_LEN;
	return 0;
}


/*
 * 功能:从队列中取出一个完整的字符串命令。
 * 失败:返回-1
 * 成功:返回0
 *cmd 存放命令的指针,param 存放参数的指针。
*/
int get_q_string(char *cmd,char *param)
{
	int i = 0;
	int timeout = 0;
	char data;
	if(read_queue(&data)) //查看队列中是否有数据,没有数据返回,有数据等待接收完整命令。
		return -1;
	cmd[i++] = data;
	for(;;){
		if(0==read_queue(&cmd[i]))
			i++;
		if(cmd[i-1]==' ')
			break;
		if(timeout>TIMEOUT)
			return -1;
		timeout++;
	}
	cmd[i] = 0; //提供一个cmd结束符
	timeout = 0;
	i = 0;
	for(;;){
		if(0==read_queue(&param[i]))
			i++;
		if(param[i-1]=='\r')
			break;
		if(timeout>TIMEOUT)
			return -1;
			timeout++;		
	}
	param[i-1] = 0; //去掉\r 换成结束符
	return 0;
}
























下面一个.c和一个.h用于处理上面.c取出的字符串。

#ifndef _USART_CMD_H
#define _USART_CMD_H




struct _cmd_list{
	char *cmd;
	void (*func)(char *param);
};

#define CMD_CALLBACK_LIST_BEGIN struct _cmd_list cmd_list[] = {NULL,null,
#define CMD_CALLBACK_LIST_END NULL,NULL};
#define CMD_CALLBACK(cmd_string,callback)	cmd_string,callback,



#endif


#include "queue.h"
#include "string.h"
#include "math.h"
#include "stdio.h"
#include "usart_cmd.h"


extern void usart_sendstring(char *str); //定义一个串口发送字符串的函数

//字符串转int
int str_to_int(char *str)
{
	int i = 0,j = 0;
	int ret = 0;
	for(;;){
	if(str[i++]==0||i>20)
		break;
	}
	j = i = i-2;
	for(;i>=0;i--)
	{
		ret += (str[i]-'0')*(pow(10,(j-i)));
	}
	return ret;
}

/********************一些回调函数 不必在意*****************************/
void setfreq(char *param)
{
SX1276LoRaSetRFFrequency(str_to_int(param));   
												memset(param,0,32);
												sprintf(param,"setfreq ok! freq=%d\r\n",SX1276LoRaGetRFFrequency());   
												usart_sendstring(param);  	
}

extern int send_receive_flag ;
extern int packet_num ;

void send(char *param)
{
	send_receive_flag = 0;
	packet_num = str_to_int(param);
}

void receive(char *param)
{
	send_receive_flag = 1;
}

void null(char *param)
{}
/********************一些回调函数 不必在意*****************************/	

//在此处添加你的命令字符串和回调函数
CMD_CALLBACK_LIST_BEGIN

CMD_CALLBACK("setfreq",setfreq)
CMD_CALLBACK("send",send)
CMD_CALLBACK("receive",receive)



CMD_CALLBACK_LIST_END






char cmd[10];
char param[32];
int get_cmd(void)
{
	int i = 0;
	if(get_q_string(cmd,param))
		return 0;
	for(;;){
		if(strcmp(cmd,cmd_list[i].cmd)==0)
			return i;	
		if(cmd_list[++i].cmd==NULL)
			return 0;
	}
}



//这个函数需要在main函数中轮询调用
void dispose_cmd(void)
{
	cmd_list[get_cmd()].func(param);
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值