实验效果:
采用温湿度传感器模块和ZigBee模块组成一个数字量传感器采集节点,实现温湿度传感器的采集,并将采集数据通过自定义协议无线传输至汇聚节点。发送节点有数据发送时,LED1 亮100毫秒。
任务实施
打开上节课创建的工程。 编写程序(1) 在 sensor.c 中增加头文件
#include "hal_defs.h"
#include "hal_cc8051.h"
#include "hal_int.h"
#include "hal_mcu.h"
#include "hal_board.h"
#include "hal_led.h"
#include "hal_adc.h"
#include "hal_rf.h"
#include "basic_rf.h"
#include "hal_uart.h"
#include "TIMER.h"
#include "get_adc.h"
#include "sh10.h"
#include "UART_PRINT.h"
#include "util.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <math.h>
( 2 ) 新增宏定义,定义点对点通讯地址设置、定义消息格式宏定义、各个数组的大小及
LED 灯闪烁宏。
/*点对点通讯地址设置*/
#define RF_CHANNEL 16 // 频道 11~26
#define PAN_ID 0xD0C2 //网络 id
#define MY_ADDR 0xC2BD //本机模块地址
#define SEND_ADDR 0xB4F3 //发送地址
/* 自定义消息格式 */
#define START_HEAD 0xCC//帧头
#define CMD_READ 0x01//读传感器数据
#define SENSOR_TEMP 0x01//温度
#define SENSOR_RH 0x02//湿度
#define SENSOR_FIRE 0x03//火焰
/* LED n 闪烁 time 毫秒 宏 */
#define FlashLed(n,time) do{\
halLedSet(n);\
halMcuWaitMs(time);\
halLedClear(n);\
}while(0)
/*数组大小*/
#define MAX_SEND_BUF_LEN 128 //无线数据最大发送长度
#define MAX_RECV_BUF_LEN 128 //无线数据最大接收长度
( 3 ) 定义变量和数组。定义 basicRfCfg_t 变量、无线接收和发送缓存数组、定时器
超时标志的变量
static basicRfCfg_t basicRfConfig;
static uint8 pTxData[MAX_SEND_BUF_LEN]; //定义无线发送缓冲区的大小
static uint8 pRxData[MAX_RECV_BUF_LEN]; //定义无线接收缓冲区的大小
uint8 APP_SEND_DATA_FLAG;
(4) 新增计算校验和函数 CheckSum()
/*****************************************************************************************
*函数:uint8 CheckSum(uint8 *buf, uint8 len)
*功能:计算校验和
*输入:uint8 *buf-指向输入缓存区, uint8 len 输入数据字节个数
*输出:无
*返回:返回校验和
*特殊说明:无
*****************************************************************************************/
uint8 CheckSum(uint8 *buf, uint8 len)
{
uint8 temp = 0;
while(len--)
{
temp += *buf;
buf++;
}
return (uint8)temp;
}
( 5 ) 关键函数
① 定时器初 始化函数,主要通过设置 T4CTL 和 T4IE 寄存器完成初始化工作,定时器相
关的函数已经定义在 mylib 文件夹下的 TIMER.c 中。
void Timer4_Init(void)
{
// Set prescaler divider value to 128 (32M/128 = 250KHZ)
T4CTL |= 0xE0;
T4CTL &= ~(0x10); // Stop timer
T4CTL &= ~(0x08); // 禁止溢出中断
T4CTL |= 0x04; //计数器清零
T4IE = 0; // 禁止中断
}
第4行设置定时器的分频值为128分频。
第5行暂停定时器。
第6行禁止计数器溢出中断。
第7行清除计数器。
第8行禁止定时器4中断。
在TIMER.c定义了变量SEND_DATA_FLAG和NUM,需要计时2秒,用于定时采集传感数据,Timer4经过上述函数初始化后,定时器一个节拍是(1/250000)S,8位定时器 的 溢 出 周 期 为 256 个 节 拍 , 每 进 一 次 定 时 器 中 断 就 经 历 :
256*(1/250000)=0.001024秒,这是进一次中断所需要的时间,进1953次中断大约是0.001024*1953≈2s。因此NUM在中断函数中由0累加到1953,则时间经过了
2秒,此时将SEND_DATA_FLAG置1,由此得出中断函数如下。
HAL_ISR_FUNCTION(T4_ISR, T4_VECTOR)
{
T4OVFIF = 0;
T4IF = 0;
NUM ++;
if(NUM == 1953) //计时 2s
{
NUM = 0;
SEND_DATA_FLAG = 1;
Timer4_Off();
}
else
{
SEND_DATA_FLAG = 0;
}
}
② 在 sensor.c 中定义 BasicRF 初始化函数。
void ConfigRf_Init(void)
{
basicRfConfig.panId = PAN_ID; //zigbee 的 ID 号设置
basicRfConfig.channel = RF_CHANNEL; //zigbee 的频道设置
basicRfConfig.myAddr = MY_ADDR; //设置本机地址
basicRfConfig.ackRequest = TRUE; //应答信号
while(basicRfInit(&basicRfConfig) == FAILED); //检测 zigbee 的参数是否配置成功
basicRfReceiveOn(); // 打开 RF
}
(6) 主函数
Main 函数是程序运行的起始位置,运行传感数据采集应用程序前,需要先初始化各个功能模块,halBoardInit()初始化了LED灯、串口、开启总中断,ConfigRf_Init()初始化了无线收发器的初始参数,Timer4_Init()对定时器4进行初始化,完成定时器4的初始化后用Timer4_On()打开定时器4。
初始化完成后需要执行无限循环任务,这个任务就是每隔 2 秒采集传感数据并通过无线通信功能和串口发送出去, basicRfSendPacket()用来发送无线数据, uart_printf()用来往串口打印调试信息,uart_printf()的用法和 printf()一样。用 GetSendDataFlag() 查询APP_SEND_DATA_FLAG的值,每当APP_SEND_DATA_FLAG为1的时候,系统经历了2秒的时间。call_sht11()用来采集温湿度数据,变量sensor_val、sensor_tem分别存放相对湿度和温度。工程源码中使用宏定义“CC2530_DEBUG”来控制是否在串口上打印调试信息。
针对上述功能在sensor.c编写出如下main函数功能代码。
void main(void)
{
halBoardInit(); //模块相关资源的初始化
ConfigRf_Init(); //无线收发参数的配置初始化
Timer4_Init(); //定时器初始化
Timer4_On(); //打开定时器
while(1)
{ APP_SEND_DATA_FLAG = GetSendDataFlag();
if(APP_SEND_DATA_FLAG == 1) //定时时间到
{ /*【传感器采集、处理】 开始*/
uint16 sensor_val,sensor_tem;
call_sht11((unsigned int *)(&sensor_tem),(unsigned int *)(&sensor_val)); //取温湿度数据
#ifdef CC2530_DEBUG
//把采集数据传化成字符串,以便于在串口上显示观察
uart_printf("温湿度传感器,温度:%d℃, 湿度:%d%%\r\n", sensor_tem, sensor_val);
#endif /*CC2530_DEBUG*/
memset(pTxData, '\0', MAX_SEND_BUF_LEN);
pTxData[0]=START_HEAD;//帧头
pTxData[1]=CMD_READ;//命令
pTxData[2]=8;//长度
pTxData[3]=2;//2 组传感数据
pTxData[4]=SENSOR_TEMP;//传感类型
pTxData[5]=sensor_tem;
pTxData[6]=SENSOR_RH;//传感类型
pTxData[7]=sensor_val;
pTxData[8]=CheckSum((uint8 *)pTxData, pTxData[2]); //把数据通过 zigbee 发送出去
basicRfSendPacket((unsigned short)SEND_ADDR, (unsigned char *)pTxData, pTxData[2]+1);
FlashLed(1,100);//无线发送指示,LED1 亮 100ms
Timer4_On(); //打开定时
} /*【传感器采集、处理】 结束*/
}
}
代码分析:
第11-12行,条件编译,通过call_sht11 ()函数用来读取温湿度数据。
第13行,条件编译,用来控制是否编译打印调试信息功能。
第18-26行,将采集的值获取通过自定义协议数据封装。
第28行,把采集数据通过basicRfSendPacket函数发送出去。
第30行,打开定时器。
3. 建立与配置模块设备
(1)建立模块设备
将sensor.c从workspace下的app组中移除,复制Project文件夹下的sensor.c
为副本,并将这个副本重命名为temprh_sensor.c,最后重新添加到workspace下的app 组中。
选择菜单“ProjectàEdit Configurations”,弹出项目的配置对话框,图5-11项目配置对话框所示,系统会检测出项目中存在的模块设备。
单击“New”按钮,在弹出的对话框中输入模块名称为:“temprh_sensor”,基于
Deubg模块进行配置,然后单击“OK”按钮完成模块设备的建立,对话框图5-12温湿度传
感器模块配置对话框所示。在项目配置对话框中就可以自动检测出刚才建立的模块设备
“temprh_sensor”。
图 5-11 项目配置对话框
图 5-12 温湿度传感器模块配置对话框
为了给模块设备设置对应的条件编译参数,在此需要进行如下设置:
在项目工作组中选择“temprh_sensor”模块,单击右键选择“Options”,在弹出的对话框中选择“C/C++ Compile”类别,在右边的窗口中选择“Preprocessor”选项中的
“Definedsymbols:”中输入 “CC2530_DEBUG”,具体设置如图5-13所示。
图 5-13 温湿度传感器模块“Options”设置
4. 编译和下载程序
将插有温湿度传感器模块的 ZigBee 模块固定在 NEWLab 平台,在 Workspace 中选择 “temprh_sensor”模块,编译程序无误后,给NEWLab平台上电,下载程序到ZigBee模块中。
打开串口调试助手,设置波特率为115200后点击,可以看到采集到的温湿度数据显示出来了,如图5-14所示。
图 5-14 程序运行结果
验证通过后,需要把条件编译选项中的“CC2530_DEBUG”去掉,变成 “xCC2530_DEBUG”,如图 5-15 所示。
图 5-15 去掉 CC2530_DEBUG 条件编译选项