zoukankan      html  css  js  c++  java
  • 基于CC2530的ZigBee转以太网网关的设计与实现

    *已刊登至:《无线电》8月刊

    物联网技术的实现中,无线技术是必不可少的部分。

    近年无线技术的发展,将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模块。协调器作为TCPclient连接以太网内的主机,并将终端节点发来的数据通过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的驱动程序包加入到project中。如图5所看到的,须要注意的是。CC2530的LCD驱动的部分引脚与SPI1的几个引脚是复用的,须要将和LCD有关的编译项去掉。避免发生冲突。导致SPI不可用。详细方法为在project选项的编译子项里,去掉“LCD_SUPPORTED”,并加入“HAL_LCD=FALSE”。



    Image

    图5 加入W5500驱动程序包到project

    Image

    图6 改动编译项

    • zstack应用任务程序编写

    zstack是TI公司依照Zigbee协议编写的协议栈程序,提供了完备的应用函数供用户调用。用户能够在应用层加入自己的任务和事件来完毕传感器数据採集、节点通信应答等功能,有关协议栈的任务调度机制还须要读者自行学习,这里介绍怎样在应用层维护W5500的通信。在本文的系统中,为了减少与协议栈的耦合度(尽量不在协议栈原有文件里增删改)。开机后,当系统执行起来后。我们将W5500的初始化和配置函数放在了应用层的任务里执行,协调器在完毕组网后,应用层的任务主要有下面两个事件,一个是W5500网络连接的维护,还有一个是终端节点的数据处理。当中第一个事件为定时事件,每隔一段时间就要对W5500的网络状态进行一次轮询处理。

    在project中。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);//初始化调试port

    WIZ_SPI_Init();//初始化 SPI

        Reset_W5500();

    printf(“W5500 Init… ”);

    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… ”);

    }

    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中,我们启动TCPclient程序,用来维护设备与server的连接,使得设备在插上网线后可以及时连上server。这样当协调器收到其它终端节点的数据,处理后就行调用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长亮后,网络建立完成。这时程序的网络维护事件触发,開始连接server。通过网络调试助手能够看到,有client连接。正是我们的网关节点。



    网关节点准备完成,接下来打开终端节点,开机后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

    与我们很多其它交流:wiznetbj@wiznet.co.kr

    WIZnet官方站点:http://www.iwiznet.cn

    WIZnet官方微博:http://weibo.com/wiznet2012

  • 相关阅读:
    UE4智能指针:TUniquePtr
    浅析UE4垃圾回收
    UE4中资源的引用
    ELF文件基础
    【JVM】JVM和Java 体系架构
    【Java多线程】Java线程生命周期、线程同步、线程通信(二)
    【Java多线程】Java多线程基础(一)
    【Java面试题】MySQL索引底层为什么用到B+树
    【算法】B树、B+树详解
    【Kafka】 Kafka的简介与架构(三)
  • 原文地址:https://www.cnblogs.com/gavanwanggw/p/7043432.html
Copyright © 2011-2022 走看看