ZStack版本:ZStack-CC2530-2.5.1a
下载和调试器:SmartRF04EB
IDE开发软件:IAR Embedded Workbench IDE - 8051 10.20.1
开发平台:基于TI-CC2530的任意厂家的
一、实验简介
本实验使用2个CC2530模块,一个模块作为协调器,一个模块作为终端设备。实验目的是实现终端设备和协调器的点对点无线通信,并且每隔5s,终端设备给协调器发送一个字符串信息"i am enddevice!\r\n",协调器收到该信息后,通过串口打印出该信息。工程还是基于printf()函数移植学习进行修改。
二、协调器端的代码修改
将工程配置修改为协调器配置模式:
2.1 修改Coordination.c文件,在文件的开头加入printf头文件和串口的头文件及初始化函数,代码如下:
#include "user_printf.h"
#include "MT_UART.h"
#include "MT.h"
#include "string.h"
...........................
MT_UartInit ();
MT_UartRegisterTaskID(GenericApp_TaskID);
2.2 修改Coordination.c文件中,用户任务事件处理函数uint16 GenericApp_ProcessEvent( uint8 task_id, uint16 events )里的无线收据接收事件处理函数:
case AF_INCOMING_MSG_CMD:
GenericApp_MessageMSGCB( MSGpkt );
break;
GenericApp_MessageMSGCB( MSGpkt );函数就是对接收到的无线消息的处理函数,我们修改此函数,将收到的消息通过printf函数打印即可。
原程序如下:
static void GenericApp_MessageMSGCB( afIncomingMSGPacket_t *pkt )
{
switch ( pkt->clusterId )
{
case GENERICAPP_CLUSTERID:
// "the" message
#if defined( LCD_SUPPORTED )
HalLcdWriteScreen( (char*)pkt->cmd.Data, "rcvd" );
#elif defined( WIN32 )
WPRINTSTR( pkt->cmd.Data );
#endif
break;
}
}
修改为:
static void GenericApp_MessageMSGCB( afIncomingMSGPacket_t *pkt )
{
switch ( pkt->clusterId )
{
case GENERICAPP_CLUSTERID:
// "the" message
printf("%s\r\n",pkt->cmd.Data);
break;
}
}
三、终端设备代码的修改
将工程配置切换为终端设备模式:
3.1 修改EndDevice.c文件,在文件的开头加入printf头文件和串口的头文件及初始化函数,代码如下:
#include "user_printf.h"
#include "MT_UART.h"
#include "MT.h"
#include "string.h"
...........................
MT_UartInit ();
MT_UartRegisterTaskID(GenericApp_TaskID);
3.2 修改EndDevice.c文件中,在用户任务初始化函数中,修改目标地址信息的配置:
原配置信息如下:
GenericApp_DstAddr.addrMode = (afAddrMode_t)AddrNotPresent;
GenericApp_DstAddr.endPoint = 0;
GenericApp_DstAddr.addr.shortAddr = 0;
修改如下:
GenericApp_DstAddr.addrMode = (afAddrMode_t)Addr16Bit;
GenericApp_DstAddr.endPoint = GENERICAPP_ENDPOINT;
GenericApp_DstAddr.addr.shortAddr = 0x0000;
第一个参数是地址模式使用单播的16位网络地址模式。
第二个参数是目的地址的端点号。
第三个参数是目的地址网络地址,协调器的网络地址为0x0000,而我们本次实验正是将数据发送到协调器的,所以地址设置为0x0000。
3.3 第一次发送任务事件的触发
什么时候触发第一次发送信息任务事件,在用户任务事件处理函数中,有一个设备状态更改事件:
case ZDO_STATE_CHANGE:
GenericApp_NwkState = (devStates_t)(MSGpkt->hdr.status);
if ( (GenericApp_NwkState == DEV_ZB_COORD)
|| (GenericApp_NwkState == DEV_ROUTER)
|| (GenericApp_NwkState == DEV_END_DEVICE) )
{
// Start sending "the" message in a regular interval.
osal_start_timerEx( GenericApp_TaskID,
GENERICAPP_SEND_MSG_EVT,
GENERICAPP_SEND_MSG_TIMEOUT );
}
break;
当设备检测到任务状态更改事件,并确定设备状态为上述三种状态时,启动一个消息发送事件定时器,这其中第三个参数是一个时间参数,默认是5000us即5ms。当定时时间到了之后,就触发一个消息发送事件。
3.4 周期性的消息发送。
在用户任务事件处理函数中,有一个专门的分支处理消息发送事件,代码如下:
if ( events & GENERICAPP_SEND_MSG_EVT )
{
// Send "the" message
GenericApp_SendTheMessage();
// Setup to send message again
osal_start_timerEx( GenericApp_TaskID,
GENERICAPP_SEND_MSG_EVT,
GENERICAPP_SEND_MSG_TIMEOUT );
// return unprocessed events
return (events ^ GENERICAPP_SEND_MSG_EVT);
}
在这里有一个消息发送处理函数和消息发送定时器,消息就是在这块被定时器周期性触发消息发送事情从而被周期性的发送的。发送的周期可以更改GENERICAPP_SEND_MSG_TIMEOUT参数。
消息发送处理函数如下:
static void GenericApp_SendTheMessage( void )
{
char theMessageData[] = "Hello World";
if ( AF_DataRequest( &GenericApp_DstAddr, &GenericApp_epDesc,
GENERICAPP_CLUSTERID,
(byte)osal_strlen( theMessageData ) + 1,
(byte *)&theMessageData,
&GenericApp_TransID,
AF_DISCV_ROUTE, AF_DEFAULT_RADIUS ) == afStatus_SUCCESS )
{
// Successfully requested to be sent.
}
else
{
// Error occurred in request to send.
}
发送消息的内容在theMessageData[]数组中,我们只需将其内容更改成我们需要的内容即可
char theMessageData[] = "i am enddevice!\r\n";
本实验中,我们还在该函数添加了发送成功或失败的串口提示信息:
{
// Successfully requested to be sent.
HalUARTWrite(0,"uart0 send success!\r\n",strlen("uart0 send success!\r\n"));
}
else
{
// Error occurred in request to send.
HalUARTWrite(0,"uart0 send failer!\r\n",strlen("uart0 send failer!\r\n"));
}
四、编译下载测试:
五、附加实验
将发送字符串改成char theMessageData[] = “i am enddevice1!\r\n”;烧录到一个终端设备,将数字1,依次变成2,3,4等烧录进不同的终端设备,组合成1个协调器和几个终端设备同时通信。由于物料有限,本次实验测试了1个协调器和3个终端设备,测试成功。