目录
串口的处理
数据流向分析
通信结构体设置
我的技术和整体把握和老师差太多了,先搭建起框架有点困难,所以我决定从数据流的角度开始写程序,先写数据接收,这次我们的数据主要来源于zigbee节点的采集,我使用的zigbee模块是串口通信的,我用了一个串口转USB,让他作为一个USB设备在linux中存在。
#include "linuxuart.h"
int set_com_config(int fd, int baud_rate, int data_bits, char parity, int stop_bits)
{
struct termios new_cfg, old_cfg;
int speed;
/*保存原有串口配置*/
if (tcgetattr(fd, &old_cfg) != 0){
perror("tcgetattr");
return -1;
}
new_cfg =old_cfg;
/*配置为原始模式*/
cfmakeraw(&new_cfg);
new_cfg.c_cflag &= ~CSIZE;
/*设置波特率*/
switch (baud_rate)
{
case 2400:{
speed = B2400;
break;
}
case 4800:{
speed = B4800;
break;
}
case 9600:{
speed = B9600;
break;
}
case 19200:{
speed = B19200;
break;
}
case 38400:{
speed = B38400;
break;
}
default:
case 115000:{
speed = B115200;
break;
}
}
cfsetispeed(&new_cfg, speed);
cfsetospeed(&new_cfg, speed);
/*设置数据位*/
switch (data_bits)
{
case 7:{
new_cfg.c_cflag |= CS7;
break;
}
default:
case 8:{
new_cfg.c_cflag |= CS8;
break;
}
}
/*设置奇偶校验位*/
switch (parity)
{
default:
case 'n':
case 'N':{
new_cfg.c_cflag &= ~PARENB;
new_cfg.c_iflag &= ~INPCK;
break;
}
case 'o':
case 'O':{
new_cfg.c_cflag |= (PARODD |PARENB);
new_cfg.c_iflag |= INPCK;
break;
}
case 'e':
case 'E':{
new_cfg.c_cflag |= PARENB;
new_cfg.c_cflag &= ~PARODD;
new_cfg.c_iflag |= INPCK;
break;
}
case 's':
case 'S':{
new_cfg.c_cflag &= ~PARENB;
new_cfg.c_cflag &= ~CSTOPB;
break;
}
}
/*设置停止位*/
switch (stop_bits)
{
default:
case 1:{
new_cfg.c_cflag &= ~CSTOPB;
break;
}
case 2:{
new_cfg.c_cflag |= CSTOPB;
break;
}
}
/*设置等待时间和最小接收字符*/
new_cfg.c_cc[VTIME] = 0;
new_cfg.c_cc[VMIN] = 1;
tcflush(fd, TCIFLUSH);
if ((tcsetattr(fd, TCSANOW, &new_cfg)) != 0)
{
perror("tcsetattr");
return -1;
}
return 0;
}
int open_port(char *com_port)
{
int fd;
/*打开串口*/
fd = open(com_port, O_RDWR|O_NOCTTY|O_NDELAY);
if (fd < 0){
perror("open serial port");
return -1;
}
/*恢复串口阻塞状态*/
if (fcntl(fd, F_SETFL, 0) < 0){
perror("fcntl F_SETFL\n");
}
/*判断是否为终端设备*/
if (isatty(fd) == 0){
perror("This is not a terminal device");
}
return fd;
}
/*--------------------CH340Ƥ׃---------------------------*/
void USB_UART_Config(char* path, int baud_rate)
{
int fd;
fd = open_port(path);
if(fd < 0){
printf("open %s failed\n",path);
return ;
}
if (set_com_config(fd, baud_rate, 8, 'N', 1) < 0)
{
perror("set_com_config");
return ;
}
close(fd);
return ;
}
#ifndef __LINUX_UART_H_
#define __LINUX_UART_H_
#include
#include
#include
#include
#include
#include
#include
#include
#include "data_global.h"
extern int set_com_config(int fd, int baud_rate, int data_bits, char parity, int stop_bits);
extern int open_port(char *com_port);
extern void USB_UART_Config(char* path, int baud_rate);
#endif
画的不太好,没有办法审美不太行。
在框架上我是仿照嵌入式安防监控项目搞得,但是内容上全换了,唯一可以直接用的只有a9上的LED和蜂鸣器驱动,还有之前移植好的视频服务器。
通信结构体设置
--------------------------------------------------------------------------------------------------------------
Linux主框架:
pthread_buzzer ---> 蜂鸣器控制线程 ---> 通过操作寄存器的方式操作蜂鸣器
pthread_led ---> 指示灯控制线程 ---> 操作驱动控制LED
pthread_transfer ---> 数据采集线程 ---> 采集通过zigbee上传的数据
pthread_sqlite ---> 数据库线程 ---> 操作sqlite3数据库
linuxuart ---> 串口处理函数 ---> 设置串口,尤其是封装一下ch340的接口
data_global ---> 全局性的定义 ---> 全局宏定义、线程函数、设备节点声明、消息队列结构体信息和extern声明
pthread_client_request ---> 客户端请求 ---> 主要是对zigbee和服务器所在开发板上的外设进行控制
pthread_refresh ---> 数据刷新 ---> 按照设定的时间将数据刷新到前端
--------------------------------------------------------------------------------------------------------------
#define QUEUE_MSG_LEN 32 //消息队列传递命令最大长度
#define ZIGBEE_DEV "/dev/ttyUSB0"
#define BEEPER_DEV "/dev/fsbeeper0"
#define LED_DEV "/dev/fsled0"
//未来还要实现WiFi路由器属性这里还缺一个驱动设备暂时不会做
//和上一条一样加一个触屏继续优化保留一下驱动的坑
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
//需要考虑内存对齐问题size = 64;
struct zigbee_info{
uint8_t head; // 标识位 @作为一条消息的头 #作为一条指令的头
uint8_t demo; // 货物的流向: 入库i 出库 o
uint8_t device[2]; // 设备类型
uint8_t device_id[4]; // 设备id
float humidity; // 湿度
float temperature; // 温度
float tempMIN; // 温度下限
float tempMAX; // 温度上限
float humidityMIN; // 湿度下限
float humidityMAX; // 湿度上限
float smokescope; // 烟雾浓度
float precipitation; // 降雨量
uint8_t fire[2]; // 火灾地点
uint8_t RFID[8]; // RFID的ID
uint8_t reserved_char[2]; // 预留
uint32_t reservef_int[3]; // 预留
};
//消息队列结构体
struct msg{
uint8_t head; // 标识位 @作为一条消息的头 #作为一条指令的头
uint8_t ctrl; // 控制指令
uint8_t device[2]; // 设备类型
uint8_t device_id[4]; // 设备id
uint8_t test[QUEUE_MSG_LEN]; // 消息正文
};
设备类型和id的分配:
A9 ---> 服务器平台
LE ---> 整体灯源控制
RF ---> RFID
WI ---> 开关窗
RW ---> 雨水
SD ---> 湿度
WD ---> 温度
GS ---> GSM
FA ---> 火焰
SM ---> 烟雾
SR ---> 扇热模块
JR ---> 加热模块
BP ---> 蜂鸣器
GR ---> 机器人 //预留的坑,暂时还没有机器人由于除了蜂鸣器和LED每种感知节点只有一个下面只介绍蜂鸣器ID其它默认0000
A9平台 ---> 0000
温湿度节点 ---> 1000
火焰节点 ---> 2000
烟雾节点 ---> 3000
RFID节点 ---> 4000
struct msgbuf {
long mtype; /* message type, must be > 0 */
char mtext[1]; /* message data */
};
ctrl
BEEP:关闭: 0000 0000 ---> 0x00
打开: 0000 0001 ---> 0x01LED:
全部关闭 0000 0000 ---> 0x00
全部打开 1111 1111 ---> 0xFF // 节日模式
智能模式 1111 0000 ---> 0xF0
节能模式 0101 0101 ---> 0x55
自动模式 1010 1010 ---> 0xAA
手动模式分别控制八个灯的开关 0关1开
暂时先这样后面实际操作可能会微调一下。