新闻  |   论坛  |   博客  |   在线研讨会
Zigbee基础实验(6)—简单通信编程
luker | 2016-02-25 14:20:08    阅读:461   发布文章
实验中两节点分别充当开关和电灯,通过在开关节点上的操作来控制电灯节点。

源代码:

#include
#include
#include
#include
#include
#include
#include "hal_mcu.h"
#include "hal_button.h"
#include "hal_rf.h"
#include "util_lcd.h"
#include "basic_rf.h"

#define RF_CHANNEL                25      // 信道选择。

// 定义各个参数的值
#define PAN_ID                0x2007           //网络ID
#define SWITCH_ADDR           0x2520  //开关节点的地址
#define LIGHT_ADDR            0xBEEF    //电灯节点的地址
#define APP_PAYLOAD_LENGTH        1   //负载字节的长度,信息的长度。
#define LIGHT_TOGGLE_CMD          0    //被传送的开关命令。

//节点状态。0为空闲
#define IDLE                      0          
#define SEND_CMD                  1

// 定义该节点所承担的任务(开关或电灯)
#define NONE                      0
#define SWITCH                    1
#define LIGHT                     2
#define APP_MODES                 2

static uint8 pTxData[APP_PAYLOAD_LENGTH];     //发送数组
static uint8 pRxData[APP_PAYLOAD_LENGTH];     //接收数组
static basicRfCfg_t basicRfConfig;

// 模式选择菜单
static menuItem_t pMenuItems[] =
{
  "Switch",   SWITCH,
  "Light",    LIGHT
};

static menu_t pMenu =
{
  pMenuItems,
  N_ITEMS(pMenuItems)
};


static void appLight();        //实现电灯功能
static void appSwitch();     //实现远程开关功能
static uint8 appSelectMode(void);  //功能选择

static void appLight()   //实现电灯功能
{
    halLcdWriteLine(HAL_LCD_LINE_1, "Light");
    halLcdWriteLine(HAL_LCD_LINE_2, "Ready");
   
    // 初始化射频模块
    basicRfConfig.myAddr = LIGHT_ADDR;  //网络地址
    if(basicRfInit(&basicRfConfig)==FAILED) {
      HAL_ASSERT(FALSE);  //初始化错误处理
    }
    basicRfReceiveOn();   //打开接收功能。

    //死循环
    while (TRUE) {
        while(!basicRfPacketIsReady());
        if(basicRfReceive(pRxData, APP_PAYLOAD_LENGTH, NULL)0) {   //如果接收到数据
            if(pRxData[0] == LIGHT_TOGGLE_CMD) {
                halLedToggle(1);   //开关改变状态
            }
        }
    }
}

static void appSwitch()  //实现远程开关
{
    halLcdWriteLine(HAL_LCD_LINE_1, "Switch");                    //屏幕输出
    halLcdWriteLine(HAL_LCD_LINE_2, "Joystick Push");
    halLcdWriteLine(HAL_LCD_LINE_3, "Send Command");

    pTxData[0] = LIGHT_TOGGLE_CMD;   //需要发送的数据

    // 初始化
    basicRfConfig.myAddr = SWITCH_ADDR;
    if(basicRfInit(&basicRfConfig)==FAILED) {
      HAL_ASSERT(FALSE);   //出错处理
    }
    basicRfReceiveOff();    //关闭接收机

    // 死循环
    while (TRUE) {
        if( halJoystickPushed() ) {  //当按键按下时触发
            basicRfSendPacket(LIGHT_ADDR, pTxData, APP_PAYLOAD_LENGTH);//发送命令
        }
    }
}

void main(void)
{
    uint8 appMode = NONE; //模式变量
   
    // 设置网络ID和信道
    basicRfConfig.panId = PAN_ID;
    basicRfConfig.channel = RF_CHANNEL;
    basicRfConfig.ackRequest = TRUE;

    //初始化其他设备
    halBoardInit();
    halJoystickInit();

    // 初始化射频模块
    if(halRfInit()==FAILED) {
      HAL_ASSERT(FALSE);
    }

    halLedSet(1); //LED1灯亮,提示节点已上电

    utilPrintLogo("Light Switch");

    // 等待用户按下S1进入菜单
    while (halButtonPushed()!=HAL_BUTTON_1);
    halMcuWaitMs(350);  //延时
    halLcdClear(); //清屏

    // 设置该节点是开关还是电灯
    appMode = appSelectMode();
    halLcdClear();

    // 模块开始工作
    if(appMode == SWITCH) {
        appSwitch();
    }
    else if(appMode == LIGHT) {
        appLight();
    }
    //如果没有定义该节点的功能,则LED灯不断闪烁
    HAL_ASSERT(FALSE);
}

static uint8 appSelectMode(void)      //模式选择
{
    halLcdWriteLine(1, "Device Mode: ");
    return utilMenuSelect(&pMenu);   //通过调用头文件实现功能选择
}

实验总结:
       这个实验虽然功能非常简单,只是通过按下开关节点的按键来控制电灯节点LED的亮或灭,但是通过这个实验可以了解节点间通信的基本思路。
       原代码中有许多可有可无的冗余代码,上面的代码经过代码中很多都是调用头文件,在这里就不在一一罗列,只在代码注释中注明该调用的功能。这些调用都是一些非常简单的操作,写入头文件调用是为了增加代码可读性。

    baseRF通信基本流程
1.初始化网络地址,打开接收机或关闭接收机。
2.初始化basicRfConfig,确定网络ID、信道、是否需要应答、是否采用加密机制等。
3.初始化周边设备,如时钟、各个I/O口等。
4.事件的处理,如发送报文或接受报文后的数据处理等。
参与讨论
登录后参与讨论
推荐文章
最近访客