7天快速入門Zigbee:串口透傳數據

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_115200
”可選。此處我們設置爲“HAL_UART_BR_9600”波特率。

flowControl

  硬件流控制,TRUE爲開啓硬件流控,FALSE爲關閉硬件流控。有硬件流控功能的可以開啓硬件流控,此處我們設置爲FALSE,關閉硬件流控功能。

flowControlThreshold

  此參數表示RX緩存達到“maxRxBufSize”之前還有多少字節空餘。當RX緩存到達“maxRxBufSizeflowControlThreshold”時,會觸發相應的應用事件:“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_FULLHAL_UART_RX_ABOUT_FULLHAL_UART_RX_TIMEOUT
HAL_UART_RX_FULL:當RX緩存數據的字節數到達“rx.maxBufSize”時,會產生“HAL_UART_RX_FULL”事件。
HAL_UART_RX_ABOUT_FULL:當RX緩存數據的字節數到達“maxRxBufSizeflowControlThreshold”時,會產生“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_TASKMT_SYS_FUNCMT_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_TASKMT_SYS_FUNCMT_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,謝謝。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章