赞
踩
本文介绍了一个ZIGBEE小制作——使用CC2530来实现的红绿灯。这个例子使用协调器透传,可以接受别的控制单片机的串口命令,或者使用PC机的串口助手软件来给协调器发命令,控制节点中红绿灯的状态。节点上红黄绿三个交通灯都可以独立实现开,关或者闪烁。
先说命令格式:
typedef struct
{
uint8 Header_1;
uint8 Header_2;
uint8 NodeID;
uint8 Command;
uint8 Data;
uint8 Tailer;
}UART_Format;
Header_1、Header_2与Tailer是固定的帧头和帧尾,这里用EE,CCC和FF来表示。
NodeID是设备号,如1号红绿灯可以使用0x01,2号使用0x02;
Command表示是命令,如0xAA表明是周期消息,0xDD表明是节点对协调器命令的响应。
Data是数据。这个例子中使用一个8位数据来表示红绿黄三个交通灯的状态,每个交通灯都有两个数据位, 00不亮01亮10闪烁,最高的两位预留,然后从高位到低位依次是红黄绿灯。假如红灯亮,黄灯闪烁绿灯不亮,那么data就是0001 1000,也就是0x18。
下面是节点的代码:
首先是IO口与宏定义。具体可根据自己的硬件写。我是用了红绿灯来演示,实际应用可以使用三极管或者继电器控制更高电压的交通灯。
//LED控制接口
#define LED_R P0_4
#define LED_Y P0_5
#define LED_G P0_6
//1红2黄3绿 0亮起来 1不亮
#define ON 0
#define OFF 1
截取节点的消息处理函数:(flag_X = 1 表示这个灯要闪烁。)
void SerialApp_ProcessMSGCmd( afIncomingMSGPacket_t *pkt ) //处理接收到的RF消息
{
。。。。。。
switch ( pkt->clusterId )
{
case SERIALAPP_CLUSTERID1: //处理各个传感器节数据
receiveData = (UART_Format *)(pkt->cmd.Data);
HalLedBlink(HAL_LED_1,1,50,200);
if((receiveData->Header_1==0xcc)&&(receiveData->Header_2==0xee)&&(receiveData->Tailer==0xff)) //校验包头包尾
{
if(receiveData->NodeID == 0x01) //地址,如果是发给自己的命令
{
flag_R = 0;//先将所有的标识都置零
flag_Y = 0;//这些标识用来标记是否闪烁
flag_G = 0;
Rsp.Command = 0xDD;//DD表明是响应
Rsp.Data = receiveData->Data;
switch (receiveData->Data)
{
。。。。。。。
case 0x06://RHG012 0不亮1亮2闪烁 0000 0110
LED_R = OFF;
LED_Y = ON;
flag_G = 1;
break;
。。。。。
case 0x2a://RHG222 0不亮1亮2闪烁 0010 1010
flag_ALL = 1; //如果3个灯全部闪烁,特别定义这样一个变量
flag_R = 1; //保证同时亮灭
flag_Y = 1;
flag_G = 1;
break;
default :
Rsp.Command = 0xEF;//出错
break;
}
//响应
osal_set_event(SerialApp_TaskID, LED_BLINK_EVT);
SerialApp_OTAData(&SerialApp_TxAddr, SERIALAPP_CLUSTERID1, &Rsp, sizeof(UART_Format));
}
}
break;

最后使用osal_set_event(SerialApp_TaskID, LED_BLINK_EVT);来设置了一个闪烁事件。这个事件的宏定义
#define LED_BLINK_EVT 0X0004
这个事件的处理函数:
UINT16 SerialApp_ProcessEvent( uint8 task_id, UINT16 events )
{
(void)task_id; // Intentionally unreferenced parameter
。。。。。。
if ( events & LED_BLINK_EVT )
{
if (flag_ALL)
{
LED_R = 0;
LED_Y = 0;
LED_G = 0;
flag_ALL = 0;
}
if (flag_R) LED_R = ! LED_R;
if (flag_Y) LED_Y = ! LED_Y;
if (flag_G) LED_G = ! LED_G;
osal_start_timerEx(SerialApp_TaskID, LED_BLINK_EVT, 1000);
return (events ^ LED_BLINK_EVT);
}
。。。。。。
return ( 0 ); // Discard unknown events.
}

处理函数也很简单,哪个状态位被标记过,就让其对应的灯状态反转,然后使用定时器计时1000毫秒再次反转,就实现了灯的闪烁。
协调器的功能主要是将串口数据转发为无线数据,也会将节点执行命令的结果通过串口发给控制系统,代码就不列了。
以上
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。