无线传感网络课程 - 实训报告
功能需求
基于 Z-Stack 协议栈完成一个 Zigbee 单播通信实验。
例:按键无线控制 LED。
取两块 Zibgee 实验板,当按下终端节点(开关模块)上的 SW2 按键时,向协调器(灯模块)单播发送数据。协调器(灯模块)收到数据后,切换 LED1 状态。
实现过程
-
拷贝 SampleApp 工程,并改名为 “按键无线控制LED” 。
-
打通串口,程序调试的第一步。
在 SampleApp.c 中添加头文件
#include "MT_UART.h"
在 SampleApp_Init() 中添加如下代码,向上位机输出"hello world!"
MT_UartInit(); HalUARTWrite ( 0, "hello world!\r\n", osal_strlen("hello world!\r\n") );
波特率 HAL_UART_BR_115200,关闭流控制。
-
修改例程模板,删除不需要的代码。
删除 LCD 相关的代码以及头文件。删除组播相关代码,广播相关代码。
终端节点(开关模块)
-
修改 flash 命令的目标地址 - 单播 0x0000
afAddrType_t SampleApp_Flash_DstAddr; // 单播地址类型 // 设置 flash 命令的目标地址 - 单播 0x0000 SampleApp_Flash_DstAddr.addrMode = (afAddrMode_t)Addr16Bit; SampleApp_Flash_DstAddr.endPoint = SAMPLEAPP_ENDPOINT; SampleApp_Flash_DstAddr.addr.shortAddr = 0x0000;
-
注册按键事件
RegisterForKeys( SampleApp_TaskID );
-
根据实际电路,在 hal_board_cfg.h 中配置按键引脚
及触发方式。
使用电路图中的 SW2 按键,P0_1 引脚,低电平时按键按下。ACTIVE_LOW(出现未知Bug,改为 ACTIVE_LOW 之后 LED 一直闪烁无法组网,改回 ACTIVE_HIGH 后正常)解决方法在步骤5// hal_board_cfg.h 文件中,负责按键宏定义 /* SW6 */ #define PUSH1_BV BV(1) #define PUSH1_SBIT P0_1 // #define PUSH1_POLARITY ACTIVE_LOW #define PUSH1_POLARITY ACTIVE_HIGH // hal_key.c 文件中,负责按键引脚初始化 /* SW_6 is at P0.1 */ #define HAL_KEY_SW_6_PORT P0 #define HAL_KEY_SW_6_BIT BV(1) #define HAL_KEY_SW_6_SEL P0SEL #define HAL_KEY_SW_6_DIR P0DIR
按键编号对应 Z-stack 中的 Button S1,HAL_KEY_SW_6
/* Switches (keys) */ #define HAL_KEY_SW_1 0x01 // Joystick up #define HAL_KEY_SW_2 0x02 // Joystick right #define HAL_KEY_SW_5 0x04 // Joystick center #define HAL_KEY_SW_4 0x08 // Joystick left #define HAL_KEY_SW_3 0x10 // Joystick down #define HAL_KEY_SW_6 0x20 // Button S1 if available #define HAL_KEY_SW_7 0x40 // Button S2 if available
-
配置按键采用轮询方式,默认情况下使用轮询方式
在 InitBorad( OB_READY ); 函数中
else // !OB_COLD { /* Initialize Key stuff */ HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE, OnBoard_KeyCallback); }
-
HAL_KEY_INTERRUPT_DISABLE - 采用非中断方式,即轮询方式
-
HAL_KEY_INTERRUPT_ENABLE - 采用中断方式
中断方式比轮询方式更加灵敏,节省系统资源。
-
-
修改 HalKeyPoll (void) 函数,添加如下代码:
/* 解决无法设置按键 ACTIVE_LOW 在这里取反 !*/ /* 原协议栈要将该代码复制到前面去,Z-stack 版本 ZStack-CC2530-2.5.1a */ if (!HAL_PUSH_BUTTON1()) { keys |= HAL_KEY_SW_6; }
-
在 SampleApp.c 中添加代码,当 Button S1 按下时发送无线消息
void SampleApp_HandleKeys( uint8 shift, uint8 keys ) { (void)shift; // 有意未引用的参数 if ( keys & HAL_KEY_SW_6 ) { HalUARTWrite ( 0, "SW2 pressed!\r\n", osal_strlen("SW2 pressed!\r\n") ); SampleApp_SendFlashMessage(); HalLedSet ( HAL_LED_1, HAL_LED_MODE_TOGGLE ); } }
-
SampleApp_SendFlashMessage
void SampleApp_SendFlashMessage() { if ( AF_DataRequest( &SampleApp_Flash_DstAddr, &SampleApp_epDesc, SAMPLEAPP_FLASH_CLUSTERID, 0, NULL, &SampleApp_TransID, AF_DISCV_ROUTE, AF_DEFAULT_RADIUS ) == afStatus_SUCCESS ) { } else { // Error occurred in request to send. } }
协调器(灯模块)
-
根据实际电路,在 hal_board_cfg.h 中配置LEDs。
- 增加 LED4 引脚定义,代码与其他 LED 一致
/* 1 - Red */ #define LED1_BV BV(1) #define LED1_SBIT P1_1 #define LED1_DDR P1DIR #define LED1_POLARITY ACTIVE_HIGH /* 2 - Green */ #define LED2_BV BV(0) #define LED2_SBIT P1_0 #define LED2_DDR P1DIR #define LED2_POLARITY ACTIVE_HIGH /* 3 - Red */ #define LED3_BV BV(4) #define LED3_SBIT P1_4 #define LED3_DDR P1DIR #define LED3_POLARITY ACTIVE_HIGH /* 4 - NewLand */ #define LED4_BV BV(3) #define LED4_SBIT P1_3 #define LED4_DDR P1DIR #define LED4_POLARITY ACTIVE_HIGH
\ HAL_TURN_OFF_LED1(); \ LED1_DDR |= LED1_BV; \ HAL_TURN_OFF_LED2(); \ LED2_DDR |= LED2_BV; \ HAL_TURN_OFF_LED3(); \ LED3_DDR |= LED3_BV; \ HAL_TURN_OFF_LED4(); \ LED4_DDR |= LED4_BV; \
- 修改 LEDs 宏函数
/* ----------- LED's ---------- */ #define HAL_TURN_OFF_LED1() st( LED1_SBIT = LED1_POLARITY (0); ) #define HAL_TURN_OFF_LED2() st( LED2_SBIT = LED2_POLARITY (0); ) #define HAL_TURN_OFF_LED3() st( LED3_SBIT = LED3_POLARITY (0); ) #define HAL_TURN_OFF_LED4() st( LED4_SBIT = LED4_POLARITY (0); ) #define HAL_TURN_ON_LED1() st( LED1_SBIT = LED1_POLARITY (1); ) #define HAL_TURN_ON_LED2() st( LED2_SBIT = LED2_POLARITY (1); ) #define HAL_TURN_ON_LED3() st( LED3_SBIT = LED3_POLARITY (1); ) #define HAL_TURN_ON_LED4() st( LED4_SBIT = LED4_POLARITY (1); ) #define HAL_TOGGLE_LED1() st( if (LED1_SBIT) { LED1_SBIT = 0; } else { LED1_SBIT = 1;} ) #define HAL_TOGGLE_LED2() st( if (LED2_SBIT) { LED2_SBIT = 0; } else { LED2_SBIT = 1;} ) #define HAL_TOGGLE_LED3() st( if (LED3_SBIT) { LED3_SBIT = 0; } else { LED3_SBIT = 1;} ) #define HAL_TOGGLE_LED4() st( if (LED4_SBIT) { LED4_SBIT = 0; } else { LED4_SBIT = 1;} ) #define HAL_STATE_LED1() (LED1_POLARITY (LED1_SBIT)) #define HAL_STATE_LED2() (LED2_POLARITY (LED2_SBIT)) #define HAL_STATE_LED3() (LED3_POLARITY (LED3_SBIT)) #define HAL_STATE_LED4() (LED4_POLARITY (LED4_SBIT))
-
当无线消息到达时,改变 LED1 状态。
// 无线消息到达时 case AF_INCOMING_MSG_CMD: SampleApp_MessageMSGCB( MSGpkt ); break;
void SampleApp_MessageMSGCB( afIncomingMSGPacket_t *pkt ) { switch ( pkt->clusterId ) { case SAMPLEAPP_FLASH_CLUSTERID: HalLedSet ( HAL_LED_1, HAL_LED_MODE_TOGGLE ); break; } }
试验现象
左边 协调器(灯模块)右边 终端节点(开关模块)
- 按下按键前
- 按下按键后
可见 LED1 点亮
实训心得
- 应借鉴 Z-stack 的外设驱动程序,利用 OSAL 操作系统,编写符合自己开发板的驱动。
- Z-stack 代码很简单,一行一行看就行。