点击左上角的
“关注”
,定期更新Zigbee最新资讯,总有你想要的信息!
这篇文章主要是想让大家了解如何配置Z-Stack中串口功能的参数,如何开启串口功能,如何使用串口发送和接收功能,最后实现我们要的串口透传功能。
在Z-Stack中我们可以直接调用API接口来开启设备的串口功能,此API接口函数为“uint8 HalUARTOpen(uint8 port, halUARTCfg_t *config)
”。我们先来看看这个函数的形参,形参“port
”表示要开启的串口号,CC2530有两个串口,串口0和串口1,这个看个人硬件所用的串口来选择开启哪个串口。形参“config
”里包含了这个串口的使用参数,详情如下:
typedef struct
{
bool configured;
uint8 baudRate;
bool flowControl;
uint16 flowControlThreshold;
uint8 idleTimeout;
halUARTBufControl_t rx;
halUARTBufControl_t tx;
bool intEnable;
uint32 rxChRvdTime;
halUARTCBack_t callBackFunc;
}halUARTCfg_t;
要自己配置的参数如下:
configured:
调用“
HalUARTOpen()
”函数时会自动将“.configured
”参数置为TRUE;若“.configured
”=TURE,再调用“HalUARTOpen()
”函数打开同一个串口时,则会自动清除串口的RX、TX缓存和串口配置“uartRecord
”再重新配置。此处我们设置为TRUE。
baudRate:
串口的波特率。有“
HAL_UART_BR_9600
”、“HAL_UART_BR_19200
”、“HAL_UART_BR_38400
”、“HAL_UART_ BR_115200
”可选。此处我们设置为“HAL_UART_BR_9600
”波特率。
flowControl:
硬件流控制,TRUE为开启硬件流控,FALSE为关闭硬件流控。有硬件流控功能的可以开启硬件流控,此处我们设置为FALSE,关闭硬件流控功能。
flowControlThreshold:
此参数表示RX缓存达到“
maxRxBufSize
”之前还有多少字节空余。当RX缓存到达“maxRxBufSize
–flowControlThreshold
”时,会触发相应的应用事件:“HAL_UART_RX_ABOUT_FULL
”。此处我们设置为64,一般设置为“maxRxBufSize
”的一半。
idleTimeout:
如果设备串口收到数据之后在“
idleTimout
”时间内RX没有收到新的数据了,将会触发相应的事件“HAL_UART_RX_TIMEOUT
”,这时应用程序可以选择读出所有RX的值或者一部分的值,单位:毫秒。此处我们设置为6ms,当串口收到数据后,6ms内没有再收到新的数据,则触发“HAL_UART_RX_ABOUT_FULL
”事件。
rx.maxBufSize:
rx包含“
halUARTBufControl_t
”数据结构,用于操作RX 缓冲区。当接收的字节数到达“rx.maxBufSize
”时,会产生“HAL_UART_RX_FULL
”事件。此处我们设置为128个字节
intEnable:
串口中断使能,TRUE为使能串口中断功能,FALSE为失能串口中断功能。此处我们设置为TRUE,使能串口中断功能。
callBackFunc:
回调函数,应用程序可以根据RX、TX出发的不同事件进行处理。此处会指向我们自己的串口事件处理函数“
Handle_UartEvent()
”。
配置串口参数,开启串口0。代码如下:
------------------------------------------------------------- Gateway.c -------------------------------------------------------------
void Gateway_Init( uint8 task_id )
{
halUARTCfg_t uartconf;
……
// 配置串口
uartconf.baudRate = HAL_UART_BR_115200;
uartconf.callBackFunc = Handle_UartEvent;
uartconf.configured = TRUE;
uartconf.flowControl = FALSE;
uartconf.flowControlThreshold = 64;
uartconf.idleTimeout = 6; // 6ms后串口空闲则发送串口空闲事件,参数不可设为0
uartconf.rx.maxBufSize = 128;
uartconf.tx.maxBufSize = 128;
uartconf.intEnable = TRUE;
// 开启串口0
HalUARTOpen(HAL_UART_PORT_0, &uartconf);
……
}
串口发送数据就只需要调用“uint16 HalUARTWrite(uint8 port, uint8 *buf, uint16 len)
”接口,形参“port
”可选择串口0或串口1,开启了哪个串口就用哪个串口;形参“buf
”为要发送的数据;形参“len
”为要发送数据的长度,一次性最多只能发送“HAL_UART_DMA_TX_MAX
”个字节的数据,协议栈中“HAL_UART_DMA_TX_MAX
”的默认值为256。
串口接收数据需要通过上面我们注册的回调函数“Handle_UartEvent
”来处理串口事件。关于接收数据的串口事件只有三个:HAL_UART_RX_FULL
、HAL_UART_RX_ABOUT_FULL
和HAL_UART_RX_TIMEOUT
。
HAL_UART_RX_FULL:当RX缓存数据的字节数到达“rx.maxBufSize
”时,会产生“HAL_UART_RX_FULL
”事件。
HAL_UART_RX_ABOUT_FULL:当RX缓存数据的字节数到达“maxRxBufSize
– flowControlThreshold
”时,会产生“HAL_UART_RX_ABOUT_FULL
”事件。
HAL_UART_RX_TIMEOUT:如果设备串口收到数据之后在“idleTimout
”时间内串口没有收到新的数据了,会产生“HAL_UART_RX_TIMEOUT
”事件。
下面我们会在具体实现串口透传功能时应用串口发送和接收功能。
串口透传功能具体为终端设备接收到PC端通过串口发送过来的数据,然后将数据发送至协调器端,协调器端接收到数据后再通过串口将数据发送至PC端。
以下代码是基于上篇文章《7天快速入门Zigbee:无线传输与接收》代码的基础上编程的。
要使用自己的串口功能,则必须确保关闭了Z-Stack内部的串口功能,不然两者会产生冲突,串口会出现不可预期的数据。要关闭Z-Stack内部的串口功能,我们只需要屏蔽以下几个预编译即可。
屏蔽掉Z-Stack默认开启的MT_TASK
、MT_SYS_FUNC
、MT_ZDO_FUNC
。
------------------------------------------------------------- Gateway.c -------------------------------------------------------------
去掉与本项目无关的初始化,在自己的任务初始化函数当中配置串口参数,开启串口0功能。
void Gateway_Init( uint8 task_id )
{
halUARTCfg_t uartconf;
g_gateway_taskid = task_id;
// 填充端口描述符
g_gateway_epdesc.endPoint = GATEWAY_ENDPOINT;
g_gateway_epdesc.task_id = &g_gateway_taskid;
g_gateway_epdesc.simpleDesc = (SimpleDescriptionFormat_t *)&g_gateway_simpledesc;
g_gateway_epdesc.latencyReq = noLatencyReqs;
// 注册该端口
afRegister(&g_gateway_epdesc);
/* 新添加代码 START */
// 配置串口参数
uartconf.baudRate = HAL_UART_BR_115200;
uartconf.callBackFunc = Handle_UartEvent;
uartconf.configured = TRUE;
uartconf.flowControl = FALSE;
uartconf.flowControlThreshold = 64;
uartconf.idleTimeout = 6; // 6ms后串口空闲则发送串口空闲事件,参数不可设为0
uartconf.rx.maxBufSize = 128;
uartconf.tx.maxBufSize = 128;
uartconf.intEnable = TRUE;
// 开启串口0
HalUARTOpen(HAL_UART_PORT_0, &uartconf);
/* 新添加代码 END */
// 初始化LED灯
// Init_IndicatorLight();
// 通知g_gateway_taskid任务有LED灯闪烁事件发生
// osal_set_event(g_gateway_taskid, EVENT_FLASH_LED); // 关掉上一篇文章的LED灯闪烁功能
// 开始定期发送数据给协调器
// osal_set_event(g_gateway_taskid, EVENT_PERIOD_SEND_DATA);
}
创建串口事件处理回调函数。
static void Handle_UartEvent(uint8 port, uint8 event)
{
// 处理串口0接收事件
if(port==HAL_UART_PORT_0)
{
switch(event)
{
// 当发生 RX 事件
case HAL_UART_RX_FULL:
case HAL_UART_RX_ABOUT_FULL:
case HAL_UART_RX_TIMEOUT:
{
// 读取接收数据的长度
uint16 rxbuflen = Hal_UART_RxBufLen(HAL_UART_PORT_0);
// 创建接收数据内存
uint8* rxbuf = osal_mem_alloc(rxbuflen);
// 若内存创建成功
if(rxbuf!=NULL)
{
// 读取 RX 数据
HalUARTRead(HAL_UART_PORT_0, rxbuf, rxbuflen);
// 直接透传给协调器
SendMessageToCoor(rxbuf, rxbuflen);
// 释放内存
osal_mem_free(rxbuf);
}
}
break;
default:
break;
}
}
}
创建数据无线发送函数,发送数据到协调器中。
static void SendMessageToCoor(uint8* data, uint16 datalen)
{
// 目标地址为协调器
afAddrType_t CoorAddr = {0};
CoorAddr.addrMode = (afAddrMode_t)Addr16Bit;
CoorAddr.addr.shortAddr = 0x00;
CoorAddr.endPoint = GATEWAY_ENDPOINT;
// 发送数据到协调器
AF_DataRequest(&CoorAddr, &g_gateway_epdesc,
TRANSMISSION_CLUSTERID, datalen, data,
&g_transid, AF_DISCV_ROUTE, AF_DEFAULT_RADIUS);
}
要使用自己的串口功能,则必须确保关闭了Z-Stack内部的串口功能,不然两者会产生冲突,串口会出现不可预期的数据。要关闭Z-Stack内部的串口功能,我们只需要屏蔽以下几个预编译即可。
屏蔽掉Z-Stack默认开启的MT_TASK
、MT_SYS_FUNC
、MT_ZDO_FUNC
。
------------------------------------------------------------- Gateway.c -------------------------------------------------------------
在自己的任务初始化函数当中配置串口参数,开启串口0功能。
void Gateway_Init( uint8 task_id )
{
halUARTCfg_t uartconf;
……
// 配置串口参数
uartconf.baudRate = HAL_UART_BR_115200;
uartconf.callBackFunc = NULL;
uartconf.configured = TRUE;
uartconf.flowControl = FALSE;
uartconf.flowControlThreshold = 64;
uartconf.idleTimeout = 6; // 6ms后串口空闲则发送串口空闲事件,参数不可设为0
uartconf.rx.maxBufSize = 128;
uartconf.tx.maxBufSize = 128;
uartconf.intEnable = TRUE;
// 开启串口0
HalUARTOpen(HAL_UART_PORT_0, &uartconf);
……
}
发送接收数据到PC端。
static void Gateway_MessageMSGCB( afIncomingMSGPacket_t *pkt )
{
switch ( pkt->clusterId )
{
case TRANSMISSION_CLUSTERID:
{
// 置反LED灯开关状态
// osal_set_event(g_gateway_taskid, EVENT_FLASH_LED);
// 发送接收数据到PC端
HalUARTWrite(HAL_UART_PORT_0, pkt->cmd.Data, pkt->cmd.DataLength);
}
break;
}
}
分别按下终端设备和协调器设备工程的编译按钮,0错误0警告。然后我们将程序分别烧录到两个CC2530设备中,等待设备自动组网后,通过“串口调试助手”发送数据给终端节点,然后再通过“串口调试助手”观察协调器就可以看到终端设备发送过来的数据了。
软件源码的下载地址
在下面的评论区有给出。
大家的支持就是我分享技术的动力,希望大家需转载时能附上原作者的博客:https://blog.csdn.net/u012993936,谢谢。
> Zigbee进阶:功能模块
> 免费的Zigbee抓包神器!比Ubiqua还好用!
文章都看完了,随手点个赞吧~
↓↓↓ ↓↓↓