第四部分 提高篇-第5章 CC2530协议栈串口透传

实验设备
硬件:PC 机一台;ZB2530(底板、核心板、仿真器、USB 线) 一套
软件:win7 系统,IAR 8.20 集成开发环境

相信各位朋友学习ZigBee都想着怎么实现无线数据传输,尽管在无线LED通信编者带领大家熟悉了协议栈工作流程,也实现了无线通讯,但是并没有告诉大家,具体怎么通信的,只是讲述了通信的整个流程。今天编者就带领大家进入无线的世界,真正的实现无线传输。串口实验很重要,很多实验都是基于串口实现的。编者在前面也讲过了串口与PC的通信。本节内容是一个 Zigbee 模块(路由/终端) 通过串口接收电脑发过来的数据,然后将数据发送出去,另一个 Zigbee 模块(协调器)将接收到的无线数据,通过串口发送给电脑显示。希望各位务必要掌握。整个过程如图所示。

这里写图片描述

图 5-1 实验功能示意图

5.1串口透传实验分析

本实验是在串口与PC的通信基础上添加的,相关配置有不懂的请回头看第第三讲,串口透传的分析按这 3 步进行:
 通过串口接受电脑发过来的数据;
 将串口接收的数据发送给其它 Zigbee 设备;
 其它 Zigbee 设备接收无线数据并由串口发给电脑显示。

1、通过串口接收电脑发过来的数据
在裸机实验里,我们已经做过串口接收电脑数据的实验,而今天的实验,是基于协议栈的,也就是说,我们今天是用协议栈的库函数实现串口数据的接收,所以,我们下面要做的工作是:
 首先要知道协议栈里,哪个函数负责接收串口数据的;
 然后,还要知道这个函数是怎么运作的,也就是看看它是怎样接收数据之类的;
 最后,看看这个函数是否满足我们的要求,如果不满足,我们就对这个函数进行修改,直到满足我们的要求为止。

首先,打开 SampleApp.eww。

好了,打开工程之后,我们就来找找哪个函数是负责接收串口数据的。大家还记得在 “基于协议栈的 Uart 实验” 里的串口初始化函数 MT_UartInit ()函数?

下面我们再来看看这个函数。在 MT_UartInit ()函数(位于 MT_UART.c)里找到图的代码,看到红色标志的代码没有?是的,红色标志的代码其实是一个函数来的,由函数名可知,它是负责管理串口相关事件的函数。那么,可能有读者就问,为什么是红色标志的函数,而不是后面的MT_UartProcessZAppData 函数?这个问题,看图就明白了。因为我们在预编译里定义了 ZTOOL_P1 ,所以,代码执行到这个条件编译时,就会选择执行MT_UartProcessZToolData 函数了。
这里写图片描述

这里写图片描述

图 5-2 预编译

接下来,我们就进入 MT_UartProcessZToolData 函数,看看它到底管理哪些串口事件。由图红色标志的地方可以知道,这个函数就是一个负责接收串口数据的函数。这样,我们总算找到了负责接收串口数据的函数了。
这里写图片描述
通过TI对该函数的注释我们知道,要通过这个函数来接收串口数据,用户就必须按照 TI 默认的格式来发送串口数据,否则,CC2530 永远接收不到数据。数据帧头MT_UART_SOF=0xFE,所以,很明显,我们在电脑上每次发送数据,都要以 FE……的格式来发送。但是,这样的结果不是我们想要的,我们只想直接将数据发送出去,而不要什么格式之类的,所以,接下来,我们就要对这个函数进行修改。
MT_UartProcessZToolData 函数接收数据的工作流程是:
(1) 接收串口数据,判断数据帧头是否为 0xFE;
(2) 获取数据长度然后给数据包 pMsg 分配内存;
(3) 给数据包 pMsg 装数据;
(4) 打包成任务发给上层 OSAL 处理;
(5) 释放数据包内存。

我们希望工作流程为:
(1)接收到数据
(2)判断长度然后给数据包 pMsg 分配内存
(3)打包发送给上层 OSAL 处理
(4)释放数据包内存

好了,知道要求后,我们下面就进行修改。具体修改后的代码如下所示:
这里写图片描述
这里写图片描述
这里写图片描述
第 331 行:串口 buffer 最大缓冲默认是 128,这个知识在裸机实验讲解过。
第 335 行:接收到数据,把数据接收放到 buf 中。
第 344~345 行:判断长度然后给数据包 pMsg 分配内存。
第 353 行:登记任务,发往上层。
第 355 行:释放内存。
数据包中数据部分的格式是:
datalen + data
到这里,数据接收的处理函数已经完成了,接下来我们要做的就是怎么在任务中处理这个包内容呢?很简单,因为串口初始化是在 SampleApp 中进行的,任务号也是 SampleApp 的 ID,所以当然是在 SampleApp.C 里面进行了。在SampleApp.C 找到任务处理函数:

uint16 SampleApp_ProcessEvent( uint8 task_id, uint16 events )。

至此,通过串口接收电脑发过来的数据讲解完毕。

2、将数据发送给其它 Zigbee 设备
其实这个部分的内容,在无线数据传输实验里早就讲过了,只不过那个实验是周期性广播,TI 为用户准备好了数据发送的代码,但是今天的实验,我们就得自己来完成代码了。
 添加 CMD_SERIAL_MSG 事件。
这里写图片描述
 写串口事件处理函数
SampleApp_SerialCMD((mtOSALSerialData_t*)MSGpkt)。那么,我们应该写些什么内容?因为我们的目的是发送数据,那就是要写发送数据的代码。
我们参考“基于协议栈的无线数据传输”实验里的 SampleApp_SendPeriodicMessage函数,只不过这里需要多做 3 件事:
(1) 定义一个指针指向由 MT 发过来的串口数据;(在 SampleApp.c 里定义)
(2) 定义一个变量用于计算数据的长度;(在 SampleApp.c 里定义)
(3) 定义一个簇(ID),用于接收方判别。(在 SampleApp.h 里定义,见下图)

这里写图片描述

图 5-3 SAMPLEAPP_COM_CLUSTERID 定义

具体 SampleApp_SerialCMD 函数的代码如下所示:
这里写图片描述
这里写图片描述
第 475行: 定义一个指针(*str)指向由 MT 发过来的串口数据, 以及定义一个变量(len)用于计算数据的长度。
第 476 行:将指针指向数据开头。
第 477 行:获取串口数据长度,msg 里的第 1 个字节代表后面的数据长度。
第 480~482 行:将接收的串口数据发回给电脑显示。
第 487 行:在 SampleApp.h 里定义的一个簇(ID),用于接收方判别
注意:(1)记得在 SampleApp.c 开头位置声明 SampleApp_SerialCMD 函数;
(2)我们可以选择 EndDeviceEB-Pro 进行编译(在预编译里注释掉有关 MT 层的),然后下载到开发板上,可以看到如下图所示的效果这就证明了已经执行了SampleApp_SerialCMD 函数。
 登记事件,设置编号、发送时间等
这里写图片描述
第 291 行: 代码的关键部分。这三个参数决定着周期性发送数据的命脉。我们逐一分析。分别看它们的定义。
SampleApp_TaskID:
任务 ID,函数开头定义了 SampleApp_TaskID = task_id;也就是 SampleApp初始化的任务 ID 号。
SAMPLEAPP_SEND_PERIODIC_MSG_EVT:
#define SAMPLEAPP_SEND_PERIODIC_MSG_EVT 0x0001
同一个任务下可以有多个事件,这个是事件的号码。 我们可以定义自己的事件,但是编号不能重复。 而且事件号码 16 位必须只占 1 位,所以只能定义 16 个事件。
SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT:
// Send Message Timeout Every 5 seconds
#define SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT 5000
事件重复执行的时间。这里以毫秒为单位,所以是 5s,也就是刚刚实验为什么隔约 5s 收到数据的原因。这里可以改你需要发送数据的时间间隔。登记好事件后,看第二行代码可以知道如果网络一直连接的就不会再次进入这个函数了,所以这个相当于初始化,只执行 1 次。
 设置发送内容。自动周期性地发送
这里写图片描述
第 318 行:判断 SAMPLEAPP_SEND_PERIODIC_MSG_EVT (0x0001)有没有发生,如果有的就执行下面函数。
第 321 行: SampleApp_SendPeriodicMessage();是主要的代码,是我们编写需要发送内容的地方, 我们进入去做一些修改。
这里写图片描述
第 437 行: SAMPLEAPP_PERIODIC_CLUSTERID 这是一个新东西,其定义为:
#define SAMPLEAPP_PERIODIC_CLUSTERID 1
定义的作用是和接收方建立联系,协调器收到这个标号,如果是 1,就证明是由周期性广播方式发送过来的。
第 438 行: 1 是数据长度。
第 439 行: (uint8*)&SampleAppPeriodicCounter 是要发送的内容。
如果想周期性发送数据,我们可以做以下修改,取消注释,注释掉红色方框部的内容。
这里写图片描述
至此,将数据发送给其它 Zigbee 设备部分讲解完毕。
3、接收数据并由串口发给电脑显示
这里写图片描述
在“基于协议栈的无线数据传输”实验里,我们已经讲过,接收数据的代码,TI 早就为客户完成了。今天的实验,也需要接收数据,那么,跟那个实验的情况一样吗?嗯,答案是肯定的。但是,还记得我们在上面讲发送数据的代码的时候,定义过一个簇,就是因为这个ID,它是接收方用于判别的,所示我们要在SampleApp_MessageMSGCB 函数里进行修改,具体修改后的代码如下所示:
这里写图片描述
这里写图片描述
第 408 行:我们在发送函数里定义的簇(SAMPLEAPP_COM_CLUSTERID)。
第 409 行:获取接收到的数据的长度。
第 410~412 行:将接收到的数据由串口发给电脑显示。
所有的数据和信息都在函数传入来的 afIncomingMSGPacket_t *pkt 里面,进入afIncomingMSGPacket_t 的定义,它是一个结构体,内容如下(AF.h文件里)
这里写图片描述
里面包含了数据包的所有东西,长地址、短地址、 RSSI 等,那么数据在哪里呢?在afMSGCommandFormat_t cmd里,又是一个结构体,继续进入。
这里写图片描述
至此,接收数据并由串口发给电脑显示部分讲解完毕。

5.2实验现象

打开工程程序,接着,分别选择 EndDeviceEB-Pro 和CoordinatorEB-Pro 编译后下载程序到两个 Zigbee 模块,然后,两个模块都通过串口连接到电脑。打开串口调试助手,设置相关配置,在其中一个串口调试助手发送一些文字,可以看到自身所接串口调试助手和另一个串口调试助手会马上出现相同的文字,如下图所示,说明测试成功。

这里写图片描述

图5-4节点
这里写图片描述

图5-5协调器

5.3总结

1、通过串口接收电脑发过来的数据的步骤:
(1)接收到数据
(2)判断长度然后给数据包 pMsg 分配内存
(3)打包发送给上层 OSAL 处理
(4)释放数据包内存
**2、将接收到的数据发送给其它 Zigbee 设备比“基于协议栈的无线数据传输”实验
里多做的工作:**
(1) 定义一个指针指向由 MT 发过来的数据; (在 SampleApp.c 里定义)
(2) 定义一个变量用于计算数据的长度; (在 SampleApp.c 里定义)
(3) 定义一个簇(ID),用于接收方判别。 (在 SampleApp.h 里定义)
3、接收其它 Zigbee 设备发送过来的数据时,要在 SampleApp_MessageMSGCB 函数里,重新定义一个 case,而且 ID 跟发送部分代码的 ID 一致。

本章参考代码

点击进入

附录:

打开
ZStack-CC2530-2.3.0-1.4.0\Projects\zstack\Utilities\SerialApp\CC2530DB\SerialApp.eww
(1) 将命令添加到命令列表,增加协调器与终端握手的 ID,分别是请求与应答(SerialApp.c文件里)。
这里写图片描述
其中,SERIALAPP_MAX_CLUSTERS在SerialApp.h文件里定义。
(2) SerialApp_Init 函数.
这里写图片描述
这里写图片描述
(3) SerialApp_ProcessEvent 函数.
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
(4) Serial App_Send 函数.

这里写图片描述

这里写图片描述

这里写图片描述

(5) 在收到空中的信号后,传递给与其相连的串口终端。
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
对于发送端来说,如果发送不成功,则数据重发,如果得知接收端数据没有接收成功,同样进行数据重发。上次数据没有发完的话,即使串口有了新数据也不重新读取串口里的新数据,而是继续重发上次数据。

实验步骤
分别编译下载到协调器、终端,两个节点用 USB 与电脑相连,打开串口软件,设置串口为:115200 8N1 后,即可随便发消息了。

这里写图片描述

图5-6协调器实验现象
这里写图片描述

图5-7终端节点实验现象

猜你喜欢

转载自blog.csdn.net/u013162035/article/details/80979896