|
本帖最后由 nome 于 2014-4-21 13:55 编辑
功能简介:
实现一个数据流(笔者用于串口)的接收缓冲,然后在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(¶m[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);
- }
复制代码 |
阿莫论坛20周年了!感谢大家的支持与爱护!!
一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。
|