ZIGBEE协议栈通信——阿里云上传数据(STM32)(一)

这篇具有很好参考价值的文章主要介绍了ZIGBEE协议栈通信——阿里云上传数据(STM32)(一)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

ZIGBEE协议栈介绍

Zigbee是一种低功耗、低成本的无线通信协议,特别适用于物联网设备之间的通信。Zigbee协议栈是一组硬件和软件层级结构,用于支持Zigbee设备之间的通信。

Zigbee协议栈通常由以下几个层级组成:

1. 物理层(Physical Layer):负责处理物理无线通信的细节,例如频率、功率控制和数据传输速率等。物理层使用的是2.4GHz频段,并支持多种调制方式。

2. 媒介接入控制层(Medium Access Control, MAC):负责管理通信介质的访问,以便多个设备可以按照一定的规则共享通信介质。MAC层处理一些基本的网络控制功能,例如设备的寻址、帧结构定义和冲突避免。

3. 网络层(Network Layer):负责设备的路由和组网管理。网络层处理设备之间的寻址、路由选择和数据包转发等任务。它使用分层路由技术,可实现灵活的网络拓扑结构,如星形、网状和多跳网络等。

4. 应用层(Application Layer):负责定义应用层协议和数据格式,以便不同设备之间可以进行有效的通信。应用层定义了设备之间的命令、控制和数据交换等。

Zigbee协议栈的设计目标是提供低功耗、低数据速率和较短通信距离的通信解决方案。它广泛应用于家庭自动化、智能电网、工业自动化和物联网等领域,能够支持大规模设备的无缝连接和通信。

物理层

stm32 zigbee,ZigBee,网络,物联网,mcu,iot

其中物理层可简单理解为,将一个设备的数据转化为电磁波信号之后,通过物理介质发送给另一个设备,再由另一个设备解读电磁波信号获取数据。

MAC层

stm32 zigbee,ZigBee,网络,物联网,mcu,iotMAC(媒体接入控制层)的作用是有序地利用网络通讯资源来进行可靠通信。

由于电磁波和物理介质的限制,同一物理资源在同一时刻只能被一个网络设备占用来发送数据,为控制多个网络设备发送数据。MAC层将设备划分成协调器和普通设备(路由器和终端),协调器产生并发送信标帧,普通设备根据所发出的信标帧和协调器同步,即可组建网络。

网络层(核心协议)

基于IEEE 802.15.4协议之上,主要负责多个设备之间的组网,其优点为支持更多设备进行组网、能够进行多通道通信服务、支持自组网;其次负责设备之间的控制指令和设备状态数据的传输,如温度监测、开关控制;还负责网络安全管理。

目前较多采用的是ZigBee 2007 (Pro)版本。

应用层(一套标准规范,即应用协议)

stm32 zigbee,ZigBee,网络,物联网,mcu,iot

应用层规定了对象的属性和状态。如灯具备开关的属性,这个属性由开(1)和关(0)两种状态。ZigBee技术开发一般就是指基于ZigBee应用协议的技术开发。

 为解决同一领域不同公司设备兼容性问题,ZigBee联盟根据不同领域(Profile)推出了不同的协议。stm32 zigbee,ZigBee,网络,物联网,mcu,iot

之后,为解决不同领域的兼容性问题,ZigBee联盟推出ZigBee3.0协议,提升了安全性和稳定性,是目前应用最为广泛的ZigBee应用协议。

TI 技术方案(Chipcon)

stm32 zigbee,ZigBee,网络,物联网,mcu,iot

 TI Z-Stack是ZigBee协议的代码实现, 是TI(德州仪器)针对 ZigBee 3.0 协议而开发的技术方案,也称为TI ZigBee 3.0 协议栈,包含应用层(Z-Stack 3.0)和内核层(2.7.1)。

本次项目采用TI Z-Stack3.0.1_2协议栈以及CC2530芯片进行学习开发,Z-Stack 3.0.1 是到目前为止最新版本。

Z-Stack 3.0官方下载地址 https://www.ti.com/tool/Z-STACK 。

stm32 zigbee,ZigBee,网络,物联网,mcu,iot

ZigBee设备类型

stm32 zigbee,ZigBee,网络,物联网,mcu,iot

操作系统的任务调度

任务调度涉及任务、任务池、优先级、轮询和系统调度周期。其中任务池为储存多个任务的缓冲区,适用于任务池的数据结构有多种,比如队列(先进先出)堆栈(先进后出)树状结构(遍历),这些数据结构的实现方式可以是静态的数组或者是动态的链表等;优先级为在同一时刻执行任务的等级划分;轮询为系统每隔一段时间在任务池中检查需要处理的任务;“每隔一段时间”指的就是操作系统调度周期。

简单的操作系统原理代码如下:

void main()
{
    initLed();//初始化LED灯
    taskListInit();//初始化任务池
    
    addTask(2000, TASK_LED_ON);//往任务池中添加一个任务,即2s后打开LED
    addTask(3000, TASK_LED_OFF);//往任务池中添加一个任务,即3s后关闭LED
    
    //每隔1ms轮询1次
    while(1) {
        delayMs(1);//暂停1ms
        polling();//轮询
    }
}

OSAL(Operating System Abstraction Layer,系统抽象层)

可以通俗地理解为一个简化版的操作系统,为Z-Stack的正确运行提供了内存管理、中断管理和任务调度等基本功能。

ZMain.c文件,可以找到main()函数,其代码如下:

int main( void )  
{  
  // Turn off interrupts  
  osal_int_disable( INTS_ALL );   	// 关闭所有中断
  
  // Initialization for board related stuff such as LEDs  
  HAL_BOARD_INIT();  	// 初始化板载资源,比如PA、时钟源等
  
  // Make sure supply voltage is high enough to run  
  zmain_vdd_check();  // 检测供电电压是否可以支撑芯片正常运行
  
  // Initialize board I/O  
  InitBoard( OB_COLD );  // 初始化板载I/O,比如按键配置为输入
  
  // Initialze HAL drivers  
  HalDriverInit();  // 初始化硬件适配层,比如串口、显示器等
  
  // Initialize NV System  
  osal_nv_init( NULL );  // 初始化NV(芯片内部FLASH的一块空间)
  
  // Initialize the MAC  
  ZMacInit();  // 初始化MAC层(数据链路层)
 
  // Determine the extended address  
  zmain_ext_addr();  // 确定芯片的物理地址
  
#if defined ZCL_KEY_ESTABLISH  
  // Initialize the Certicom certificate information.  
  zmain_cert_init();  // 初始化认证信息
#endif  
  
  // Initialize basic NV items  
  zgInit();  // 初始化存储在NV中的协议栈全局信息,如网络启动方式等
  
#ifndef NONWK  
// Since the AF isn't a task, call it's initialization routine
  afInit();  // 初始化AF(射频)
#endif  
  
  // Initialize the operating system  
  osal_init_system();  // 初始化OSAL(操作系统抽象层)
  
  // Allow interrupts  
  osal_int_enable( INTS_ALL );  // 使能所有中断
  
  // Final board initialization  
  InitBoard( OB_READY );  // 初始化板载IO资源,比如按键
  
  // Display information about this device  
  zmain_dev_info();  // 在显示器上显示设备物理地址
 
  /* Display the device info on the LCD */  
#ifdef LCD_SUPPORTED  
  zmain_lcd_init();  // 在显示器上显示设备信息,比如制造商等
#endif   


#ifdef WDT_IN_PM1  
  /* If WDT is used, this is a good place to enable it. */  
  WatchDogEnable( WDTIMX );  // 启动看门狗功能
#endif  

  /* 进入系统轮询 */  
  osal_start_system(); // No Return from here  
 

  return 0;  // Shouldn't get here.  
} // main()

上述代码中有两个关键的函数,代码如下:

//初始化OSAL,包括初始化任务池
osal_init_system();

//轮询任务池
osal_start_system();

osal_init_system()函数代码如下:

uint8 osal_init_system( void )
{
#if !defined USE_ICALL && !defined OSAL_PORT2TIRTOS
  // 初始化内存分配系统
  osal_mem_init();
#endif /* !defined USE_ICALL && !defined OSAL_PORT2TIRTOS */

  // 初始化消息队列
  osal_qHead = NULL;

  // 初始化OSAL定时器
  osalTimerInit();

  // 初始化电源管理系统
  osal_pwrmgr_init();

#ifdef USE_ICALL
  osal_prepare_svc_enroll();
#endif /* USE_ICALL */

  // 初始化任务池
  osalInitTasks();

#if !defined USE_ICALL && !defined OSAL_PORT2TIRTOS
  // Setup efficient search for the first free block of heap.
  osal_mem_kick();
#endif /* !defined USE_ICALL && !defined OSAL_PORT2TIRTOS */

#ifdef USE_ICALL
  // Initialize variables used to track timing and provide OSAL timer service
  osal_last_timestamp = (uint_least32_t) ICall_getTicks();
  osal_tickperiod = (uint_least32_t) ICall_getTickPeriod();
  osal_max_msecs = (uint_least32_t) ICall_getMaxMSecs();
  /* Reduce ceiling considering potential latency */
  osal_max_msecs -= 2;
#endif /* USE_ICALL */

  return ( SUCCESS );
}

 osal_start_system()函数代码如下:

void osal_start_system( void )
{
#ifdef USE_ICALL
  /* Kick off timer service in order to allocate resources upfront.
   * The first timeout is required to schedule next OSAL timer event
   * as well. */
  ICall_Errno errno = ICall_setTimer(1, osal_msec_timer_cback,
                                     (void *) osal_msec_timer_seq,
                                     &osal_timerid_msec_timer);
  if (errno != ICALL_ERRNO_SUCCESS)
  {
    ICall_abort();
  }
#endif /* USE_ICALL */

#if !defined ( ZBIT ) && !defined ( UBIT )
  //主循环
  for(;;)
#endif
  {
	//系统轮询调度
    osal_run_system();

#ifdef USE_ICALL
    ICall_wait(ICALL_TIMEOUT_FOREVER);
#endif /* USE_ICALL */
  }
}

在osal_start_system()函数的主循环中,循环调用了 osal_run_system()函数,该函数主要工作轮询任务池。

void osal_run_system( void )    
{    
    uint8 idx = 0;    
   
  /* 更新时间,并整理出到期的任务。系统的时钟周期是:320us */  
  osalTimeUpdate();  
  Hal_ProcessPoll();// 硬件适配层中断查询  
    
  do {    
    if (tasksEvents[idx])// 查看是否有任务需要处理  
    {    
      break;    
    }    
  } while (++idx < tasksCnt);// 轮询整个任务池  
    
  if (idx < tasksCnt)//循环结束后,如果idx < tasksCnt表示任务池有任务需要处理
  {    
    uint16 events;    
    halIntState_t intState;   
    HAL_ENTER_CRITICAL_SECTION(intState);//关闭中断  
    events = tasksEvents[idx];//evets中保存了该任务中的待处理事件  
    tasksEvents[idx] = 0;//清空此任务中的所有待处理事件 
    HAL_EXIT_CRITICAL_SECTION(intState);//恢复中断  
    
    activeTaskID = idx;    
    events = (tasksArr[idx])( idx, events ); // 处理任务中的事件  
    activeTaskID = TASK_NO_TASK;    
    
    HAL_ENTER_CRITICAL_SECTION(intState);//关闭中断  
    tasksEvents[idx] |= events;//保存还没被处理的事件到任务中  
    HAL_EXIT_CRITICAL_SECTION(intState);//恢复中断  
  }    

#if defined( POWER_SAVING ) && !defined(USE_ICALL)    
 else// Complete pass through all task events with no activity? {
    osal_pwrmgr_powerconserve(); //如果没有任务需要处理则进入低功耗  
 }    
#endif    
    
  /* Yield in case cooperative scheduling is being used. */    
#if defined (configUSE_PREEMPTION)&&(configUSE_PREEMPTION == 0) {    
    osal_task_yield();    
 }    
#endif

Z-Stack 3.0采用了独热码(one-hot code)的方式对事件类型(UINT16 events)进行编码。

stm32 zigbee,ZigBee,网络,物联网,mcu,iot

假设events的值为0000 0000 0101 0101,其中的右起第1、3、5和7位为1,于是可以理解为事件集合events包含了用户事件A、C、E和G。可以得到events最多可以包含15种用户事件,和一种系统事件。

创建事件:在zcl_samplesw.h文件中定义一个用户事件,代码如下:

#define SAMPLEAPP_TEST_EVT 0x0040

处理事件:在zcl_samplesw.c文件中的应用层事件处理函数中添加相关的处理,代码如下:

  if ( events & SAMPLEAPP_TEST_EVT )
  {
    printf("Hello World!\r\n");

    //把events中的第3位清0,然后把这个值作为函数的返回值,表示events中的这个事件已经被处理了
    return ( events ^ SAMPLEAPP_TEST_EVT );
  }

触发事件

在OSAL_Timers.h文件中,可以找到触发事件的API,函数声明如下:

uint8 osal_start_timerEx(uint8 task_id,uint16 event_id,uint32 timeout_value);

如果希望在触发事件的3s后处理刚才自定义的事件,可在应用层初始化函数zclSampleSw_Init()的末尾位置添加如下代码:

osal_start_timerEx(
    zclSampleSw_TaskID,//标记本事件属于应用层任务
    SAMPLEAPP_TEST_EVT,//标记本事件的类型
    3000);//表示3000ms后才处理这个事件
//zclSampleSw_TaskID是一个全局变量,用于标记这个事件是属于应用层任务的。

动态内存的申请和释放

/**
 * @fn osal_mem_alloc
 * 
 * @brief 动态申请内存空间
 *
 * @param   size - 申请多少个字节的内存空间
 * 
 * @return  返回该内存空间的指针
 */
void *osal_mem_alloc( uint16 size );

/**
 * @fn osal_mem_free
 * 
 * @brief 动态释放内存空间
 *
 * @param   ptr - 待释放的内存空间指针
 * 
 */
void osal_mem_free( void *ptr );

动态内存操作

/**
 * @fn osal_memcpy
 * 
 * @brief 把内存空间的内容复制到另一个内存空间中
 *
 * @param   void* - 目标内存空间
 * @param   const void GENERIC * - 源内存空间
 * @param   unsigned int - 复制多少个字节
 * 
 * @return
 */
void *osal_memcpy(void*, const void GENERIC *,unsigned int);  

/**
 * @fn osal_memset
 * 
 * @brief 把内存空间的值设置为指定的值
 *
 * @param   dest - 内存空间
 * @param   value - 指定的值
 * @param   len - 把从dest起的len个字节的存储空间的值设置为value
 * 
 * @return
 */
extern void *osal_memset( void *dest, uint8 value, int len );

示例代码如下:

//事件:SAMPLEAPP_TEST_EVT
if ( events & SAMPLEAPP_TEST_EVT )
{
    //字符串:”Hello World!\n”
    char *str = "Hello World!\n";

    //从堆空间中申请32个字节的内存空间
    char *mem = osal_mem_alloc(32);
    
    //如果申请成功
    if (mem != NULL) {
        //清零内存空间
        osal_memset(mem, 0, 32);

        //将字符串拷贝到内存空间中
        osal_memcpy(mem, str, osal_strlen(str));

        //打印内存空间内存
        printf(mem);

        //释放内存空间
        osal_mem_free(mem);
    }

    //重新触发事件,3000毫秒后执行
    osal_start_timerEx(zclSampleSw_TaskID, SAMPLEAPP_TEST_EVT, 3000);

    //消除已经处理的事件,然后返回未处理的事件
    return ( events ^ SAMPLEAPP_TEST_EVT );    
}

内容来自善学坊,如有侵权,立即删除。

ZigBee 3.0 开发指南 (topthink.com)

/**********************************分割线**********************************

后续章节内容:文章来源地址https://www.toymoban.com/news/detail-787928.html

二、ZIGBEE单播(完成)

三、ZIGBEE串口发送及数据上传(待完成)

到了这里,关于ZIGBEE协议栈通信——阿里云上传数据(STM32)(一)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • (新手必看)自定义数据传输通信协议+STM32代码详解

           本篇博客主要学习和了解一些单片机协议的格式,在对传输大数据或者要求准确性的时候,都需要通过协议来发送接收,下面通过了解协议的基本构成和代码来分析和实现协议的发送和接收。本篇博客大部分是自己收集和整理,如有侵权请联系我删除。 本次博客开发

    2024年02月03日
    浏览(33)
  • lesson 12 Zigbee绑定通信

    目录 Zigbee绑定通信 通信原理 实验过程 实现步骤 实验现象  实验分析 1、Zigbee一共有五种通信方式:单播、广播、组播、MAC、广播 2、绑定是Zigbee的一种基本通信方式,具体绑定通信又分为三种模式,模式大同小异,在这里我只拿源绑定来说明 3、绑定通信:发送模块必须要

    2024年02月12日
    浏览(22)
  • Matter协议与Zigbee

            Matter是Zigbee3.0互联互通梦想的继任者,Zigbee3.0的高度开放性导致Zigbee网络架构中的协调器厂家可以控制是否允许第三方厂家的终端设备接入网络,导致入网许可的私有化,直接导致了Zigbee互联互通梦想的破灭。         2019年12月,Zigbee联盟联合苹果、亚马逊、

    2024年02月05日
    浏览(21)
  • STM32教学——JQ8900语音模块+光照传感器+4G模块数据上传阿里云物联网

    原理图 PCB 实物图 选用EC200U模块,集成4g和GPS以及蓝牙功能 通过串口2与4G模块串口连接,串口传输数据指令。 这个时候4g模块已经成功启动,下一步注册进阿里云物联网平台 然后就是上发数据给阿里云平台 上发了之后阿里云就可以收到这些数据 根据厂家提供的手册资料,可

    2024年03月14日
    浏览(31)
  • STM32+ESP8266+DHT11通过MQTT协议连接新版ONENET云平台上传数据

    项目讲解视频 新版 云平台搭建视频演示 单片机代码修改演示视频 APP参数修改 实物演示 前段时间ONENET云平台进行了升级更新,此前平台的多协议接入(包含旧版MQTT、HTTP、EDP、Modbus、TCP透传等)接口已经隐藏,后续应该会下架,为了能够后续继续使用ONENET云平台,就需要学

    2024年02月09日
    浏览(27)
  • STM32+ESP8266+APP连接阿里云监测环境温湿度系列笔记1:阿里云物联网平台配置及数据上传

            在数据传递过程中阿里云物联网平台相当于服务器,ESP8266为客户端,通过路由器连接服务器时需要在物联网平台创建设备,具体过程如下: 1. 首先 在物联网平台创建公共实例,并点击进入, 图1 2.可见设备接入物联网平台的整体流程如图2中红色方框所示, 接下

    2024年02月04日
    浏览(37)
  • 了解无线通信技术WiFi,Sub 1G,Zigbee

    本文主要记录一些无线通信技术的常识,用处不大但是至少能让你在别人谈论通信的时候能够听得懂。 通信技术是移动互联网中至关重要的一环,从2G到今天的5G,都显示了移动互联网通信技术的进步。5G通信技术,即第五代移动通信技术,是最新一代的蜂窝移动通信技术,也

    2024年02月11日
    浏览(43)
  • lesson7-1 Zigbee协议栈的使用

    目录 协议栈的使用 协议栈的安装和协议栈工程创建 协议栈工程配置 选项卡选择 用户代码编写注意 信道选择及PANID分配 首先进行协议栈的安装 如何创建自己的协议栈工程: (1)先把整个协议栈目录拷贝到自己指定地方 (2)只留下两个文件夹 (3)进入Sample样例目录内 只

    2024年02月11日
    浏览(22)
  • STM32通信协议

    通信接口 通信的目的:将一个设备的数据传送到另一个设备,扩展硬件系统 通信协议:制定通信的规则,通信双方按照协议规则进行数据收发 USART: TX是数据发送脚 RX是数据接收脚 I2C: SCL是时钟 SDA是数据 SPI: SCLK是时钟 MOSI是主机输出数据脚 MISO是主机输入数据脚 CS是片选用于

    2024年03月28日
    浏览(30)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包