Z-stack实训按键单播控制LED

无线传感网络课程 - 实训报告

文章目录

  • 无线传感网络课程 - 实训报告
    • 功能需求
    • 实现过程
      • 终端节点(开关模块)
      • 协调器(灯模块)
    • 试验现象
    • 实训心得

功能需求

基于 Z-Stack 协议栈完成一个 Zigbee 单播通信实验。

例:按键无线控制 LED。

取两块 Zibgee 实验板,当按下终端节点(开关模块)上的 SW2 按键时,向协调器(灯模块)单播发送数据。协调器(灯模块)收到数据后,切换 LED1 状态。

实现过程

  1. 拷贝 SampleApp 工程,并改名为 “按键无线控制LED” 。

  2. 打通串口,程序调试的第一步。

    在 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,关闭流控制。

  3. 修改例程模板,删除不需要的代码。

    删除 LCD 相关的代码以及头文件。

    删除组播相关代码,广播相关代码。

终端节点(开关模块)

  1. 修改 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;
    
  2. 注册按键事件

    RegisterForKeys( SampleApp_TaskID );
    
  3. 根据实际电路,在 hal_board_cfg.h 中配置按键引脚及触发方式
    Z-stack实训按键单播控制LED_第1张图片
    使用电路图中的 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
    
  4. 配置按键采用轮询方式,默认情况下使用轮询方式

    在 InitBorad( OB_READY ); 函数中

    else  // !OB_COLD
      {
        /* Initialize Key stuff */
        HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE, OnBoard_KeyCallback);
      }
    
    • HAL_KEY_INTERRUPT_DISABLE - 采用非中断方式,即轮询方式

    • HAL_KEY_INTERRUPT_ENABLE - 采用中断方式

      中断方式比轮询方式更加灵敏,节省系统资源。

  5. 修改 HalKeyPoll (void) 函数,添加如下代码:

    /* 解决无法设置按键 ACTIVE_LOW 在这里取反 !*/
    /* 原协议栈要将该代码复制到前面去,Z-stack 版本 ZStack-CC2530-2.5.1a */
    if (!HAL_PUSH_BUTTON1())
    {
      keys |= HAL_KEY_SW_6;
    }
    
  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 );
    	}
    }
    
  7. 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.
    	}
    }
    

协调器(灯模块)

  1. 根据实际电路,在 hal_board_cfg.h 中配置LEDs。

    Z-stack实训按键单播控制LED_第2张图片

    • 增加 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))
    
  2. 当无线消息到达时,改变 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;
    }
    }
    

试验现象

左边 协调器(灯模块)右边 终端节点(开关模块)

  • 按下按键前

Z-stack实训按键单播控制LED_第3张图片

  • 按下按键后

Z-stack实训按键单播控制LED_第4张图片
Z-stack实训按键单播控制LED_第5张图片

可见 LED1 点亮

实训心得

  • 应借鉴 Z-stack 的外设驱动程序,利用 OSAL 操作系统,编写符合自己开发板的驱动。
  • Z-stack 代码很简单,一行一行看就行。

你可能感兴趣的:(ZIGBEE技术,物联网,zigbee)