Zigebee复习

主要是在老师给的重点上做一些扩展吧。

WPAN及ZigBee基础

Zigbee、蓝牙、IEEE802.11b(WiFi)标准都是工作在2.4G频段的无线通信标准

Zigbee主要用在短距离无线控制系统,传输少量的控制信息

短距离无线网络主要分为:
无线局域网
无线个域网

无线个域网所对应的通信协议
HR-WPANS:802.15.3 Hign-Rate 高速:最高速度大于100Mbps
MR-WPANS:蓝牙 Medium-Rate
LR-WPANS:802.15.4 Low-Rate低速:最低速度小于1Mbps

Zigbee最大传输速率:250kbps

Zigbee无线网络分层: 物理层(PHY) 介质访问控制(MAC)网络层(NWK)应用程序支持子层(APS) 应用层(APL)

802.15.4 定义了物理层和介质访问控制层
Zigbee协议定义了网络层、应用程序支持子层和应用层

Zigbee特点:(自组网)高可靠性 低成本 低功耗 高安全 低数据速率

Zigbee设备分类:
协调器:主要负责无线网络的建立与维护
路由器:主要负责无线网络的路由
终端节点:主要负责无线网络数据的采集
Zigebee复习_第1张图片

Zigbee工作在ISM(工业、科学和医疗)频带,共规定了27个信道:
2.4GHz频段 共16个信道,通信速率为250kbps
915MHz频段 共10个信道,通信速率为40kbps
896MHz频段 共1个信道,通信速率为20kbps
补充:2.4GHz是全球通用的ISM频段,915Mhz是北美的ISM频段,896MHz是欧洲认可的IS频段。 bps是每秒传输的二进制位数,即比特每秒。

Zigbee网络拓扑结构:星型 网络型 簇状(树状)

Zigbee应用为周期性 反复 间断数据采集应用
Zigebee复习_第2张图片

Zigbee模块开发一般包括两个文件:.h头文件和.c文件
.h文件可理解为一份接口描述文件
.c文件主要功能是对.h文件中声明的外部函数进行具体实现

补充

1、Z-stack的工作流程:
Zigebee复习_第3张图片
Z-stack采用操作系统的思想来构建,可以降低系统功耗

CC2530

CC2530单片机是一款完全兼容8051内核,支持802.15.4协议的无线射频单片机(高性能,低功耗)
CC2530的Flash(非易失性存储器)容量可选: 32KB 64KB 128KB 256KB(我们用的是256)
CC2530有两个晶振: 32MHz晶振 32.768KHz
I/O口控制
CC2530内部自带温度传感器:
使用步骤:
1、使能温度传感器
2、连接温度传感器到ADC(不是lol那个了,指模拟数字转换器)
3、初始化ADC,确定参考电压、分辨率等,启动ADC读取温度数据

补充

1、 CC2530的通用I/O端口相关的常用寄存器
引脚的控制寄存器 PxDIR:作为通用I/O时,用来设置数据的传输方向。学的是设置为0为输入,设置为1为输出
电平设置 Px:数据端口,用来控制端口的输出或获取端口的输入。
x代表的是数字

2、设置寄存器常用方法
清零:与&,置一:或|
3、 CC2530内部自带温度传感器
使能温度传感器 :ATEST=0x01;
连接温度传感器:TRO|=0x01;
4、CC2530的LED间隔闪烁代码

#include 
#define LED1 P1_0    //定义P1_0口为D1控制端(红)
#define LED2 P1_1    //定义P1_1口为D2控制端(蓝)
//初始化
void IO_Init(void)
{
     
  P1DIR |= 0x02;     //P1_1定义为输出
  P1DIR |= 0x01;     //P1_0定义为输出
}
void delay(void)
{
     
  unsigned int i;
  unsigned char j;
  for(i = 0; i < 10000; i++)
  {
     
    for(j = 0; j < 240; j++)
    {
     
      asm("NOP"); //nop是内嵌汇编做空指令 延时用
      asm("NOP"); //是一个空等待汇编指令,这个指令执行时,单片机是什么也不做,仅仅起一个时间延时作用。
      asm("NOP"); //是指函数内部的参数翻译为汇编指令,其作用是在C语言环境下直接使用汇编指令执行
    }  
  }  
}

void main(void)
{
        
    IO_Init();      //调用初始化程序
    int i = 0;
    //蓝灯闪烁10次后红灯闪烁
    /*
    while(i<10){
      LED1=0;         //点亮D1(红)
      delay();
      LED1=1;
      delay();
      i++;
    }
      LED2=0;         //点亮D2(蓝)
      delay();
      LED2=1;
    */
  //蓝灯红灯交替闪烁
     while(1){
     
      LED1=0;         //点亮D1(红)
      delay();
      LED1=1;
      delay();
      LED2 =0;
      delay();
      LED2=1;
    }
}

Zigbee地址相关

设备地址:
64位IEEE地址:长地址 MAC地址 扩展地址 全球唯一
16位网络地址:短地址 逻辑地址(协调器地址为0x0000,其他设备入网时由协调器分配)在一个网络中唯一

网络地址:唯一标示网络中的一个节点(用网络地址来区分不同的节点)
网络地址最多可以分配65536个节点,地址分配取决于整个网络的架构,整个网络的架构由一下3个值决定:
1、网络最大深度 (5)
2、每个父节点拥有的孩子节点最大数目 (20)
3、每个父节点拥有的孩子节点路由器的最大数目 (6)
同一父节点相连的终端节点的网络地址是连续的
同一父节点相连的路由器节点的网络地址通常是不连续的

端口:每个节点上最多支持**240(1-240)**个端口,每个节点上的所有端口共用一个发射/接收天线(用端口来区分同一节点的端口)

2、信道
范围(11——26)共16个
Zigebee复习_第4张图片
3、PANID:Zigbee网络号 可手动设置(或自动随机生成),如果指定的PANID被占用则自动加1。

补充

1、为啥是65536个节点?
16位的网络地址,那就是2^16次方
2、PANID(网络号)
如果ZDAPP_CONFIG_PAN_ID被定义为0xFFFF,那么协调器将建立一个随机的PANID
若要在应用中查看PANID可以这样获得,_NIB.nwkPanId,读取这个就OK了
Zigebee复习_第5张图片Zigebee复习_第6张图片

数据发送接收

数据发送:调用AF_DataRequest()函数通过天线发送数据

afStatus_t  AF_DataRequest( afAddrType_t *dstAddr,
							endPointDesc_t *srcEP, 
							uint16 cID, uint16 len,
							uint8 *buf, 
							uint8 *transID,
							uint8 options,
							uint8 radius )

参数含义依次是:
afAddrType_t *dstAddr目的节点的网络地址以及目的地址的模式,如广播,单播,或多播。
endPointDesc_t *srcEP源网络地址描述
uint16 cID簇号
uint16 len长度
uint8 *buf指向发送数据缓冲区的指针
uint8 *transID事务序列号指针
uint8 options发送选项,
uint8 radius最大跳数

数据接收:调用osal_msg_receive()函数从消息队列中接收一个消息(包含事件与数据)

uint8 *osal_msg_receive( uint8 task_id )

数据存储位置(结构):

typedef struct
{
     
  osal_event_hdr_t hdr;     /* OSAL Message header */
  uint16 groupId;           /* Message's group ID - 0 if not set */
  uint16 clusterId;         /* Message's cluster ID */
  afAddrType_t srcAddr;     /* Source Address, if endpoint is STUBAPS_INTER_PAN_EP,
                               it's an InterPAN message */
  uint16 macDestAddr;       /* MAC header destination short address */
  uint8 endPoint;           /* destination endpoint */
  uint8 wasBroadcast;       /* TRUE if network destination was a broadcast address */
  uint8 LinkQuality;        /* The link quality of the received data frame */
  uint8 correlation;        /* The raw correlation value of the received data frame */
  int8  rssi;               /* The received RF power in units dBm */
  uint8 SecurityUse;        /* deprecated */
  uint32 timestamp;         /* receipt timestamp from MAC */
  afMSGCommandFormat_t  cmd; /* 重点 真正的成员数据储存在这里 */
} afIncomingMSGPacket_t;
typedef struct
{
     
  byte   TransSeqNumber;			//不重要,貌似是分包用的
  uint16 DataLength;               // 长度
  byte  *Data;					//真正的数据
} afMSGCommandFormat_t;

补充

1、如何取出发送的数据?
pkt->cmd.Data;
2、数据发送函数

//向路由器发送数据
void GenericApp_SendTheMessage( void )
{
     
  char theMessageData[] = "Coordinator Send!";
  afAddrType_t  my_DstAddr;
  my_DstAddr.addrMode=(afAddrMode_t)AddrBroadcast;//发送模式为广播
  my_DstAddr.endPoint=GENERICAPP_ENDPOINT;
  my_DstAddr.addr.shortAddr=0xFFFF;//网络地址为0xFFFF时,向网络中所有节点发送数据包
  AF_DataRequest( &my_DstAddr, &GenericApp_epDesc,
                       GENERICAPP_CLUSTERID,
                       (byte)osal_strlen( theMessageData ) + 1,
                       (byte *)&theMessageData,
                       &GenericApp_TransID,
                       AF_DISCV_ROUTE, AF_DEFAULT_RADIUS );
}

3、数据接收处理函数
数据的接受上,在GenericApp_ProcessEvent回调函数中响应AF_INCOMING_MSG_CMD消息。这里zstack会默认调用一个函数,是GenericApp_MessageMSGCB。在这里处理根据afIncomingMSGPacket_t参数来进行数据的处理。
例如:

//对收到的路由器发送的数据包进行处理
void GenericApp_MessageMSGCB( afIncomingMSGPacket_t *pkt )
{
     
  unsigned char buf[20];
  unsigned char buffer[2] ={
     0x0A,0x0D};

  switch ( pkt->clusterId )
  {
     
    case GENERICAPP_CLUSTERID:
      osal_memcpy(buf, pkt->cmd.Data,20);
      HalUARTWrite(1,buf,20); //向上位机写路由器发来的数据
      HalUARTWrite(1,buffer,2);
      break;
  }
}

OSAL(操作系统抽象层)

OSAL(操作系统抽象层)是一种支持多任务运行的系统资源分配机制
OSAL主要功能:
任务注册、初始化和启动
任务间的同步、互斥
中断处理
存储器分配和管理

事件驱动: 任务(task)轮询,事件(event )驱动
Zigbee将事件和任务的事件处理函数联系方法:
1、 建立一个事件表,保存各个任务的对应事件
2、 建立另一个函数表,保存各个任务事件处理函数地址
3、 将两张表建立某种对应关系

OSAL工作原理(轮询)osal_start_system(void)
通过tasksEvents指针访问事件表的每一项,如果有时间发生,则查找函数表找到事件处理函数进行处理,处理完后,继续访问事件表,查看是否有事件发生,无限循环

协议栈定义的事件成为系统强制事件:
**AF_INCOMING-MSG-CMD:**收到一个新的无线数据
ZDO_STATE_CHANGE:设备网络状态变化
ZDO_CB_MSG:注册的ZDO响应信息
AF_DATA_CONFIRM_CMD:发送事件后的确认信息

用户自定义事件:用户自定义事件

Zigbee协议栈为半开源

补充

1、OSAL通过一个16位宽度的数组来管理事件,意味着OSAL最多可以支持16个事件,其中最高位(0x08000,SYS_EVENT_MSG)系统保留,用户可以使用的事件有15个。
2、Zigebee复习_第7张图片
3、给任务添加事件:osal_set_event(uint8 task_id,uint16 event_flag)
在这里插入图片描述
4、事件的使用
1)需要找个地方定义事件的ID,实际上是指定该事件占用事件数组的哪个位。如#define MY_EVENT 0x02,占用bit1。
2)在需要触发事件的地方调用osal_set_event(task_id, event_flag) ,这个函数有两个参数,一个是接收事件任务的ID,另一个参数指定事件ID.
3)在相应任务的处理函数,检查该事件执行相应代码即可。
4)清除事件标识。

Zigbee协议栈串口操作

串口基本操作步骤:
1、初始化串口,包括设置波特率、中断等
2、向发送缓冲区发送数据或从接收缓冲区读取数据
操作函数:

uint8    HalUARTOpen(uint8 port,halUARTCfg_t *config);// 初始化
uint16  HalUARTRead(uint8 port,uint8 *buf,uint16 len);//读
uint16  HalUARTWrite(uint8 port,uint8* buf,uint16  len);//写

举个栗子:
uartConfig.configured           = TRUE;
uartConfig.baudRate             = HAL_UART_BR_115200;//波特率
uartConfig.flowControl          = FALSE;//流控制
uartConfig.callBackFunc         = NULL; //不需要回调函数时
uartConfig.callBackFunc         = rxCB;//需要回调函数时
HalUARTOpen(1,&uartConfig);

unsigned char buf[20];
HalUARTWrite(1,buf,20); //向上位机写路由器发来的数据
HalUARTRead(1,buf,20);//从上位机读数据

串口回调函数:回调函数不是由该函数实现方直接调用的,而是在特定的事件或条件发生的,由另外的一方调用,用于对该事件或条件进行响应。因此,串口回调函数是在有串口操作(事件)发生时(自动触发)调用的

当应用有串口操作时,应该对应用程序模块的工程属性的编译预处理的Definedsymbols下拉列表框中输入“HAL_UART=TRUE”。(即用条件编译来控制是否编译与该模块相关的程序,目的是为了节约存储资源)
课上教的配置:
HAL_UART_ISR=2
串口操作端口用1
Hal目录下的Target下的Drivers目录的_hal_uart_isr.c中的注释掉if(isrCfg.txMT)

程序中波特率的设置要与上位机(如串口助手)一致。

Zigbee协议栈NV操作

NV(Non Volatile),即非易失性存储器(Flash存储器),即系统掉电,存储器中的数据不掉失。主要用途保存网路的配置参数,或掉电后,上电该节点还是加入原来的网络并且该节点的网络地址就可以从NV读取。
NV存储器主要的操作有初始化NV存储器、读NV存储器、写NV存储器。这些都在OSAL文件夹下中的OSAL_Nv.h和OSAL.h文件中定义和实现。
下面三个操作函数分别是:
NV初始化函数:uint8 osal_nv_item_init( uint16 id, uint16 len, void *buf ),NV存储器将该存储器分成多个条目,每个条目都有一个ID号。
条目的分类见OSAL文件夹中的ZcomDef.h文件,其中要知道的是:用户应用程序定义的条目地址范围为是0x0201到0x0FFF;

NV写操作函数:uint8 osal_nv_write( uint16 id, uint16 ndx, uint16 len, void buf );
NV读取函数:uint8 osal_nv_read( uint16 id, uint16 ndx, uint16 len, void buf );
第一个参数:uint16:NV条目ID号
第二参数:举例条目开始的偏移量
第三参数:要写入的数据长度
第四参数:执行要存放写入或读取数据函数缓冲区的指针

用户只能使用条目ID范围0x0201~0x0FFF
可在OSAL文件夹下的ZcomDef.h文件中添加自己的条目
如:#define Test_NV 0x0201

常用API

事件添加函数:osal_set_event()
uint8 osal_set_event(uint8 task_id,uint16 event_flag)
uint8 task_id:任务号
uint16 event_flag:2字节的位图,其中每位指定了一个事件。只有一个系统事件(SYSTEM_EVENT_MSG),其余的事件/位由接收任务指定;
作用:运行一个任务,设置一个事件

定时器函数:osal_start_timerEx()
uint8 osal_start_timerEx(uint8 task_id,uint16 event_id,uint16 timeout_value)
例如:osal_start_timerEx( GenericApp_TaskID,SEND_TO_ALL_EVENT,5000);
参数:任务,事件,定时毫秒数5000对应5ms

内存拷贝函数:osal_memcpy()
例如: osal_memcpy(recvbuf, pkt->cmd.Data,osal_strlen("Coordinator Send!"+1));

内存比较函数:osal_memcmp()
例如:osal_memcmp(recvbuf,"Coordinator Send!",osal_strlen("Coordinator Send!"+1)

字符串长度函数:osal_strlen()

无线发送函数AF_DataRequest( afAddrType_t *dstAddr, endPointDesc_t *srcEP,
uint16 cID, uint16 len, uint8 *buf, uint8 *transID,
uint8 options, uint8 radius )
消息接收函数uint8 *osal_msg_receive( uint8 task_id )

Zigbee通信相关:

Zigbee协议栈中的规范(Profile)和簇(Cluester)
Zigbee网络中进行数据收发都是建立在应用规范基础上的。每个应用规范都有一个ID来标示。在一个规范(Profile)下又提出了簇(Cluester)的概念,这个Cluester要理解为一个应用领域下的一个特定对象。簇是由命令组成的。

同一规范下的发送命令(簇号)和接受命令(簇号)要相同才能通信

Zigbee网络通信必须建立在具体设备节点的具体通信端口:
网络地址可以描述一个节点,用户可使用简单描述符来描述一个端口。(用户可用的端口号是1-240

Zigbee通信模式:点播 广播 组播

点播
发送模式:Addr16Bit
发送目的端口:目的节点的简单描述符设定的工作端口
发送地址:目的节点的网络地址

my_DstAddr.addrMode=(afAddrMode_t)Addr16Bit;   //发送
my_DstAddr.endPoint=GENERICAPP_ENDPOINT;       //目的端口号
my_DstAddr.addr.shortAddr=0x0000;              //目标设备网络地址

广播
发送模式:AddrBroadcast
发送目的端口:目的节点的简单描述符设定的工作端口
发送地址:0xFFFF 全网发送 包括休眠节点
0xFFFD 只发往休眠节点
0xFFFC 发往所有路由节点

my_DstAddr.addrMode=(afAddrMode_t)AddrBroadcast;//广播发送
my_DstAddr.endPoint=GENERICAPP_ENDPOINT;       //目的端口号
my_DstAddr.addr.shortAddr=0xFFFF;              //协调器网络地址

组播(同一组的节点才能通信)
发送模式:AddrGroup
发送目的端口:目的节点的简单描述符设定的工作端口
发送地址:组ID
#include “aps_groups.h”
1、设置组对象(ID 和 name)
2、加入对象组 aps_AddGroup()
3、退出组

Zigbee协议栈网络管理
Zigbee协议栈实现网络管理的函数:
获得该节点的网络地址:uint16 NLME_GetShortAddr(void)
获得该节点的MAC地址:byte * NLME_GetExtAddr(void)

获得该节点的父节点网络地址:uint16 NLME_GetCoordShortAddr(void)
获得该节点的父节点MAC地址:void NLME_GetCoordExtAddr(byte *buf)

补充

1、afAddrType_t *dstAddr 该参数包含了目的节点的网络地址、端点号及数据传送的模式,如单播、广播或多播等。
afAddrType_t 是个结构体如下:

typedef struct
{
          
	union
     {
     
       uint16 shortAddr;      //用于标识该节点网络地址的变量
     } addr;
    afAddrMode_t addrMode;   //用于指定数据传送模式,单播、多播还是广播
    byte endPoint;           //端点号
} afAddrType_t;  // 其定义在AF.h中

2、组播详细
1.首先声明一个组对象aps_Group_t SampleApp_Group;
aps_Group_t结构体的定义:

typedef struct
{
     
  uint16 ID;                       // Unique to this table
  uint8  name[APS_GROUP_NAME_LEN]; // #define APS_GROUP_NAME_LEN  16
} aps_Group_t;

每个组有个特定的ID跟组名,组名存放在name数组中,name数组的第一个元素是组名的长度,第二个元素开始存放组名字符串。
2.对SampleApp_Group赋值:

 GenericApp_Group.ID=0x0001; //初始化组号
 GenericApp_Group.name[0]=6; //定义组名长度
 osal_memcpy(&(GenericApp_Group.name[1]),"Group1",6); //存放组名

3.在本任务里将端点加入到组中:

aps_AddGroup( SAMPLEAPP_ENDPOINT, &SampleApp_Group );

4.设定通信的目标地址及模式:

afAddrType_t  my_DstAddr;
my_DstAddr.addrMode=(afAddrMode_t)AddrGroup;//发送模式为组播
my_DstAddr.endPoint=GENERICAPP_ENDPOINT;
my_DstAddr.addr.shortAddr=GenericApp_Group.ID;//网络地址设置为组ID

5、如何将一个设备移除组?
调用aps_RemoveGroup

aps_Group_t *grp;
grp = aps_FindGroup( SAMPLEAPP_ENDPOINT, SAMPLEAPP_FLASH_GROUP );
if ( grp )
{
     
   aps_RemoveGroup( SAMPLEAPP_ENDPOINT, SAMPLEAPP_FLASH_GROUP );
}

蓝牙

采用高速跳频扩展,实现语音和数据在短距离上的稳定无缝无线连接
在2.4GHz的ISM频带上设立79个带宽为GHz的信道,用每秒钟切换1600次的频率的跳频(Hobbing)扩展技术实现信息的收发。
蓝牙系统中的功能模块分为:无线射频单元、链路控制单元、链路管理单元、软件结构

微微网: 1主设备 7从设备

蓝牙技术采用了全开放的框架结构
蓝牙技术的系统结构分为三大部分:
1.底层硬件模块
2.中间协议层
3.高层应用
蓝牙协议分为四层:
1.核 心 协 议:BaseBand、LMP、L2CAP、SDP;
2.电 缆 替 代 协 议:RFCOMM;
3.电 话 传 送 控 制 协 议:TCS-Binary、AT 命 令 集;
4.选 用 协 议:PPP、UDP/TCP/IP、OBEX、WAP、vCard、vCal、IrMC、 WAE。

近场通信NFC 及WIFI

你可能感兴趣的