7天快速入門Zigbee:串口透傳數據
1. 概述
這篇文章主要是想讓大家瞭解如何配置Z-Stack中串口功能的參數,如何開啓串口功能,如何使用串口發送和接收功能,最後實現我們要的串口透傳功能。
2. 配置串口參數,開啓串口功能
在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_115200HAL_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);
……
}
3. 串口發送和接收功能
串口發送數據就只需要調用“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
”事件。
下面我們會在具體實現串口透傳功能時應用串口發送和接收功能。
4. 串口透傳功能
串口透傳功能具體爲終端設備接收到PC端通過串口發送過來的數據,然後將數據發送至協調器端,協調器端接收到數據後再通過串口將數據發送至PC端。
以下代碼是基於上篇文章《7天快速入門Zigbee:無線傳輸與接收》代碼的基礎上編程的。
4.1. 終端節點編程
要使用自己的串口功能,則必須確保關閉了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);
}
4.2. 協調器編程
要使用自己的串口功能,則必須確保關閉了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,謝謝。