在ZIGBEE协议栈中已经自带了按键与LED的驱动与使用函数,所以只需要将按键与LED修改为使用的开发板所连接IO就可以使用了。接下来将主要分析在协议栈中按键的初始化、按键的检测以及按键事件的传递与处理。按键流程分析过后,着手于无线数据传输,而协议栈已经写好了无线广播,只需要直接调用就可以使用了。

1、修改LED灯IO

由于协议栈中按键与LED所配置IO口与使用的开发板不同,所以需要对按键LED的IO口进行修改。

在协议栈ZMain.c文件中的main函数中找到函数HAL_BOARD_INIT(),右键go to进入该函数,可以看到关于LED的配置,由于本实验使用的开发板只有两个LED,所以我们只需要修改LED1、LED2的IO口就可以了。同样的,利用右键找到LED底层定义的地方(文件)hal_board_cfg.h中,将其修改如下:

/* 1 - Green */
#define LED1_BV           BV(3) // BV(0)改为BV(3)
#define LED1_SBIT         P1_3  // P1_0改为P1_3
#define LED1_DDR          P1DIR
#define LED1_POLARITY     ACTIVE_HIGH/* 2 - Red */
#define LED2_BV           BV(2) // BV(1)改为BV(2)
#define LED2_SBIT         P1_2 // P1_1改为P1_2
#define LED2_DDR          P1DIR
#define LED2_POLARITY     ACTIVE_HIGH

LED的开与关也需要进行修改,原理同不带协议栈的无线点灯实验。在函数HAL_BOARD_INIT()中,右键进入HAL_TURN_OFF_LED1()中,可以找到两个LED的开关定义,修改如下:

#define HAL_TURN_OFF_LED1()       st( LED1_SBIT = LED1_POLARITY (1); ) // 括号中0改为1
#define HAL_TURN_OFF_LED2()       st( LED2_SBIT = LED2_POLARITY (1); ) // 括号中0改为1
#define HAL_TURN_OFF_LED3()       st( LED3_SBIT = LED3_POLARITY (0); )
#define HAL_TURN_OFF_LED4()       HAL_TURN_OFF_LED1()#define HAL_TURN_ON_LED1()        st( LED1_SBIT = LED1_POLARITY (0); ) // 括号中1改为0
#define HAL_TURN_ON_LED2()        st( LED2_SBIT = LED2_POLARITY (0); ) // 括号中1改为0
#define HAL_TURN_ON_LED3()        st( LED3_SBIT = LED3_POLARITY (1); )
#define HAL_TURN_ON_LED4()        HAL_TURN_ON_LED1()

2、按键IO修改与流程分析

在main函数中找到函数HalDriverInit(),右键进入其中,可以看到有很多外设的初始化,其他的在这里我们都不关心,我们只关注按键KEY,找到KEY的初始化函数右键进入其中,KEY_SW_6即为接下来我们要用的按键 ,JOY为摇杆按键,我们用不到,不用关心或者注释掉。右键进入到HAL_KEY_SW_6_SEL定义的地方,进行如下修改:

/* SW_6 is at P1.1 */
#define HAL_KEY_SW_6_PORT   P1 // P0改为P1
#define HAL_KEY_SW_6_BIT    BV(1)
#define HAL_KEY_SW_6_SEL    P1SEL // P0SEL改为P1SEL
#define HAL_KEY_SW_6_DIR    P1DIR // P0DIR改为P1DIR
/* SW_6 interrupts */
#define HAL_KEY_SW_6_IEN      IEN2  // IEN1改为IEN2
#define HAL_KEY_SW_6_IENBIT   BV(5) // 5改为4 IEN2第4位P1中断
#define HAL_KEY_SW_6_ICTL     P1IEN // P0IEN改为P1IEN
#define HAL_KEY_SW_6_ICTLBIT  BV(1) /* P1EN – P1.1 enable/disable bit */
#define HAL_KEY_SW_6_PXIFG    P1IFG /* Interrupt flag at source */

按键初始化后, InitBoard( OB_READY )用来配置按键触发方式以及按键的回调函数,如下:

/********************************************************************** @fn      InitBoard()* @brief   Initialize the CC2420DB Board Peripherals* @param   level: COLD,WARM,READY* @return  None*/
void InitBoard( uint8 level )
{if ( level == OB_COLD ){// IAR does not zero-out this byte below the XSTACK.*(uint8 *)0x0 = 0;// Interrupts offosal_int_disable( INTS_ALL );// Check for Brown-Out resetChkReset();}else  // !OB_COLD{/* Initialize Key stuff */// 配置为按键中断不使能,扫描触发        回调函数HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE, OnBoard_KeyCallback);}
}

进入HalKeyConfig函数中,根据所传参数HAL_KEY_INTERRUPT_DISABLE,中断不使能的话,就会配置为定时检测,这个时候会触发HAL_KEY_EVENT事件:

else    /* Interrupts NOT enabled */{HAL_KEY_SW_6_ICTL &= ~(HAL_KEY_SW_6_ICTLBIT); /* don't generate interrupt */HAL_KEY_SW_6_IEN &= ~(HAL_KEY_SW_6_IENBIT);   /* Clear interrupt enable bit */osal_set_event(Hal_TaskID, HAL_KEY_EVENT); // 触发HAL_KEY_EVENT事件}

这个事件将会在HAL层事件处理函数中被处理,在OSAL_SampleApp.c文件中找到HAL层事件处理函数Hal_ProcessEvent,进入其中,可以看到这样一个判断:

if (events & HAL_KEY_EVENT) // HAL_KEY_EVENT事件{#if (defined HAL_KEY) && (HAL_KEY == TRUE)/* Check for keys */HalKeyPoll(); // 检测按键/* if interrupt disabled, do next polling */if (!Hal_KeyIntEnable){osal_start_timerEx( Hal_TaskID, HAL_KEY_EVENT, 100);}
#endif // HAL_KEYreturn events ^ HAL_KEY_EVENT;}

如果判断成功,就会调用HalKeyPoll()对按键进行扫描,进入这个扫描函数,函数前一部分都是跟摇杆按键有关的,可以直接删除或者注释,或者将下部分对KEY_SW_6按键的判断放在前面,不然会影响按键的检测,如下:

/*************************************************************************************************** @fn      HalKeyPoll** @brief   Called by hal_driver to poll the keys** @param   None** @return  None**************************************************************************************************/
void HalKeyPoll (void)
{uint8 keys = 0;if (HAL_PUSH_BUTTON1()) // 按键检测判断{keys |= HAL_KEY_SW_6;}/* Invoke Callback if new keys were depressed */if (keys && (pHalKeyProcessFunction)){(pHalKeyProcessFunction) (keys, HAL_KEY_STATE_NORMAL); // 调用回调函数}
}

由于官方板按键按下去是高电平,所以检测if判断里读取按键状态的函数需要进行修改,右键goto之后,将PUSH1_POLARITY的定义以及PUSH1_SBIT的定义进行修改,如下:

/* S1 */
#define PUSH1_BV          BV(1)
#define PUSH1_SBIT        P1_1 // P0_1 改为 P1_1
#define PUSH1_POLARITY    ACTIVE_LOW // ACTIVE_HIGH改为ACTIVE_LOW

最后函数调用按键回调函数将按键检测值传进去,又回到了一开始初始化时配置的回调函数。在回调函数OnBoard_KeyCallback()中,我们并不会在这里对按键事件进行处理,而是通过函数OnBoard_SendKeys( keys, shift )将检测值又传递到了其他地方,如下:

/********************************************************************** @fn      OnBoard_SendKeys** @brief   Send "Key Pressed" message to application.** @param   keys  - keys that were pressed*          state - shifted** @return  status*********************************************************************/
uint8 OnBoard_SendKeys( uint8 keys, uint8 state )
{keyChange_t *msgPtr;if ( registeredKeysTaskID != NO_TASK_ID ){// Send the address to the taskmsgPtr = (keyChange_t *)osal_msg_allocate( sizeof(keyChange_t) );if ( msgPtr ){msgPtr->hdr.event = KEY_CHANGE; // 按键事件msgPtr->state = state;msgPtr->keys = keys;osal_msg_send( registeredKeysTaskID, (uint8 *)msgPtr ); // 把事件发往绑定的任务}return ( ZSuccess );}elsereturn ( ZFailure );
}

在这个函数里,又将按键检测值标记为KEY_CHANGE事件,通过osal_msg_send()函数将事件打包发给了registeredKeysTaskID任务,registeredKeysTaskID为任务号,通过RegisterForKeys()进行注册,注册在APP层里面,现在我们去APP层的初始化任务中查找一下,可以通过osal_init_system()函数找到osalInitTasks()函数,在任务初始化函数中调用了APP层的初始化函数,在SampleApp_Init()中调用了RegisterForKeys(),把按键事件绑定在了APP层,如下:

// Register for all key events - This app will handle all key eventsRegisterForKeys( SampleApp_TaskID ); // 这句代码在SampleApp_Init()中

所以按键事件最后会到达APP层,被APP层事件处理函数处理,如下图:

最后如果事件判断成功,就会调用SampleApp_HandleKeys()函数,在这个函数中,我们就可以对按键事件作出相应,比如接下来我们要做的,通过调用无线发送函数,发送一个数据,如下:

void SampleApp_HandleKeys( uint8 shift, uint8 keys )
{(void)shift;  // Intentionally unreferenced parameterif(keys & HAL_KEY_SW_6){SampleApp_SendPeriodicMessage(); // 广播发送一个数据}
}

在广播发送函数中,将会发送出去一个0,如下:

void SampleApp_SendPeriodicMessage( void )
{if ( AF_DataRequest( &SampleApp_Periodic_DstAddr, &SampleApp_epDesc,SAMPLEAPP_PERIODIC_CLUSTERID, // 数据类型ID 现在为表示广播1, // 发送数据长度(uint8*)&SampleAppPeriodicCounter, // 发送数据的地址 变量值为0&SampleApp_TransID,AF_DISCV_ROUTE,AF_DEFAULT_RADIUS ) == afStatus_SUCCESS ){}else{// Error occurred in request to send.}
}

3、LED灯响应

发送部分完成之后,再来看接收部分。小灯响应部分比较简单,首先需要关注数据的来源,来源就是无线广播接收,这个事件的处理也在APP层事件处理函数中,如图:

在事件处理函数中,会调用SampleApp_MessageMSGCB( MSGpkt )函数对接到的数据包进行处理,判断如果接到的数据为0,即为接收正确,就可以让小灯响应了,如下:

void SampleApp_MessageMSGCB( afIncomingMSGPacket_t *pkt )
{uint16 flashTime;switch ( pkt->clusterId ){case SAMPLEAPP_PERIODIC_CLUSTERID: // 判断为广播数据if( *pkt->cmd.Data == 0) // 从数据包中找到用户数据{HalLedSet(1,HAL_LED_MODE_TOGGLE); // 切换LED的状态}break;case SAMPLEAPP_FLASH_CLUSTERID:flashTime = BUILD_UINT16(pkt->cmd.Data[1], pkt->cmd.Data[2] );HalLedBlink( HAL_LED_4, 4, 50, (flashTime / 4) );break;}
}

从数据包中找到用户数据有必要说明一下,首先函数传进来的参数类型为afIncomingMSGPacket_t,这个结构体内存放了所有的数据,如下:

typedef struct
{osal_event_hdr_t hdr;     /* OSAL Message header */uint16 groupId;           /* Message's group ID - 0 if not set */uint16 clusterId;         /* Message's cluster ID */afAddrType_t srcAddr;     /* Source Address, if endpoint is STUBAPS_INTER_PAN_EP,it's an InterPAN message */uint16 macDestAddr;       /* MAC header destination short address */uint8 endPoint;           /* destination endpoint */uint8 wasBroadcast;       /* TRUE if network destination was a broadcast address */uint8 LinkQuality;        /* The link quality of the received data frame */uint8 correlation;        /* The raw correlation value of the received data frame */int8  rssi;               /* The received RF power in units dBm */uint8 SecurityUse;        /* deprecated */uint32 timestamp;         /* receipt timestamp from MAC */uint8 nwkSeqNum;          /* network header frame sequence number */afMSGCommandFormat_t cmd; /* Application Data 用户数据*/
} afIncomingMSGPacket_t;

这个结构体里面又包含了一个结构体afMSGCommandFormat_t,这个结构体用于存放用户数据,如下:

typedef struct
{uint8   TransSeqNumber;uint16  DataLength; // Number of bytes in TransDatauint8  *Data; // 数据
} afMSGCommandFormat_t;

而我们通过无线发送的数据就在以Data为首地址的内存中。

实验完成,将程序分别下载到协调器和终端节点。点击协调器的按键,终端节点的LED状态会随之切换。

ZIGBEE通讯-10.ZigBee协议栈的无线点灯相关推荐

  1. ZIGBEE通讯-7.ZigBee协议栈简介

    想要学习协议栈,必须先知道协议是什么.协议定义的是一系列的通信标准,通信双方需要共同按照这一标准进行正常的数据收发,而协议栈是协议的具体实现形式,通俗的理解为用代码实现的函数库,以便于开发人员调用. ...

  2. Zigbee 学习计划——第4天——基于CC2530 Basic RF的无线点灯

    就像Hellow world一样,无线点灯也是Zigbee的经典例子.根据<网蜂实战演练>中介绍,虽然还没有用到协议栈,但它体现出来的数据发送.接收和用协议栈是差不多的,而且TI公司的Ba ...

  3. zigbee无线传感网技术与应用开发v2.0_物联网通讯协议——Zigbee

    一.什么是Zigbee ZigBee是一种新兴的短距离.低速率无线网络技术.具有成本低.体积小.能量消耗小和传输速率低等优势. ZigBee是介于无线标识技术和蓝牙之间的一种技术,主要用于近距离无线连 ...

  4. ZigBee远程无线点灯

    ZigBee远程无线点灯 一.任务要求: 二.任务逻辑分析: 三.逻辑代码实现: 四.开发中注意的事项: 一.任务要求: 大棚种植区改造过程中提出新的需求,要求部分设备需要支持短距离无线 通讯控制风扇 ...

  5. Zigbee通讯之开发篇(基于TI 的Z-Stack)

    1.Zigbee协议和Z-Stack   Zigbee协议和Z-Stack是什么关系?这可能是初学Zigbee同学想知道的问题.给大家举个例子吧,我们生活中使用的插排是要符合一定的标准的,现在国家标准 ...

  6. Zigbee通讯漫谈(初次见面)

    郑重声明:以下文章内容适合初学Zigbee的童鞋们,大神请略过-- 1 缘由:   工作中听说过Zigbee技术,只是知道是一种无线通讯技术,具体技术细节及使用都不是很清楚.不料,一个项目中需要使用Z ...

  7. zigbee通讯技术复习笔记

    这门课对于我一个学嵌入式的来说,还是比较重要的,所以我还是以老师给出的大纲为主体,好好复习一下! 题型:选择题24x1.5 判断10x1 填空15x1 简答4x5 程序1x5 另外一个设计题1x14 ...

  8. 【ember zigbee】序章:协议栈相关文档学习笔记

    原文地址:https://blog.csdn.net/tainjau/article/details/90648114 文章目录 写在前面 一.材料出处 二.文档解析 2.1.EZSP Protoco ...

  9. zigbee zcl规范及其协议栈实现3 读取服务器端属性值

    zigbee zcl规范及其协议栈实现2   中有介绍 对通用命令的处理,按照那个思路和信息流程添加读取服务器端属性值的功能 客户端samplesw想要知道与自己的12号端点SAMPLESW_ENDP ...

最新文章

  1. 脑细胞膜等效神经网路
  2. JMeter入门,测试计划编写(http请求)
  3. [C++11]自动类型推导auto
  4. 每卖出一部新款iPhone SE,苹果就要赚1500元?
  5. 常用的关系型数据库的优劣与选择
  6. 当开源奔向物流,阿里云 PolarDB-X 数据库与韵达携手的背后
  7. 批处理查找html,批处理(bat)实现全盘搜索指定文件获取其完整路径方法大全,bat大全分享...
  8. React路由配置:React Router
  9. spring boot2整合dubbox全注解
  10. 阿里云 centos 7.6 安装和启动redis 6
  11. 工作中windows客户端常见问题
  12. idea 字体颜色设置 + 背景图片
  13. 中国国际电子商务中心与易观分析联合发布:2021年4季度全国网络零售发展指数同比增长0.6%
  14. vbs教程《弹出窗口》
  15. 你拍一我拍一上学得学计算机,儿歌你拍一我拍一
  16. 轻松编写您自己的拖拉机算法,进行算法大战
  17. 结构化数据 VS 半结构化数据 VS 非结构化数据
  18. 计算机主硬盘,电脑是固态和机械双盘系统在固态为什么显示主硬盘是机械盘
  19. 去除重复字母Python解法
  20. 论文超详细精读|五千字:STGR

热门文章

  1. vue项目引入秀米插件
  2. Java数据库建立学生表
  3. oracle分析函数:一、窗口子句的使用
  4. 图像算法三 —— 贝叶斯和朴素贝叶斯
  5. 高温焊接对晶振的影响
  6. python 系统学习笔记(八)---文件操作
  7. 腾讯面了五轮,面委挂了,挂的原因让大家唏嘘...
  8. moodle学习网址系统安装部署
  9. 《Hadoop权威指南.大数据的存储与分析.第4版.修订版升级版》
  10. 童诗白模电--基本运算电路