||
实验目的:终端设备采集自身工作电池电压,将数据发往协调器,协调器将数据通过串口发送到PC上的串口调试助手
CoordinateEB(协调器):
typedef union h
{
unsigned char dat[18];
struct rtfx
{
uint8 head[2]; //&&
uint8 type[3]; //节点的类型
uint8 myNWK[4]; //自身网络地址
uint8 pNWK[4]; //父节点网络地址
uint8 value[4]; //第一个字节value[0]为V表示电压,后面三位为数据
uint8 tail; //&
}BUF;
}RTFX;
RTFX rtfx; //保存发送过来的数据
void GenericApp_Init( byte task_id ) //任务初始化函数
{
GenericApp_TaskID = task_id;
// GenericApp_NwkState = DEV_INIT;
GenericApp_TransID = 0; //发送数据包的序列初始化为0
GenericApp_DstAddr.addrMode = (afAddrMode_t)AddrNotPresent;
GenericApp_DstAddr.endPoint = 0;
GenericApp_DstAddr.addr.shortAddr = 0;
//对节点描述符进行初始化
// Fill out the endpoint description.
GenericApp_epDesc.endPoint = GENERICAPP_ENDPOINT;
GenericApp_epDesc.task_id = &GenericApp_TaskID;
GenericApp_epDesc.simpleDesc
= (SimpleDescriptionFormat_t *)&GenericApp_SimpleDesc;
GenericApp_epDesc.latencyReq = noLatencyReqs;
afRegister( &GenericApp_epDesc ); //afRegister()对节点的描述符进行注册,注册后,才能使用OSAL提供服务
RegisterForKeys( GenericApp_TaskID );
#if defined ( LCD_SUPPORTED )
HalLcdWriteString( "GenericApp", HAL_LCD_LINE_1 );
#endif
ZDO_RegisterForZDOMsg( GenericApp_TaskID, End_Device_Bind_rsp );
ZDO_RegisterForZDOMsg( GenericApp_TaskID, Match_Desc_rsp );
/*以下为设置串口,定义在hal_uart.h文件里*/
halUARTCfg_t uartConfig; //该结构体变量实现串口的配置
uartConfig.configured = TRUE;
uartConfig.baudRate = HAL_UART_BR_9600; //波特率9600
uartConfig.flowControl = FALSE; //流控制
uartConfig.callBackFunc = NULL; //回调函数,类型为void (*halUARTCBack_t)(uint8 port,uint8 event)
HalUARTOpen(0,&uartConfig); //串口是否打开
}
void GenericApp_MessageMSGCB( afIncomingMSGPacket_t *pkt )
{
uint8 changline[2] = {0x0a, 0x0d};
switch(pkt->clusterId) //对消息簇中的命令ID进行匹配
{
case GENERICAPP_CLUSTERID: //这里的这个与发送方发送数据时的一样
HalLedBlink(HAL_LED_1,0,50,500); //LED1闪烁
HalUARTWrite(0, changline, 2);
osal_memcpy(&rtfx, pkt->cmd.Data, sizeof(rtfx));
HalUARTWrite(0, rtfx.dat, sizeof(rtfx));
HalUARTWrite(0, changline, 2);
break;
}
}
EndDeviceEB(终端):
typedef union h
{
unsigned char dat[18];
struct rtfx
{
uint8 head[2]; //&&
uint8 type[3]; //节点的类型
uint8 myNWK[4]; //自身网络地址
uint8 pNWK[4]; //父节点网络地址
uint8 value[4]; //第一个字节value[0]为V表示电压,后面三位为数据
uint8 tail; //&
}BUF;
}RTFX;
void GenericApp_Init( byte task_id ) //任务初始化函数
{
GenericApp_TaskID = task_id;
GenericApp_NwkState = DEV_INIT;
GenericApp_TransID = 0; //发送数据包的序列初始化为0
GenericApp_DstAddr.addrMode = (afAddrMode_t)AddrNotPresent;
GenericApp_DstAddr.endPoint = 0;
GenericApp_DstAddr.addr.shortAddr = 0;
//对节点描述符进行初始化
// Fill out the endpoint description.
GenericApp_epDesc.endPoint = GENERICAPP_ENDPOINT;
GenericApp_epDesc.task_id = &GenericApp_TaskID;
GenericApp_epDesc.simpleDesc
= (SimpleDescriptionFormat_t *)&GenericApp_SimpleDesc;
GenericApp_epDesc.latencyReq = noLatencyReqs;
afRegister( &GenericApp_epDesc ); //afRegister()对节点的描述符进行注册,注册后,才能使用OSAL提供服务
RegisterForKeys( GenericApp_TaskID );
// Update the display
#if defined ( LCD_SUPPORTED )
HalLcdWriteString( "GenericApp", HAL_LCD_LINE_1 );
#endif
ZDO_RegisterForZDOMsg( GenericApp_TaskID, End_Device_Bind_rsp );
ZDO_RegisterForZDOMsg( GenericApp_TaskID, Match_Desc_rsp );
}
UINT16 GenericApp_ProcessEvent( byte task_id, UINT16 events ) //消息处理函数
{
afIncomingMSGPacket_t *MSGpkt; //用于指向接收消息结构体的指针
afDataConfirm_t *afDataConfirm;
// Data Confirmation message fields
byte sentEP;
ZStatus_t sentStatus;
byte sentTransID; // This should match the value sent
(void)task_id; // Intentionally unreferenced parameter
if ( events & SYS_EVENT_MSG )
{
MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( GenericApp_TaskID ); //osal_msg_receive()从消息队列上接收消息
while ( MSGpkt )
{
switch ( MSGpkt->hdr.event ) //消息头部中的event进行匹配
{
case ZDO_CB_MSG:
GenericApp_ProcessZDOMsgs( (zdoIncomingMsg_t *)MSGpkt );
break;
case ZDO_STATE_CHANGE:
GenericApp_NwkState = (devStates_t)(MSGpkt->hdr.status); //读取节点的设备信息
if( (GenericApp_NwkState == DEV_ROUTER)
|| (GenericApp_NwkState == DEV_END_DEVICE)) //该节点路由器或终端
{
osal_set_event( GenericApp_TaskID, GENERICAPP_SEND_MSG_EVT); //设置发送事件
}
break;
default:
break;
}
// Release the memory
osal_msg_deallocate( (uint8 *)MSGpkt ); //接收到的消息处理完后,释放消息所占的存储空间
// Next
//处理完一个消息后,再从消息队列里接受消息,然后进行相应的处理,直到所有消息处理完
MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( GenericApp_TaskID );
}
// return unprocessed events
return (events ^ SYS_EVENT_MSG); //返回未处理的事件
}
if ( events & GENERICAPP_SEND_MSG_EVT )
{
sendVdd(); //这个函数是关键
// Setup to send message again
//参数1:标示哪个任务
//参数2:事件名
//参数3:定时的时间,单位毫秒
osal_start_timerEx( GenericApp_TaskID,
GENERICAPP_SEND_MSG_EVT,
GENERICAPP_SEND_MSG_TIMEOUT );
// return unprocessed events
return (events ^ GENERICAPP_SEND_MSG_EVT);
}
return 0;
}
//发送采集的电压信息
static void sendVdd()
{
uint16 nwk;
osal_memcpy(rtfx.BUF.head, "&&", 2);
//根据网络状态,填写类型字段
if(GenericApp_NwkState == DEV_ROUTER)
{
osal_memcpy(rtfx.BUF.type, "ROU", 3);
}
else if(GenericApp_NwkState == DEV_END_DEVICE)
{
osal_memcpy(rtfx.BUF.type, "DEV", 3);
}
//获取地址信息
nwk = NLME_GetShortAddr();
binary_To_hex(rtfx.BUF.myNWK, (uint8*)&nwk, 2);
nwk = NLME_GetCoordShortAddr();
binary_To_hex(rtfx.BUF.pNWK, (uint8*)&nwk, 2);
rtfx.BUF.value[0] = 'V';
unsigned int Vdd = read_vdd();
rtfx.BUF.value[1] = Vdd / 10 + '0';
rtfx.BUF.value[2] = '.';
rtfx.BUF.value[3] = Vdd % 10 + '0';
rtfx.BUF.tail = '&';
afAddrType_t my_DstAddr;
my_DstAddr.addrMode = (afAddrMode_t)Addr16Bit;
my_DstAddr.endPoint = GENERICAPP_ENDPOINT;
my_DstAddr.addr.shortAddr = 0x0000; //协调器网络地址
if(AF_DataRequest(&my_DstAddr, &GenericApp_epDesc, GENERICAPP_CLUSTERID,
sizeof(rtfx.dat)+1, rtfx.dat,
&GenericApp_TransID, AF_DISCV_ROUTE, AF_DEFAULT_RADIUS) == afStatus_SUCCESS)
{
}
}
//读取电压
unsigned int read_vdd()
{
uint16 value;
/* Clear ADC interrupt flag */
ADCIF = 0;
ADCCON3 = 0x1f;
/* Wait for the conversion to finish */
while ( !ADCIF );
/* Get the result */
value = ADCL;
value |= ((uint16) ADCH) << 8;
/*
* value now contains measurement of Vdd/3
* 0 indicates 0V and 32767 indicates 1.25V
* voltage = (value*3*1.25)/32767 volts
* we will multiply by this by 10 to allow units of 0.1 volts
*/
value = value >> 6; // divide first by 2^6
value = (uint16)(value * 37.5);
value = value >> 9; // ...and later by 2^9...to prevent overflow during multiplication
return value;
}
综合上述,只要自己添加自己的消息以及消息处理函数,在适当的时候设置事件即可达到效果。再者这里传输的是电压,如果是传感器的数据,那么组合起来就是一个传感网,这个可以自行实现,不难。