nRF2401三点通信设计

更新时间:2024-03-02 00:45:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

沈阳航空航天大学电子信息工程学院毕业设计(论文)

第1章 绪论

随着传感器网络技术的发展,传感器网络在物联网的应用成为目前电子信息技术的热点,本题目选取nRF2401无线通信芯片作为收发模块来实现节点之间的无线数据通信,包括:研究一种适合与传感器网络应用的无线通信协议,开发基于nRF2401的嵌入式51单片机的协议栈,并能够实现nRF2401的信道选择、数据通信、差错处理等基本功能。

1.1 课题来源

WSN网络技术一经提出,就迅速在研究界和工业界得到广泛的认可。1998年到2003年,各种与无线通信、Ad Hoc网络、分布式系统的会议开始大量收录与WSN网络技术相关的文章。2001年,美国计算机学会(ACM)和IEEE成立了第一个专门针对传感器网络技术的会议International Conference on Information Processing in Sensor Network(IPSN),为WSN网络的技术发展开拓了一片新的技术园地。2003年到2004年,一批针对传感器网络技术的会议相继组建。ACM在2005年还专门创刊ACM Transaction on Sensor Network,用来出版最优秀的传感器网络技术成果。2004年,Boston大学与BP、Honeywell、Inetco Systems、Invensys、Millennial Net、Radianse、Sensicast Systems等公司联合创办了传感器网络协会,旨在促进WSN技术的开发。2006年10月,在中国北京,中国计算机学会传感器网络专委会正式成立,标志着中国WSN技术研究开始进入一个新的历史阶段。

基于以上信息,可以看出无线网络在以后的发展上有这巨大的潜力,所以我在毕业设计中设计了一个简单的无线网络节点机,可以实现点对点、点对多点和路由转发功能。

1.2 设计任务

本论文主要完成的任务有:熟悉nRF2401的性能、特点及使用方法;熟悉51单片机的指令系统和编程方法;设计无线数据传输模块的通信协议,协议要求提供基本

- 1 -

沈阳航空航天大学电子信息工程学院毕业设计(论文)

的信道选择、数据通信、差错处理、路由转发等功能,数据编码及格式等;使用C语言来实现协议栈设计。

在此基础上,要去了解TCP/IP、UDP、802.11、802.15.4等协议,参考这些协议完成自己的毕业设计,了解无线局域网的基本结构和无线局域网在现实中的应用。

本论文主要实现的功能有:完成点对点通信、点对多点通信、路由转发通信。给出详细的协议设计过程、实现协议的基本功能、实现nRF2401的数据通信。

- 2 -

沈阳航空航天大学电子信息工程学院毕业设计(论文)

第2章 方案分析

对于nRF2401的无线传感器节点机的设计主要有三个部分:发送数据、路由转发数据和接收数据。

对于这三个部分,都研究的是信道选择、数据通信和差错处理上,而对于路由转发,主要有两个方法,第一种方法是利用泛洪的思想,第二种方法就是建路径表。无线节点机的系统测试模型图如图2.1所示。

单片机A 单片机B nRF2401 nRF2401 nRF2401 单片机C

图 2.1 无线节点机测试模型

在这个测试模型中,单片机A与nRF2401组成网络节点A,单片机B与nRF2401组成网络节点B,单片机C与nRF2401组成个网络节点C。在数据传输过程中,A向B发送数据,如果A、B两个节点的距离大于nRF2401本身的传输距离,但是A、C节点和B、C节点的距离为nRF2401有效传输距离,那么A发送的数据可以通过C节点将数据转发到B节点。

nRF2401是一款工作在2.4~2.5GHz世界通用ISM频段的单片无线收发器芯片。无线收发器包括:频率发生器、增强型Shock Burst模式控制器、功率放大器、晶体振荡器、调制器、解调器。输出功率、频道选择和协议的设置可以通过SPI接口进行设置。

nRF2401具有极低的消耗电流,当工作在发射模式下,发射功率为-6dBm时电流

- 3 -

沈阳航空航天大学电子信息工程学院毕业设计(论文)

消耗为9.0mA,接收模式时为12.3mA。掉电模式和待机模式下电流消耗更低。

2.1信道选择

无线网络中,信道选择的重要性不言而喻。在nRF2401中,在配置为接收模式时可以接收6路不用地址(通道0到通道5)的相同频率的数据。每个数据通道拥有自己的地址并且可以通过寄存器来进行分别配置。通常情况下不允许不同的数据通道设置完全相同的地址。

所有数据通道可以设置多达40位地址,数据通道0有40位可配置地址,是唯一的一个可以配置为40位自身地址的数据通道。数据通道1~5的地址为32位共用地址+各自的地址的最低字节,其中共用地址必须相同而各自的地址必须不同。如图2.2所示。

图 2.2 数据通道0~5的地址配置

当从一个数据通道中接收到数据,如果数据通道设置为应答方式的话,那么nRF2401在收到数据后产生应答信号,此应答信号的目标地址为接收通道地址。

在发送端,数据通道0被用做接收应答信号,因此数据通道0的接收地址要与发送端地址相等以确保接收到正确的应答信号。

2.2 发送和接收数据包

- 4 -

沈阳航空航天大学电子信息工程学院毕业设计(论文)

在接收数据的时候,nRF2401模块配置成接收模式(CE=1),在发射数据的时候,nRF2401模块配置为发射模式(CE=1,持续至少10us),130us后启动发射,再过37us后发送一个字节。数据发送结束后,发送模块自动转入接收模式等待应答信号。发送模块在收到应答信号后产生中断通知MCU,接收模块接收到数据包后产生中断通知MCU。发送数据包时序图如图2.3所示。

图 2.3 发送数据包时序图

2.3差错处理

在nRF2401中,自带了CRC校验,CRC校验的长度是通过SPI接口进行配置的。一定要注意CRC计算范围包括整个数据包:地址、PID和有效数据等。

每一包数据都包括两位的PID(数据包序号)来识别接收的数据是新数据包还是重发的数据包。PID序号可以防止接收端同一数据包多次送入MCU,在发送方每次从MCU取得一包新数据后PID值加一。PID和CRC校验应用在接收方,识别接收的数据是重发的数据包还是新数据包。如果在链接中有一些数据丢失了,则PID值与上一包数据的PID值相同。这时,nRF2401将对两包数据的CRC值进行比较,如果CRC值也相

- 5 -

沈阳航空航天大学电子信息工程学院毕业设计(论文)

图 2.7 路径表方式路由转发数据

路由节点要按照某种路由通信协议,查找路由表,路由表中列出整个无线局域网中包含的各个节点,以及节点间的路径情况和与它们相联系的传输费用。如果到特定的节点有一条以上路径,则基于预先确定的准则选择最优(最经济)的路径。由于各种网络段和其相互连接情况可能发生变化,因此路由情况的信息需要及时更新,这是由所使用的路由信息协议规定的定时更新或者按变化情况更新来完成。网络中的每个路由节点按照这一规则动态地更新它所保持的路由表,以便保持有效的路由信息。 路由节点在转发报文的过程中,为了便于在网络间传送报文,按照预定的规则把大的数据包分解成适当大小的数据包,到达目的地后再把分解的数据包包装成原有形式。

多协议的路由节点可以连接使用不同通信协议的网络段,作为不同通信协议网络段通信连接的平台。

路由节点的主要任务是把通信引导到目的地网络,然后到达特定的节点站地址。后一个功能是通过网络地址分解完成的。例如,把网络地址部分的分配指定成网络、子网和区域的一组节点,其余的用来指明子网中的特别站。分层寻址允许路由节点对有很多个节点站的网络存储寻址信息。

在广域网范围内的路由器按其转发报文的性能可以分为两种类型,即中间节点路由器和边界路由器。尽管在不断改进的各种路由协议中,对这两类路由器所使用的名称可能有很大的差别,但所发挥的作用却是一样的。

路由节点在网络中传输时,提供报文的存储和转发。同时根据当前的路由表所保持的路由信息情况,选择最好的路径传送报文。由多个互连的LAN组成的公司或企业网络一侧和外界广域网相连接的路由器,就是这个企业网络的边界路由器。它从外部广域网收集向本企业网络寻址的信息,转发到企业网络中有关的网络段;另一方面集中企业网络中各个LAN段向外部广域网发送的报文,对相关的报文确定最好的传输路径。

2.5 软件设计思路

nRF2401是一款工作在2.4~2.5GHz世界通用ISM频段的单片无线收发器芯片。无

- 11 -

沈阳航空航天大学电子信息工程学院毕业设计(论文)

线收发器包括:频率发生器增强型Shock Burst模式控制器、功率放大器、晶体振荡器、调制器、解调器。输出功率、频道选择和协议的设置可以通过SPI接口进行设置。 在nRF2401工作的时候,最重要的一种协议就是SPI协议。

SPI是英语Serial Peripheral interface的缩写,就是串行外围设备接口。主要应用在EEPROM、FLASH、实时时钟、AD转换器,还有数字信号处理和数字信号解码器之间。SPI是一种高速的,全双工,同步通信总线,在芯片的管脚上只有4跟线,节约了芯片的管脚,同时为PCB的布局节省空间,操作方便,正是因为这种简单的特征,越来越多的芯片使用了这种通信协议。

SPI的通信原理很简单,它以主从方式工作,这种模式通常有一个主设备和一个或多个从设备,需要至少4根线,事实上3根也可以(用于单向传输时,也就是半双工方式)。也是所有基于SPI的设备共有的,它们是SDI(数据输入),SDO(数据输出),SCLK(时钟),CS(片选)。在nRF2401中,数据输入为MOSI,数据输出为MISO,时钟为SCK,片选为CSN。

(1) MOSI– SPI 总线主机输出/ 从机输入 (2) MISO– SPI 总线主机输入/ 从机输出 (2) SCK –时钟信号,由主设备产生 (4) CSN – 从设备使能信号,由主设备控制

其中CSN是控制芯片是否被选中的,也就是说只有片选信号为预先规定的使能信号时(高电位或低电位),对此芯片的操作才有效。这就允许在同一总线上连接多个SPI设备。

接下来就负责通讯的3根线了。通讯是通过数据交换完成的,这里先要知道SPI是串行通讯协议,也就是说数据是一位一位的传输的。这就是SCK时钟线存在的原因,由SCK提供时钟脉冲。MOSI、MISO则基于此脉冲完成数据传输。数据输出通过MOSI线,数据在时钟上升沿或下降沿时改变,在紧接着的下降沿或上升沿被读取。完成一位数据传输,输入也使用同样原理。这样,在至少8次时钟信号的改变(上沿和下沿为一次),就可以完成8位数据的传输。

要注意的是,SCK信号线只由主设备控制,从设备不能控制信号线。同样,在一

- 12 -

沈阳航空航天大学电子信息工程学院毕业设计(论文)

个基于SPI的设备中,至少有一个主控设备。这样的传输方式与普通的串行通讯不同,普通的串行通讯一次连续传送至少8位数据,而SPI允许数据一位一位的传送,甚至允许暂停,因为SCK时钟线由主控设备控制,当没有时钟跳变时,从设备不采集或传送数据。也就是说,主设备通过对SCK时钟线的控制可以完成对通讯的控制。因为SPI的数据输入和输出线独立,允许同时完成数据的输入和输出,所以SPI还是一个数据交换协议。不同的SPI设备实现方式不尽相同,主要是数据改变和采集的时间不同,在时钟信号上沿或下沿采集有不同定义。

SPI主模块和与之通信的外设备时钟相位和极性应该一致。这句话有2层意思:其一,主设备SPI时钟和极性的配置应该由外设来决定;其二,二者的配置应该保持一致,即主设备的MOSI同从设备的MOSI配置一致,主设备的MISO同从设备的MISO配置一致。因为主从设备是在SCK的控制下,同时发送和接收数据,并通过2个双向移位寄存器来交换数据。

在点对点的通信中,SPI接口不需要进行寻址操作,且为全双工通信,显得简单高效。在多个从设备的系统中,每个从设备需要独立的使能信号,硬件上比I2C系统要稍微复杂一些。

Shock Burst模式下nRF2401可以与成本较低的低速MCU相连。高速信号处理是由芯片内部的射频协议处理的,nRF2401提供SPI接口,数据率取决于单片机本身接口速度。Shock Burst模式通过允许与单片机低速通信而无线部分高速通信,这样可以减小通信的平均消耗电流。

在Shock Burst接收模式下,当接收到有效的地址和数据时IRQ通知MCU,随后MCU可将接收到的数据从RX_FIFO寄存器中读出。

在Shock Burst发送模式下,nRF2401自动生成前导码及CRC。数据发送完毕后IRQ通知MCU。减少了MCU的查询时间,也就意味着减少了MCU工作量的同时减少了软件的开发时间,nRF2401内部有三个不同的RX_FIFO寄存器和三个不同的TX_FIFO寄存器。在掉电模式下、待机模式下和数据传输的过程中MCU可以随时访问FIFO寄存器。这就允许SPI接口可以以低速进行数据传送,并且可以应用于MCU硬件上没有SPI接口的情况。

- 13 -

沈阳航空航天大学电子信息工程学院毕业设计(论文)

增强型Shock Burst模式可以使得双向链接协议执行起来更为容易、有效。典型的双向链接为:发送方要求终端设备在接收到数据后有应答信号,以便于发送方检测有无数据丢失。一旦数据丢失,则通过重新发送功能将丢失的数据恢复。增强型的Shock Burst模式可以同时控制应答及重发功能而无需增加MCU工作量。

2.5.1 自动应答(RX):

自动应答功能减少了外部MCU的工作量,因此降低成本减少电流消耗。自动应答功能可以通过SPI口对不同的数据通道分别进行配置。

在自动应答模式使能的情况下,收到有效的数据包后,系统将进入发送模式并发送确认信号。发送完确认信号后,系统进入正常工作模式。

2.5.2 自动重发功能ART(TX):

自动重发功能是针对发送方的自动应答系统。SETUP_RETR寄存器设置启动重发数据的时间长度。在每次发送结束后系统都会进入接收模式并在设定的时间范围内等待应答信号。接收到应答信号后,系统转入正常发送模式。如果TX_FIFO中没有待发送的数据且CE脚电平为低,则系统将进入待机模式I。如果没有收到确认信号,则系统返回到发送模式并重发数据直到收到确认信号或重发次数超过设定值。有新的数据发送或PRIM_RX寄存器配置改变时丢包计数器复位。

- 14 -

沈阳航空航天大学电子信息工程学院毕业设计(论文)

第3章 硬件设计

整个无线传感器节点机的设计的硬件电路主要是以51单片机为核心的数处理系统、nRF2401的无线通信片和电源电路。

在硬件的设计中,nRF2401使用的是无线模块,电源电路是由AMS1117这种稳压芯片组成。

3.1 51单片机部分

单片机是本设计中数据处理的重要部分,本文采用的是STC公司的STC89C51系列单片机中的STC89C52芯片。这是一款8051的内核芯片,内部含有Flash、 EEPROM存储器,该器件为CMOS产品。单片机的内部RAM为512B,芯片外部晶振最高可以接入40MHz,温度是0到70摄氏度。单片机为双列直插式,51 单片机的最小系统电路如图3.1所示。

图 3.1 单片机最小系统

3.1.1单片机的空闲与掉电模式

- 15 -

沈阳航空航天大学电子信息工程学院毕业设计(论文)

当单片机进入空闲模式时,除了CPU处于休眠期状态外,其余硬件全部处于活动状态,芯片中程序未涉及的数据存储器和特殊功能寄存器中的数据在空闲模式期间都保持原值。假若定时器正在运行,那么计数器存储器中的值还会增加。单片机在空闲模式下可由nRF2401发送或者接收数据来唤醒。让单片机进入空闲模式是为了减少功耗。

当单片机进入掉电模式时,外部晶振停震,CPU、定时器、串行口全部停止工作,只有外部中断继续进行工作。使单片机进入掉电模式的指令将成为休眠前单片机执行的最后一条指令。进入掉电模式后,芯片中程序未涉及的数据存储器和特殊功能寄存器中的数据将保持原值。可以用外部中断低电平触发,或下降沿触发中断,或硬件复位模式唤醒单片机。需要注意的是,使用中断唤醒单片机时,程序从原停止处继续运行;当使用硬件复位唤醒单片机时,程序将从头开始执行。如果单片机进入掉电模式以后重新上电nRF2401将重新工作,不会记录原来发送的数据。

3.1.2单片机的“看门狗”

在单片机构成的系统中,由于单片机的工作有可能受到来自外界电磁场的干扰,造成程序的跑飞,从而陷入死循环,程序的正常运行被打断,单片机控制的系统便无法继续工作,这样会造成整个系统陷入停滞状态,发生不可预料的后果,所以出于对单片机运行状态进行实时监测的考虑,便产生了一种专门用于监测单片机程序运行状态的芯片,俗称“看门狗”。

加入看门狗电路的目的是使单片机可以在无人状态下实现连续工作,其工作过程如下:单片机程序控制看门狗。使它定时地往看门狗芯片中送入高电平(或低电平),这一程序语句是分散地放在单片机其他控制语句中的,一旦单片机由于干扰造成程序跑飞而陷入某一程序段进入死循环时,给看门狗送电平的程序便不会被执行,这时,看门狗电路就会由于得不到单片机送来的信号,便对它与单片机复位引脚送一个复位信号,使单片机复位,从而使单片机从程序存储器的起始位子重新开始执行程序,这样便实现了单片机的自动复位。

在STC89C51系列单片机中,内置了看门狗功能,这样就不用单独完成看门狗,通过相对应的特殊功能寄存器的设置就可以实现看门狗的应用。

- 16 -

沈阳航空航天大学电子信息工程学院毕业设计(论文)

3.1.3内部扩展RAM

RAM是在程序运行中存放随机变量的数据空间,51单片机默认的内部RAM只有128B。对于编程者来说,一个芯片的RAM空间越大,写起程序来就容易得心应手,不用考虑因为RAM不够而不敢过多的对变量进行定义。

一旦程序中的总变量超过了128B,必须对所有变量进行初始化,否则没有被初始化的变量默认值将不会确定。当变量总和超过128B时,还必须要在编译器中重新设定存储器的存储模式。

存储器模式有三种,分别是small、compact和large模式。他决定了没有明确指定存储类型的变量。如果在某些函数中需要使用非默认的存储模式,也可以使用关键字直接说明。

small模式中,所有默认变量均装入单片机内部128B的RAM中,当定义类似“uchar a;”“float b;”等变量时,这些变量都装入内部128B的RAM中;compact模式中,所有默认变量均位于单片机内部的256B的RAM中,和在small模式中使用关键字pdata来定义变量的效果相同;在large模式中,所有默认变量可放在多达64KB的RAM区,包括内部RAM和外部RAM,这和使用关键字xdata来定义变量的效果相同。

3.1.4内部EEPROM的应用

STC89C51,STC89C52内部都自带有2KB的EEPROM,STC单片机是利用IAP技术实现的EEPROM,内部Flash擦写次数可达100000次以上。

IAP就是片子提供一系列的机制,当片子在运行程序时可以提供一种改变Flash数据的方法。也就是说,程序自己往程序存储器里写数据或修改程序。

3.2 电源电路部分

由于单片机最小系统需要5v电压供电,nRF2401芯片需要3.3v电压供电。所以,我在设计电源的时候,设计了5v和3.3v两种电源。电源是通过4节干电池通过AMS1117-5和AMS1117-3.3两种稳压芯片得到的。

- 17 -

沈阳航空航天大学电子信息工程学院毕业设计(论文)

AMS1117是一款正电压输出低压差的三段线性稳压电路的芯片,在输出1A电流时,输入输出的电压差典型值为1.8v。

AMS1117是一个低漏失电压调整器,它的稳压调整管是由一个PNP驱动的NPN管组成的,漏失电压定义为:VDROP=VBE+VSAT。

AMS1117有固定和可调两个版本可用,输出电压可以是:1.8v,3.3v 和5.0v。片内过热切断电路提供了过载和过热保护,以防环境温度造成过高的结温,其中过流保护和过热保护模块,能够在应用电路的环境温度大于120℃以上或负载电流大900mA 时,保证芯片和系统的安全。。

为了确保AMS1117 的稳定性,输出需要连接一个至少22μF 的钽电容。通常,线性调整器的稳定性随着输出电流增加而降低,电源电路如图3.2所示。

图 3.2 电源模块电路图

3.3 nRF2401无线通信模块部分

nRF2401是挪威Nordic公司推出的单片无线收发一体芯片,工作在2.4GHz,ISM频

段,具有接收灵敏度高、外围电路少、发射功率低、传输速率高和功耗低等特点,可

- 18 -

沈阳航空航天大学电子信息工程学院毕业设计(论文)

以实现点对点、点对多点的通信。

3.3.1 模块介绍

nRF2401是有126频道,满足多点通信和跳频通信需要;内置硬件CRC 检错和点对多点通信地址控制;低功耗1.9 - 3.6V 工作,待机模式下状态为22uA;掉电模式下为900nA;内置2.4GHz天线,体积小巧15mm X29mm;模块可软件设地址,只有收到本机地址时才会输出数据(提供中断指示),可直接接各种单片机使用,软件编程非常方便;内置专门稳压电路,使用各种电源包括DC/DC开关电源均有很好的通信效果;2.54mm间距接口,DIP封装;工作于Enhanced Shock Burst具有Automatic packet handling, Auto packet transaction handling,具有可选的内置包应答机制,极大的降低丢包率;与51系列单片机P0口连接时候,需要加10K的上拉电阻,与其余口连接不需要,模块结构如图3.3所示。

图 3.3 nRF2401模块的结构示意图

- 19 -

沈阳航空航天大学电子信息工程学院毕业设计(论文)

3.3.2 PCB板设计及去耦

一个好的PCB布线对射频性能有很大影响。一个差的PCB板设计可能导致丢包甚至可能不能实现其应有的功能。

在设计nRF2401的时候,要避免使用长的电源走线,所有元器件的地VDD及VDD与去耦电容应尽可能的靠近nRF2401芯片。直流供电电源应尽可能靠近芯片的VDD引脚。最好用一个大电容(比如:4.7uF钽电容)并联一个小电容。如果在PCB板的顶层有铺铜的“地”网,VSS应直接与铺铜面连接。如果在PCB板的底层有铺铜的“地”网,则应该在离VSS脚尽可能近的地方放置过孔连接。每个VSS最少应有一个过孔。所有数字信号线和控制信号线都不能离晶振和电源线太近,nRF2401原理图如图3.4所示。

图 3.4 nRF2401原理图

- 20 -

沈阳航空航天大学电子信息工程学院毕业设计(论文)

第4章 软件设计

基于nRF2401无线传感器节点机的设计采用的是模块化的思想,这样软件实现模块化、标准化,易于理解和移植。传感器节点上的软件是无线传感器网络进行有效工作的灵魂,负责完成现场数据的采集以及通过无线通信模块将采集数据包无线传送。

节点机的软件设计主要包括三个部分,分别是发送数据、路由转发数据和接收数据。

4.1 nRF2401的配置

nRF2401的所有配置工作都是通过SPI完成,共有30字节的配置字。

我们推荐nRF2401工作于Shock Burst收发模式,这种工作模式下,系统的程序编制会更加简单,并且稳定性也会更高。因此,下文着重介绍把nRF2401配置为Shock Burst收发模式的器件配置方法。

Shock Burst的配置字使nRF2401能够处理射频协议,在配置完成后,在nRF2401工作的过程中,只需改变其最低一个字节中的内容,以实现接收模式和发送模式之间切换。

Shock Burst的配置字可以分为以下四个部分:

数据宽度:声明射频数据包中数据占用的位数。这使得nRF2401能够区分接收数据包中的数据和CRC校验码;

地址宽度:声明射频数据包中地址占用的位数。这使得nRF2401能够区分地址和数据;

地址:接收数据的地址,有通道0到通道5的地址; CRC:使nRF2401能够生成CRC校验码和解码。

当使用nRF2401片内的CRC技术时,要确保在配置字中CRC校验被使能,并且发送和接收使用相同的协议。

- 21 -

沈阳航空航天大学电子信息工程学院毕业设计(论文)

4.2 收发模式

nRF2401的收发模式操作是通过CE、CLK和DATA三个引脚完成的。当nRF2401要采用Shock Burst发射数据时,首先将CE脚置高,把接收节点的地址和要发送的数据按时序送入nRF2401,然后将CE脚置低,激发nRF2401发射。当采用Shock Burst接收数据时,首先配置本节点地址和要接收的数据包大小,将CE脚置高,等待200us后,nRF2401进入监听状态,等待数据的到来。当接收到正确的数据包后,将DR脚置高,通知MCU取走数据。待MCU取走数据后,nRF2401将DR置低,此时,如果CE脚为高,则等待下一个数据包,否则开始其它的工作流程。

4.2.1发送模式

首先要配置寄存器PRIM_RX为低;当MCU有数据要发送时,接收节点地址和有效数据通过SPI接口写入nRF2401芯片。发送数据的长度以字节计数,从MCU写入TX_ FIFO。当CSN为低时数据被不断地写入。发送端发送完数据后,将通道0设置为接收模式来接收应答信号,其接收地址(RX_ADDR_P0)与接收端地址(TX_ADDR)相同;设置CE为高,启动发射。CE高电平持续时间最小为10us;nRF2401设置为Shock Burst模式,无线系统上电、启动内部16MHz时钟、无线发送数据打包、高速发送数据;如果启动了自动应答模式无线芯片立即进入接收模式。如果在有效应答时间范围内收到应答信号,则认为数据成功发送到了接收端,此时状态寄存器的TX_DS位置高并把数据从TX _FIFO中清除掉。如果在设定时间范围内没有接收到应答信号,则重新发送数据。如果自动重发计数器(ARC_CNT)溢出,则状态寄存器的MAX_RT位置高。不清除TX _FIFO中的数据,当MAX_RT或TX_DS为高电平时,IRQ引脚产生中断。IRQ中断通过写状态寄存器来复位。如果重发次数在达到设定的最大重发次数时还没有收到应答信号的话,在MAX_RX中断清除之前不会重发数据包。数据包丢失计数器(PLOS_CNT)在每次产生MAX_RT中断后加一。

在发射模式下,首先要将nRF2401端口与单片机的I/O口连接,设置为待机模式、禁止SPI协议启动、SPI时钟置低、中断复位、同时将LED全部关闭流,然后,初始化为发射模式,具体步骤为:定义发射信号按键,将信号给到单片机并放到单片机的缓存中去,将nRF2401设置为发射模式,当有按键按下的时候,发送数据,发送完毕后

- 22 -

沈阳航空航天大学电子信息工程学院毕业设计(论文)

清空TX FIFO寄存器程。初始化完毕后,进行数据发送。流程图如图4.1下所示。

开始 nRF2401初始化端口 判断按键是否按下 是 nRF2401发送初始化 数据发送到单片机的缓存中 设置nRF2401为发射模式 数据到LED显示 清楚nRF2401寄存器数据 LED关闭 图 4.1 发送端流程图

4.2.2接收模式

否 - 23 -

沈阳航空航天大学电子信息工程学院毕业设计(论文)

Shock Burst接收模式是通过设置寄存器中PRIM_RX位为高来选择的。准备接收数据的通道必须被使能。所有工作在增强型Shock Burst模式下的数据通道的自动应答功能是由EN_AA寄存器来使能的,有效数据宽度是由RX_PW_Px寄存器来设置的;接收模式由设置CE为高来启动;130us后nRF2401开始检测数据信息;接收到有效的数据包后(地址匹配、CRC检验正确)数据存储在RX_FIFO中,同时RX_DR位置高,并产生中断。状态寄存器中RX_P_NO位显示数据是由哪个通道接收到的;如果使能自动确认信号,则发送确认信号,MCU设置CE脚为低,进入低功耗模式,MCU将数据以合适的速率通过SPI口将数据读出,芯片准备好进入发送模式、接收模式或掉电模式。

在发射模式下,首先要将nRF2401端口与单片机的I/O口连接,设置为待机模式、禁止SPI协议启动、SPI时钟置低、中断复位、同时将LED全部关闭流。然后,将nRF2401设置为接收模式。首先读取nRF2401寄存器状态,判断是否接收到数据,如果接收到数据,将数据从RX_FIFO寄存器中读出来,同时设置一个读出数据标志,当读出数据成功以后,清除RX_DX中断标志,当读出数据的时候,数据发送到LED显示,然后将LED全部关闭。接收端流程图如图4.2所示。

- 24 -

沈阳航空航天大学电子信息工程学院毕业设计(论文)

开始 nRF2401端口初始化 nRF2401设置为接收模式 读取转改寄存器 否 是否接收到数据 是 读出数据 读取标志至1 否 是否完成接收数据 是 读取标志至0 LED显示数据发送成功 LED关闭

图4.2 接收端流程图

4.2.3 路由转发

- 25 -

沈阳航空航天大学电子信息工程学院毕业设计(论文)

对于路由转发的节点机,我在软件的设计上,简单的说是先让这个路由节点接收到发送端发送的数据,这个数据通过泛洪的方式,将数据发送出去,这时,接收端就可以接收到发送端的数据。

在无线局域网中,之所以要用到路由转发这个功能,是因为发送端和接收端的距离超过了nRF2401本身的传输距离,这样,接收端就不能接收到发送端发送过来的数据。这时,我们就要利用这个路由节点,将数据转发到接收端。

在路由端,我们要完成的软件中最重要的就是接收数据和发送数据。但是在现实的无线局域网中是远远不够的,在现实中的无线路由转发,是要考虑传输路径的。在这条路径中,有着最好的传输效率,最小的误码率。在这条路径的选择上,是需要大量的实验的,这实验数据中,找到这条最好的数据传输路径。

在数据发送的时候,我们需要将发送数据打上标号,这个标号是节点的记号,用来记录这个数据是在那个节点机中发送过来的,在路由端的这个节点机中,也有自己的标号,路由节点接收到数据的时候,这个数据的标号是发送节点的标号,在这时,要判断路由节点是否为目标节点,如果是目标节点,那么就处理这个数据。如果不是目标节点,那么就要将这个数据发送出去,这时,这个数据的标号已经变为了路由节点的标号,在接收端接到的数据,也是这个有路由节点标号的数据。在这个数据的传输上,数据是不变的,变化的只是记录节点的标号,这样,数据在传输的时候,不会发送数据混叠。路由转发的流程图如图4.3所示。

- 26 -

沈阳航空航天大学电子信息工程学院毕业设计(论文)

开始 初始化 nRF2401配置 否 接收数据信号DRI是否为1 发送标志位是否为1 否 是 进入接收状态 是 进入发送状态 接收1位数据 否 发送1位数据 是 数据是否接收完毕 否 是 数据校验 数据是否方完毕 是 数据是否正确 否 丢弃接收数据请求

图 4.3 路由转发节点流程图

- 27 -

沈阳航空航天大学电子信息工程学院毕业设计(论文)

第5章 调试情况及其排故

在这次毕业设计的调试过程中分为硬件检查、软件调试和软硬件联调三个步骤。系统模拟调试是把已调好的各个模块,按照总体要求连成一个完整的整体。软件部分还要与所设计的硬件系统进行联机调试。在任何一个设计中,电路调试部分能够检验设计方案的可行性和正确性。在这个过程中可能要遇到在设计中没有考虑到的地方,通过调试可以使设计得到更好的补充。

首先是确保硬件的每一个连接都是正确的,没有漏焊和虚焊的情况。还有所用的器件都是正确的。其次,要保证软件的编译能通过,对代码本身来讲是没有错误的。最后完成的是最艰难的工作—软硬件联调。

5.1 硬件调试部分

硬件调试部分主要是检查焊接点和确定各个功能部件无故障,从而保证后续工作的顺利进行。在整个毕业设计中,其实硬件调试部分是非常重要的一个环节,因为当我们在最后的软硬件联调的时候,往往认为问题是软件的问题,而忽略了硬件本身的问题。这个时候我们往往是不停地去解决软件上的问题,殊不知软件本身没有什么问题,而是因为硬件上某个焊接点没有焊接好而造成整个系统不能使用。 5.1.1电源模块的调试

在整个设计系统中,因为nRF2401需要3.3v的电压,而单片机需要5v电源供电,所以我需要三个3.3v和5v的电源模块。因为干电池本身的噪声过大,所以不能用干电池作为单片机的供电系统。而AMS1117是一款很常用的稳压芯片,使用也很简单,如果想要一个5v的稳定电压,只要在AMS1117-5这个芯片的VIN端输入一个大于5v的电源,在VOUT端就可以输出稳定的5v电压。3.3v的电压原理相同。

在电路连接好后,只要用电压表测试VOUT端的电压,就可以确定整个电源模块是否可以正常工作。电源电路输入输出电压如表5.1所示。

- 28 -

沈阳航空航天大学电子信息工程学院毕业设计(论文)

表 5.1 电源模块的输入输出电压

模块电压 ams117-5输入端 ams117-5输出端 ams117-3.3输入端 ams117-3.3输出端 第一个稳压模块 5.86v 5.01v 5.01v 3.34v 第二个稳压模块 5.64v 5.03v 5.03v 3.31v 第三个稳压模块 5.73v 5.01v 5.01v 3.32v 5.1.2 nRF2401无线模块

在nRF2401模块中,主要有10个外接引脚,其中: 1管脚和2管脚为电源,需要接入3.3v电压;

3管脚为CE,芯片使能,其中发送模式时高电平>10us,接收模式为高电平,待机模式为低电平;

4管脚为CSN,SPI片选使能,低电平使能; 5管脚为SCK,SPI时钟; 6管脚为MOSI,SPI串行输入; 7管脚为MISO,SPI串行输出; 8管脚为IRQ,中断,低电平使能;

9管脚和10管脚为芯片接地端。在这两个管脚上要分别于单片机和电源共地。 由于nRF2401使用的是模块,所以在nRF2401的硬件模块上,没有什么需要过多调试的东西,只要保证这个模块没有虚焊的情况即可。在检测是否有虚焊的时候,只需要一个万用表,将其打倒二极管档,然后将两个焊点分别用两个表笔相连,如果万用表显示导通,则表明这个nRF2401的模块上是没有虚焊的。

5.2 软件调试部分

首先,确定设计思想和设计方案后,画出各个阶段的流程图,归纳总结各阶段

- 29 -

沈阳航空航天大学电子信息工程学院毕业设计(论文)

流程图所需要的子程序。然后根据流程图编写程序。最后,将编好的程序在keil软件中进行编译调试,观察程序的运行情况。在编译调试的过程中,出现最大的问题是没有定义这样的问题,这里边有两种情况,一个是找不到自己定义的变量,另一个是找不到已经定义好的函数。

对与第一种问题主要是因为在定义变量的时候,取名字不够规范,这样在自己调用变量的时候,有时候会忘掉某个字母或者字母的大小写没有区别好,这个是需要自己在以后编写代码的时候,需要注意的地方,即规范自己的变量名。

对于第二种问题,那就是在自己编写函数的时候,有时候定义了一个或多个形参,但是在调用函数的时候,没有在函数中写入参数,这样也是不对的。

当编译代码没有语法错误的时候,就要考虑代码的结构和语法上了逻辑是否有问题了,这就要通过软硬件联调来实现了。

5.3 软硬件联调部分

nRF2401无线传感器节点机的设计中,最重要的部分是路由转发的功能,但在这之前,我们要完成的是点对点通信、点对多点通信和双机通信。因为只有完成了点对点和点对多点的通信,才能让nRF2401这个无线通信模块完成通信的功能,而双机通信是完成无线路由转发功能的重要组成部分,因为无线路由就是在一个节点上接收到信号后再将数据发送出去,这也就是相当于双机通信的一个过程。

在两个nRF2401无线模块单向发送数据的时候,我们将代码烧写到单片机后,通过一个按键作为外部中断,当检测到按键按下的下降沿的时候,发送数据。

在刚开始的时候,肯定会出现在接收端没有现象的情况,这样就需要我们细心的检查是发送端没能发送数据还是在接收端没能接收到数据。这也是在整个毕业设计中最先要解决的地方,同时也是困难的地方。正所谓万事开头难就是这个道理。因为在这个过程中,我们要完成的是nRF2401的配置,SPI协议和发送和接收数据基本方法。若果没能完成这个任务,那么无法完成整个毕业设计。

在检查到底是那个模块没有工作还是两个模块都没有工作的时候,首先在单片机的一个I/O口上接一个一个发光二级管,当发送模块发送完数据的时候,让这个I/O

- 30 -

沈阳航空航天大学电子信息工程学院毕业设计(论文)

口变成低电平,这样发光二极管就会变亮,这样就可以显示发送端发送数据成功,这时如果还没与接收到数据,则表明接收模块的配置出了问题。

当nRF2401发送端没有问题了以后,可以肯定无法传输数据出现的问题是接收端了,同时也可以确定是在接收端的软件编程上出现了问题。这时我们就要考虑在编写代码的时候,接收端定义的静态发送地址与发送端的是否相同,接收通道是否相同,发送端和接收端的使能通道是否相同,对于0通道射频通道是否配置为40,当这些配置都正确了以后,重新烧写代码,这时就可以发现两个nRF2401模块可以实现单向通信了。

这时,我发现了一个在无线传输中的漏洞,那就是发送端发送的数据,接收端只能接收一次数据,有时候不能接收数据。换句话来说,那就是发送端连续发送数据的时候,接收端只能接收一次,接收端就不会继续工作了。

这样的问题出现也是代码的问题,出现这个问题的主要原因是因为在接收端接收完数据的时候,没能及时的清除寄存器里边的数据,寄存器的空间一直被占用,就不会接收到新的数据。解决这个问题也很简单,那就是在接收端接收完数据的时候,及时清除掉接收端nRF2401芯片中寄存器的数据,释放寄存器空间,同时在发送端也要进行这样的处理,因为发送端的寄存器数据如果没有清除的话,也就不会有新的数据写到寄存器中,这样在发送端也是不好用的。

当整个毕业设计的单向发送数据完成以后,可以说我已经对nRF2401已经有了一定的认识,这时候在双向传输数据的调试中,也就有了一定的信心。所以在双向调试的时候,也就没有那么多的困难了。

在双向通信中,我将单向通信中所用到的东西全部结合到了一起,通过外部按键进行双向通信。但这个时候,出现了一个新的问题。在发送0x01这一个个数据的时候,在接收端接收到了0x01到0xff之间的所有数据,这时我尝试用P1.0一个管脚接收数据,但是没有定义的其他管脚也会接收到数据。这个问题困扰了我很长时间,我不明白的是为什么我只定义了一个I/O口,为什么其他的I/O口也会工作,理论上当I/O口为低电平的时候,法官二极管才会点亮,但这时候的I/O口电压不是0v,而是1v左右的电压,这说明我在软件编程的结构上出现了问题。

- 31 -

沈阳航空航天大学电子信息工程学院毕业设计(论文)

因为nRF2401在配置为接收模式的时候,无论什么通道发送过来的数据,都回接收到,我在写代码的时候,在发送数据的时候,直接检测是否有数据发送过来,而且也没有对数据进行加标号,这样在发送数据的时候,再配置为接收模式,就会不停的检测每个数据通道发送过来的数据。因此在工作时,就会有电平上的变化,这些数据不是发送端发送过来的数据,而是在检测是否有数据传输过来的时候,发生的信号干扰。

当两个nRF2401可以实现双向通信的时候,我们就要完成在整个毕业设计中最重要的部分,那就是路由转发功能了。

在整个代码中,使用的是泛洪的方法进行路由转发,这样在毕业设计的难度上就有了很大程度上的下降。因为在无线局域网传输数据的时候只有三个节点,路由节点完成接收数据并发送数据,这样就和双向通信差不多了,只要能接收到数据,并判断是否为这个节点应该接收的数据,如果是,那么接收,如果不是,那就将数据发送出去,不用考虑传输路径的问题。

在路由节点,在刚开始的时候,发现接收完数据以后可以将数据发送出去,但是这个节点同时可以接收到自己发送出去的信号,这样,这个节点就不停的接收自己发过来的信号,同时因为自己接收到了信号,也就不停的去发送信号。这是在以前没有发现的问题,因为以前都是通过开关控制发送数据,而不是自己去发送数据。所以在毕业设计的最后阶段,也就是要去解决这个问题。

解决这个问题,其实只要在发送的数据上加一个标号就行了,这样在路由节点只去处理带有发送端标号的数据,而不去处理这个带有路由节点标号的数据,这样,在接收到数据的时候,就不会出现不停接收同一个数据,进而不停工作的情况了。

- 32 -

沈阳航空航天大学电子信息工程学院毕业设计(论文)

第6章 结论

本论文是在指导教师武卫东教授的悉心指导下完成的,经过一个学期的不懈努力,我基本完成了毕业设计的任务要求。在设计过程中,我通过查阅大量有关资料,与同学交流经验和自学,向老师请教等方式,使自己学到了不少知识,也经历了不少艰辛,但收获同样巨大。

在整个设计中我懂得了许多东西,也培养了我独立工作的能力,树立了对自己工作能力的信心,相信会对今后的学习工作生活有非常重要的影响。而且大大提高了动手的能力,使我充分体会到了在创造过程中探索的艰难和成功时的喜悦。但由于水平和条件的不足,该系统还存在需要改进和提高的地方。其中,路由转发功能应该使用更为准确的建立路径表的方法,这样可以减少功率,数据传输更为准确。本设计效果良好,简单的通信基本完成,可以实现发送、接收和路由转发功能。

通过毕业设计,使我加深了对无线局域网节点机的认识,也带动我复习了专业知识和英语水平。实际工作经验的不足让我客观的正视了自己的能力,发现自己的薄弱环节,及时补充不足之处,构成了完整的知识体系。

本次毕业设计,给了我一个很好的锻炼机会,使我能够将大学四年的理论知识与实际有机的结合起来,不但对知识有了更深了理解,并且对他们的运用能力有了更大的提高。在完成毕业设计期间养成了良好的学习态度,培养了自己敢于面对困难,解决问题的能力,这不仅仅为我积累了宝贵财富,还激励我在今后的学习生活中更加努力。

- 33 -

沈阳航空航天大学电子信息工程学院毕业设计(论文)

第7章 经济与设计效益

本设计完成以后,笔者曾利用多种渠道考证其学术意义、经济价值和社会效益。 由于WSN资源有限且与应用高度相关,研究人员采用多种策略来设计路由协议,其中好的协议具有以下特点:针对能量高度受限的特点,高效利用能量几乎是设计的第一策略;针对开销大、通信耗能、节点之间合作关系、数据有相关性、节点能量有限等特点,采用数据聚合、过滤等技术;针对流量特征、通信耗能等特点,采用通信量负载平衡技术;针对节点少移动的特点,不维护其移动性;针对网络相对封闭、不提供计算等特点,只在sink点考虑与其他网络互联;针对网络节点不常编址的特点,采用基于数据或基于位置的通信机制;针对节点易失效的特点,采用多路径机制。通过对当前的各种路由协议进行分析与总结,可以看出将来WSN路由协议采用的某些研究策略与发展趋势:

(1) 减少通信量以节约能量。由于WSN中数据通信最为耗能,因此应在协议中尽量减少数据通信量。例如,可在数据查询或者数据上报中采用某种过滤机制,抑制节点上传不必要的数据;采用数据聚合机制,在数据传输到sink点前就完成可能的数据计算。

(2) 保持通信量负载平衡。通过更加灵活地使用路由策略让各个节点分担数据传输,平衡节点前剩余能量,提高整个网络的生存时间。例如,可在层次路由中采用动态簇头;在路由选择中采用随机路由而非稳定路由,在路径选择中考虑节点的剩余能量。

(3) 路由协议应具有容错性。由于WSN节点容易发生故障,因此应尽量利用节点易获得的网络信息计算路由,以确保在路由出现故障时能够尽快得到恢复,并可采用多路径传输来提高数据传输的可靠性。

(4) 路由协议应具有安全机制。由于WSN的固有特性,其路由协议极易受到安全威胁,尤其是在军事应用中,目前的路由协议很少考虑安全问题,因此在一些应用中必须考虑设计具有安全机制的路由协议。

(5) WSN路由协议将继续向基于数据、基于位置的方向发展。这是由WSN一般不

- 34 -

沈阳航空航天大学电子信息工程学院毕业设计(论文)

统一编址和以数据、位置为中心的特点决定的。

研究发现,被调查的家企业中有95%已经部署了无线网络。回应者集中在三个组中:行动迟缓的企业,行业平均水平的企业,以及最佳级别的企业。最佳级别的企业从无线局域网部署中收获了最大的商业利益。根据无线局域网性能评分,行动迟缓的企业占最后的30%。处于行业平均水平的企业则占中间的50%,最佳级别的企业占据前20%。

该研究表明,最佳级别的企业同那些行业平均水平的企业相比,从无线局域网中获利更多。最佳级别企业对无线网络进行协调来改善用户的使用效率并与此同时简化实施和降低管理开销。

根据调查,最佳级别企业在劳动力灵活性方面实现了27%的增长幅度,而这种灵活性来源于无线局域网的部署,同时还有劳动力协同工作方面的26%的增长,这也来源于无线局域网的部署,以及在会议质量方面的29%的增长,这归功于使用无线局域网的小组成员。这些优点要比那些无线局域网使用情况一般的公司获得的优点高出三倍。

调查结果还发现,最佳级别企业比所有其它企业在为集中的无线局域网管理制定策略方面多出67%,在拥有无线网络管理专业职员方面多出一倍,比行业平均水平企业在拥有用户访问策略方面高出25%。

- 35 -

沈阳航空航天大学电子信息工程学院毕业设计(论文)

致 谢

本论文是在指导教师武卫东教授的悉心指导下完成的。他严谨细致、一丝不苟的作风一直是我工作、学习中的榜样。他循循善诱的教导和不拘一格的思路给予我无尽的启迪。武卫东老师不仅在学业上给我以精心指导,同时还在思想、生活上给我以无微不至的关怀,在此谨向武卫东老师致以诚挚的谢意和崇高的敬意。

由衷感谢父母的支持和鼓励,无时无刻给予我的温暖和关怀,你们的陪伴和支持,无形中给了我很大的力量和勇气去面对困难。

最后,感谢培养了我四年的沈阳航空航天大学,在这里,我不仅仅学习了理论知识,更学会了为人处世的道理。感谢一同在电子创新实验室学习、研究过的同学们。和你们共同学习、互利互勉的日子是我一生当中最美好的时光,这是一段值得我用一生去回忆日子,也是我非常珍贵的财富,感谢你们陪伴我度过了这段对我来说意义非凡的岁月。

再次感谢帮助过我的人,愿这份论文得已完成的荣耀和喜悦能同各位分享。

- 36 -

沈阳航空航天大学电子信息工程学院毕业设计(论文)

参考文献

[1] 华兵.MCS-51单片机原理应用.武汉:武汉华中科技大学出版社,2002.5 [2] 李华.MCU-51系列单片机实用接口技术.北京:北京航空航天大学出版社,1993.6

[3] 谢希仁.计算机网络.北京:电子工业出版社,2011.5 [4] 曹雪红,张宗橙.信息论于编码.北京:清华大学出版社

[5] 孙利民,李建中,陈渝等.无线传感器网络.北京:清华大学出版社,2005.4 [6] 于海斌,曾鹏等.智能无线传感器网络系统.北京:科学出版社,2006.7 [7] 王鹏,张尧弼。802.11 WLAN的安全缺陷及其对策. 计算机工程,2004.3 [8]. JEANLJ著,邵贝贝译.嵌入式实时操作系统IzC/OS-Ⅱ.北京:北京航空航天大学出版社,2003.7

[9] 田苗.嵌入式系统设计与实例开发.北京:清华大学出版社,2002.9 [10] HOLGERKARL氏无线传感器网络协议与体系结构.电子工业出版社,2007 [11] 孙亭,杨永田,李立宏.无线传感器网络技术发展现状.电子技术应用。2006.1—5

[12] 尹勇,龙毅宏.嵌入式无线传感器网络节点设计.武汉理工大学学报:自然科学版,2006,28(3):107—109

[13] 任丰原,黄海宁,林闯.无线传感器网络.软件学报,2003.14(7) [14] 行健,郑青,姜伟.基于nRF2401无线监控系统的应用与实现.自动化仪表,2007,28(9):38—40

[15] 李国辉,李友红,刘立新,等.基于ARM和nRF2401的无线自动抄表系统.电测与仪表,2007,44(2):25—28

[16] Wright G R, Stevens W R. 陆雪莹, 蒋慧译. TCP/IP 详解卷2 实现. 北京机械工业出版社, 2000

- 37 -

沈阳航空航天大学电子信息工程学院毕业设计(论文)

[17] VahidF,GivargisT.嵌入式系统设计.北京:北京航空航天大学出版社,2004 [18] 蒋伟宏,魏急波.嵌入式Linux的设备接口驱动程序的设计与实现[J].嵌入式操作系统.2002,7(11):363—366

[19] 周敬东,陈幼平,周祖德等.组态软件硬件接口的设计与实现[J].机械与电子,2004,4(6):44—47

[20] 杨宗源,黄海涛.Uni/Linux编程实践教程.清华大学出版社,2004 [21] 王尽秋.数字无线视频通信系统的设计[J].单片机与嵌入式系统应用.Z004 7~ZZ-Z5.

[22] 张毅刚 彭喜源 谭晓昀 曲春波.MCS-51单片机应用设计[M].哈尔滨~哈尔滨工业大学出版社.1997~11-1Z

[23] 永红.孙运强基于nRF2401的无线数传系统设计[J3.国外电子测量技术,2008,04:45-47

[24] IEEE 802.15.4 Standard-2006.Wireless MAC and PHY specification for Low-Rate Wireless Personal Area Networds(LR-WPANs).USA,2006.46-225

[25] Zhang,Gaofeng Wang,ⅧOong.Adaptive contentioll window adjustment for 802.1 1-based mesh networks[A] J.Proc.IEEE WICOM(2008)[C].Dalian,China,2008.12

[26] Tabular Techniques For or-coincidence Logic [J].2006,02

[27] Samuel Dasberg,Eshel Bresler.Drip Irrigation Design Manual.Institute of SoBs and Water,Agricultural Research Organization.Israel,1987

[28] Dasberg S,Bresler E.Drip irrigation manual.International irrigation information center.Publication No.9,Bet Dagan,Israel,1985

[29] Cherry,A.S.and Jones,R.P,Fuzzy Logic Control of an Automative Suspension System,Control Theory and Applications,V01.142,No.2,1995

[30] Anonyms.2001.2002 Annual irrigation Survey:continuous steady growth.Irrigation Journal

- 38 -

沈阳航空航天大学电子信息工程学院毕业设计(论文)

附录Ⅰ 程序清单

发送端

/**

*描述:nRF2401发送端发送数据 *作者:丁豫 *版本:1.0 */

#ifndef _API_DEF_ #define _API_DEF_

sbit CE = P1^0; // Chip Enable pin signal (output)

sbit CSN = P1^1; // Slave Select pin, ('output to CSN, nRF24L01) sbit SCK = P1^2; // Master Out, Slave In pin (output) sbit MOSI = P1^3; // Serial Clock pin, (output)

sbit MISO = P1^4; // Master In, Slave Out pin (input)

sbit IRQ = P1^5; // Interrupt signal, from nRF24L01 (input)

// SPI(nRF24L01) commands

#define READ_REG 0x00 // Define read command to register #define WRITE_REG 0x20 // Define write command to register #define RD_RX_PLOAD 0x61 // Define RX payload register address #define WR_TX_PLOAD 0xA0 // Define TX payload register address #define FLUSH_TX 0xE1 // Define flush TX register command #define FLUSH_RX 0xE2 // Define flush RX register command

#define REUSE_TX_PL 0xE3 // Define reuse TX payload register command

#define NOP 0xFF // Define No Operation, might be used to read status register

// SPI(nRF24L01) registers(addresses)

#define CONFIG 0x00 // 'Config' register address

#define EN_AA 0x01 // 'Enable Auto Acknowledgment' register address #define EN_RXADDR 0x02 // 'Enabled RX addresses' register address #define SETUP_AW 0x03 // 'Setup address width' register address #define SETUP_RETR 0x04 // 'Setup Auto. Retrans' register address #define RF_CH 0x05 // 'RF channel' register address #define RF_SETUP 0x06 // 'RF setup' register address #define STATUS 0x07 // 'Status' register address

#define OBSERVE_TX 0x08 // 'Observe TX' register address #define CD 0x09 // 'Carrier Detect' register address

#define RX_ADDR_P0 0x0A // 'RX address pipe0' register address #define RX_ADDR_P1 0x0B // 'RX address pipe1' register address #define RX_ADDR_P2 0x0C // 'RX address pipe2' register address #define RX_ADDR_P3 0x0D // 'RX address pipe3' register address #define RX_ADDR_P4 0x0E // 'RX address pipe4' register address #define RX_ADDR_P5 0x0F // 'RX address pipe5' register address #define TX_ADDR 0x10 // 'TX address' register address

#define RX_PW_P0 0x11 // 'RX payload width, pipe0' register address #define RX_PW_P1 0x12 // 'RX payload width, pipe1' register address #define RX_PW_P2 0x13 // 'RX payload width, pipe2' register address #define RX_PW_P3 0x14 // 'RX payload width, pipe3' register address #define RX_PW_P4 0x15 // 'RX payload width, pipe4' register address #define RX_PW_P5 0x16 // 'RX payload width, pipe5' register address #define FIFO_STATUS 0x17 // 'FIFO Status Register' register address

- 39 -

沈阳航空航天大学电子信息工程学院毕业设计(论文)

#endif /* _API_DEF_ */ #include

#include

#define uchar unsigned char #define uint unsighed int

#define TX_ADR_WIDTH 5 // 5字节宽度的发送/接收地址 #define TX_PLOAD_WIDTH 4 // 数据通道有效数据宽度 #define LED P2

uchar code TX_ADDRESS[TX_ADR_WIDTH] = {0x34,0x43,0x10,0x10,0x01}; // 定义一个静态发送地址

uchar code TX_ADDRESS2[TX_ADR_WIDTH] = {0x55,0x56,0x22,0x22,0x03}; // 定义另外一个静态发送地址

uchar RX_BUF[TX_PLOAD_WIDTH]; //接收特有寄存器 。。。。。。。。。。。。 uchar TX_BUF[TX_PLOAD_WIDTH]; uchar flag;

uchar DATA = 0x01; //发送的数据。。。。。。。。。。。。。。。 uchar DATA2 = 0x02; //发送的数据。。。。。。。。。。。。。。。 uchar bdata sta;

sbit RX_DR = sta^6; sbit TX_DS = sta^5; sbit MAX_RT = sta^4;

int check_flag = 0;//用于检测是发送还是接收模式,0表示发送,1表示接收

int while_flag = 0;//用于检测while中得函数是否执行,0表示执行,1表示不执行 int receive_middle_flag = 0; int i; /**

*函数:init_io() *描述:初始化IO *参数:空

*返回值:空 */

void init_io(void) { CE = 0; // 待机 CSN = 1; // SPI禁止 SCK = 0; // SPI时钟置低 IRQ = 1; // 中断复位 LED = 0xff; // 关闭指示灯 } /**

*函数:delay_ms() *描述:延迟x毫秒 *参数:x *返回值:空 */

void delay_ms(uchar x) {

uchar i, j;

- 40 -

沈阳航空航天大学电子信息工程学院毕业设计(论文)

i = 0;

for(i=0; i

j = 250; while(--j); j = 250; while(--j); } } /**

*函数:SPI_RW()

*描述:根据SPI协议,写一字节数据到nRF2401,同时从nRF2401读出一字节 *参数:byte *返回值:byte */

uchar SPI_RW(uchar byte) { uchar i;

for(i=0; i<8; i++) // 循环8次 { MOSI = (byte & 0x80); // byte最高位输出到MOSI byte <<= 1; // 低一位移位到最高位 SCK = 1; // 拉高SCK,nRF24L01从MOSI读入1位数据,同时从MISO输出1位数据 byte |= MISO; // 读MISO到byte最低位 SCK = 0; // SCK置低 }

return(byte); // 返回读出的一字节 } /**

*函数:SPI_RW_Reg()

*描述:写数据value到reg寄存器 * 参数:reg,value *返回值:static */

uchar SPI_RW_Reg(uchar reg, uchar value) { uchar status;

CSN = 0; // CSN置低,开始传输数据 status = SPI_RW(reg); // 选择寄存器,同时返回状态字 SPI_RW(value); // 然后写数据到该寄存器 CSN = 1; // CSN拉高,结束数据传输 return(status); // 返回状态寄存器 } /**

*函数:SPI_Write_Buf()

*描述:把pBuf缓存中的数据写入到nRF2401,通常用来写入发射通道数据或接收/发送地址 *参数:reg,*pBuf,bytes *返回值:static

- 41 -

沈阳航空航天大学电子信息工程学院毕业设计(论文)

*/

uchar SPI_Write_Buf(uchar reg, uchar * pBuf, uchar bytes) { uchar status, i;

CSN = 0; // CSN置低,开始传输数据 status = SPI_RW(reg); // 选择寄存器,同时返回状态字 for(i=0; i

*函数:TX_Send_One_Mode()

*描述:这个函数设置nRF24L01为发送模式,(CE=1持续至少10us),130us后启动发射,数

据发送结束后,发送模块自动转入接收模式等待应答信号。

*参数:*BUF *返回值:空 */

void TX_Send_One_Mode(uchar * BUF) { CE = 0;

SPI_Write_Buf(WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH); // 写入发送地址

SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH); // 为了应答接收设备,接收通道0地址和发送地址相同

SPI_Write_Buf(WR_TX_PLOAD, BUF, TX_PLOAD_WIDTH); // 写数据包到TX FIFO

SPI_RW_Reg(WRITE_REG + EN_AA, 0x01); // 使能接收通道0自动应答 SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01); // 使能接收通道0

SPI_RW_Reg(WRITE_REG + SETUP_RETR, 0x0a); // 自动重发延时等待250us+86us,自动重发10次

SPI_RW_Reg(WRITE_REG + RF_CH, 40); // 选择射频通道0x40

SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07); // 数据传输率1Mbps,发射功率0dBm,低噪声放大器增益

SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e); // CRC使能,16位CRC校验,上电 CE = 1; } /**

*函数:TX_Send_Two_Mode()

*描述:这个函数设置nRF24L01为发送模式,(CE=1持续至少10us),130us后启动发射,数

据发送结束后,发送模块自动转入接收模式等待应答信号

*参数:*BUF *返回值:空 */

void TX_Send_Two_Mode(uchar * BUF) { CE = 0;

SPI_Write_Buf(WRITE_REG + TX_ADDR, TX_ADDRESS2, TX_ADR_WIDTH); // 写入

- 42 -

沈阳航空航天大学电子信息工程学院毕业设计(论文)

发送地址

SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS2, TX_ADR_WIDTH); // 为了应答接收设备,接收通道0地址和

// 发送地址相同

SPI_Write_Buf(WR_TX_PLOAD, BUF, TX_PLOAD_WIDTH); // 写数据包到TX FIFO

SPI_RW_Reg(WRITE_REG + EN_AA, 0x01); // 使能接收通道0自动应答 SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01); // 使能接收通道0

SPI_RW_Reg(WRITE_REG + SETUP_RETR, 0x0a); // 自动重发延时等待250us+86us,自动重发10次

SPI_RW_Reg(WRITE_REG + RF_CH, 40); // 选择射频通道0x40

SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07); // 数据传输率1Mbps,发射功率0dBm,低噪声放大器增益

SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e); // CRC使能,16位CRC校验,上电 CE = 1; } /**

*函数:Check_ACK()

*描述:检查接收设备有无接收到数据包,设定没有收到应答信号是否重发 发送特有。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。 *参数:clear

*返回值:是否接到数据 */

uchar Check_ACK(bit clear) { while(IRQ); sta = SPI_RW(NOP); // 返回状态寄存器 if(MAX_RT) if(clear) // 是否清除TX FIFO,没有清除在复位MAX_RT中断标志后重发 SPI_RW(FLUSH_TX); SPI_RW_Reg(WRITE_REG + STATUS, sta); // 清除TX_DS或MAX_RT中断标志 IRQ = 1; if(TX_DS) return(0x00); else return(0xff); } /**

*函数:CheckButtonsOne()

*描述:检查按键是否按下,按下则发送一字节数据 发送特有。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。 *参数:空 *返回值:空 */

void CheckButtonsOne() {

- 43 -

沈阳航空航天大学电子信息工程学院毕业设计(论文)

TX_BUF[0] = ~DATA; // 数据送到缓存 TX_Send_One_Mode(TX_BUF); // 把nRF24L01设置为发送模式并发送数据,发送模式的寄存器配置 LED = ~DATA; // 数据送到LED显示 delay_ms(100); Check_ACK(1); // 等待发送完毕,清除TX FIFO delay_ms(250); delay_ms(250); LED = 0xff; // 关闭LED while(!(P3 & 0x01)); DATA = 0x00; if(!DATA) { DATA = 0x01; } } /**

*函数:CheckButtonsTwo()

*描述:检查按键是否按下,按下则发送一字节数据 发送特有。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。 *参数:空 *返回值:空 */

void CheckButtonsTwo() { TX_BUF[0] = ~DATA2; // 数据送到缓存 TX_Send_Two_Mode(TX_BUF); // 把nRF24L01设置为发送模式并发送数据,发送模式的寄存器配置 LED = ~DATA2; // 数据送到LED显示 delay_ms(100); Check_ACK(1); // 等待发送完毕,清除TX FIFO delay_ms(250); delay_ms(250); LED = 0xff; // 关闭LED while(!(P3 & 0x01)); DATA2 = 0x00; if(!DATA2) { DATA2 = 0x02; } } /**

*函数:main() *描述:主函数 *参数:空 *返回值:空 */

void main(void) {

init_io(); // 初始化IO

- 44 -

沈阳航空航天大学电子信息工程学院毕业设计(论文)

P3 |= 0x00;

if(!(P3 & 0x01)) { delay_ms(20); if(!(P3 & 0x01)) { while(1) {

if(while_flag == 0) { CheckButtonsOne(); //receive_information(); //接收信号 while_flag = 1; } else if(while_flag == 1) { while_flag = 0; }

break; } } }

else if(!(P3 & 0x02)) { delay_ms(20); if(!(P3 & 0x02)) { while(1) {

if(while_flag == 0) { CheckButtonsTwo(); //receive_information(); //接收信号 while_flag = 1; } else if(while_flag == 1) { while_flag = 0; } break; } } }

接收端

/**

*描述:nRF2401发送端发送数据 *作者:丁豫 *版本:1.0 */

#ifndef _API_DEF_

- 45 -

沈阳航空航天大学电子信息工程学院毕业设计(论文)

#define _API_DEF_

sbit CE = P1^0; // Chip Enable pin signal (output)

sbit CSN = P1^1; // Slave Select pin, ('output to CSN, nRF24L01) sbit SCK = P1^2; // Master Out, Slave In pin (output) sbit MOSI = P1^3; // Serial Clock pin, (output)

sbit MISO = P1^4; // Master In, Slave Out pin (input)

sbit IRQ = P1^5; // Interrupt signal, from nRF24L01 (input)

// SPI(nRF24L01) commands

#define READ_REG 0x00 // Define read command to register #define WRITE_REG 0x20 // Define write command to register #define RD_RX_PLOAD 0x61 // Define RX payload register address #define WR_TX_PLOAD 0xA0 // Define TX payload register address #define FLUSH_TX 0xE1 // Define flush TX register command #define FLUSH_RX 0xE2 // Define flush RX register command

#define REUSE_TX_PL 0xE3 // Define reuse TX payload register command

#define NOP 0xFF // Define No Operation, might be used to read status register

// SPI(nRF24L01) registers(addresses)

#define CONFIG 0x00 // 'Config' register address

#define EN_AA 0x01 // 'Enable Auto Acknowledgment' register address #define EN_RXADDR 0x02 // 'Enabled RX addresses' register address #define SETUP_AW 0x03 // 'Setup address width' register address #define SETUP_RETR 0x04 // 'Setup Auto. Retrans' register address #define RF_CH 0x05 // 'RF channel' register address #define RF_SETUP 0x06 // 'RF setup' register address #define STATUS 0x07 // 'Status' register address

#define OBSERVE_TX 0x08 // 'Observe TX' register address #define CD 0x09 // 'Carrier Detect' register address

#define RX_ADDR_P0 0x0A // 'RX address pipe0' register address #define RX_ADDR_P1 0x0B // 'RX address pipe1' register address #define RX_ADDR_P2 0x0C // 'RX address pipe2' register address #define RX_ADDR_P3 0x0D // 'RX address pipe3' register address #define RX_ADDR_P4 0x0E // 'RX address pipe4' register address #define RX_ADDR_P5 0x0F // 'RX address pipe5' register address #define TX_ADDR 0x10 // 'TX address' register address

#define RX_PW_P0 0x11 // 'RX payload width, pipe0' register address #define RX_PW_P1 0x12 // 'RX payload width, pipe1' register address #define RX_PW_P2 0x13 // 'RX payload width, pipe2' register address #define RX_PW_P3 0x14 // 'RX payload width, pipe3' register address #define RX_PW_P4 0x15 // 'RX payload width, pipe4' register address #define RX_PW_P5 0x16 // 'RX payload width, pipe5' register address #define FIFO_STATUS 0x17 // 'FIFO Status Register' register address #endif /* _API_DEF_ */

#include #include

#define uchar unsigned char #define uint unsighed int

#define TX_ADR_WIDTH 5 // 5字节宽度的发送/接收地址 #define TX_PLOAD_WIDTH 4 // 数据通道有效数据宽度 #define LED P2

uchar code TX_ADDRESS[TX_ADR_WIDTH] = {0x34,0x43,0x10,0x10,0x01}; // 定义一个静态发送地址

- 46 -

沈阳航空航天大学电子信息工程学院毕业设计(论文)

uchar code TX_ADDRESS2[TX_ADR_WIDTH] = {0x55,0x56,0x22,0x22,0x03}; // 定义另外一个静态发送地址

uchar RX_BUF[TX_PLOAD_WIDTH]; //接收特有寄存器 。。。。。。。。。。。。 uchar TX_BUF[TX_PLOAD_WIDTH]; uchar flag;

uchar DATA = 0x01; //发送的数据。。。。。。。。。。。。。。。 uchar DATA2 = 0x02; //发送的数据。。。。。。。。。。。。。。。 uchar bdata sta;

sbit RX_DR = sta^6; sbit TX_DS = sta^5; sbit MAX_RT = sta^4;

int check_flag = 0;//用于检测是发送还是接收模式,0表示发送,1表示接收

int while_flag = 0;//用于检测while中得函数是否执行,0表示执行,1表示不执行 int receive_middle_flag = 0; int i; /**

*函数:init_io() * 描述:初始化IO *参数:空

*返回值:空 */

void init_io(void) { CE = 0; // 待机 CSN = 1; // SPI禁止 SCK = 0; // SPI时钟置低 IRQ = 1; // 中断复位 LED = 0xff; // 关闭指示灯 } /**

*函数:delay_ms() *描述:延迟x毫秒 *参数:x *返回值:空 */

void delay_ms(uchar x) {

uchar i, j; i = 0;

for(i=0; i

j = 250; while(--j); j = 250; while(--j); } } /**

- 47 -

沈阳航空航天大学电子信息工程学院毕业设计(论文)

*函数:SPI_RW()

*描述:根据SPI协议,写一字节数据到nRF2401,同时从nRF2401读出一字节 *参数:byte *返回值:byte */

uchar SPI_RW(uchar byte) { uchar i;

for(i=0; i<8; i++) // 循环8次 { MOSI = (byte & 0x80); // byte最高位输出到MOSI byte <<= 1; // 低一位移位到最高位 SCK = 1; // 拉高SCK,nRF24L01从MOSI读入1位数据,同时从MISO输出1位数据 byte |= MISO; // 读MISO到byte最低位 SCK = 0; // SCK置低 }

return(byte); // 返回读出的一字节 } /**

*函数:SPI_RW_Reg()

*描述:写数据value到reg寄存器 * 参数:reg,value *返回值:static */

uchar SPI_RW_Reg(uchar reg, uchar value) { uchar status;

CSN = 0; // CSN置低,开始传输数据 status = SPI_RW(reg); // 选择寄存器,同时返回状态字 SPI_RW(value); // 然后写数据到该寄存器 CSN = 1; // CSN拉高,结束数据传输 return(status); // 返回状态寄存器 } /**

*函数:SPI_Read()

*描述:从reg寄存器读一字节。 *参数:reg

*返回值:reg_val */

uchar SPI_Read(uchar reg) { uchar reg_val;

CSN = 0; // CSN置低,开始传输数据 SPI_RW(reg); // 选择寄存器

reg_val = SPI_RW(0); // 然后从该寄存器读数据 CSN = 1; // CSN拉高,结束数据传输 return(reg_val); // 返回寄存器数据 }

- 48 -

沈阳航空航天大学电子信息工程学院毕业设计(论文)

/**

*函数:SPI_Read_Buf()

*描述:从reg寄存器读出bytes个字节,通常用来读取接收通道数据或接收/发送地址。 *参数:reg,*pBuf,bytes *返回:static */

uchar SPI_Read_Buf(uchar reg, uchar * pBuf, uchar bytes) { uchar status, i;

CSN = 0; // CSN置低,开始传输数据 status = SPI_RW(reg); // 选择寄存器,同时返回状态字 for(i=0; i

*函数:SPI_Write_Buf()

*描述:把pBuf缓存中的数据写入到nRF24L01,通常用来写入发射通道数据或接收/发送地址 *参数:reg,*pBuf,bytes *返回值:static */

uchar SPI_Write_Buf(uchar reg, uchar * pBuf, uchar bytes) { uchar status, i;

CSN = 0; // CSN置低,开始传输数据 status = SPI_RW(reg); // 选择寄存器,同时返回状态字 for(i=0; i

*函数:RX_Receive_One_Mode()

*描述:这个函数设置nRF24L01为接收模式,等待接收发送设备的数据包 与发射不一样。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。 接收第一组数据 *参数:空 *返回值:空 */

void RX_Receive_One_Mode(void) { CE = 0;

SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH); // 接收设备接收通道0使用和发送设备相同的发送地址

SPI_RW_Reg(WRITE_REG + EN_AA, 0x01); // 使能接收通道0自动应答 SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01); // 使能接收通道0 SPI_RW_Reg(WRITE_REG + RF_CH, 40); // 选择射频通道0x40

- 49 -

沈阳航空航天大学电子信息工程学院毕业设计(论文)

SPI_RW_Reg(WRITE_REG + RX_PW_P0, TX_PLOAD_WIDTH); // 接收通道0选择和发送通道相同有效数据宽度

SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07); // 数据传输率1Mbps,发射功率0dBm,低噪声放大器增益

SPI_RW_Reg(WRITE_REG + CONFIG, 0x0f); // CRC使能,16位CRC校验,上电,接收模式

CE = 1; // 拉高CE启动接收设备 } /**

*函数:RX_Receive_Two_Mode()

*描述:这个函数设置nRF24L01为接收模式,等待接收发送设备的数据包 与发射不一样。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。 接收第二组数据 *参数:空 *返回值:空 */

void RX_Receive_Two_Mode(void) { CE = 0;

SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS2, TX_ADR_WIDTH); // 接收设备接收通道0使用和发送设备相同的发送地址

SPI_RW_Reg(WRITE_REG + EN_AA, 0x01); // 使能接收通道0自动应答 SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01); // 使能接收通道0 SPI_RW_Reg(WRITE_REG + RF_CH, 40); // 选择射频通道0x40

SPI_RW_Reg(WRITE_REG + RX_PW_P0, TX_PLOAD_WIDTH); // 接收通道0选择和发送通道相同有效数据宽度

SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07); // 数据传输率1Mbps,发射功率0dBm,低噪声放大器增益

SPI_RW_Reg(WRITE_REG + CONFIG, 0x0f); // CRC使能,16位CRC校验,上电,接收模式

CE = 1; // 拉高CE启动接收设备 } /**

*函数:receive_information()

*描述:双机交互中,发送端的可以接收信号 *参数:空 *返回值:空 */

void receive_information() { sta = SPI_Read(STATUS); // 读状态寄存器 if(RX_DR) // 判断是否接收到数据 { SPI_Read_Buf(RD_RX_PLOAD, RX_BUF, TX_PLOAD_WIDTH); // 从RX FIFO读出数据 flag = 1; } SPI_RW_Reg(WRITE_REG + STATUS, sta); // 清除RX_DS中断标志 if(flag) // 接收完成

- 50 -

本文来源:https://www.bwwdw.com/article/hzda.html

Top