林丽蓉, 余红英, 姜世杰, 洪永学
(中北大学 信息与通信工程学院 , 太原 030051)
随着测控技术的发展,nRF24L01越来越多的应用于无线传输测控系统。近年来,随着ARM和嵌入式Linux系统的迅速发展,在Linux系统下nRF24L01和ARM的通信也越来越多,但大都都是用ARM的GPIO端口来模拟SPI操作时序来与nRF24L01进行通信,而ARM本身带有可灵活配置的SPI 接口这一功能却被忽视,用ARM的SPI接口和nRF24L01的通信充分利用了这一优势。
NRF24L01通过SPI接口和外部控制器件进行数据交换,在Linux系统中SPI通信的实现可以通过ARM的SPI接口,也可以通过ARM的GPIO端口软件模拟SPI时序的方式来实现,在本次设计中选用的SPI接口。
设计中ARM芯片选择三星公司生产的S3C2440,S3C2440包括两个SPI接口,每个SPI接口分别有两个8位的数据移位器用于发送和接收数据。在SPI的发送期间,数据同时发送(串行移出)和接收(串行移入)。S3C2440通过外接12 MHz的晶振,经时钟控制逻辑的PLL倍频后将HCLK、HCLK和PCLK设置为200 MHz、100 MHz、50 MHz,其中PCLK将用作SPI的时钟输入,NRF24L01模块与S3C2440的硬件连接电路如1图所示。
在Linux系统中一个完善的设备驱动既要有硬件的支持,同时也要符合硬件设计的驱动模块。结合nRF24L01芯片的特点以及Linux系统下设备类型的不同,可以把它认为是字符设备驱动的一种。本次设计中使用的是2.6.30的内核,根据 Linux 字符驱动的特定架构,本文设计的nRF24l01 芯片驱动由init、exit、 open、close、read 等函数结构组成,以完成不同的功能。本次设计的是nRF24l01一次连续接收4字节数据接收驱动程序,其中open、close函数没做什么工作,只是让其返回个0值。
图1 NRF24L01与S3C2440的连接电路图
当加载该模块时,系统调用init函数,init除了完成字符设备的注册外,还对相关硬件进行初始化。图2为nRF24L01的SPI写时序图,由图可知上升沿输入,下降沿输出,往NRF24L01的MOSI写入一个字节数据数据的同时nRF24L01的MISO引脚输出相应的返回值。初始化主要完成如下工作:
① 将 S3C2440 的 GPE11、GPE12、GPE13 配置为SPI接口,GPG2、GPF3、GPF4配置为输出I/O口
② S3C2440的SPI寄存器映射内存。
③ 根据 nRF24L01的写时序图,配置S3C2440 的SPI的相关寄存器,将SPI设为主机查询模式,传输格式为A格式(上升沿采样,下降沿输出),且高电平有效,传输波特率预定标寄存器的值为0x18(波特率 = PCLK / 2 / (标寄存器的值 + 1),小于4MHz);
④ 开SPI时钟,否则SPI是不会工作的。
卸载模块时调用exit函数,exit函数完成内存的释放。
图2 nRF24L01的SPI写时序图
引脚配置成功后还需实现SPI的通信nRF24L01相关寄存器的初始化工作。涉及的子函数如下,函数中使用的延时函数都是2.6.30内核自带的,时间的延迟是根据nRF24L01的SPI时序图的时间要求设置的。
当往S3C2440的SPTDAT0寄存器写入一个字节后, 如果ENSCK、SPCON0寄存器的MSTR被置为,S3C2440的MOSI引脚开始向nRF24L01发送一个字节数据,并且SPRDAT0寄存器返回由nRF24L01的MISO引脚输出的数据,当SPSTA0状态寄存器的READY为1时,说明SPRDAR0的读已准备,读取SPRDAR0并返回。
此函数是向nRF24L01指定的寄存器地址 reg(命令字) 写入一个字节数据value,从函数中可以看出,先发送命地址,然后再发送数据。
此函数是向nRF24L01指定的寄存器地址reg(命令字) 写入多个字节的数据,数据内容是以pBuf 为首地址的数组, 数据长度由bytes定义。该函数主要用于发送地址和数据。
NRF24L01所有的配置都在配置寄存器中,且配置寄存器都是通过SPI口来进行配置。此函数是将nRF24L01设置为Enhance ShockBurstTM接收模式,其工作原理可查阅nRF24L01的技术资料。需注意的是接收地址必须和发送地址一样,否则接收不到数据。CE拉高后必需让高电平维持至少10 μs时间,否则将出现不能连续接收的情况。
在读操作函数中,先调用RX_Mode()子函数将nRF24L01设置为Enhance ShockBurstTM接收模式,判断NRF24L01是否接收到数据,即判断NRF24L01状态寄存器的第6位是否为1,当为1说明已接收到数据,可以读取RX FIFO中的数值,最后将读出的值通过函数copy_to_user()传给用户。
要验证编写的驱动程序是否正确,首先需要有数据的发送(51单片机控制nRF24L01模块连续发送4字节的数据,分别是4,2,6,8),然后编写一应用程序来测试所接收的数据是否正确。该应程序首先打开该字符设备,之后每隔1s调用驱动程序的read()函数,并将驱动程序传送给用户程序值的在串口终端打印显示出来,显示结果如图3所示。图中spi read即为驱动程序返回给应用程序的数据,其余为编写驱动程序时所加的调试信息的调试信息,从图中可看出nRF24L01接收到的数据与另一nRF24L01发送的数据一致,说明实现了nRF24L01驱动程序设计。
图3 测试结果
本文详细介绍了新型无线收发芯片nRF24L01的特性和具体应用,结合 ARM和Linux系统给出了具体的硬、软件设计,通过ARM的SPI接口实现了NRF24L01的无线收发,可供无线数据传系统应用。
[1]韦东山.嵌入式Linux应用开发完全手册[M].北京:人民邮电出版社,2008.
[2]李亚锋.ARM嵌入式Linux设备驱动实例开发[M].北京:中国电力出版社,2008.
[3]陈渝,李明,杨晔,等.源码开放的嵌入式系统软件分析与实践[M].北京:北京航空航天大学出版社,2004.
[4]王学龙.嵌入式ARM系统设计与应用[M].北京:清华大学出版社,2007.
[5]刘淼.嵌入式系统接口设计与Linux驱动程序开发[M].北京:北京航空航天大学出版社,2006.
[6]宋宝华.设备驱动开发详解[M].2版.北京:人民邮电出版社,2010.
[7]刘靖,陈在平,李其林.基于nRF24L01的无线数字传输系统[J].天津理工大学学报,2007(3):38-40.
[8]李进,王太宏,张恩迪.嵌入式linux中nRF24L01驱动的设计与实现[J].计算机系统应用,2011(9):226-229.