精华内容
下载资源
问答
  • 2021-05-27 17:54:43

    一、串口通信原理

    1.什么是UART

    ​ UART : Universal Asynchronous Receiver/Transmitter 通用异步收发器
    ​ 一种常用也是最简单的串行数据传输协议。数据线只需要两根就可以实现全双工。
    ​ Tx:发送数据线
    ​ Rx:接收数据线
    ​ A B
    ​ Tx <-----------> Rx
    ​ Rx <-----------> Tx
    ​ GND<-----------> GND

    2.上位机与下位机

    ​ 模块之间的通信,根据其在系统中的功能与作用可分为上位机 与 下位机。

    上位机:
    把处理性能强的计算机称为上位机。数据的统一处理都在上位机完成。

    下位机:
    把数据采集和发送的终端,处理性能单一的计算机,称为下位机。

    一般一个上位机会对应多个下位机,这种模式可以使数据处理的更加全面,同时也大大降低成本。

    3.UART数据帧

    UART protocol 串口协议
    串口发送和接收数据是以帧为单位,Frame

    1帧(Frame) = 1start bit(起始位) + 5~9bits数据位 + 0/1bit校验位 + stop bits(0.5,1,1.5)停止位
    起始位:一个周期的低电平
    数据位:5~9bits数据位,具体是多少bits,需要双方协商,并且传送先传送最低位(LSB)
    校验位:
    	0bit:没有校验
    	1bit:有校验
    		奇校验:数据位+校验位的这一段数据里的1的个数是奇数。
    		偶校验:数据位+校验位的这一段数据里的1的个数是偶数。
    停止位:高电平
    	
    	1个停止位
    			
    Baudrate(波特率):传输速率,即没一个秒传输了多少个bit位
    	4800
    	9600
    	115200bps: bits per second
    

    二、串口配置

    1. 串口初始化相关的结构体halUARTCfg_t

    typedef struct
    {
      bool                configured;//是否设置串口
      uint8               baudRate; //波特率设置
      bool                flowControl;//控制流设置
      uint16              flowControlThreshold;//RX缓存安全字节数(了解)
      uint8               idleTimeout;//RX来数据超时时间(了解)
      halUARTBufControl_t rx;//接收数据长度
      halUARTBufControl_t tx;//发送数据长度
      bool                intEnable;//中断使能
      uint32              rxChRvdTime;//接收数据时间
      halUARTCBack_t      callBackFunc;//回调函数
    }halUARTCfg_t;
    

    2. 串口初始化示例

    static void InitUart(void)
    {
    	halUARTCfg_t   uartConfig;
    	uartConfig.configured           = TRUE;  //
    	uartConfig.baudRate             = HAL_UART_BR_38400;
    	uartConfig.flowControl          = FALSE;
    	uartConfig.flowControlThreshold = 64; 
    	uartConfig.rx.maxBufSize        = 128;  
    	uartConfig.tx.maxBufSize        = 128;  
    	uartConfig.idleTimeout          = 6;    
    	uartConfig.intEnable            = TRUE;                
    	uartConfig.callBackFunc         = SerialApp_CallBack;   
    	HalUARTOpen (SERIAL_APP_PORT, &uartConfig);   
    }
    

    3.串口实现

    ​ 串口的读操作函数为HalUARTRead(),主要功能是读取上位机通过串口发送至设备节点的数据。

    ​ uint16 HalUARTRead(uint8 port, uint8 *buf, uint16 len)
    ​ @port:串口端口的设置,可以设置为串口0或串口1;
    ​ @buf:数据缓冲区;
    ​ @len:数据长度。
    ​ 返回值:实际成功读取的字节数

    串口的操作函数为HalUARTRead(),主要功能是读取上位机通过串口发送至设备节点的数据。

    uint16 HalUARTRead(uint8 port, uint8 *buf, uint16 len)
    {
     
    #if (HAL_UART_DMA == 1)
      if (port == HAL_UART_PORT_0)  return HalUARTReadDMA(buf, len);
    #endif
    #if (HAL_UART_DMA == 2)
      if (port == HAL_UART_PORT_1)  return HalUARTReadDMA(buf, len);
    #endif
    #if (HAL_UART_ISR == 1)
      if (port == HAL_UART_PORT_0)  return HalUARTReadISR(buf, len);
    #endif
    #if (HAL_UART_ISR == 2)
      if (port == HAL_UART_PORT_1)  return HalUARTReadISR(buf, len);
    #endif
     
    #if HAL_UART_USB
      return HalUARTRx(buf, len);
    #else
      return 0;
    #endif
    }
    

    串口的操作函数为HalUARTWrite(),主要功能是实现向上位机或其他设备通过串口发送数据。
    uint16 HalUARTWrite(uint8 port, uint8 *buf, uint16 len)
    @port:串口端口的设置,可以设置为串口0或串口1;
    @buf:数据缓冲区;
    @len:数据长度。
    返回值:实际成功发送的字节数

    uint16 HalUARTWrite(uint8 port, uint8 *buf, uint16 len)
    { 
    #if (HAL_UART_DMA == 1)
      if (port == HAL_UART_PORT_0)  return HalUARTWriteDMA(buf, len);
    #endif
    #if (HAL_UART_DMA == 2)
      if (port == HAL_UART_PORT_1)  return HalUARTWriteDMA(buf, len);
    #endif
    #if (HAL_UART_ISR == 1)
      if (port == HAL_UART_PORT_0)  return HalUARTWriteISR(buf, len);
    #endif
    #if (HAL_UART_ISR == 2)
      if (port == HAL_UART_PORT_1)  return HalUARTWriteISR(buf, len);
    #endif
     
    #if HAL_UART_USB
      HalUARTTx(buf, len);
      return len;
    #else
      return 0;
    #endif
    }
    

    三、程序设计

    void SerialApp_CallBack(uint8 port, uint8 event)   //接收数据会触发
    {
        unsigned char buf[32]={0};
        HalUARTRead(HAL_UART_PORT_0,buf,32);
        if(strcmp((char*)buf,"hello") == 0)
        {
            led_ctrl(LED0,LED_ON);
            led_ctrl(LED1,LED_ON);
        }
        else if(strcmp((char*)buf,"byebye") == 0)
        {
            led_ctrl(LED0,LED_OFF);
            led_ctrl(LED1,LED_OFF);
        }
    
    }
    
    static void InitUart(void)
    {
    	halUARTCfg_t   uartConfig;
    	uartConfig.configured           = TRUE;  
    	uartConfig.baudRate             = HAL_UART_BR_9600; //设置波特率
    	uartConfig.flowControl          = FALSE;
    	uartConfig.flowControlThreshold = 64; 
    	uartConfig.rx.maxBufSize        = 128;  
    	uartConfig.tx.maxBufSize        = 128;  
    	uartConfig.idleTimeout          = 6;    
    	uartConfig.intEnable            = TRUE;                
    	uartConfig.callBackFunc         = SerialApp_CallBack;  //设置回调函数 
    	HalUARTOpen (HAL_UART_PORT_0, &uartConfig);   
    }
    
    if ( events & GENERICAPP_MY_EVT1 )	//事件
      {//事件要做的事
        P1_0 = !P1_0;
        P1_1 = !P1_1;
        unsigned char str[32]={"hello,are you ok?\r\n"};
        HalUARTWrite(HAL_UART_PORT_0,str,strlen((char *)str));
        unsigned char temp[32];
        if(Start_DHT11() == 1)	//读取dht11数据
        {
          sprintf(temp,"temperature:%d,humidity:%d\r\n",temperature,humidity);
          HalUARTWrite(HAL_UART_PORT_0,temp,strlen((char *)temp));
        }
        else
        {
            HalUARTWrite(HAL_UART_PORT_0,"error\r\n",strlen("error\r\n"));
        }
        return (events ^ GENERICAPP_MY_EVT1);
      }
    
    更多相关内容
  • 7天快速入门Zigbee自定义通信协议设计基础 目录 概述 串口通信的数据结构 基于有限状态机的同步方法 1. 概述   串口通信是目前单片机和DSP等嵌入式系统之间,以及嵌入式系统与 PC 机或无线模块之间的一种...

    7天快速入门Zigbee:自定义通信协议设计基础



    点击左上角的“关注”,定期更新Zigbee最新资讯,总有你想要的信息!

    目录

    1. 概述
    2. 串口通信的数据帧结构
    3. 基于有限状态机的帧同步方法

    1. 概述

      串口通信是目前单片机和DSP等嵌入式系统之间,以及嵌入式系统与 PC 机或无线模块之间的一种非常重要且普遍使用的通信方式。在嵌入式系统的硬件结构中,通常只有一个8位或16位的CPU,不仅要完成主流程的工作,同时还要处理随时发生的各种中断,因而嵌入式系统中的串口通信程序设计与PC机有很大的不同。若嵌入式系统中的中断服务子程序在系统运行过程中占用了较多的时间,就有可能在中断服务子程序正运行时,又产生一个同类型或其它类型的中断,从而造成主程序得不到执行或后续中断数据丢失等问题。所以嵌入式系统中的串口通信虽然看似简单,但其中仍有许多问题值得研究,例如串口通信过程中的帧同步问题。
      本文推荐一种“基于有限状态机的帧同步方法”给大家,可以快速有效地实现了串口通信的同步,而且程序结构清晰,便于维护,也易于向其它的串口通信协议移植。

    2. 串口通信的数据帧结构

      现在的单片机系统中,往往需要由多个独立的控制模块来共同完成功能。不同模块之间可以通过串口,RS232,SPI等不同的通信接口来进行通信,在通信过程中我们可以加入一些通信协议,以提高系统的可靠性和稳定性;而要完成特定的通信协议,就得有一定的同步机制。下面介绍一下简化的通信数据帧结构,以便分析说明嵌入式系统通信过程中的帧同步方法。
    假定串口发送的数据帧结构为:

    帧头帧长度帧类型帧数据校验

    其中:“帧头”用于同步,一般是一个或多个字节,本文中假定数据帧同步头有2字节(0xFE、0xEF);“帧长度”表示数据包中除去“帧头”和“帧长度”的字节数,即“帧类型”、“帧数据”和“校验”的总长度;“帧类型”为通信协议里规定的命令类型;“帧数据”为应发送的主要信息;“校验”可以采用简单的单字节“异或”的方法,复杂点的可以采用“CRC校验”。

    3. 基于有限状态机的帧同步方法

      下面我们就来说说“基于有限状态机的帧同步方法”,该方法是将数据帧的接收过程分为若干个状态:“接收帧头HEAD1状态”、“接收帧头HEAD2状态”、“接收帧长度状态”、“接收帧类型状态”、“接收数据状态”及“接收校验和状态”。系统的初始状态为“接收帧头HEAD1状态”,各接收状态间的状态转移图如下图所示。随着串口接收中断新数据的接收,系统的接收状态依次为 HEAD1→HEAD2→LEN→TYPE→DATA→CHECK。该方法也快速、有效地实现了同步;但是需要注意的是,在每一次接收完1帧完整的数据之后,必须把系统的接收状态重新设置为HEAD1,否则将会影响下一帧的数据接收。
    在这里插入图片描述
      此后,程序按照协议开始依次接收数据帧长度、命令类型、数据和校验位。接收完后,重新设置系统接收状态为HEAD1,同时对该数据帧进行校验。校验正确后,利用消息机制通知主程序根据命令类型对数据帧进行处理或执行相应的命令操作。
    下面给出该方法在CC2530裸机中的实例程序:

    #include "iocc2530.h"
    
    #define TRUE    1
    #define FALSE   0
    // 状态机状态
    #define HEAD1   0x00
    #define HEAD2	0x01
    #define LEN     0x02
    #define TYPE	0x03
    #define DATA	0x04
    #define CHECK	0x05
    // 命令
    #define COMMAND1 0x01
    #define COMMAND2 0x02
    
    // 状态机用到的全局变量
    unsigned char g_datrev[48];				// 串口数据缓存
    unsigned char g_cmd;					// 接收的命令
    unsigned char g_recok;					// 串口事件标志位
    unsigned char g_recstate = HEAD1;       // 接收状态
    unsigned char g_len = 0;                // 已接收的数据长度
    unsigned char g_check_sum = 0;          // 校验和
    unsigned char g_lentotal = 0;           // 包长
    
    void main(void)
    {
      // 初始化程序
      
      
      // 任务轮询
      while(1)
      {
        // 有新的事件发生
        if(g_recok==TRUE)
        {
          // 清除串口事件标志位
          g_recok = FALSE;
          // 处理命令
          switch(g_cmd)
          {
            case COMMAND1:
              {
                // 处理命令1
                
              }
              break;
              
            case COMMAND2:
              {
                // 处理命令2
                
              }
              break;
              
            default:
              break;
          }
        }
      }
    }
    
    // 串口0中断处理函数
    #pragma vector = URX0_VECTOR
    __interrupt void UART0_ISR(void)
    {
      // 接收串口数据
      unsigned char recdata = 0;
      // 清中断标志
      URX0IF = 0;
      
      // 接收串口0数据
      recdata = U0DBUF;
      // 进入接收状态机
      switch(g_recstate)
      {
        case HEAD1:
        {
          // 如果接收到HEAD1的值0xFE,则进入状态HEAD2
          if(recdata==0xFE)
          {
            g_recstate = HEAD2;
          }
        }
        break;
        
        case HEAD2:
        {
          // 如果接收到HEAD2的值0xEF,则进入状态LEN接收帧数据长度
          if(recdata==0xEF)
          {
            g_recstate = LEN;
          }
          // 如果接收到的还是HEAD1的数据0xFE,则不跳转,等待下一个数据
          else if(recdata==0xFE)
          {
            g_recstate = HEAD2;
          }
          // 如果没有接收到HEAD1或HEAD2的数据则返回HEAD1状态重新再来
          else
          {
            g_recstate = HEAD1;
          }
        }
        break;
        
        case LEN:
        {
          // 将状态机指向下一个状态“TYPE”
          g_recstate = TYPE;
          // 接收帧数据长度
          g_lentotal = recdata;
          // 异或校验,先校验“HEAD1”和“HEAD2”
          g_check_sum = 0xFE^0xEF;
        }
        break;
        
        case TYPE:
        {
          // 将状态机指向下一个状态“DATA”
          g_recstate = DATA;
          // 接收帧命令数据
          g_cmd = recdata;
          // 校验命令数据
          g_check_sum = g_check_sum ^ recdata;
          // 将下一状态要用的“g_len”先清零
          g_len = 0;
        }
        break;
        
        case DATA:
        {
          // 将接收到的帧数据存储在数据缓存数组中
          g_datrev[g_len] = recdata;
          // 校验帧数据
          g_check_sum = g_check_sum ^ recdata;
          // 记录接收了多少字节数据
          g_len++;
          // 接收总帧长度的数据后转向“CHECK”状态校验整个帧是否正确
          if(g_len>=g_lentotal)
          {
            g_recstate = CHECK;
          }
        }
        break;
        
        case CHECK:
        {
          // 检测接收到的帧数据是否正确,正确则通知主函数有新的事件;错误则抛弃此帧,重置状态机
          if(g_check_sum==recdata)
          {
            g_recok = TRUE;
          }
          g_recstate = HEAD1;
        }
        break;
        
        default:
        {
          g_recstate = HEAD1;
        }
        break;
      }
    }
    
    

      由于采用了状态机和消息机制的结构,上述设计思路快速有效地实现了串口通信的同步,而且程序结构清晰,便于维护,也易于向其他的串口通信协议移植。另外,串口中断服务子程序中需要处理的工作很少,大大减轻了串口接收中断服务程序的压力,缓解了嵌入式系统有限资源与需求之问的矛盾,提高了嵌入式系统的稳定性。
    大家的支持就是我分享技术的动力,希望大家需转载时能附上原作者的博客:https://blog.csdn.net/u012993936,谢谢。



    --- End ---
    你可能还想看:

    > Zigbee进阶:功能模块
    > 免费的Zigbee抓包神器!比Ubiqua还好用!


    文章都看完了,随手点个赞吧~
    在这里插入图片描述
    ↓↓↓ ↓↓↓

    展开全文
  • ZigBee结构

    万次阅读 2016-09-05 09:31:43
    IEEE 802.15.4/ZigBee帧结构的设计原则为在保证网络在有噪音的信道上以足够健壮性的传输的基础上将网络的复杂性降到最低。每一后继的协议层都是在其前一层添加或者剥除了头和尾而形成,IEEE 802.15.4的MAC层定义...

            IEEE 802.15.4/ZigBee帧结构的设计原则为在保证网络在有噪音的信道上以足够健壮性的传输的基础上将网络的复杂性降到最低。每一后继的协议层都是在其前一层添加或者剥除了帧头和帧尾而形成,IEEE 802.15.4的MAC层定义了4种基本帧结构。

    1. 信标帧:协调器用以传输信标。
    2. 数据帧:用于传输数据。
    3. 响应帧:用于子确认帧已被成功的接收
    4. MAC命令帧:用子处理所有MAC层对等实体的控制传输。

    信标帧

           信标帧MPDU由MAC子层产生。在信标网络中,协调器通过向网络中的所有从设备发送信标帧,以保证这些设备能够同协调器进行同步(同步工作和同步休眠),以达到网络功耗最低(非信标模式只允许ZE进行周期性休眠,ZC和所有ZR必须长期处于工作状态)。其帧结构如下图所示。
    这里写图片描述
           信标帧包含MAC服务数据单元(MSDU)、MAC头部(MHR)和MAC尾部(MFR)三部分。MSDU包含超帧域、未处理数据地址域、地址列表域、信标净荷域;MHR包含帧控制域、信标序列号和寻址信息域。MFR包含16bit的帧校验序列。

           当MAC层协议数据单元(MPDU)被发送到物理层(PHY)时,它便成为了物理层服务数据单元(PSDU)。如果在PSDU前面加上一个物理层帧头(PHR)便可构成物理层协议数据单元(PPDU)。如果再加上一个同步帧头(SHR),则这个数据包便成为最终在空气中传播的数据包。


    MSDU = 超帧域+ 示处理数据地址域 + 地址列表域 + 信标净荷域

    MHR = 帧控制域+ 信标序列号 + 寻址信息域

    MFR = 16BIT的帧校验序列FCS

    MPDU = MHR + MSDU + MFR

    MAC协议数据单元= MAC帧头 + MAC服务数据单元 + MAC帧尾

    PPDU = PHR + PSDU + PFR

    物理层协议数据单元 = 物理层帧头 + 物理层数据单元 + 物理层帧尾

    空气中最终传播的数据包= PPDU + 同步帧头SHR

    数据帧

           数据帧由高层(应用层)发起,在ZigBee设备之问进行数据传输的时候,要传输的数据由应用层生成,经过逐层数据处理后发送给MAC层,形成MAC层服务数据单元(MSDU)。通过添加MAC层帧头信息和帧尾,便形成了完整的MAC数据帧MPDU,其帧结构如下图所示。
    这里写图片描述
           数据载荷传输到MAC子层就称之为MSDU,在MSDU的前面加上MHR,后面加上MFR就构成了MAC数据帧,也就是MPDU。其中MFR包含帧控制域、序列号和寻址信息域。MFR由16bitFCS构成。
           MPDU传输到物理层后就作为物理层数据静载荷,也就是PSDU。PSDU的前面加上SHR和PHR就形成了PPDU,其中SHR包含前导序列和SFD域;PHR由PSDU的长度值(字节表示)组成。


    应用层生成要传输的数据——>逐层数据处理——>MSDU——>添加MHR、MFR——>MPDU——>PSDU——>添加SHR、PHR——>PPDU

    SHR = 前导码序列 + SFD域

    PHR = PSDU长度值

    响应帧

           应答帧由MAC子层发起。为了保证设备之问通信的可靠性,发送设备通常要求接收设各在接收到正确的帧信息后返回一个应答帧,向发送设备表示已经正确的接收了相应的信息。其帧结构如下图所示。
    这里写图片描述
           MAC子层应答帧由MHR和MFR组成。MHR包括MAC帧控制域和数据序列号;MFR由16bit的FCS组形成。

           MPDU传到物理层就形成物理应答帧的净载荷,即PSDU。在PSDU前面加上SHR和PHR就形成PPDU。其中SHR由前导码序列和SFD域构成;PHR由PSDU的长度值域构成。

    MAC命令帧

           MAC命令帧由MAC子层发起。在ZigBee网络中,为了对设备的工作状态进行控制,同网络中的其他设备进行通信,MAC层将根据命令类型生成相应的命令帧。其帧结构如下图所示。
    这里写图片描述
           MSDU由命令类域活命令数据域(命令净荷)构成。在MSDU前面加上MHR,后面加上MFR就形成MAC命令帧,也就是MPDU。其中,MHR包含MAC帧控制域、数据序列号和寻址信息域;MFR包含了16bitFCS。接着MPDU传输到物理层形成物理层命令帧静载荷,也就是PSDU。在PSDU的前面加上SHR和PHR就形成物理层命令风阻,也就是PPDU其中,SHR包含前导序列(保证接收机和符号同步)和SFD域构成;PHR包含PSDU的长度值(字节表示)。


    MSDU = 命令类型域 + 数据域(命令净载荷)

    MHR = MAC帧控制域 + 数据序列号 + 寻址信息域

    MFR = 16bitFCS
    MPDU = MHR + MSDU + MFR

    超帧结构

           LR-WPAN标准中允许使用超帧结构。超帧格式由协调器定义。超帧由协调器发送并受网络信标的限制(如下图图),而且它还被分为16个大小相同的时隙。超帧的第一个时隙用来传输信标帧。如果协调器不希望使用超帧结构,它就不发送信标。
    这里写图片描述
           信标在网络中用于设备之间的同步、区分PAN和描述超帧结构。任何设备想要在两个信标之间的竞争接入期(contention Access period,CAP)进行通信,就必须同其他设备采用时隙免冲突载波检测多路接入CSMA-CA机制进行竞争,所有的处理必须在下一个网络信标的到达之前完成。超帧有活动和不活动部分(网络休眠区和网络活动区)。在不活动部分,协调器与PAN之间不能发生联系,并进入低功耗模式。

           对于应用于低延迟或需要在特定数据带宽的情况下,PAN协调器可以用活动超帧的一部分来实现,这部分称为保证时隙(Guaranteed Time Slot GTS)。保证时隙(可有多个)形成了非竞争期(CFP),它始终出现在CAP之后和活动超帧之前。PAN协调器可分配七个GTS,而每个GTS时间不少于一个时隙。然而CAP的有效部分应当保留,使基于竞争的其它网络设备和新设备能接入网络。所有基于竞争的传输应当在CFP开始之前完成,同时每个工作在GTS时期的设备应当确保它的传输在下一个GTS开始和CFP的结束之前完成。
    这里写图片描述

    GTS:保证时隙:是活动超帧的一部分,为实现一些特殊应用开辟的

    CAP:竞争接入期:任何设备想在此时通信,必须采用CSMA-CA竞争机制

    CFP:非竞争期:由GTS组成,这段时期内不需竞争

    展开全文
  • 这里写自定义目录标题zigbee是什么zigbee模块的选择 zigbee是什么 类似于蓝牙或者lora等等,属于物联网终端得一种无线通信技术。 蓝牙:距离较短,功耗低,组网数量不错,数据传输不大。 WiFi:数据量比较大,功耗...

    zigbee是什么

    类似于蓝牙或者lora等等,属于物联网终端得一种无线通信技术。
    蓝牙:距离较短,功耗低,组网数量不错,数据传输不大。
    WiFi:数据量比较大,功耗比较大,比较耗电,无线局域网得数量不大。
    zigbee:功耗低,休眠几个ua,也可以进行组网,单网络组网数目比较大。

    这三种无线模块的载波都是2.4G频率,穿透能力较差

    zigbee模块的选择

    一般来说,TI公司和silicon公司的zigbee模块做得比较好

    TI:
    芯片特点是比较便宜,但是组网没有slilicon稳定,一般学习都使用TI公司生产的
    TI方案 zigbee协议栈(ZSTACK)

    silicon公司模块:
    特点 组网目前来说是最稳定的,但是比较贵

    我们通常使用zigbee是用TI公司生产的CC253X系列的模块,我们可以把它当成一个普通的单片机来进行学习,对后面的协议栈分析打下铺垫。
    CC2530F256 CPU:8051 RAM:8K Byte Flash: 256K Byte, 工作频率无线通信32M,数据通信量是非常少
    250K bps(bit 每秒)芯片的供电电压通常是3.3V

    1.实验一:点灯

    CC2530 的I/O 控制口一共有21 个,分成3 组,分别是P0、P1 和P2;由图可知,P1_0 与P1_1 分别控制LED1和LED2
    在这里插入图片描述
    相关寄存器
    P1DIR(P1 方向寄存器,P0DIR 同理)

    在这里插入图片描述

    P1SEL(P1 功能选择寄存器,P0SEL 同理)
    在这里插入图片描述

    我们只需要配置该引脚的输出方向和功能即可

    代码演示

    #define LED0 P1_0
    #define LED1 P1_1
    void GPIO_init()
    {
      P1SEL = P1SEL & ~0x03;
      P1DIR = P1DIR |  0x03;  
      LED0 = 0;
      LED1 = 0;
    }
    void DelayMs(unsigned int msec)//大约1ms延时
    {
      for(unsigned int x = msec;x > 0;x --)
      {
        for(unsigned int y = 620;y > 0;y --)
        {
          asm("NOP");
        }    
      }
    }
    void main(void)
    {
      GPIO_init(); 
      while(1)
       {
         DelayMs(500);
         LED0 = 1;
         DelayMs(500);
         LED0 = 0;
         DelayMs(500);
         LED1 = 1;
         DelayMs(500);
         LED1 = 0;      
       }
    }
    

    实验现象

    两个灯交互闪烁

    2.实验二:按键控制灯

    从原理图可知,按键没有按下时是高电平,按下之后是低电平,因为接地了。我们需要对P00和P01引脚进行操作
    在这里插入图片描述

    代码演示

    #include <iocc2530.h>
    #define LED0 P1_0
    #define LED1 P1_1
    #define K1   P0_0
    #define K2   P0_1
    void GPIO_init()
    {
      P1SEL = P1SEL & ~0x03;//设置P1_0,P1_1为普通IO口
      P1DIR = P1DIR |  0x03;//设置P1_0,P1_1为输出模式
      P0SEL = P0SEL & ~0x03;//设置P1_0,P1_1为普通IO口
      P0DIR = P0DIR & ~0x03;//设置P1_0,P1_1为输入模式
        
      LED0 = 0;
      LED1 = 0;
    }
    void DelayMs(unsigned int msec)//大约1ms延时
    {
      for(unsigned int x = msec;x > 0;x --)
      {
        for(unsigned int y = 620;y > 0;y --)
        {
          asm("NOP");
        }    
      }
    }
    void main(void)
    {
      GPIO_init(); 
      while(1)
      {
        if(K1 == 0)
         LED0 = 1;
        else
         LED0 = 0;
           
        if(K2 == 0)
        {
          DelayMs(100);//延时消斗
          if(K2 == 0)
          {
            LED1 = ~LED1;
          }
          while(K2 == 0);
        }   
      }
    }
    

    实验现象

    K1按键控制led0的亮灭,k2按键控制led1的亮灭

    3.实验三:外部中断

    相关寄存器
    P0IEN:各个控制口的中断使能,0 为中断禁止,1 为中断使能。
    在这里插入图片描述
    P0INP:设置各个I/O 口的输入模式,0 为上拉/下拉,1 为三态模式。
    在这里插入图片描述
    PICTL:D0~D3 设置各个端口的中断触发方式,0 为上升沿触发,1 为下降沿x发。
    在这里插入图片描述
    IEN1:中断使能1,0 为中断禁止,1 为中断使能。
    在这里插入图片描述
    P0IFG:中断状态标志寄存器,当输入端口有中断请求时,相应的标志位将置1。
    在这里插入图片描述

    代码演示

    #include "exit.h"
    #include "exit.h"
    #define LED0 P1_0
    #define LED1 P1_1
    #define KEY0 P0_0
    #define KEY1 P0_1
    void DelayMs(unsigned int msec)//大约1ms延时
    {
      for(unsigned int x = msec;x > 0;x --)
      {
        for(unsigned int y = 620;y > 0;y --)
        {
          asm("NOP");
        }    
      }
    }
    void led_init(void)
    {
      P1SEL &= ~0x03 ; //清0第一次 第一为0,代表工作在普通模式
      P1DIR |= 0x03; //第一位为1,输出,否则输入
      P1_0= 0;                //关LED
      P1_1= 0;
    }
    //外部中断
    void exit_init(void)
    {
      //按键寄存器的操作,设置为普通模式和输入模式
        P0SEL &= ~0x03;
        P0DIR &= ~0x03;
       //P0IEN:各个控制口的中断使能,0 为中断禁止,1 为中断使能。
        P0IEN |= 0x03;
      //P0INP:设置各个I/O 口的输入模式,0 为上拉/下拉,1 为三态模式
        P0INP &= ~0x03;
      //PICTL:D0~D3 设置各个端口的中断触发方式,0 为上升沿触发,1 为下降沿触发
        PICTL |= 0x01;//下降沿触发
         
      //IEN1:中断使能1,0 为中断禁止,1 为中断使能。
      
      //P0IFG:中断状态标志寄存器,当输入端口有中断请求时,相应的标志位将置1。 
        P0IFG &= ~0x03;        //P0.0中断标志清0    
        P0IE = 1;              //P0中断使能    
        EA = 1;                //总中断使能  
    }
    
    #pragma vector = P0INT_VECTOR
    __interrupt void P0_ISR(void)
    {
      EA=0;
      if((P0IFG & 0x02 ) >0 )         //按键中断 ,p0_1
      {
            P0IFG &= ~0x02;               //P0.1中断标志清0
        LED1 = !LED1;
      }
      P0IF = 0;                       //P0中断标志清0
      EA = 1;                         //开中断
      
      if((P0IFG & 0x01 ) >0 )         //按键中断 ,p0_0
      {
            P0IFG &= ~0x01;               //P0.0中断标志清0
        LED1 = !LED1;
      }
      P0IF = 0;                       //P0中断标志清0
      EA = 1;                         //开中断
      void main(void)
    {
      led_init();
      ext_init();
      while(1);//通过while循环等待中断,
    }
    }
    

    实验现象

    主要用到了中断,该中断可以需要配置多个寄存器,假设配置p01,需要开启总中断,然后是设置p0的中断位,后面通过读取P0IFG 这个寄存器的值来判断是否产生了中断

    连续按下CC2530主板上K1按键,会发现当按键被按下时,LED的亮灭状态会发生改变。

    4.实验四:定时器中断

    定时器1 是一个16 位定时器,具有定时器/计数器/脉宽调制功能。它有3 个单独可编程 输入捕获/输出比较 信道,每一个信道都可以用来当做PWM 输出或用来捕获输入信号的边沿时间。
    定时器有一个很重要的概念:操作模式。
    操作模式包含:自由运行模式(free-running)、 模模式(modulo)和 正计数/倒计数模式(up-down)。本次实验学习到的新寄存器:

    T1CTL:定时器1 的控制,D1D0 控制运行模式,D3D2 设置分频划分值。
    在这里插入图片描述

    T1STAT:定时器1 的状态寄存器,D4~D0 为通道4~通道0 的中断标志,D5 为溢出标志位,当计数到最终技术值是自动置1。在这里插入图片描述

    T1CCTL0:D1D0 为捕捉模式选择:00 为不捕捉,01 为上升沿捕获,10 为下降沿捕获,11 为上升或下降沿都捕获。在这里插入图片描述

    IRCON:中断标志4,;0 为无中断请求。1 为有中断请求。
    在这里插入图片描述

    在配置寄存器之前还需要配置时钟频率相关的寄存器

    CLKCONCMD:时钟频率控制寄存器。在这里插入图片描述D7 位为32KHZ 时间振荡器选择,0 为32KRC 震荡,1 为32K 晶振。
    D6 位为系统时钟选择。0 为32M 晶振,1 为16M RC 震荡。当D7 位为0 时D6 必须为1。
    D5~D3 为定时器输出标记。000 为32MHZ,001 为16MHZ,010 为8MHZ,011 为4MHZ,100 为2MHZ,101 为 1MHZ,110 为500KHZ,111 为250KHZ。默认为001。需要注意的是:当D6 为1 时,定时器频率最高可采用频率为16MHZ。
    D2~D0:系统主时钟选择:000 为32MHZ,001 为16MHZ,010 为8MHZ,011 为4MHZ,100 为2MHZ,101 为1MHZ,110 为500KHZ,111 为250KHZ。当D6 为1 时,系统主时钟最高可采用频率为16MHZ。

    CLKCONSTA:时间频率状态寄存器。
    在这里插入图片描述
    D7 位为当前32KHZ 时间振荡器频率。0 为32KRC 震荡,1 为32K 晶振。
    D6 位为当前系统时钟选择。0 为32M 晶振,1 为16M RC 震荡。
    D5~D3 为当前定时器输出标记。000 为32MHZ,001 为16MHZ,010 为8MHZ,011 为4MHZ,100 为2MHZ,101 为 1MHZ,110 为500KHZ,111 为250KHZ。
    D2~D0 为当前系统主时钟。000 为32MHZ,001 为16MHZ,010 为8MHZ,011 为4MHZ,100 为2MHZ,101 为1MHZ,110 为500KHZ,111 为250KHZ。

    代码演示

    #include "time.h"
    #include <iocc2530.h>
    #define  LED0   P1_0
    #define  LED1   P1_1
    #define  K1     P0_0
    
    unsigned char counter;
    void SysClockInit(void)
    {
     unsigned int i;
      SLEEPCMD &= ~0x04;              //都上电
      while(!(CLKCONSTA & 0x40));     //晶体振荡器开启且稳定
      for (i=0; i<504; i++) asm("NOP");//适当延时
      CLKCONCMD &= ~0x47;             //选择32MHz晶体振荡器
      SLEEPCMD |= 0x04; 
    }
    
    //IRCON:中断标志4,;0 为无中断请求。1 为有中断请求。
    
    void time1_init(void)
    {
      //T1CTL:定时器1 的控制,D1D0 控制运行模式,D3D2 设置分频划分值。
    T1CTL = 0x05 ;//自由运行和8分频
    
    //T1STAT:定时器1 的状态寄存器,D4~D0 为通道4~通道0 的中断标志,D5 为溢出标志位,当计数到最终技术值是自动置1。
    T1STAT =0x21; //
    //T1CCTL0:D1D0 为捕捉模式选择:00 为不捕捉,01 为上升沿捕获,10 为下降沿捕获,11 为上升或下降沿都捕获。
    T1CCTL0 |=0x01; //上升沿捕捉
    
    IEN1 |=0X02;
    EA = 1;//开启中断
    }
    
    #pragma vector = T1_VECTOR      
     __interrupt void T1_ISR(void)
     {
         EA = 0;
       
         if(counter>30)
       {
         counter=0;  
         LED0 = !LED0;
         LED1 = !LED1;
       }
       counter++;
       T1IF = 0;//清除中断位
       EA = 1;//开启中断
     }
    void main(void)
    {
      SysClockInit();
      led_init();
      time1_init();
      while(1);  
    } 
    
    

    实验现象

    在这里插入图片描述
    当某个中断发送后会进入这个向量中断表执行相对应的函数

    精确控制LED 灯的闪烁间隔为2s,即:亮1s → 暗1s → 亮1s→ 暗1s(即从暗转亮的时刻间隔为1s)。

    5.实验五:串口通信

    相关寄存器

    U0CSR:USART0 控制与状态。在这里插入图片描述
    D7 为工作模式选择,0 为SPI 模式,1 为USART 模式。
    D6 为UART 接收器使能,0 为禁用接收器,1 为接收器使能。
    D5 为SPI 主/从模式选择,0 为SPI 主模式,1 为SPI 从模式。
    D4 为帧错误检测状态,0 为无错误,1 为出现出错。
    D3 为奇偶错误检测,0 为无错误出现,1 为出现奇偶校验错误。
    D2 为字节接收状态,0 为没有收到字节,1 为准备好接收字节。
    D1 为字节传送状态,0 为字节没有被传送,1 为写到数据缓冲区的字节已经被发送。
    D0 为USART 接收/传送主动状态,0 为USART 空闲,1 为USART 忙碌。

    U0GCR:USART0 通用控制寄存器。在这里插入图片描述
    D7 为SPI 时钟极性:0 为负时钟极性,1 为正时钟极性;
    D6 为SPI 时钟相位:
    D5 为传送为顺序:0 为最低有效位先传送,1 为最高有效位先传送。
    D4~D0 为波特率设置
    在这里插入图片描述

    代码演示

    对串口进行配置的时候先要配置好系统的时钟,然后设置相应串口的配置,如波特率 校验位等等,最后在开启相关串口的中断,通过U0DBUF这个寄存器来接受和发送数据,当这个串口收到数据时,会产生接收中断,并接收一个字符

    #include <iocc2530.h>
    #define  LED0   P1_0
    #define  LED1   P1_1
    unsigned char Flag_RX,temp;
    void led_init(void)
    {
      P1SEL &= ~0x03;          //P1.0 P1.1为普通 I/O 口
      P1DIR |= 0x03;           //输出 
      LED0 = 0;                  //关LED
      LED1 = 0;
    }
    void SysClock_Init(void)
    {
      SLEEPCMD &= ~0x04;              //都上电
      while(!(CLKCONSTA & 0x40));     //晶体振荡器开启且稳定
      CLKCONCMD &= ~0x47;             //选择32MHz晶体振荡器
      SLEEPCMD |= 0x04;
    }
    //接着初始化串口,代码为:
    void uart0_init(void)
    {
      PERCFG = 0x00;        //位置1 P0口 
      P0SEL = 0x3c;        //P0_2,P0_3,P0_4,P0_5用作串口,第二功能 
      P2DIR &= ~0XC0;      //P0 优先作为UART0 ,优先级
    
      U0CSR |= 0x80;       //UART 方式 
      U0GCR |= 11;         //U0GCR与U0BAUD配合     
      U0BAUD |= 216;       // 波特率设为115200 
      UTX0IF = 0;          //UART0 TX 中断标志初始置位1  (收发时候)
      U0CSR |= 0X40;       //允许接收 
      IEN0 |= 0x84;        // 开总中断,接收中断    
    
    }
    //串口发送字节函数
    void Uart_Send_char(char ch)
    {
      U0DBUF = ch;
      while(UTX0IF == 0);
      UTX0IF = 0;
    }
    //串口接收一个字符: 一旦有数据从串口传至CC2530, 则进入中断,将接收到的数据赋值给变量temp. 
    #pragma vector = URX0_VECTOR 
    __interrupt void UART0_ISR(void) 
    { 
      LED0 = 1;
      URX0IF = 0;    // 清中断标志 
      temp = U0DBUF; 
      Flag_RX = 1;
    }
    
    void main(void)
    {
      SysClock_Init();
      led_init();
      uart0_init();
      while(1)
      {
        LED0 = 0;
        if(Flag_RX)
        {
          LED1 = 1;
          Flag_RX = 0;
          Uart_Send_char(temp);
          LED1 = 0;
        }   
      }
    }
    

    实验现象

    发送什么数据给单片机单片机将会返回给相应的数据给pc端
    在这里插入图片描述

    展开全文
  • 英文 中文 含义 备注 EndPoint 端点 是协议栈应用层的入口,即入口地址,也可以理解应用对象(Application Object)存在的地方,它是为实现一个设备描述而定义的一组群集 端点0 :用于整个ZigBee设备的配置和管理,...
  • 本系统实现了Zigbee组网监测,应用于变电站使用,多节点监测,上位机软件实时显示状态,同时检测到有人入侵就会报警。上位机将数据存到mysql数据库中。便于后续管理查询。Zigbee协调器连接上位机,Zigbee终端连接...
  • .ZigBee网络的自定义协议消息 起始位 + 命令类型 + 数据总长度 + 传感器个数 + 传感器类型 + 数据域 + 校验位 START + CMD + LEN + Count + TYPE + DATA0~DATAN + CHK 协议各个报文的协议详解: 起始位(START):...
  • XBee3 zigbee AT命令集

    千次阅读 2019-04-07 14:46:04
    此操作会在接收传输的所有设备上快速闪烁Associate LED,并从API设备的串行端口发送API。 Digi建议您为大型网络禁用此功能,以防止过度广播。 参数值 描述 ...
  • JN5169 JN-AN-1217-Zigbee-3-0-Base-Device一、JN-AN-1217 介绍二、设备描述1、路由器① 路由器功能② 组建或加入网络a、使用网络引导加入现有网络b、使用 NFC 加入现有网络c、组建分布式网络③ 允许其他设备加入...
  • 四川农业大学ZigBee复习重点

    千次阅读 2018-11-02 15:01:38
    Zigbee概述 1、 Zigbee是一种近距离、低复杂度、低功耗、低成本的双向无线通信技术 2、 Zigbee的特点是功耗低、成本低、时延短、网络容量大、可靠安全。 3、 常见的Zigbee芯片有CC243X系列、MC1322X系列和CC253X系列...
  • ZIGBEE的硬件介绍和应用工程

    千次阅读 2017-09-29 10:34:48
    数据由: Start bit(1位低电平), Data bit(5/6/7/8位,用户的数据), 校验位(奇偶校验1位, 或不用校验), Stop bit(1,2两位高电平) uart通常需配置的内容: 波特率, 数据位, 校验位, 停止位  如果...
  • zigbee芯片cc2430资料

    千次阅读 2019-01-07 23:58:30
    这种解决方案能够提高性能并满足以ZigBee为基础的2.4GHz ISM波段应用对低成本,低功耗的要求。它结合一个高性能2.4GHz DSSS(直接序列扩频)射频收发器核心和一颗工业级小巧高效的8051控制器。 CC2430的设计结合了8...
  • Zigbee协议网络相关的东西(1)

    千次阅读 2018-03-24 10:56:23
    1. 为了让ZigBee的开发更加简单高效,TI公司推出了基于CC2530芯片的协议栈-Z-Stack。协议栈实质上就是能实现各个功能的示例框架代码,我们要实现自己想要的功能,只需要在协议栈的基础上修改或添加即可。 2. Z-...
  • Zigbee Smart Energy安全加密机制

    千次阅读 2017-02-17 14:12:20
    Product CA的安全性高于Test CA,使用Ubiqua等软件经行抓包时如果是Test CA可以分析出数据里的Attribute,但采用Product CA只能解析出是哪个Cluster,里面的Attribute由于更高的加密特性无法解析出。由于每个...
  • 17 ZigBee小项目 终于完结了 day05

    千次阅读 2017-02-22 20:04:42
    //无奇偶校验 serial.setStopBits(QSerialPort::OneStop); //停止位 serial.setFlowControl(QSerialPort::NoFlowControl); //无控制 emit startThread(); //发送启动子线程的信号--实际意义的启动子线程...
  • android安卓源码海量项目合集打包-1

    万次阅读 多人点赞 2019-06-11 16:16:24
    │ │ EditText内容分不同块显示,支持校验,删除块,添加块,得到块代表的字符串集合.rar │ │ edittext失去焦点,收起键盘.rar │ │ EditText字数检测与限制.rar │ │ EditText字数检测与限制的冲突文件 2016-11...
  • 1.2,时分多址 1.3,与FDMA对比 二,物理层协议及类型 2.1,LoRa 2.2,ZigBEE 2.2.1 调制原理 2.2.2 IEEE 802.15.4 物理层RF要求 2.3,BLE 5.0物理层 2.3.1 物理层结构 2.3.2 调制方式 2.3.3 发射机 2.3.4 接收机...
  • 温湿度节点数据采集

    千次阅读 2020-02-17 15:21:59
    采用温湿度传感器模块和ZigBee模块组成一个数字量传感器采集节点,实现温湿度传感器的采集,并将采集数据通过自定义协议无线传输至汇聚节点。发送节点有数据发送时,LED1 亮100毫秒。 任务实施 打开上节课创建的...
  • 【XBEE手册】XBEE操作

    千次阅读 2018-07-28 17:33:39
    @(ZigBee)[ZigBee, XBEE手册] 【XBEE手册】XBEE操作 串口接口 UART数据流 串行数据 SPI通信 SPI操作 串口选择 串口缓冲区 串口接受缓冲区 串口发送缓冲区 UART流控制 CTS¯¯¯¯¯¯¯¯¯¯¯CTS¯\...
  • 蓝牙BLE详解

    千次阅读 2021-03-13 11:03:01
    广播报文类型: 发送地址类型: 0: 公共地址 1:随机地址 长度:广播报文的长度域包含8个比特,有效值的范围是6~37 数据: 广播者地址(6个字节)+广播数据(31个字节) 校验: 3个字节,为CRC校验。 广播数据: 分为...
  • 传感网应用开发知识点总结

    千次阅读 2021-12-23 22:01:20
    其它网络数据参考网络协议报文详解 五、基于BasicRf的无线通信应用 BasicRf重要知识点 基于CC253x芯片的BasicRf软件包,包括硬件层、硬件抽象层、基本无线传输层和应用层,不包括数据交互层,ZigBee技术体系不...
  • 目录一、理论知识(部分来自... CRC校验模块(三)注意事项 一、理论知识(部分来自野火、正点原子资料) (一)TCP/IP五层模型 TCP/IP(Transmission Control Protocol/Internet Protocol),供已连接网络的计算机进
  • 前段时间写了一个关于Vimi-Net简要的收发码以及CRC校验的博客(http://blog.csdn.net/u011348999/article/details/16803829) 然后一直说把QT串口与Vimi-net的联机调试做一个总结。。结果一直拖到现在,人太懒了真...
  • 一、实验目的 1.掌握单片机串行口通信的程序设计,及简易三线式通讯的方法。 2.了解实现串行通讯的硬环境、...特率自定义,实现:将甲机中 8 个开关所代表的数据传送到乙机,并在乙机的 8 个 LED 灯显示。请在 ...
  • AIoT(人工智能+物联网)知识总结+实战项目

    万次阅读 多人点赞 2021-11-27 23:05:41
    基于 YOLO-V3 并进行源码解读 9.5.6 基于 YOLO-V3 的自定义目标检测 9.5.7 YOLO-V4 网络模型介绍 9.5.8 YOLO-V5 网络模型介绍 9.5.9 Resnet 网络框架结合迁移学习 9.5.10 目标检测算法 SSD 9.5.11 目标检测算法 ...
  • AOS与阿里名称冲突,现改为OACS;面向对象汇编语言OASM(Object assembly language),又带一点点C风格,改名为OACS、即是带一点C风格的面向对象汇编语言系统(Object assembly language C system)。...
  • 蓝牙的学习

    2022-02-09 21:53:11
    没有GATT,BLE协议栈也能跑,但互联互通就会出问题,也正是因为有了GATT和各种各样的应用profile,BLE摆脱了ZigBee等无线协议的兼容性困境,成了出货量最大的2.4G无线通信产品。 举个栗子:设备A发给设备B设备电量为...

空空如也

空空如也

1 2 3 4
收藏数 70
精华内容 28
关键字:

zigbee 自定义校验帧