嘿,又和大家见面了 ,下面我们就正式开始学习各种通信方式了。
言归正传,
在Zigbee网络里,模块之间要进行通信,发射模块非常明确知道接收模块的网络地址,以这个地址发送数据给接收模块,叫单播。
模块在入网的时候,
父节点随机分配网络地址给子节点,但是协调器模块在网络里的地址永远是0x0000.
下面就从单播实验说起,附件,我会上传一个我的单播实验云地址 会上传一个实验包,大家可以下载结合看
单播实验百度云地址:http://pan.baidu.com/s/1bpJ35HP
一、单个任务挂钩一个端点!!!!!!!!!!!!!
1、发送数据的流程
在SDApp.c文件里的SDApp_MY_EVT 事件处理中按钮1 按下的相关处理代码
char theMessageData[] ="Hello lao da";//通过终端传输到协调器利用串口打印的字符串
SDApp_DstAddr.addrMode = (afAddrMode_t)Addr16Bit;
SDApp_DstAddr.addr.shortAddr = 0x0000;//协调器接收模块的网络地址
// Take the first endpoint, Can be changed to search through endpoints
SDApp_DstAddr.endPoint =SDApp_ENDPOINT ;//接收模块的端点房间号
//&SDApp_epDesc结构体 端点描述符有源端点的信息,即SDApp_ENDPOINT也是10
AF_DataRequest( &SDApp_DstAddr, &SDApp_epDesc,
SDApp_CLUSTERID,//目标端点镞,房间里的接收人数据宏也是1,2个字节,所以在射频0x0001
(byte)osal_strlen( theMessageData ) + 1,//发送字符串的长度
(byte *)&theMessageData,//字符串内容数组的首地址
&SDApp_TransID,
AF_DISCV_ROUTE, AF_DEFAULT_RADIUS )
P1SEL &=0Xfe;// 1111 1110 通过led闪烁判断数据传输次数 接收数据出现延时问题 需要的数据位 传输数据为一帧一帧的传输
P1DIR |=0X01;
P1_0 ^=1;
2、接收数据的流程(以函数讲解)
void SDApp_MessageMSGCB( afIncomingMSGPacket_t *pkt )
//afIncomingMSGPacket_t *pkt为无线数据包内容
{
// switch ( pkt->clusterId )
// {
// case SDApp_CLUSTERID:
// // "the" message
//#if defined( LCD_SUPPORTED )
// HalLcdWriteScreen( (char*)pkt->cmd.Data, "rcvd" );
Draw_BMP(0,0,128,8,BMP) ;
//#elif defined( WIN32 )
// WPRINTSTR( pkt->cmd.Data );
//#endif
// LCD_P16x16Ch(8,4,pkt->cmd.Data[100]);
//注,是否要以上注释内容都对数据传输运行无影响,
Draw_BMP(0,0,128,8,BMP);
Uart_Send_String(pkt->cmd.Data,pkt->cmd.DataLength);
// break;
// }
}
数据传输原理:
端点 (Endpoint)
1、他是一个字节编号的,数据收和发送的基本单元,在模块通信的时候,发送模块必须指定收发双方模块的网络地址和端点一致,这样,才能挂载在一起。
2、端点要使用必须要和模块里的某个任务挂钩定义;
首先每一个端点可以看成是一个1个字节数字编号的开有一扇门的房间,数据最终的目标是进入到无线数据包指定的目标端点房间,而取无线数据这个相关的代码在任务事件处理函数里,TI协议栈有那么多的任务事件处理函数,所以必须要指定在哪个任务事件处理函数 来取这个无线数据包里面的有用数据。
3、一个端点只能挂钩在一个任务上,而一个任务可以挂钩多个端点,且端点对所有的任务是公用的,定义一个少一个。
一个端点加入可以挂钩在多个任务上,那么接收模块接到无线数据时候,这个时候同一个端点有多个任务事件处理函数去处理,不合理;一个任务上挂多个端点(6 7 挂应用层任务),发送给协调器模块的6 7端点的数据都会进入到应用层任务事件处理函数里来,仅仅做个判断到底是投递到6房间还是7号房间就可以了。
结合代码,定义端点和任务挂钩在基础实验的代码里是那些代码
SDApp.c
void SDApp_Init( byte task_id ) //定义了10号端点并且和这个模块的应用层任务挂钩
{
..
// Fill out the endpoint description.
SDApp_epDesc.endPoint = 10;//SDApp_ENDPOINT; 此端点编号为10
SDApp_epDesc.task_id = &SDApp_TaskID; 和我们应用层任务挂钩
SDApp_epDesc.simpleDesc
= (SimpleDescriptionFormat_t *)&SDApp_SimpleDesc;//更加详细的描述这个端点一些情况就像我们定义一个编号房间,描述房间里大概有多少人之类的信息。
SDApp_epDesc.latencyReq = noLatencyReqs;//差不多
// Register the endpoint description with the AF
afRegister( &SDApp_epDesc );//这个函数必须要调用才能完成整个挂钩操作
..
}
所以,基本实验室0xA406 10 0x0000 10 无线数据包发出去以后,首先目标协调器模块的网络地址0x0000对上了,协调器可以拿到这个无线数据包在底层任务,判断10号端点房间已经定义且和我们应用层任务挂钩,那么这个无线数据包发送一个消息
到们应用层任务
case AF_INCOMING_MSG_CMD:
SDApp_MessageMSGCB( MSGpkt );
break;
端点在带编号的房子,代码里一个结构体SDApp_epDesc
在消息处理里,把hello lao da 通过串口送出去
Uart_Send_String(pkt->cmd.Data,pkt->cmd.DataLength);
镞 ClusterID
镞就是相当于端点房间里面的人,是接收最终的目标。这东西是2个字节编号,
在射频发送的时候,必须要指定接收模块的镞,发送模块不需要指定。
二,多个任务挂钩一个端点执行!!!!!!!!!!!!!!!!
结合代码发送模块:
在发送模块里,我们用的数据发送源端点,也是10,所以我们也定义这个10端点也挂钩应用层任务,原则上,外部给我们终端模块10号端点来数据,也会进入终端应用层任务事件处理 函数里。而我们这个端点仅仅这里作为发送模块,但是我们要实用10端点,必须要挂钩定义。
if(0==P0_1)//按钮3按下
{
char theMessageData[] = "hello word";
//char themessagedata[]="hello word";
// LS164_BYTE(3);
// P1_1 =0;
// LCD_CLS();
// Draw_BMP(0,0,128,8,BMP); //图片显示
SDApp_DstAddr.addrMode = (afAddrMode_t)Addr16Bit;
SDApp_DstAddr.addr.shortAddr = 0x0000;//接收模块的网络地址
// Take the first endpoint, Can be changed to search through endpoints
SDApp_DstAddr.endPoint = 7;//接收模块的端点房间号
//发送函数 //SDApp_epDesc 结构体 端点描述符有源端点的信息,也是10
if( AF_DataRequest( &SDApp_DstAddr, &SDApp_epDesc,
0x0001,//目标端点镞,房间里的接收人数据宏是1,2个字节,所以在射频0x0001
(byte)osal_strlen( theMessageData ) + 1,//发送字符串的长度
(byte *)&theMessageData,
&SDApp_TransID,
AF_DISCV_ROUTE, AF_DEFAULT_RADIUS )== afStatus_SUCCESS );
P1SEL &=0Xfe;// 1111 1110
P1DIR |=0X01;//此处点亮led 显示的数据为需要的数据位
P1_0 ^=1;
}
// if(0==P2_0)
// {//按钮4按下
// char theMessageData[] ="hello huanhuan";
// SDApp_DstAddr.addrMode = (afAddrMode_t)Addr16Bit;
// SDApp_DstAddr.addr.shortAddr = 0x0000;
// // Take the first endpoint, Can be changed to search through endpoints
// SDApp_DstAddr.endPoint = 7;
//
// if( AF_DataRequest( &SDApp_DstAddr, &SDApp_epDesc,
// 0x0002,
// (byte)osal_strlen( theMessageData ) + 1,
// (byte *)&theMessageData,
// &SDApp_TransID,
// AF_DISCV_ROUTE, AF_DEFAULT_RADIUS )== afStatus_SUCCESS) ;
// }
if(0==P2_0)//按钮4按下
{
char theMessageData[] = "Hello huan ";
SDApp_DstAddr.addrMode = (afAddrMode_t)Addr16Bit;
SDApp_DstAddr.addr.shortAddr = 0x0000;
// Take the first endpoint, Can be changed to search through endpoints
SDApp_DstAddr.endPoint = 8;
if(AF_DataRequest( &SDApp_DstAddr, &SDApp_epDesc,
0x0002,
(byte)osal_strlen( theMessageData ) + 1,
(byte *)&theMessageData,
&SDApp_TransID,
AF_DISCV_ROUTE, AF_DEFAULT_RADIUS) == afStatus_SUCCESS) ;
// P1_0=0;
// LS164_BYTE(4);
// LCD_CLS();
// for(i=0; i<8; i++)
// {
// LCD_P16x16Ch(i*16,0,i); //点阵显示
// LCD_P16x16Ch(i*16,2,i+8);
// LCD_P16x16Ch(i*16,4,i+16);
// LCD_P16x16Ch(i*16,6,i+24);
// }
}
接收模块:
在SDapp.c里面,SDApp_Init函数里面添加
SDApp_epDesc.endPoint = 7;
SDApp_epDesc.task_id = &SDApp_TaskID;
SDApp_epDesc.simpleDesc
= (SimpleDescriptionFormat_t *)&SDApp_SimpleDesc;
SDApp_epDesc.latencyReq = noLatencyReqs;
// Register the endpoint description with the AF
afRegister( &SDApp_epDesc );
SDApp_epDesc1.endPoint = 8;//SDApp_ENDPOINT;
SDApp_epDesc1.task_id = &SDApp_TaskID;
SDApp_epDesc1.simpleDesc
= (SimpleDescriptionFormat_t *)&SDApp_SimpleDesc;
SDApp_epDesc1.latencyReq = noLatencyReqs;
// Register the endpoint description with the AF
afRegister( &SDApp_epDesc1 );
当然,在前面需要声明:
endPointDesc_t SDApp_epDesc;//7号端点的结构体 端点描述符
endPointDesc_t SDApp_epDesc1;//8号
最后,在void SDApp_MessageMSGCB( afIncomingMSGPacket_t *pkt )函数里,
if(7==pkt->endPoint)
{//外来数据包要投入到7号端点房间
switch ( pkt->clusterId )//clusterId ==镞ID
{
case 0x0001://led1
Draw_BMP(0,0,128,8,BMP);//显示图片
Uart_Send_String(pkt->cmd.Data,pkt->cmd.DataLength);将发送模块发送的字符串,接收模块接收到的数据在串口上面打印出来
P1SEL &=0XFE;//1111 1110 LED1
P1DIR |=0X01;//
P1_0 ^=1;
break;
// case 0x0002:
// Uart_Send_String(pkt->cmd.Data,pkt->cmd.DataLength);
// P2SEL &=0XFD;// 1111 1101;
// P2DIR |=0X02;
// P2_1 ^=1;
// break;
}
}
if(8==pkt->endPoint)
{
switch ( pkt->clusterId )
{
case 0x0002://led3
LCD_CLS();
LCD_P8x16Str(44,0,"saler");
LCD_P8x16Str(20,2,"OLED DISPLAY");
LCD_P8x16Str(8,4,"TEL:15283869923");
LCD_P6x8Str(20,6,"
[email protected]");
LCD_P6x8Str(20,
7,"2016-11-21 23:42");
Uart_Send_String(pkt->cmd.Data,pkt->cmd.DataLength);
P1SEL &=0XEF;// 1110 1111 LED3
P1DIR |=0X10;
P1_4 ^=1;
break;
}
}
最后,使用了olcd 实现了zigbee点播数据的通信,也使用了串口显示发送的字符串
分别使用了单个镞挂载一个端点的实验,和多个镞挂载一个端点的实验