嵌入式安防监控zigbee 总结(来自实验手册)

Zigbee小总结

应用逻辑和基本实现步骤

> 我们需要关⼼的是我们的应⽤逻辑,数据从哪⾥到哪⾥,怎么存储,处理;还有系统⾥的

设备之间的监听顺序是什么,以及当我的应⽤需要数据通信时,调⽤组⽹函数,给我组建我想

要的⽹络,是如何组建?当我想从⼀个设备发数据到另⼀个设备时,调⽤⽆线数据发送函数,

它⼜是怎么使⽤的?当然,接收端就调⽤接收函数,如何接收?当我的设备没事⼲的时候,就

调⽤睡眠函数;要⼲活的时候就调⽤唤醒函数,这些都要有个认识和了解。

综合上述,当我们做具体应⽤时,不需要关⼼协议栈是怎么写的,⾥⾯的每条代码是什

么意思。除⾮你要做协议研究。每个⼚商的协议栈有区别,也就是函数名称和参数可能有区

别,这个要看具体的例⼦、说明⽂档。

举个例⼦,⽤户实现⼀个简单的⽆线数据通信时的⼀般步骤:

第三章 Z-stack 协议栈

3.1 什么是zigbee协议栈?

3.2 如何使⽤zigbee协议栈?19

1、组⽹:调⽤协议栈的组⽹函数、加⼊⽹络函数,实现⽹络的建⽴与节点的加⼊。

2、发送:发送节点调⽤协议栈的⽆线数据发送函数,实现⽆线数据发送。

3、接收:接收节点调⽤协议栈的⽆线数据接收函数,实现⽆线数据接收。

协议栈把很多都封装好了,再⽐如"⽆线发送函数":

注意: AF_DataRequest 的作⽤不是发送数据,⽽是把要发送的数据放到发送队

列,由MAC来发送。MAC收到要发的数据就务必尽全⼒把数据发出去,⽽且不管有没

有发出去,要通过消息 AF_DATA_CONFIRM_CMD 返回给应⽤层。

AF_DataRequest 返回Success表示发送数据成功进⼊发送队列,即⼀般都认为发

送成功了。但实际上AF_DataRequest是⼀个⽐较⾼级的函数接⼝了,只要返回了

success,就说明输⼊的发送数据格式有效,⽽数据并不会发送出去,⽽是进⼊⼀个

等待队列。其实串⼝通信也很类似,⽐如典型的UartWrite函数,返回值代表当前串⼝

发送队列的状态。串⼝发送和⽆线发送最⼤的区别是,串⼝是⼀个字节⼀个字节的发

送,⽽且发送完成时间是固定的,发送⽬标是固定的,发送结果也是固定的(100%

能发出去)。⽆线就不⼀样,CSMA机制介⼊,导致每次函数调⽤填⼊发送数据,到

发送的数据到空中,这段时间是随机的。同样CSMA机制还会导致填⼊的数据根本⽆

法发出去。在zigbee⽹络⾥⾯还有⼀种情况就是你发送数据的时候⽬标正在休眠,数

据要先缓存在MCU中等待⽬标唤醒后再发出去。

 串口发送回显

/*SampleApp.c*/
#include "stdio.h"
#include "MT_UART.h"
#include "MT.h"
/*在SampleApp_Init()函数上⾯,添加printf重定向,即将输出流定向到串⼝*/
__near_func int putchar(int c)
{
UTX0IF = 0;
U0DBUF = (char)c;
while(UTX0IF == 0);
return 0;
}
/*SampleApp_Init()函数*/
void SampleApp_Init( uint8 task_id )
{
SampleApp_TaskID = task_id;
SampleApp_NwkState = DEV_INIT;
SampleApp_TransID = 0;
MT_UartInit(); //串⼝初始化API
MT_UartRegisterTaskID(task_id); //登记串⼝的任务号,即注册该事
件,注意,该函数必须在MT_UartInit()调⽤之后才调⽤
printf("Uart is ok!\r\n");
SampleApp_Periodic_DstAddr.addrMode = (afAddrMode_t)AddrBroadcast;
SampleApp_Periodic_DstAddr.endPoint = SAMPLEAPP_ENDPOINT;
SampleApp_Periodic_DstAddr.addr.shortAddr = 0xFFFF;
SampleApp_epDesc.endPoint = SAMPLEAPP_ENDPOINT;
SampleApp_epDesc.task_id = &SampleApp_TaskID;
SampleApp_epDesc.simpleDesc
= (SimpleDescriptionFormat_t *)&SampleApp_SimpleDesc;
SampleApp_epDesc.latencyReq = noLatencyReqs;
afRegister( &SampleApp_epDesc);
RegisterForKeys( SampleApp_TaskID );
}
还要修改⼀下串⼝相关配置,关闭流控,配置波特率位115200
/*MT_UART.h*/
#if !defined( MT_UART_DEFAULT_OVERFLOW )
// #define MT_UART_DEFAULT_OVERFLOW TRUE
#define MT_UART_DEFAULT_OVERFLOW FALSE //关闭流控
#endif
#if !defined MT_UART_DEFAULT_BAUDRATE
//#define MT_UART_DEFAULT_BAUDRATE HAL_UART_BR_38400
#define MT_UART_DEFAULT_BAUDRATE HAL_UART_BR_115200 //设置波特率
#endif
⑤ 重写串⼝接收回调函数

 

case AF_INCOMING_MSG_CMD:
SampleApp_MessageMSGCB( MSGpkt );
break;
case CMD_SERIAL_MSG: //串⼝回显
mtOSALSerialData_t * UartMsg;
UartMsg = (mtOSALSerialData_t *)MSGpkt;
HalUARTWrite(0,&UartMsg->msg[1],UartMsg->msg[0]);
break;

风扇控制

case CMD_SERIAL_MSG: //串⼝回显
mtOSALSerialData_t * UartMsg;
UartMsg = (mtOSALSerialData_t *)MSGpkt;
FanControl(&UartMsg->msg[1]); //调⽤⻛扇控制

风扇控制函数

#define FAN_ON 0
#define FAN_OFF 1
int FanControl(uint8 * pkt)
{
if(strncmp(pkt,"00",2)==0){
//功能设置寄存器,设置为普通I/O⼝
printf("fan open");
P1DIR |= (1 << 3); //设置为输出模式
P1_3 = FAN_ON;
}else{
P1DIR |= (1 << 3); //设置为输出模式
printf("fan close");
P1_3 = FAN_OFF;
}
return 0;
}

采集电池剩余电量

电池供电模块,怎么能少的了电量的测量,我们本次实验就利⽤ CC2530⾃带的 ADC 控制器
来测量锂电池的电压,并定时通过串⼝打印。
/*adc.h*/
#ifndef __AD_H__
#define __AD_H__
//macro
//#define uint8 unsigned char
//#define uint unsigned int
//#define FAN P1_3
extern void AD_init(void);
extern unsigned char get_volatile(void);
#endif
/*adc.c*/
#include "ad.h"
#include <ioCC2530.h>
//#include "uart.h"
//#include "DHT11.h"
//#include "MT_UART.h"
//#include "Onboard.h"
#include "hal_led.h"
/*
typedef signed char int8;
typedef unsigned char uint8;
typedef signed short int16;
typedef unsigned short uint16;
typedef signed long int32;
typedef unsigned long uint32;
*/
void AD_init(void)
{
APCFG = 0x01; //将P0_0配置为ADC输⼊
ADCIF = 0; //关中断(默认就是关的)
}
uint8 get_volatile(void)
{
// uint8 AdValue=0;
float temp;
uint8 percent = 0;
uint16 voltage = 0;
uint16 voltage_value =0;
ADCCON1 |= 0x30; //⼿动启动ADC
ADCCON3 = 0xB0; //参考电压选择为AVDD5 pin(是电源引脚,为3.3v), 12位分辨
率, 选择通道0
ADCCON1 |= 0x40; //开启ADC转换
while(!(ADCCON1 & 0x80));
/* Get the result in register*/
voltage_value = ADCL >> 4;
voltage_value |= (((uint16) ADCH) << 4);
#if 0
Uart_Send_Char(voltage_value / 10000 + '0');
Uart_Send_Char(voltage_value / 1000 % 10 + '0');
Uart_Send_Char(voltage_value / 100 % 10 + '0');
Uart_Send_Char(voltage_value / 10 % 10 + '0');
Uart_Send_Char(voltage_value % 10 + '0');
#endif

/*get the voltage*/
temp = voltage_value * 3.3 / 2048; //12位,为何2048?
voltage = (uint16)(temp * 100); //扩⼤100倍,假如是2.76v
就是276
if (voltage >= 280) {
voltage = 280;
} else if (voltage <= 234) {
voltage = 234;
} else {
}
/*我们规定最低放电电压为3.51v ,经过分压AD检测到的应该是2.34v*/
/*我们规定最低放电电压为4.20v ,经过分压AD检测到的应该是2.8v*/
//计算百分⽐ 满电的时候是2.8v ,该充电的时候是2.34v, 46是满电280与没电234的差
percent = (voltage - 234) * 100 / 46;
#if 0
Uart_Send_Char(percent / 10 + '0');
Uart_Send_Char(percent % 10 + '0');
#endif
if (percent < 30) {
HalLedBlink( HAL_LED_4, 2, 30, 200);
}
return percent;
}

应用层添加

/*SampleApp.c 添加两全局变量*/
#include "string.h"
volatile uint8 voltage_percent = 0;
uint8 voltage_percent_ascii[4] = {0};
void SampleApp_Init( uint8 task_id )
{
SampleApp_TaskID = task_id;
SampleApp_NwkState = DEV_INIT;
SampleApp_TransID = 0;
MT_UartInit(); //串⼝初始化API
MT_UartRegisterTaskID(task_id); //登记串⼝的任务号,即注册该事
件,注意,该函数必须在MT_UartInit()调⽤之后才调⽤
printf("Uart is ok!\r\n");
AD_init();
/*产⽣⼀个定时事件,准备要开始采集电压*/
osal_start_timerEx( SampleApp_TaskID,START_CAPTURE_VOLTAGE,
SAMPLEAPP_CAPTURE_VOLTAGE_TIMEOUT);
⑥ 在SampleApp.h中添加电压有关宏事件
// adc采样捕获超时溢出时间
#define SAMPLEAPP_CAPTURE_VOLTAGE_TIMEOUT 3000 // Every 5 seconds
//电压事件
#ifndef START_CAPTURE_VOLTAGE
#define START_CAPTURE_VOLTAGE 0x0004
#endif

多节点相互通讯(⽆限透传)

7.1 需求:

pc通过串⼝下发命令到达协调器,协调器负责将命令下发,终端节点解析命令、并执⾏。

需求分析及知识点

(1) 透传顾名思义就是透明传输,透明传输就是在传输过程中,对外界透明,就是说你看不⻅
他是传送⽹络,不管传输的业务如何,我只负责将需要传送的业务传送到⽬的节点,相当于⼀条数
据线或者串⼝线,同时保证传输的质量即可,⽽不对传输的业务进⾏处理。 透传⼀般都是⽤来读取
远程的串⼝数据。在物物相连的物联⽹时代,要想实现智能设备的数据透传就需要仰仗⽆线透传模
块的⼒量,可实现发送⽅和接收⽅数据的⻓度和内容完全⼀致,不需对数据做任何处理,相当于⼀
条数据线或者串⼝线,可⼴泛应⽤在能源电⼒、⾃动抄表、智慧城市、⼯业⾃动化、⻋载交通、环
境监测、设备监控、现代农业等诸多⾏业
(2)ZigBee 协调器模块接收到从 PC 机发送消息,然后将这包数据⽆线发送出去。ZigBee
终端节点接收到 ZigBee协调器发来的消息,然后发送给 PC 机。
协调器和终端分别配置好串口回显
风扇配置好收到命令后的应用逻辑处理函数
a、打开03fan_wireless项⽬的SampleApp.c⽂件(添加应⽤层逻辑处理函
数)
 
/*增加三个功能函数*/
#include "string.h"
//⻛扇的功能处理函数
#define FAN_ON 0
#define FAN_OFF 1
int FanControl(uint8 * pkt)
{
if(strncmp(pkt,"00",2)==0){
//功能设置寄存器,设置为普通I/O⼝
printf("fan open");
P1DIR |= (1 << 3); //设置为输出模式
P1_3 = FAN_ON;
}else{
P1DIR |= (1 << 3); //设置为输出模式
printf("fan close");
P1_3 = FAN_OFF;
}
return 0;
}
//⽹络来数据的⼀个功能处理函数
void SerialData_Analysis(uint8 *msg)
{
if (zgDeviceLogicalType == ZG_DEVICETYPE_ENDDEVICE) {//如果收到⽹络数据的
是终端,则上报温度
FanControl(msg);
} else if (zgDeviceLogicalType == ZG_DEVICETYPE_COORDINATOR) {
//如果设备是协调器设备,则打印⾄串⼝
HalUARTWrite(0, msg, 6);
}
}
//串⼝来数据的⼀个功能处理函数
void SerialData(uint8 *msg)
{
AF_DataRequest( &SampleApp_Periodic_DstAddr,
&SampleApp_epDesc,SAMPLEAPP_PERIODIC_CLUSTERID,*msg,msg +
1,&SampleApp_TransID,AF_DISCV_ROUTE,AF_DEFAULT_RADIUS );
}
b、修改SampleApp.c⽂件内的SampleApp_ProcessEvent事件处理函数。
// Received when a messages is received (OTA) for this endpoint
//当有⽆线消息到来的时候,会产⽣ AF_INCOMING_MSG_CMD 事件,这时我们调⽤
case AF_INCOMING_MSG_CMD:
printf("Cmd_new=%s\n",Cmd_new);
SerialData_Analysis(Cmd_new);
break;
case CMD_SERIAL_MSG: //串⼝回显
mtOSALSerialData_t * UartMsg;
UartMsg = (mtOSALSerialData_t *)MSGpkt;
HalUARTWrite(0,&UartMsg->msg[1],UartMsg->msg[0]);
SerialData(((mtOSALSerialData_t *)MSGpkt)->msg);

温湿度函数的应用处理逻辑

/*增加三个功能函数,记着所有功能函数,都需要提前声明⼀下,不然会报错*/
//获取温度功能函数
void temperture(void)
{
uchar temp[3], humidity[3], strTemp[7];
DHT11(); // 获取温湿度
// 将温湿度的转换成字符串
temp[0] = wendu_shi+0x30;
temp[1] = wendu_ge+0x30;
temp[2] = '\0';
humidity[0] = shidu_shi+0x30;
humidity[1] = shidu_ge+0x30;
humidity[2] = '\0';
// 将数据整合后⽅便发给协调器显示
osal_memcpy(strTemp, temp, 2);
osal_memcpy(&strTemp[2], " ", 2);
osal_memcpy(&strTemp[4], humidity, 3);
// 获得的温湿度通过串⼝输出到电脑显示
HalUARTWrite(0, "T&H:", 4);
HalUARTWrite(0, strTemp, 6);
HalUARTWrite(0, "\n",1);
//将接收到的串⼝数据原封不动地⽆线发送出去
AF_DataRequest( &SampleApp_Periodic_DstAddr, &SampleApp_epDesc,
SAMPLEAPP_PERIODIC_CLUSTERID,
sizeof(strTemp),
strTemp,
&SampleApp_TransID,
AF_DISCV_ROUTE,
AF_DEFAULT_RADIUS );
}
//⽹络来消息后的处理函数
void SerialData_Analysis(uint8 *msg)
{
if (zgDeviceLogicalType == ZG_DEVICETYPE_ENDDEVICE) {//如果收到⽹络数据的
是终端,则上报温度
if(strncmp(msg,"22",2)==0){ //判断是不是收集温
湿度命令
temperture();
}else{
printf("不是发给我的命令");
}
} else if (zgDeviceLogicalType == ZG_DEVICETYPE_COORDINATOR) {
//如果设备是协调器设备,则打印⾄串⼝
HalUARTWrite(0, msg, 6);

//串⼝来消息后的处理函数
void SerialData(uint8 *msg)
{
AF_DataRequest( &SampleApp_Periodic_DstAddr,
&SampleApp_epDesc,SAMPLEAPP_PERIODIC_CLUSTERID,*msg,msg +
1,&SampleApp_TransID,AF_DISCV_ROUTE,AF_DEFAULT_RADIUS );
}
case AF_INCOMING_MSG_CMD:
printf("Cmd_new=%s\n",Cmd_new);
SerialData_Analysis(Cmd_new);
break;
case CMD_SERIAL_MSG: //串⼝回显
mtOSALSerialData_t * UartMsg;
UartMsg = (mtOSALSerialData_t *)MSGpkt;
HalUARTWrite(0,&UartMsg->msg[1],UartMsg->msg[0]);
SerialData(((mtOSALSerialData_t *)MSGpkt)->msg);
break;
// Received whenever the device changes state in the network

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值