1.zigbee采集控制功能实现
zigbee采集控制功能硬件连接
zigbee组网代码介绍及烧写
硬件连接
协调器连接
温湿度&风扇连接
代码路径
文件路径
智慧教室项目实战\day09\03-Zigbee源码
IAR工程路径
智慧教室项目实战\day09\03-Zigbee源码\Projects\zstack\Samples\ZigbeeApp\CC2530DB
代码编译配置
协调器编译
温湿度节点编译
风扇节点编译
STM32实现代码移植及分析
文件路径
智慧教室项目实战\02-智慧教室项目实战\day09\02-STM32需要移植的代码
zigbee应用协议解析实现
protocol.c protocol.h
zigbee串口数据接收
usart.c
//主要配置使能uart1空闲中断
freertos.c
//创建zigbee消息队列
//在zigbee任务中进行接收消息,解析消息
stm32f4xx_it.c
//zigbee消息入队
数据封装
CmdAndSensor.c
//增加了风扇控制
webserver
httpserver-socket.c
//传感器数据获取
//风扇控制
触摸屏展示
TempDLG.c
HumDLG.c
LightDLG.c
//增加传感器数据动态展示功能
FanDLG.c
//增加实际的风扇控制功能
整体功能验证
2.Zigbee组网设计
组网架构
使用Zigbee技术组建无线网络,网络中包含温湿度采集节点、风扇控制节点、Zigbee协调器
- Zigbee协调器负责Zigbee网络组建,通过串口与STM32进行通信
- STM32负责Zigbee传感器数据解析,和控制命令下发
通信协议
协议格式
-
包头/版本:表示一包完整的数据/当前使用的协议版本
-
节点ID:在Zigbee网络里的节点ID号
-
节点类型:
- 0x0:温湿度传感器
- 0x01:风扇控制
-
数据长度:
- 范围:0~255
- 单位:字节
-
数据域:
-
温湿度传感器:温度+湿度(1+1字节)
-
风扇:风扇状态 (1个字节)
-
CRC-8
-
8位循环冗余校验(保证通信可靠)
-
校验域为节点ID~数据域
包头 | 节点ID | 节点类型 | 数据长度 | 数据域 | CRC-8 | 包尾/版本 |
---|---|---|---|---|---|---|
0x99 | 0x0~0XxFFFF | 0x0~0xFF | 0x0~0xFF | xx | CRC | 0x01 |
温湿度协议格式
上行
包头 | 节点ID | 节点类型 | 数据长度 | 数据域 | CRC-8 | 包尾/版本 |
---|---|---|---|---|---|---|
0x99 | 0x0001 | 0x00 | 2 | 温度:25℃,湿度:80% | CRC | 0x01 |
风扇协议格式
上行
包头 | 节点ID | 节点类型 | 数据长度 | 数据域 | CRC-8 | 包尾/版本 |
---|---|---|---|---|---|---|
0x99 | 0x0002 | 0x01 | 1 | 开:0x01,关:0x00 | CRC | 0x01 |
下行
包头 | 节点ID | 节点类型 | 数据长度 | 数据域 | CRC-8 | 包尾/版本 |
---|---|---|---|---|---|---|
0x99 | 0x0002 | 0x01 | 1 | 开:0x01,关:0x00 | CRC | 0x01 |
Zigbee组网设计
通信方式
Zigbee支持单播,组播,广播,绑定通信,根据我们功能定义,协调器可以采用广播通信,节点采用单播通信
协调器地址恒为:0x0000
广播地址为:0xFFFF
节点地址:采用短地址通信,但是地址是有协调器进行动态分配的
协议解析 组包设计
在实际的网络的通信中即有上行又有上行,需要我们通过代码具体实现
####设计思路
- 判断接收协议是否合法
- 检查协议头
- 检查协议尾
- 校验CRC
- 获取有效数据
- 解析数据
- 创建协议数据
协议组包拆包功能实现
CRC教研算法
/***************************************************************************
* File : protocol.c
* Function Name :
* Description : 协议处理
* Version : v1.0
* Author : zhengdao.liu
* Date : 2019/8/22
* Parameter :
* Return :
* Note :
***************************************************************************/
#include "protocol.h"
#include "stdio.h"
#include "string.h"
extern UART_HandleTypeDef huart1;
ProtocolDataType ProtocolData = {
HEAD,
NODE_ID,
NODE_TYPE,
DATA_LEN,
0x0,
0x0,
TAIL,
};
/******************************************************************************
* Name: CRC-8 x8+x2+x+1
* Poly: 0x07
* Init: 0x00
* Refin: False
* Refout: False
* Xorout: 0x00
* Note:
*****************************************************************************/
uint8 crc8(uint8 *data, uint8 length)
{
uint8 i;
uint8 crc = 0; // Initial value
while(length--)
{
crc ^= *data++; // crc ^= *data; data++;
for ( i = 0; i < 8; i++ )
{
if ( crc & 0x80 )
crc = (crc << 1) ^ 0x07;
else
crc <<= 1;
}
}
return crc;
}
/***************************************************************************
* Function Name : ProtocolCheck
* Description : 检查协议是否合法
* Parameter :Data:协议数据包 DataLen:数据包长度
* Return :合法:1,非法:-1
* Note : NULL
***************************************************************************/
uint8 ProtocolCheck(uint8 *Data,uint16 DataLen){
uint8 crc = 0;
// 1.检查协议头
if(Data[0] != HEAD){
printf("Protocol Head Error!\r\n");
return 0;
}
// 2.检查协议尾
if(Data[DataLen-1] != TAIL){
printf("Protocol Tail Error!\r\n");
return 0;
}
// 3.校验CRC
crc = crc8(&Data[1],DataLen-3);
if(crc != Data[DataLen-2]){
printf("Protocol CRC Error!\r\n");
return 0;
}
return 1;
}
/***************************************************************************
* Function Name :
* Description : 协议处理
* Parameter :
* Return :
* Note :
***************************************************************************/
void ProtocolParse(uint8 *Data,uint16 DataLen){
if(ProtocolCheck(Data,DataLen) == 0){
return;
}
switch(Data[3]){
case 0x0:
SensorData[0] = Data[5];
SensorData[1] = Data[6];
break;
case 0x01:
SensorData[2] = Data[5];
break;
default:
break;
}
}
/***************************************************************************
* Function Name :
* Description : 协议处理
* Parameter :
* Return :
* Note :
***************************************************************************/
uint16 CreateData(uint8 *Data){
//检查是否有错误
if(Data !=NULL){
Data[0] = ProtocolData.Head;
Data[1] = ProtocolData.NodeId>>8;
Data[2] = ProtocolData.NodeId;
Data[3] = ProtocolData.NodeType;
Data[4] = ProtocolData.DataLen;
Data[5] = ProtocolData.Data;
Data[6] = crc8(&Data[1],5);
Data[7] = ProtocolData.Tail;
return 8;
}
else{
printf("CreateData Error!\r\n");
return 0;
}
}
void FanControl(uint8_t Status){
uint8_t DataBuff[10];
uint8_t DataLen = 0;
ProtocolData.Data = Status;
DataLen = CreateData(DataBuff);
HAL_UART_Transmit(&huart1,DataBuff,DataLen,100);
}