基於CC2530的ZigBee轉以太網網關的設計與實現

物聯網技術的實現中,無線技術是不可缺少的部分。近年無線技術的發展,將ZigBee推入人們的視線中,那麼ZigBee是怎樣的一種技術呢?帶着疑問,我查詢了它的來歷:

ZigBee,來源於蜜蜂的八字舞,由於蜜蜂(bee)是靠飛翔和“嗡嗡”(zig)地抖動翅膀的“舞蹈”來與同伴傳遞花粉所在方位信息,可以想象蜜蜂依靠這樣的方式構成了群體中的通信網絡!
是不是有點意思,那麼隨之 ZigBee的出現就成了一種我們熟知的無線組網通訊技術並廣為應用。本篇就帶你認識ZigBee,並實現一種常見應用:ZigBee轉以太網網關。

  • 將ZigBee技術連接互聯網

Image

圖1 智能家居中ZigBee應用示意圖

ZigBee是一種低成本,低功耗的近距離無線組網通訊技術,在智能家居、智能樓宇、工業監控等領域均有廣泛應用。基於ZigBee的智能家居應用,如圖1所示,用戶在家庭中安裝一個主控中心(ZigBee網關),及若干個與家電設備相連的分控終端,來遠程操控所有家用電器,設想下躺在沙發上控制廚房的電飯煲煮飯是不是無限暢快呢?如果網關可以連到互聯網上,甚至遠在公司,打開手機就能登錄到家裡的網關查看家裡的情況。 作為開源愛好者,可能很多人已經做過ZigBee方面的開發,一般使用TI公司的CC2530射頻芯片較多,TI公司也針對這類芯片制定了完備的軟件協議棧zstack。CC2530受處理器速度和內存限制,無法運行TCP/IP協議,用戶往往通過串口獲得協調器匯聚的數據。想要讓協調器直接連上互聯網只能藉助其他以太網芯片,由於W5500以太網芯片在硬件上實現了TCP/IP協議,即使像CC2530這樣的8位單片機也可以自如操控W5500,實現聯網,無需藉助其他輔助處理器做數據轉換。 本文我們使用兩個CC2530模塊,組建一個小型的ZigBee網絡,一個作為協調器建立網絡,另一個作為終端節點不斷的採集溫濕度數據並發送給協調器。為實現協調器的聯網,我們在協調器上外接一個W5500模塊,協調器作為TCP客戶端連接以太網內的主機,並將終端節點發來的數據通過W5500上傳給主機。應用系統的實物如圖2所示: Zigbee2

Image
圖2系統實物

  • 準備工作

1. 安裝編譯環境IAR Embedded Workbench for MCS-51 7.51A
2. 安裝協議棧ZStack-CC2530-2.2.2-1.3.0
3. 安裝CC2530模塊調試下載器驅動

  • 硬件連接與驅動程序重寫

W5500在硬件上實現TCP/IP協議,用戶幾乎不需要任何網絡基礎,並且WIZnet公司針對W5500也有很好的程序包的支持,只需調用socket函數,就可以完成網絡的建立和通訊,當然,要獲得以上便利,我們要先將CC2530與W5500連接起來,並能夠發送數據控制W5500。 W5500與MCU通信使用SPI接口,CC2530是帶有8051內核的無線MCU,片上有兩個SPI接口,並且與USART復用,這裡我們選擇SPI1作為W5500的控制接口。圖2為W5500模塊的管腳對應關係,控制這個模塊僅需J1插針上的1-7引腳(程序上使用輪詢機制,所以可以省略INT中斷管腳)。圖3為CC2530模塊上SPI1引腳的對應關係,另外使用P13作為W5500模塊RST(複位)的輸出控制引腳。通過排線將以上引腳對應連好後就可以編寫硬件驅動程序啦。 Zigbee3

Image
圖3 W5500模實物與原理圖管腳對照

Image

圖4 CC2530EB板SPI管腳對照

由於W5500的函數驅動庫是分層次書寫的,我們只需將SPI通信的硬件抽象層的函數重新編寫即可。 以下為CC2530的SPI1的初始化配置函數和數據收發函數的程序,以及複位管腳的控制程序:

CODE: SELECT ALL
#include “ioCC2530.h”

//SPI管腳和初始化配置

voidWIZ_SPI_Init(void)

{

PERCFG |=0×02;//打開UART1外設

P1SEL  |=0xE0;// 使能P1_7, P1_6, and P1_5 外設功能

P1SEL  &=~0×10;// 配置P1_4為普通GPIO (SPI_CS)

P1DIR  |=0×10;// 配置P1_4輸出引腳

// Set baud rate to max (system clock frequency / 8)

U1BAUD =0×00;// BAUD_M = 0

U1GCR |=0×11;// BAUD_E = 17

U1CSR &=~0xA0;// SPI 主機模式

// Configure phase, polarity, and bit order

U1GCR &=~0xC0;// CPOL = CPHA = 0

U1GCR |=0×20;// ORDER = 1

P1SEL  &=~0×08;// 配置P1_3為普通GPIO (RST)

P1DIR  |=0×08;// 配置P1_3為輸出引腳

}

//W5500 複位引腳的控制

void WIZ_RST(uint8 val)

{

if(val== LOW){

P1_3=0;//引腳拉低

}elseif(val== HIGH){

P1_3=1;//引腳拉高

}

}

//SPI CS管腳的電平控制

void WIZ_CS(uint8 val)

{

if(val== LOW){

P1_4=0;

}elseif(val== HIGH){

P1_4=1;

}

}

//SPI數據發送和接收

uint8 SPI2_SendByte(uint8 byte)

{

uint8 temp;

U1DBUF = byte;

while(!(U1CSR&0×02));//等待數據發送完畢

U1CSR &=0xFD;

temp = U1DBUF;//讀取數據緩衝區接收字節

return temp;

}

程序重寫完畢後,打開zstack的例程,將W55[*]00的驅動程序包添加到工程中。如圖5所示,需要注意的是,CC2530的LCD驅動的部分引腳與SPI1的幾個引腳是復用的,需要將和LCD有關的編譯項去掉,避免發生衝突,導致SPI不可用。具體方法為在工程選項的編譯子項里,去掉“LCD_SUPPORTED”,並添加“HAL_LCD=FALSE”。

Image

圖5 添加W5500驅動程序包到工程

Image

圖6 修改編譯項

  • zstack應用任務程序編寫

zstack是TI公司按照Zigbee協議編寫的協議棧程序,提供了完備的應用函數供用戶調用,用戶可以在應用層添加自己的任務和事件來完成傳感器數據採集、節點通信應答等功能,有關協議棧的任務調度機制還需要讀者自行學習,這裡介紹如何在應用層維護W5500的通信。在本文的系統中,為了降低與協議棧的耦合度(盡量不在協議棧原有文件中增刪改),開機後,當系統運行起來後,我們將W5500的初始化和配置函數放在了應用層的任務里執行,協調器在完成組網後,應用層的任務主要有以下兩個事件,一個是W5500網絡連接的維護,另一個是終端節點的數據處理。其中第一個事件為定時事件,每隔一段時間就要對W5500的網絡狀態進行一次輪詢處理。 在工程中,APP子欄下有sapi、SimpleCollector(協調器)、SimpleSensor(終端節點)三組文件,其中sapi中定義了節點組網和入網的應用函數,用戶不需要改寫這些程序,但是其中一些事件會調用SimpleCollector和SimpleSensor中的函數,用戶需要在這兩個文件中編寫處理函數。 先看下協調器的應用層的程序處理過程,在sapi.c文件中初始化了SAPI 任務,在這個任務中定義了ZB_ENTRY_EVENT和ZB_USER_EVENTS兩個事件,其中初始化函數SAPI_Init()中啟動了ZB_ENTRY_EVENT事件,即在任務建立後會首先進入該事件。任務事件處理函數SAPI_ProcessEvent()中在處理這兩個事件時調用zb_HandleOsalEvent()函數,交給用戶文件SimpleCollector去處理。其中ZB_ENTRY_EVENT只執行一次,用來定義設備的類型(協調器或終端節點),ZB_USER_EVENTS會執行多次,在這個事件里我們用來維護W5500的網絡連接。 以下是任務事件處理函數有關這兩個事件的處理程序:

CODE: SELECT ALL
UINT16 SAPI_ProcessEvent( byte task_id, UINT16 events )
{

……

if( events & ZB_ENTRY_EVENT )

{

uint8startOptions;

// 設備啟動應用程序時給出指示

zb_HandleOsalEvent( ZB_ENTRY_EVENT );

zb_ReadConfiguration( ZCD_NV_STARTUP_OPTION,sizeof(uint8),&startOptions);

if(startOptions& ZCD_STARTOPT_AUTO_START )

{

zb_StartRequest();

}

else

{

// led閃爍並等待外部輸入進行配置及重啟

HalLedBlink(HAL_LED_2,0,50,500);

}

return(events ^ ZB_ENTRY_EVENT );

}

// 這是最後一個要處理的事件

if( events &( ZB_USER_EVENTS ))

{

// 用戶事件傳遞給應用程序

zb_HandleOsalEvent( events );

// 這裡不要返回,稍後返回0

}

……

}

程序中都調用了zb_HandleOsalEvent( events ),我們看一下協調器中如何處理的:

voidzb_HandleOsalEvent( uint16 event )

{

uint8startOptions;

uint8logicalType;

if( event & ZB_ENTRY_EVENT )

{

initUart(uartRxCB);//初始化調試端口

WIZ_SPI_Init();//初始化 SPI

Reset_W5500();

printf(“W5500 Init…\r\n”);

set_default();

set_network();

logicalType= ZG_DEVICETYPE_COORDINATOR;//配置節點類型

zb_WriteConfiguration(ZCD_NV_LOGICAL_TYPE,sizeof(uint8),&logicalType);

startOptions= ZCD_STARTOPT_AUTO_START;// 配置啟動類型

zb_WriteConfiguration( ZCD_NV_STARTUP_OPTION,sizeof(uint8),&startOptions);

printf(“Waiting the Network…\r\n”);

}

if( event & ZB_USER_EVENTS )

{

do_tcpclient(SOCKET_TCPC);  //tcp 客戶端保持

osal_start_timerEx(sapi_TaskID, ZB_USER_EVENTS, ENTHER_TIMEOUT );

}

}

鑒於開機後ZB_ENTRY_EVENT只會執行一次,所以我們將應用的初始化函數放在這裡執行,並且配置好網絡啟動的相關參數並寫入到配置信息里,跳出這個函數後,程序就會啟動自動組網的程序,完成組網。在ZB_USER_EVENTS中,我們啟動TCP客戶端程序,用來維護設備與服務器的連接,使得設備在插上網線後能夠及時連上服務器。這樣當協調器收到其他終端節點的數據,處理後就可以調用socket發送函數發送給主機,我們的協調器就變成了一個zigbee轉以太網的網關了。 有了網關節點,我們還需要終端節點提供溫濕度數據。我們將DHT11溫濕度傳感器連接到終端節點上,並在終端節點的應用層添加採集函數,定時採集溫濕度數據。 終端節點的應用處理程序在SimpleSensor.c中定義,下面來介紹下終端節點是如何處理相關的任務的:

CODE: SELECT ALL
void zb_HandleOsalEvent( uint16 event )

{

uint8startOptions;

uint8logicalType;

if( event & ZB_ENTRY_EVENT)

{

logicalType= ZG_DEVICETYPE_ENDDEVICE;//配置成終端節點

zb_WriteConfiguration(ZCD_NV_LOGICAL_TYPE,sizeof(uint8),&logicalType);

startOptions= ZCD_STARTOPT_AUTO_START;// 配置成自啟動

zb_WriteConfiguration( ZCD_NV_STARTUP_OPTION,sizeof(uint8),&startOptions);

}

if( event & MY_START_EVT )

{

//nothing to do

}

if( event & MY_REPORT_TEMP_EVT )

{

ReadValue();//收集DHT11 數據

zb_SendDataRequest(0xFFFE, SENSOR_REPORT_CMD_ID,4,SensorValueBuf,0, AF_ACK_REQUEST,0);//給網關節點發送數據

osal_start_timerEx(sapi_TaskID, MY_REPORT_TEMP_EVT,myTempReportPeriod);// Timed loop collection

}

if( event & MY_FIND_COLLECTOR_EVT )

{

// 查找並綁定到收集器設備

zb_BindDevice( TRUE, SENSOR_REPORT_CMD_ID,(uint8 *)NULL);//找到協調器,啟動入網

}

}

一張表一目了然網關節點和終端節點的流程比較:

Image

了解了程序執行流程後,我們就可以操作設備了。 我們首先選擇SimpleCollectorEB,編譯後通過調試器將程序下載到網關節點中,然後選擇SimpleSensorEB,編譯後下載到終端節點中。我們在電腦端打開TCP/IP調試助手和串口調試助手,分別用來接收數據和觀察網關節點運行的調試信息。

Image

圖7 串口及網絡調試助手界面

網關節點上電後,串口端會打印設備的IP地址等信息,接下來LED1閃爍,表示網關節點正在組網,當Led1長亮後,網絡建立完畢,這時程序的網絡維護事件觸發,開始連接服務器,通過網絡調試助手可以看到,有客戶端連接,正是我們的網關節點。

網關節點準備完畢,接下來打開終端節點,開機後Led1閃爍,啟動網絡,入網後Led1頻閃,表示正在數據採集和發送,這時可以看到網絡調試助手上有溫濕度數據顯示,表示終端節點已經將數據發送給網關節點,網關節點解析後再通過W5500發送給了PC。至此,CC2530+W5500實現了ZigBee轉以太網網關,數據成功遞達網關節點。

以上是以太網網關的實現過程。實際應用中,我們可以看到眾多的物聯網設備,都可以藉助此網關節點,來連入Internet,比如,連接Yeelink這樣的雲平台,上傳傳感器數據,可輕鬆實現!在這裡就不給大家列舉了,關於Zigbee轉以太網網關的應用,同樣是個重要且龐大的課題,我們會接下來展開與大家繼續分享的。

  • 尾聲

目前,在設備的無線通信領域, Zigbee技術相比藍牙及WiFi,有着成本低、功耗低和低複雜度的特點,同時非常適合電池供電的設備。大量的Zigbee設備會產成龐大的數據量,這些數據不可能全部交付給協調器處理分析,但將協調器接入互聯網就完美的解決了此問題,配合W5500,協調器變成了Zigbee和以太網網關,從而使無線Zigbee網絡輕鬆接入互聯網,實現物聯網應用!

程序下載:http://wizwiki.net/forum/viewtopic.php?f=91&t=1075

By Allen,Katrina,Jerry
*已刊登至:《無線電》8月刊