测试内容及流程:
一个终端节点的底板连接两个传感器采集数据并将数据无线发送给协调器, 协调器接收数据后串口打印数据在 PC 上。
Common.h
#ifndef COORDINATOR_H
#define COORDINATOR_H
#include "ZComDef.h"
#define GENERICAPP_ENDPOINT 10
#define GENERICAPP_PROFID 0x0F04
#define GENERICAPP_DEVICEID 0x0001
#define GENERICAPP_DEVICE_VERSION 0
#define GENERICAPP_FLAGS 0
#define GENERICAPP_MAX_CLUSTERS 2
#define GENERICAPP_CLUSTERID 1
#define GENERICAPP_GUANGMIN_ID 2
/*此处要特别留意这三个参数: GENERICAPP_MAX_CLUSTERS 表示最大簇数量, 此处有
GENERICAPP_CLUSTERID 和 GENERICAPP_GUANGMIN_ID 两个簇 ID, 分别表示温湿度的簇 ID
和光敏传感器的簇 ID,(将簇 ID 理解为数据包, 一个是温湿度传感器的数据包 ID 号, 一个
是光敏传感器的数据包 ID 号, 最大数据包数量为 2) */
extern void GenericApp_Init(byte task_id);
extern UINT16 GenericApp_ProcessEvent(byte task_id,UINT16 events);
#endif
Coordinator.c
#include "OSAL.h"
#include "AF.h"
#include "ZDApp.h"
#include "ZDObject.h"
#include "ZDProfile.h"
#include
#include "Common.h"
#include "DebugTrace.h"
#if !defined( WIN32 )
#include "OnBoard.h"
#endif
#include "hal_lcd.h"
#include "hal_led.h"
#include "hal_key.h"
#include "hal_uart.h"
#include "DHT11.h"//温湿度
#include "GuangMin.h"//光敏强度
/*包含两个传感器的头文件*/
const cId_t GenericApp_ClusterList[GENERICAPP_MAX_CLUSTERS] =
{
GENERICAPP_CLUSTERID, //温湿度的簇ID
GENERICAPP_GUANGMIN_ID //光敏传感器数据包ID
/*最大簇数量两个, 分别是温湿度和光敏电阻传感器的簇 ID*/
};
const SimpleDescriptionFormat_t GenericApp_SimpleDesc =
{
GENERICAPP_ENDPOINT,
GENERICAPP_PROFID,
GENERICAPP_DEVICEID,
GENERICAPP_DEVICE_VERSION,
GENERICAPP_FLAGS,
GENERICAPP_MAX_CLUSTERS,
(cId_t *)GenericApp_ClusterList,
0,
(cId_t *)NULL
};
endPointDesc_t GenericApp_epDesc; //定义节点描述符GenericApp_epDesc
byte GenericApp_TaskID; //定义任务优先级GenericApp_TaskID
byte GenericApp_TransID; //定义数据发送序列号GenericApp_TransID
void GenericApp_MessageMSGCB(afIncomingMSGPacket_t *pckt); //声明消息处理函数
//void GenericApp_SendTheMessage(void); //声明数据发送函数
void GenericApp_Init( byte task_id ) //任务初始化函数,格式较为固定
{
halUARTCfg_t uartConfig;
GenericApp_TaskID = task_id; //初始化了任务优先级
GenericApp_TransID = 0; //将发送数据包的序列号初始化为0
GenericApp_epDesc.endPoint = GENERICAPP_ENDPOINT;
GenericApp_epDesc.task_id = &GenericApp_TaskID;
GenericApp_epDesc.simpleDesc
= (SimpleDescriptionFormat_t *)&GenericApp_SimpleDesc;
GenericApp_epDesc.latencyReq = noLatencyReqs;
afRegister( &GenericApp_epDesc );
/*任务初始化的格式是相对固定的, 基本上不需要大改动, 需要串口显示在 PC 上就配置串
口并在此函数内将其初始化*/
uartConfig.configured = TRUE;
uartConfig.baudRate = HAL_UART_BR_115200;
uartConfig.flowControl = FALSE;
uartConfig.callBackFunc = NULL;
HalUARTOpen(0,&uartConfig);
}
UINT16 GenericApp_ProcessEvent(byte task_id,UINT16 events)
{
afIncomingMSGPacket_t *MSGpkt;
if(events & SYS_EVENT_MSG)
{
MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive(GenericApp_TaskID);
while(MSGpkt)
{
switch(MSGpkt->hdr.event)
{
case AF_INCOMING_MSG_CMD:
GenericApp_MessageMSGCB(MSGpkt); //调用消息处理函数
break;
default:
break;
}
osal_msg_deallocate((uint8 *)MSGpkt);
MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive(GenericApp_TaskID);
}
return(events ^ SYS_EVENT_MSG);
}
return 0;
}
void GenericApp_MessageMSGCB(afIncomingMSGPacket_t *pkt)
{
/*此函数是协调器的消息处理函数*/
switch(pkt->clusterId)
{
case GENERICAPP_CLUSTERID:
HalUARTWrite(0, "T&H:", 4);
HalUARTWrite(0,pkt->cmd.Data,pkt->cmd.DataLength);
HalUARTWrite(0,"\n",1);
HalLedBlink(HAL_LED_1,0,50,500);
break;
/*如果协调器接收到温湿度的簇 ID 就执行相应的操作, 若是接收到光敏传感器的簇 ID 就
执行另外的操作(此处都是将接收到的数据串口打印在 PC 上)。
(对于 cluster 的翻译业界主流的叫法是集群或者簇, 叫簇的多一些, 所谓的簇 ID 跟数据包
ID 号一样的意思, 终端节点的某个传感器采集到的信号将其打包并且赋予数据包一个 ID 号,
终端节点将带有 ID 号的数据包发送给协调器, 协调器根据接收到的数据包 ID 号才知道是哪
个传感器的数据再决定做何处理, 在终端节点有多个传感器采集多种数据的时候, 簇 ID(理
解为数据包 ID) 是必须赋予的, 不然得到的数据没有对应 ID 号给它排队被接收会造成混乱)
*/
case GENERICAPP_GUANGMIN_ID:
HalUARTWrite(0,pkt->cmd.Data,pkt->cmd.DataLength); //输出接收到的数据
HalUARTWrite(0,"\n",1);
HalLedBlink(HAL_LED_2,0,50,500);//LED 2闪烁
break;
}
}
EndDevice.c
#include "OSAL.h"
#include "AF.h"
#include "ZDApp.h"
#include "ZDObject.h"
#include "ZDProfile.h"
#include
#include "Common.h"
#include "DebugTrace.h"
#if !defined( WIN32 )
#include "OnBoard.h"
#endif
#include "hal_lcd.h"
#include "hal_led.h"
#include "hal_key.h"
#include "hal_uart.h"
#include "DHT11.h"//温湿度
#include "GuangMin.h"//光敏强度
#define Send_All_Event 0x01 //定义事件
const cId_t GenericApp_ClusterList[GENERICAPP_MAX_CLUSTERS] =
{
GENERICAPP_CLUSTERID, //温湿度的簇ID
GENERICAPP_GUANGMIN_ID //光敏传感器数据包ID
};
const SimpleDescriptionFormat_t GenericApp_SimpleDesc =
{
GENERICAPP_ENDPOINT,
GENERICAPP_PROFID,
GENERICAPP_DEVICEID,
GENERICAPP_DEVICE_VERSION,
GENERICAPP_FLAGS,
0,
(cId_t *)NULL,
GENERICAPP_MAX_CLUSTERS,
(cId_t *)GenericApp_ClusterList,
};
endPointDesc_t GenericApp_epDesc;
byte GenericApp_TaskID;
byte GenericApp_TransID;
devStates_t GenericApp_NwkState; //存储网络状态
void GenericApp_MessageMSGCB(afIncomingMSGPacket_t *pckt);
void GenericApp_SendThe_DHT11_Message(void);
void GenericApp_SendThe_GuangMin_Message(void);
void DHT11(void);//温湿度写入
void GenericApp_Init( byte task_id )
{
GenericApp_TaskID = task_id;
GenericApp_NwkState = DEV_INIT; //网络状态初始化
GenericApp_TransID = 0;
//P0SEL &= 0x7f; //P0_7配置成通用io
P0SEL &= 0x5f; //P0.5,P0.7配置成通用IO
GenericApp_epDesc.endPoint = GENERICAPP_ENDPOINT;
GenericApp_epDesc.task_id = &GenericApp_TaskID;
GenericApp_epDesc.simpleDesc
= (SimpleDescriptionFormat_t *)&GenericApp_SimpleDesc;
GenericApp_epDesc.latencyReq = noLatencyReqs;
afRegister( &GenericApp_epDesc );
}
UINT16 GenericApp_ProcessEvent(byte task_id,UINT16 events)
{
afIncomingMSGPacket_t *MSGpkt;
if(events & SYS_EVENT_MSG)
{
MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive(GenericApp_TaskID);
while(MSGpkt)
{
switch(MSGpkt->hdr.event)
{
case ZDO_STATE_CHANGE:
GenericApp_NwkState = (devStates_t)(MSGpkt->hdr.status);
if(GenericApp_NwkState == DEV_END_DEVICE)
{
osal_set_event(GenericApp_TaskID,Send_All_Event);
}
break;
default:
break;
}
osal_msg_deallocate((uint8 *)MSGpkt);
MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive(GenericApp_TaskID);
}
return(events ^ SYS_EVENT_MSG);
}
if(events & Send_All_Event);
{
GenericApp_SendThe_DHT11_Message();
GenericApp_SendThe_GuangMin_Message();
osal_start_timerEx(GenericApp_TaskID,Send_All_Event,1000);
return(events ^ Send_All_Event);
}
return 0;
}
void GenericApp_SendThe_DHT11_Message(void)
{
//温湿度传感器
byte temp[3], humidity[3], strTemp[7];
DHT11(); //获取温湿度
//将温湿度的转换成字符串,供LCD显示
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_memset(strTemp,0,7); //数组初始化
osal_memcpy(&strTemp[0], 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);
afAddrType_t my_DstAddr;
my_DstAddr.addrMode = (afAddrMode_t)Addr16Bit;
my_DstAddr.endPoint = GENERICAPP_ENDPOINT;
my_DstAddr.addr.shortAddr = 0x0000;
AF_DataRequest(&my_DstAddr,
&GenericApp_epDesc,
GENERICAPP_CLUSTERID, //温湿度的簇ID
7, //计算长度
strTemp,
&GenericApp_TransID,
AF_DISCV_ROUTE,
AF_DEFAULT_RADIUS);
HalLedBlink(HAL_LED_2,0,50,500);
}
/*之前的实验都是终端节点采集一个传感器的信号并无线发送给协调器, 所以我们调用
AF_DataRequest()函数写程序的时候只需要留意数据长度和数据缓冲区就可以了, 其他的参
数都可以默认。 但这次我们终端是有两个传感器采集数据, 需要修改另外两个参数:
xxx_DstAddr 和 xxx_ID, 即发送的地址和簇 ID 将两个传感器采集的数据区分开来发送*/
void GenericApp_SendThe_GuangMin_Message(void)
{
char str[9];
uint16 value; //存储光敏强度数值
osal_memset(str,0,9); //数组初始化
value = ReadLightData(); //读取光强数据
osal_memcpy(str, "BRI:", 4);
str[4] = value / 100 + '0';
str[5] =value / 10%10 + '0';
str[6] = value % 10 + '0';
str[7] = ' ';
afAddrType_t GuangMin_DstAddr;
GuangMin_DstAddr.addrMode = (afAddrMode_t)Addr16Bit;
GuangMin_DstAddr.endPoint = GENERICAPP_ENDPOINT;
GuangMin_DstAddr.addr.shortAddr = 0x0000;
AF_DataRequest(&GuangMin_DstAddr, //发送的地址,光敏
&GenericApp_epDesc,
GENERICAPP_GUANGMIN_ID,//光敏传感器数据包ID号
8,
(uint8 *)str,
&GenericApp_TransID,
AF_DISCV_ROUTE,
AF_DEFAULT_RADIUS);
HalLedBlink(HAL_LED_1,0,50,500);//LED1闪烁
}
土壤湿度检测传感器和光敏电阻传感器是一样的源程序代码, 这两个传感器需要一起用
的时候注意管脚配置就好了, 同理, 要使用多个传感器采集数据的时候, 除了管脚配置不要
冲突外, 还要给数据包赋予簇 ID 号。 这个很重要!!!
DHT11.h
#ifndef __DHT11_H__
#define __DHT11_H__
#define uchar unsigned char
extern void Delay_ms(unsigned int xms); //延时函数
extern void COM(void); // 温湿写入
extern void DHT11(void); //温湿传感启动
extern uchar temp[2];
extern uchar temp1[5];
extern uchar humidity[2];
extern uchar humidity1[9];
extern uchar shidu_shi,shidu_ge,wendu_shi,wendu_ge;
#endif
DHT11.c
#include
#include "OnBoard.h"
typedef unsigned char uchar;
typedef unsigned int uint;
#define DATA_PIN P0_7 //使用端口:P0_7
void Delay_us(void); //1微秒延时
void Delay_10us(void); //10微秒延时
void Delay_ms(uint Time); //n毫秒延时
void COM(void); // 温湿写入
void DHT11(void); //温湿传感启动
//温湿度定义
uchar ucharFLAG,uchartemp;
uchar shidu_shi,shidu_ge,wendu_shi,wendu_ge=4;
uchar ucharT_data_H,ucharT_data_L,ucharRH_data_H,ucharRH_data_L,ucharcheckdata;
uchar ucharT_data_H_temp,ucharT_data_L_temp,ucharRH_data_H_temp,ucharRH_data_L_temp,ucharcheckdata_temp;
uchar ucharcomdata;
//延时函数
void Delay_us(void) //1 us延时
{
MicroWait(1);
}
void Delay_10us(void) //10 us延时
{
MicroWait(10);
}
void Delay_ms(uint Time)//n ms延时
{
unsigned char i;
while(Time--)
{
for(i=0;i<100;i++)
Delay_10us();
}
}
//温湿度传感
void COM(void) // 温湿写入
{
uchar i;
for(i=0;i<8;i++)
{
ucharFLAG=2;
while((!DATA_PIN)&&ucharFLAG++);
Delay_10us();
Delay_10us();
Delay_10us();
uchartemp=0;
if(DATA_PIN)uchartemp=1;
ucharFLAG=2;
while((DATA_PIN)&&ucharFLAG++);
if(ucharFLAG==1)break;
ucharcomdata<<=1;
ucharcomdata|=uchartemp;
}
}
void DHT11(void) //温湿传感启动
{
DATA_PIN=0;
Delay_ms(19); //>18MS
DATA_PIN=1;
P0DIR &= ~0x80; //重新配置IO口方向 P0DIR = 0111 1111即P0_7端口方向设置为输入
Delay_10us();
Delay_10us();
Delay_10us();
Delay_10us();
if(!DATA_PIN)
{
ucharFLAG=2;
while((!DATA_PIN)&&ucharFLAG++);
ucharFLAG=2;
while((DATA_PIN)&&ucharFLAG++);
COM();//调用温湿度写入函数
ucharRH_data_H_temp=ucharcomdata;//湿度数据高位temp
COM();
ucharRH_data_L_temp=ucharcomdata;//湿度数据低位temp
COM();
ucharT_data_H_temp=ucharcomdata;//温度数据高位temp
COM();
ucharT_data_L_temp=ucharcomdata;//温度数据低位temp
COM();
ucharcheckdata_temp=ucharcomdata;//校验和temp
DATA_PIN=1;
uchartemp=(ucharT_data_H_temp+ucharT_data_L_temp+ucharRH_data_H_temp+ucharRH_data_L_temp);//temp=温度数据高位temp+温度数据低位temp+湿度数据高位temp+湿度数据低位temp
if(uchartemp==ucharcheckdata_temp)//temp = 校验和temp
{
ucharRH_data_H=ucharRH_data_H_temp;//湿度数据高位 = 湿度数据高位temp
ucharRH_data_L=ucharRH_data_L_temp;//湿度数据低位 = 湿度数据低位temp
ucharT_data_H=ucharT_data_H_temp;//温度数据高位 = 温度数据高位temp
ucharT_data_L=ucharT_data_L_temp;//温度数据低位 = 温度数据低位temp
ucharcheckdata=ucharcheckdata_temp;//校验和 = 校验和temp
}
wendu_shi=ucharT_data_H/10; //温度十位
wendu_ge=ucharT_data_H%10; //温度个位
shidu_shi=ucharRH_data_H/10; //湿度十位
shidu_ge=ucharRH_data_H%10; //湿度个位
}
else //没有成功读取,返回0
{
wendu_shi=0;
wendu_ge=0;
shidu_shi=0;
shidu_ge=0;
}
P0DIR |= 0x80; //IO口需要重新配置
}
GuangMin.h
#ifndef __GuangMin_H__
#define __GuangMin_H__
extern uint16 ReadLightData(void);//读取光强数据
#endif
GuangMin.c
#include
#include "OnBoard.h"
#define HAL_ADC_DEC_064 0x00 /* Decimate by 64 : 8-bit resolution */
#define HAL_ADC_DEC_128 0x10 /* Decimate by 128 : 10-bit resolution */
#define HAL_ADC_DEC_256 0x20 /* Decimate by 256 : 12-bit resolution */
#define HAL_ADC_DEC_512 0x30 /* Decimate by 512 : 14-bit resolution */
#define HAL_ADC_DEC_BITS 0x30 /* Bits [5:4] */
#define HAL_ADC_CHANNEL_5 0x05 //在这里定义端口,使用端口:P0_5 ???
uint16 ReadLightData(void);
//读取光敏强度数据:
uint16 ReadLightData( void )
{
uint16 reading = 0;
P0DIR &= ~0x20; // 设置P0.5为输入方式
asm("NOP");asm("NOP");
/* Clear ADC interrupt flag */
ADCIF = 0;
ADCCON3 = (0x80 | HAL_ADC_DEC_064 | HAL_ADC_CHANNEL_5);
/* Wait for the conversion to finish */
while ( !ADCIF );
asm("NOP");asm("NOP");
/* Read the result */
reading = ADCL;
reading |= (int16) (ADCH << 8);
reading >>= 8;
return reading;
}