以下为《无线传感器网络》的无排版文字预览,完整格式请下载
下载前请仔细阅读文字预览以及下方图片预览。图片预览是什么样的,下载的文档就是什么样的。
无线传感器网络
*如果一个无线局域网用于传感器的数据收集和监控,那么这个网络叫做无线传感器网络,无线传感器网络是无线局域网的一种具体应用。
·Zigbee
1.解释:无线设备之间的通信方式
2.作用:构建无线局域网
*例:互联网的构建中,以太网作为一种通信方式,将各个计算机连成一片局域网,而在无线传感器的通信中,Zigbee代替了以太网。
3.优缺点:无线设备之间的其他通信方式:蓝牙、wifi等
蓝牙:优:功耗低
缺:组件网络的节点数少
wifi:优:通信速率大
缺:功耗大
Zigbee:优:可以组建大规模网络、功耗低
缺:通信速率小
4.应用:家居、军事、农业、医疗等
5.实现原理:
/
·CC2530芯片简介
1.CC2530芯片只具有QFN40封装,即有40个接口(本该为41个,其中一个芯片背面的接地,所以不算)
2.工作电压范围是:2--3.6V(标准选择3.3V)
3.在40(41)个封装接口中,只要保证以下红圈内四个元件正常,便可以下载程序并运行:分别为接地端、电源正常、去耦电容、偏置电阻
/
·通用I/O接口简介
1.共有21个通用I/O,分为3组:P0/P1/P2
P0:P0_0--P0_7
P1:P1_0--P1_7
P2:P2_0--P2_4
在21个通用I/O中,只有P1_0和P1_1有20mA的输出驱动能力,其余的都只有4mA输出驱动能力
普通I/O口:负责LED灯等芯片上有的元件
片上外设:负责连接串口等芯片上没有的元件
寄存器:I/O接口的寄存器主要有3个:PxSEL、PxDIR、PxINP(x代表I/O接口的组别)
*复位后,默认都是0
PxSEL:8位,每一位都对应具体的I/O组中的相应的一位,决定它是普通I/O口还是片上外设;0:普通I/0口 1:片上外设
PxDIR:8位,每一位都对应具体的IO组中的相应的一位,决定它是输入还是输出;0:输入 1:输出
PxINP:8位,每一位都对应具体的IO组中的相应的一位,决定它是上拉,还是下拉,还是三态模式; 0:上拉/下拉 1:三态模式
具体的上拉还是下拉,有P2INP多出来的第5,6,7为决定:
P2INP第5位:0组
P2INP第6位:1组
P2INP第7位:2组
0:上拉 1:下拉
控制IO口的输入输出,只需控制IO口的SEL和DOIR寄存器
*例:
1.控制P1_0的输出配置:
(1)设置1组0位为普通IO口
代码:P1SEL &=0xFE
//1111 1110→FE,
因为默认各接口均为0,即普通IO口,所以该句可以不要
(2)设置1组0位为输出状态
代码:P1DIR |=0x01
//0000 0001→01
P1_0=0控制的灯的状态
代码:P1_0=0
若想要一直亮需要加一个死循环
代码:while(1);
2.控制P0_6的输入配置,P0_6的跳线帽控制灯
(1)设置0组6位为普通IO口
代码:P0SEL &=0xBF
//1011 1111
(2)设置0组6位为输入状态
代码:P1DIR &=0xBF
//1011 1111
设置0组6位为上拉
代码:P0INP &=0xBF
P2INP &=0xDF//1101 1111
由P0_6控制的跳线帽的状态控制某灯的状态(改灯需要配置状态)
代码:if(1==P0_6)
{//P0_6接高电平,即拔掉了接线帽(短接)
PX_X=0;
}
else
{//P0_6接低电平,即盖上了接线帽
PX_X=1;
}
*注:将某一位强行置0用&,将某一位强行置1用|
·外部中断
上升下降沿触发寄存器:PICTL
0:上升沿触发 1:下降沿触发
总中断寄存器:EA
0:禁用 1:使能
组中断位:PXIE
0:禁用 1:使能
引脚中断位:PXIEN
0:禁用 1:使能
组中断标志位:PXIF
引脚中断标志位:PXIFG
*例:设置P0_5为中断控制程序的步骤,灯的状态改变即可:
(1)初始化需要作为中断按键的IO接口为:普通IO口,上拉,输入
(2)初始化中断按键所需要控制的灯,若非灯则可忽略该步
(3)设总中断使能
代码:EA=1
(4)设0组中断使能
代码:P0IE=1
(5)设0组5位中断使能
代码:P0IEN |=0x20 //0010 0000
(6)设置中断为下降沿触发
代码:PICTL |=0x01//将P0组均设置为下降沿触发
(7)死循环
(8)中断配置成功,进入中断函数
#progma vector =P0INT_VECTOR
__interrupt void ny()
{
if(P0IFG & 0x20)//P0组的5位触发了外部中断
{
P1_0 ^=1;//异或操作,总是取反
}
P0IFG=0;//清中断标志位
P0IF=0;//清中断标志位
}
*注:若想用外部中断实现跑马灯,可将跑马灯函数在第(7)步while中实现,此时while的条件是flag的状态,flag的状态由中断函数改变,上述例子同样可以用次写法:
(7)flag=0;
while(1)
{
if(flag)
{
P1_0 =0;
}
if(!flag)
{
P1_0=1;
}
}
#pragma vector =P0INT_VECTOR
__interrupt void ny(void)
{
if(P0IFG & 0x20)
{
flag=!flag;
P0IFG=0;
}
P0IF=0;
}
中断标志位(PXIF、PXIFG)以及中断使能开关(PXIE、PXIEN)以及总中断控制EA的顺序尽量有小到大,会更严谨
该例中用到的PXIE、PXIEG均为位,是IEN1、IEN2寄存器中的位!
P0IE在IEN1寄存器的第5位
P1IE在EN2寄存器的第4位
P2IE在EN2寄存器的第1位
如果是P1组的中断按键(P2同理),需要在头文件中找到P1组的对应的名称,P1IE是错误的,EN2 |=0x10j相当于P1IE=1,因为在ioCC2530.h中,要是寄存器的地址可以被8整除,则定义了该寄存器的每一个位,而在IEN1寄存器的地址可以被8整除,IEN2的地址不能被8整除,所以IEN2的位并没有进行定义,所以不能用
·时钟
CC2530工作需要1个高频时钟信号和1个低频时钟信号
高频时钟信号:主要供给CPU,保证程序的正常运行
低频时钟信号:主要供给看门狗、睡眠定时等片上外设
高频时钟源:CC2530内部的16M RC电路
外接的32M石英晶振
低频时钟源:CC2530内部的32 K RC电路
外接的32.768K石英晶振
CC2530默认上电时,是内部两个RC电路作为高频时钟和低频时钟起作用,即当没有两个外接石英晶振时,程序照样可以下载运行
如果我们在用串口,尤其是无线通信时,必须用32M石英晶振作为高频时钟
高、低频时钟源的特点:
高频:两个高频时钟源可以同时起振产生高频时钟信号
低频:两个低频时钟源不能同时刻起振,起振的那一个时钟源必须供给CC2530
相关寄存器:SLEEPCMD、SLEEPSTA、CLKCONCMD、CLKCONSTA
SLEEPCMD寄存器:第2位为0:让两个高频时钟源都起振
第2位为1:让未供给CPU的时钟源关闭
SLEEPSTA寄存器:第6位为0:目标时钟源未稳定
第6位为1:目标时钟源稳定
CLKCONCMD寄存器:(1)低三位(Bit[2:0])控制分频
000:32M HZ(不分频)
001:16M HZ(2分频)
010:8M HZ(4分频)
011:4M HZ(8分频)
100:2M HZ(16分频)
101:1M HZ(32分频)
110:500K HZ
111:250K HZ
(2)第6位设置系统主时钟(第6位默认值为1):
0:32M为系统主时钟
1:16M为系统主时钟
CLKCONSTA寄存器:第6位为0:32M时钟源已经作为了系统主时钟
第6位为1:16M时钟源已经作为了系统主时钟
*注:CMD结尾的为命令寄存器、STA结尾的为状态寄存器
可以通过状态寄存器的值来判断当前时钟状态
*例:系统高频时钟源切换步骤:
让两个高频时钟源起振
代码:SLEEPCMD &=0xFB //1111 1011
等待目标时钟源振荡稳定(要等待,所以需要用循环判断当前是否稳定)
代码:while((SLEEPSTA & 0x40) ==0) ;//若未稳定死循环,稳定后跳出循环↓
延时大于63微秒
设置不分频输出
代码:CLKCONCMD &=0xF8 //1111 1000
选择目标时钟源为系统主时钟
代码:CLKCONCMD &=0xBF //1011 1111
等待目标时钟源成为当前系统工作的主时钟源(同理(2))
代码:while(CLKCONSTA &0xBF);//成为之后就要进行操作了
·串口
在用串口时,必须用32M石英晶振为时钟源
CC2530有两个串口 0、1
每个串口有两个位置:USART 0:TX、RX USART 1:TX、RX
USART 0:备用位置1:TX ---> P0_3、RX ---> P0_2
备用位置2:TX ---> P1_5 、RX ---> P1_4
USART 1:备用位置1:TX ---> P0_4、RX ---> P0_5
备用位置2:TX ---> P1_6、RX ---> P1_7
/
CC2530中有一个寄存器UXDBUF,该寄存器负责接收和发送数据缓存
UXCSR寄存器:
/
波特率:
/
/
*例:串口配置流程(发送字节)
(1)配置32M时钟,参考时钟篇
(2)中指定串口的IO位置(备用位置1)
代码:PERCFG &=0xFE//1111 1110选中串口0的备用位置1
(3)将相应的IO口配置为片上外设
代码:P0SEL |=0x0C //0000 1100
(4)8个数据位、1个停止位、无流控、无校验确立
代码:U0CSR |=0x0C(可不必深究)
(5)波特率(选择56700 bps)参照表
代码:U0GCR=10
U0BAUD=216
(6)开CPU中断,对应串口接收中断
代码:EA=1 //总中断使能
URX0IE=1 //串口接收中断使能
配置成功后,进入中断函数
代码:#pragma vector=URX0_VECTOR
__interrupt void ny(void)
{
URX0IF=0;//清空接收中断标志位(一旦接收到数据便会被自动置1)
ch=U0DBUF;//从串口接收寄存器中取出数据放在ch中
U0DBUF=ch;//将ch的数据给串口发送寄存器
while(UTX0IF==0);//发送成功后跳出循环
UTX0IF==0;//清空发送中断标志位
}
·组网
Zigbee无线通信时,需要高频的载波来提供发射效率
Zigbee模块之间要正常通信,要求接收方必须有和发送方同样频率的载波才可以
载波叫做信道(无线通信的通道)
在Zigbee无线通信中,每一个模块都有一个在该网络里唯一的2个字节的地址,这个地址叫做网络地址
Zigbee中的节点也叫做无线模块,节点之间相互可以通信的前提是,必须在同一个网络中
Zigbee中的节点按照功能划分,分为:协调器,路由器,终端,他们可以是一模一样的硬件,使他们划分为不同节点功能的,是他们下载的不同版本的代码。
这些节点成为协调器、路由器、终端的前提是必须在一个Zigbee无线局域网里,若没有入网,则不能称之为协调器、路由器、终端
下载了路由器、终端的代码的节点,上电后的第一件事就是寻找网络,请求加入,而下载了协调器代码的模块,上电后第一件事就是创建Zigbee网络。
判断一个Zigbee无线局域网是否创建成功的标准时:
确定了PANID(个域网ID)
确定了协调器的位置(永远是0x0000)
由9可知,任何一个Zigbee网络,第一个节点,一定是协调器,且一个网络里有且仅有一个协调器
协调器成功创建网络后,就是一个很普通的节点
任何一个Zigbee节点想要加入到网络,都需要一个介绍人,该介绍人为该节点的父节点,该介绍人可以是协调器和路由器,但不能为终端。
*例:下载了协调器代码的模块A
下载了路由器代码的模块B
下载了终端代码的模块C
当A成功创建网络后
下载了终端代码的模块C先入网 则:
A介绍C入网,A为C的父节点
A再介绍B入网,A为B的父节点
网络拓扑图为:
/
下载了路由器代码的模块B先入网,则有两种情况:
I:A介绍B入网,A为B的父节点
A介绍C入网,A为C的父节点
网络拓扑图为:
/
II:A介绍B入网,A为B父节点
B介绍C入网,B为C父节点
网络拓扑图为:
/
在上例中,C选择时,会选择信号强度更强的节点作为介绍人
在组网时,协调器、路由器、终端需要选择信道,在同一个信道时,路由器和终端的PANID如果与协调器创建的PANID相同,则入网成功。
代码:
选择信道:
/
PANID
I:当PANID为非0xFFFF时,协调器创建为该值的PANID,路由器和终端信道相同且值相同时入网
II:当PANID为0xFFFF时,协调器创建随机值的PANID,路由器和终端信道相同是,可以以随机值入网
15、当两个模块都下载协调器代码,且PANID均选择0xFFF8(非0xFFFF)时,则先上电的模块会建立PANID参数为0xFFF8的Zigbee网络,后上电的模块会创建0xFFF8+1,即0xFFF9的Zigbee网络
·通信(抓包)
组建了Zigbee网络后,网络中的节点可以相互通信,通信的方式有4种:
单某某
组播
广播
MAC地址通信
绑定
·协议栈的使用App层
在ZStack协议中,每个层执行不同的功能,每个层几乎都有一个任务,每个任务都有一个任务ID,如:
App层的任务ID的变量是:FirstApp_TaskID
Hal层的任务ID的变量是:Hal_TaskID
以Appc层例,程序首先会在初始化的时候将tsak_id通过初始化函数传参进来保存在任务ID的变量FirstApp_TaskID
FirstApp_TaskID所能处理的事件,在FirstApp_ProcessEvent( byte task_id, UINT16 events )函数中,函数中的每个if代表一个事件,if中的语句代表事件的内容:
//判断是否存在系统事件
if ( events & SYS_EVENT_MSG )
{
.........
while ( MSGpkt )
{
switch ( MSGpkt->hdr.event )
{
case KEY_CHANGE:
uint8 osal_set event(FirstApp_TaskID, FIRSTAPP_USER_LED_EVT);
break;
default:
break;
}
.........
}
}
//用户自定义事件
if ( events & FIRSTAPP_USER_LED_EVT)
{
LED2_DDR |=0X03;
LED1_SBIT=0;
LED2_SBIT=1;
Delay(100000);
LED1_SBIT=1;
LED2_SBIT=0;
Delay(100000);
return (events ^ SYS_EVENT_MSG);
}
给任务添加事件时,需要给每个事件进行宏定义并取值,取值为两个字节16位,取值要求:十六位中,只能有一位为1,其余全部为0,即,16位的四个数字中,只能有一位的取值为8421中的一个值,其余三个数字必须全部为0,如:
#define SYS_EVENT _MSG 0x8000
#define FIRSTAPP_USER_LED_EVT 0x0004
#define SECOND_EVT 0x0008
App层默认了两个事件:系统事件SYS_EVENT_MSG,用户自定义事件
由4可知,因为任务事件定义的要求,导致每个任务最多只能处理16个事件,其中事件编号为0x8000的任务已经默认为系统任务,所以用户可以自己添加的任务仅有15个
当系统要处理的事件多于16个事件,任务处理不了,则引入“消息”
消息的用法:
首先需要给App层任务FirstApp_TaskID发送一个消息
然后调用设置任务事件函数uint8 osal_set_event(FirstApp_TaskID,SYS_EVENT_MSG),意为任务FirstApp_TaskID处理SYS_EVENT_MSG事件
所以进入,SYS_EVENT_MSG事件后,判断引发进入该函数的消息是什么消息,由此有switch-case语句判断消息语句,不同的消息处理不同的事务类型,消息的类型可以自定义。
函数
uint8 osal_set_event(uint task_id,uint16 event_flag)//设置任务事件函数:
task_id:任务编号
event_flag:该任务要处理的事件
一般会在APP层初始化的时候将任务编号传参进来
uint8 osal_start_timerEX(uint taskID,uint16 event_id,uint16 timeout_value):
taskID:任务编号
event_id:该任务要处理的事件
timeout_value:延时多少秒之后执行事件
·协议栈的运行OSAL层
App层有的任务有一个系统分配给他的唯一的编号叫做任务ID
任务处理事件,处理事件的代码都在一个叫做任务事件处理函数中
App层还有一个任务事件变量events,如果events和某个任务事件 内容过长,仅展示头部和尾部部分文字预览,全文请查看图片预览。 应层的相应任务处理函数中
void osal_start_system( void )
{
for(;;)
{
uint8 idx = 0;
........
do {
if (tasksEvents[idx])
{
break;
}
} while (++idx < tasksCnt);
if (idx < tasksCnt)
{
uint16 events;
.........
events = (tasksArr[idx])( idx, events );
tasksEvents[idx]|=events;
H AL_EXIT_CRITICAL_SECTION(intState);
}
.........
·绑定
1、在终端设备向路由器发送时,无线数据包中一定包含:
发送模块的网络地址
发送模块的发送端点
接收模块的网络地址
接收模块的接收端点
接收模块的接收族
[文章尾部最后500字内容到此结束,中间部分内容请查看底下的图片预览]请点击下方选择您需要的文档下载。
以上为《无线传感器网络》的无排版文字预览,完整格式请下载
下载前请仔细阅读上面文字预览以及下方图片预览。图片预览是什么样的,下载的文档就是什么样的。