目前,对WSN(Wireless Sensor Network)的研究主要集中在协议栈、定位算法、能耗管理以及体系结构设计上,而针对无线传感网络操作系统的研究却相对较少,尤其是对其底层平台的研究更少,所以针对无线传感网络操作系统底层平台的研究有十分广阔的空间。本论文针对意法半导体STM32系列MCU和TI公司的CC2520无线模块进行介绍。主要描述了操作系统底层平台的构建,以及硬件驱动程序的实现。本论文的底层硬件抽象层是针对CC2520无线射频模块的,包括了平台构建、相关寄存器,以及外围接口等各个部分。而硬件驱动程序主要是为完成无线通信所需的硬件驱动设计,这主要包括:相应异步事件的中断机制;和PC通信的USART驱动;连接MCU和CC2520的SPI驱动;完成超时计时的定时器等。这些模块的有效组成,才能构成一个完整的无线传感器网络最小通信系统,完成节点间数据传输、数据处理,以及定位和导航等任务。
STM32系列MCU采用ARM公司V7架构的CortexM3内核。CC2520是第二代ZigBee/IEEE 802.15.4收发器。
1 底层平台研究
硬件抽象层的底层硬件模块有很多,本节只简单介绍和无线传感器网络相关的底层模块设计。
1.1 定时器
STM32 系列的 CPU能提供8个定时器,其中TIM1和TIM8是高级定时器,可用于各种用途,包括测量输入信号的脉冲长度(输入捕捉)或产生输出波形(输出比较)等,它们的时钟由 APB2提供。TIM2~TIM7是普通定时器,时钟由 APB1提拱。图1为STM32时钟树中有关定时器的部分。
图1 STM32中有关定时器的时钟树
从图1可以看出,从系统设置的时钟源产生的时钟频率输入到AHB预分频器,进行分频处理,然后经过APB1预分频器和APB2预分频器给不同模块提供不同的时钟频率。下面以定时器2作为例子说明。当AHB预分频器输入频率为72 MHz的时候,由于APB1支持的最大频率为36 MHz,所以APB1预分频器,设置必须大于或等于2,假设设置为2,则在APB1倍频器中,频率被设置为72 MHz(当APB1分频数=1的时候,APB1倍频器加倍系数为1,当APB1分频数》1的时候,APB1倍频器加倍系数为2),所以最终提供给定时器2~7的频率为72 MHz。所以只需要设置APB1预分频器和APB1倍频器的值,便可以提供不同频率的定时器。定时器采用计数溢出的方式触发定时器中断,因此想要使用定时器,必须先配置好定时器中断。
1.2 中断
对STM32系列MCU的中断配置步骤如下:
① 系统初始化:如系统时钟初始化,使用固件模板中自带的SystemInit()函数即可,此函数把主频默认调整到72 MHz。
② GPIO配置:配置触发CPU中断的引脚,务必注意打开相应引脚的GPIO时钟和AFIO时钟。配置引脚的频率和输入模式,一般为浮空输入模式。
③ EXTI配置:首先指明当前系统中使用哪个引脚作为触发外部中断的引脚,然后清除中断标志位,配置中断请求和触发方式(上升沿触发或下降沿触发)。
④ NVIC配置:主要配置中断对应的通道,并且设置优先级别,最后需要对通道使能。
⑤ 编写中断服务程序:中断服务程序是发生中断时实际运行的程序,它打断了正在运行的程序,对相应中断事件进行相应处理。由于中断程序打断了现有程序的运行,而且需要对中断事件作出快速响应,所以要尽量短小,而且不能传递参数,没有返回值。
1.3 USART
USART模块一般分为三大部分:数据发送器、数据接收器和时钟发生器。所有模块共享控制寄存器。时钟发生器由波特率发生器和同步逻辑电路组成。
数据发送器部分由写入缓冲寄存器(USART_DR)、校验位发生器、串行移位寄存器和控制逻辑电路构成。使用写入缓冲寄存器,可以连续快速地发送多帧数据。
数据接收器是USART模块最复杂的部分,最主要的是数据接收单元和时钟。数据接收单元用作异步数据的接收。数据接收器还包括移位寄存器、控制逻辑、校验位校验器和接收缓冲器。数据接收器支持与数据发送器相同的帧结构,同时支持数据溢出、帧错误和校验错误的检测。
无线节点可以通过USART与PC通信。本文只实现了简单的USART功能。串口使用前需要完成初始化,主要设置字长、波特率、奇偶校验位、传输模式、数据位数、流控制、打开串口时钟和配置串口发送接收引脚等。
有了串口的输入/输出功能后,可以自己重写库函数printf,便于调试和观察节点运行情况,让节点终端输出重定向到PC,然后在PC上通过串口工具显示节点发送过来的数据信息,从而分析终端运行情况。具体函数设计是:如果节点输出字符串数据,则直接调用串口输出字符串函数,通过串口把字符串数据发送到PC 显示;如果是输出数字,则先把数字按指定显示进制转换成字符串,然后按照输出字符串方式处理。可以重写itoa()函数,把输入的数字按照任意进制保存到字符串中。
1.4 SPI
SPI有三种寄存器:控制寄存器(SPI_CR)、状态寄存器(SPI_SR)、数据寄存器(SPI _DR)。SPI接口包括4种信号:MOSI ——从器件数据输入,主器件数据输出;MISO ——从器件数据输出,主器件数据输入;SCLK——时钟信号,由主器件产生;NSS——从器件选择使能信号,由主器件控制,有的芯片厂家会标注为 CS(Chip Select)。
由于无线模块CC2520必须通过SPI接口才能和MCU通信,所以必须先实现SPI接口,才能控制CC2520接收和发送数据。SPI接口的处理方式和USART接口的处理方式很像,本文只实现了简单的SPI功能。SPI使用前必须初始化,主要工作包括设置主从模式、波特率、数据位数、数据帧格式、配置输入/输出引脚和时钟信号的相位和极性等。
1.5 CC2520驱动
MCU 通过SPI接口控制CC2520启动、关闭、收发数据等。SPI接口由SI、SO、CSn和SCLK 四个引脚构成。在MCU和CC2520通信过程中,CC2520为SPI接口从设备,接收MCU发来的时钟信号和片选信号,并在MCU的控制下执行发送数据、接收数据等操作;STM32为接口主设备,可以通过SPI接口访问CC2520内部存储区和寄存器。CC2520通过FIFO、FIFOP、SFD和 CCA四个引脚来表示工作状态。MCU可以通过读取这些引脚的数据来获得CC2520收发数据的状态。SFD信号表示刚接收到或者刚发送完帧开始信号;FIFO信号表示一个或者多个字节在接收缓冲区;FIFOP信号表示接收缓冲区中的字节数超出设置的门限或者接收到至少一帧完整的数据;CCA信号表示信道空闲。
CC2520大概工作流程:首先是准备工作。上层应用程序中使用halRfInit()函数完成CC2520的一些初始化工作,如复位CC2520,关闭电压调整器,根据CC2520数据手册需要延时1100 μs。延时完成后,开启电压调整器,再延时200 μs,然后使能CC2520,完成后,申请SPI资源并初始化。开启振荡器,然后通过SPI接口配置CC2520中一些寄存器的默认值,如 TXPOWER、CCACTRL0、MAMCTRL0、MAMCTRL1等寄存器的值。然后对MCU和CC2520相连的引脚进行初始配置,比如把 RSTN、VREN和CSN配置为输出模式,把FIFO、FIFOP、CCA和SFD配置为输入模式。
上层应用程序中使用basicRfInit()函数完成对信道、短地址和网络ID的设置,并配置接收中断处理函数,用于接收到数据产生中断时处理接收数据。
应用程序执行发送命令时,按照协议栈从上层一层层封装好数据后,最终把数据交给basicRfSendPacket()函数处理。具体发送过程如图2所示。
图2 CC2520发送数据流程图
图中封装的格式按照协议要求,内容主要包括数据长度、帧控制域(FCF)、目的地址、源地址、目的网络ID、源网络ID、发送数据、CRC(Cyclic Redundancy Check)校验码等。当采用的是硬件CRC检验时,不需要用户计算添加CRC检验码,也不需要CRC检验数据写入TXFIFO(CC2520发送缓冲区)中,有专门的寄存器存储CRC检验数据,由硬件完成检验和发送。当采用软件CRC检验时,需要用户自己计算CRC检验数据,并填写在帧的最后两字节中,随帧中其他数据一起写入TXFIFO。
封装好后把数据写入TXFIFO中,注意CC2520发送缓冲区为128 字节,不能超出这个范围,否则会引发TX_OVERFLOW异常。然后,打开接收数据中断后才能调用发送命令发送数据,在这里可以对发送过程进行完全的控制,比如在发送数据的过程中,可以通过捕获SFD引脚的上升沿信号来对发送准确计时。发送数据后等待接收方回复ACK,如果在规定时间内没有收到ACK,则判定重传次数是否超过最大重传次数,没有的话则按照一定策略退避一段时间后再重新发送这个数据包,如果超过最大重传次数则丢弃这个包,并设置发送失败标志供上层程序参考。如果在规定时间内收到ACK,则会触发RX_FRM_DONE中断,会调用basicRfRxFrmDoneIsr()接收数据中断处理程序对收到的ACK包进行分析,如果是对刚发送包的正确回复,则表示发送成功,更新相应信息,例如发送序列号加1,更新发送状态,清除 TX_FRM_DONE异常等。
接收过程和发送过程类似,具体接收流程如图3所示。
2 测试
2.1 测试方法
测试的每个节点都通过一根串口线连接到PC。在测试程序中添加测试代码,把测试节点发送和接收的MAC(Media Access Control)层数据信息通过串口发送到PC上。然后通过PC上的串口调试助手显示出来。对这些数据信息进行分析便可以知道节点上各模块程序的运行情况。
2.2 测试过程及结果
通过分析群首节点广播数据帧到群中终端节点的过程来判断底层模块的运行情况。群首节点A和群中终端节点(B、C、D)都通过串口线连接到PC上。群网络号为0x0001,节点A、B、C、D地址分别为:0x0001、0x0002、0x0003、0x0004。A通过无线模块发送广播数据到B、C、D,并把发送数据发送到PC显示,最后把接收到的 ACK回复帧也发送到PC显示;B、C、D通过无线模块接收到A发过来的数据,按自己节点地址大小进行延时后对接收数据帧进行回复,并把接收数据帧和回复 ACK帧通过串口发送到PC显示。
图4为群首节点发送数据帧和接收ACK帧的过程。协议栈MAC层帧的封装格式按照IEEE 802.15.4标准。从图4可以看出:第一个框中为发送节点发送数据帧,后面三个框中为接收到的终端节点回复的ACK帧。按照IEEE Std 802.15.42006标准中的帧封装格式,发送窗口显示的第一个字节为物理层数据长度。后面紧跟的是FCF(Frame Control Field帧控制字段,占2字节),对发送可信广播数据帧为0x8801。参考标准手册中FCF设置,可以看出对数据帧的设置如下:节点地址和网络地址都采用16位;在帧中同时包括源网络ID、源节点地址、目的网络ID、目的节点地址;需要ACK帧确认;没有采用安全设置。后面是DSN(1字节),这是传输的第一个帧,所以设置为0x01。后面为目的网号0x0001(占2字节)。后面为目的节点地址0xFFFF(占2字节),这是广播地址,当 CC2520发现目的节点地址为广播地址时,便向所有节点传输广播帧。后面为源网络号0x0001(占2字节)。后面为源节点地址0x0001(占2字节)。因为这是同一个网段中的群首向终端节点发送广播帧,所以目的网络号和源网络号相同。后面接着的2字节为MAC层数据,为了测试简单,测试时只发送了 2字节的数据(1和2,ASCALL码为0x31和0x32)。可信广播帧要求接收节点回复ACK帧,后面三个框中数据分别是节点B、C、D回复的ACK 帧。回复帧的格式和数据帧的设置情况类似,区别是回复帧的FCF为0x8802,表示是回复帧且不需要确认,回复帧中没有数据字段,且回复帧中的目的网络号、目的地址为接收数据帧中的源网络号、源地址。
图4 群首广播发送节点串口显示图
图 5为接收节点B的接收数据帧。从图中可以看出,第一个框中为接收到的可信广播数据帧,第二框中数据为发送的ACK帧。接收窗口中前面的数据和发送窗口中数据一样。不一样的是最后的2字节(具体解释请参考3.5节 CC2520接收过程)。接收节点解析目的地址,发现是广播地址,需要再检查FCF字段中的Ack Request是否为1,如果为1,则需要回复ACK帧。为了避免群中节点收到可信广播数据帧,同时回复ACK帧造成信道碰撞,回复ACK帧的时候按照自己节点地址大小延时发送。群中其他节点(C、D)的接收串口显示数据和节点B的类似,这里就不再详细说明。
图5 可信广播接收节点B串口显示图
结语
从测试的结果看,发送节点通过CC2520发送的数据能被接收,节点正确接收并通过串口发送到PC。这说明论文介绍的各个模块都能够正确稳定地工作。通过这些底层模块的协同工作,为上层操作系统和协议栈提供了通信的基础服务。本论文只是简单地完成了各模块的功能,还有很多可以改进的地方,比如,可以在 CC2520通信过程中加入精确的时序控制,为上层提供更好的服务。