热度 20
2012-12-29 21:45
4427 次阅读|
0 个评论
摘要: 本文介绍了无线透传模块之24L01方案的实现,算是我的STM32学习体验吧。文中讨论了24L01的传输特性,并基于此设计了软件实现方式。 一、 背景 基于 24L01 及 STM32F051kxu6 设计了一款无线透明传输模块,作为 STM32F0 的应用实例,详细介绍见: 要求能结合透明无线传输模块的需求,尽量发挥 STM32F0 的优势。 二、 需求分析 基于上述文中所描述的“透明无线传输模块”,首先分析一下它的需求: a) 能够实现任意字节数据的无线透传; b) 保证数据传输的准确性和快速性。 三、 概要设计 无线透传模块的工作框图 在进行设计前需要了解 24L01、STM32F0的硬件特性,然后设计控制逻辑。 3.1 24L01工作模式分析 nRF24L01 是一款工作在 2.4 GHz 世界通用 ISM 频段的单片无线收发器芯片。它有六路不同的通道,都可以作为发送和接收的通道。 其引以为优势的ShockBurst模式发送的数据包格式为: 要注意的是:因为数据包中未含帧长信息,所以24L01收、发双方在通讯前要约定好收发数据的长度,否则将无法实现通讯! 那如何实现任意字节数据的发送呢? 如果将六个通道固定发送的字节数依次设置为1、2、4、8、16、32,通过拆包正好可以满足32字节以下任意长度数据的发送。 但最后决定将每次发送的数据固定为32个字节。 主要原因如下: 1、24L01每次发送一包有效的数据,都包含前导码、地址、CRC校验等。所以发送32个字节的数据和发送1个字节的数据时间相差并没有想象的区别大; 2、24L01每次启动发送要延时约130us; 3、24L01如启用自动应答机制,每发送完一个数据包,还要等待应答信号,大约166us。 这些使得固定一次发送 32 字节和分包发送有效数据的时间差距很小,甚至更快。 例如:24L01的发送速率设为最大的2Mbps,当发送31个字节时,采用拆分到不同的通道分5次发送,大概要耗时:(每位数据 0.5us) ((5字节地址 +2字节CRC)*8 *0.5us + 130us+166us)*5次 + 31字节数据*8*0.5us = 1744us 而采用每次固定发送32个字节,大概耗时: (5字节 + 32字节数据 +2字节CRC)*8* 0.5us + 130us +166us=452us 后者更具优势。所以最后决定:无论通过无线发送的数据长度是多少,都固定发送32个字节,兼顾了发送速度和效率。 当发送的数据包中有效数据不足32个字节,接收方如何提取数据呢? 必须在这包数据中设置一字节长度信息,即一次发送最多31字节。 但实际测试时发现:偶尔会收到乱码,推测是 2.4GHz 频段的信号太多所致,所以又添加了一字节长度的反码,以增加有效数据的甄别能力。最后得到数据包的格式如下: 3.2 STM32F0比8位MCU增加的资源 1) 较大的RAM(所用STM32F0为8K),可设置充足的通讯缓冲区,减小了因无线传输不连续导致的串口接收数据被覆盖的可能性; 2) 高速的USART口,最高波特率6 Mbit/s; 3) 丰富的USART中断消息:除经典的收、发有效中断外,新增了字节间隙检测中断(IDLE,连续一字节时间为“1”)、字节空白中断(Break,连续一字节时间为“0”); 4) 可灵活配置的DMA,并提供丰富的中断消息,如传输完成中断(TC)等。 3.3 工作过程设计 因为USART为全双工模式,随时可以收、发数据,所以处理比较简单。 24L01则不同,它是半双工模式,即接收时不能发送,发送时不能接收。 作为无线透明传输模块,待命状态必须是USART和24L01均处于接收状态,以保证随时能收到来自无线或有线的数据。 哪何时将无线收到的数据通过无线转发呢? 按照前面对24L01工作方式的分析,肯定不能每收到一个字节就转发。 因为透传模块无法知道所转发数据的格式,所以也无法等“收完数据包”再转发。 何时触发无线数据发送是无线透明传输模块的主要问题! 我设置了两个触发条件: 1) 串口接收的字节达到一定的长度,按前面的论述,将这一长度设置为30。 2) 接收数据流产生间隙。 如果用8位MCU实现,第一个条件需要通过串口接收计数实现,第二个条件需要用定时器配合实现。 采用STM32F0,则可以方便的使用其特有的资源: 1) 用DMA管理串口数据接收,设定DMA接收字节数为触发长度,通过TC中断实现第一个触发条件; 2) 用USART的IDLE中断监测接收数据流的间隙,实现第二个触发条件。 3.4 详细工作流程设计 接下来就是本工程具体的控制流程设计了。不仅要将串口和24L01两个分别控制好,还要协调好它们之间的关系。 串口方面,要实现将电脑任何时刻发送过来的任意长度的数据以数据包的格式保存在缓冲区。 无线方面,要在满足触发条件后将数据转发出去,并能够将收到的数据保存在缓冲区内。 通过串口的RXNE中断可知道串口开始接收数据。 何时串口完成一串数据转存到缓冲区呢? 举例说明,当UASRT连续接收了32个字节,程序处理如下: 初始化时打开RXNE的中断使能,关闭IDLE和TC的中断标志。 当收到第一个字节触发RXNE后,关闭RXNE的中断使能,打开IDLE和TC的中断使能。启用DMA处理USART数据接收,通过RX的DMA通道将数据转移到缓冲区中。 收到第30个字节触发DMA的TC中断,与此同时完成如下几件事: A) 将数据长度和长度的反码保存在数据包的前两位; B) 关闭所有接收完成中断使能,打开开始接收中断使能; C) 将缓冲区的数据块标号加1. 紧接着第 31个字节触发 RXNE,在进行类似上述操作后,当接收到第 32 个字节后触发 IDLE 中断,完成同于 TC 中断时的事。 触发 IDLE 中断后如何确定收到有效数据的长度呢?DMA 有函数可以读取已收到的数据长度。 以上描述的是 USART 收到数据通过无线转发的过程。那无线收到数据后如何通过 USART 转发呢? 因为 USART 的发送处理很简单,无线收到一包数据后,填入 USART的发送缓冲区,并根据包长设置好发送的字节数,启动 USART 发送即可。 借助STM32F0 的DMA功能更为简单。 四、 总结 通过这个项目的尝试,初步体验了32位MCU和8位MCU的差别,同时感受了通过STM32库函数编程的方便之处。 通过启用STM32F0的DMA等资源,可大大简化程序,使流程更加清晰。 但也体验到由于其较为丰富的中断触发方式,在使用中断资源时需仔细理解各种中断状态的含义,否则将导致不断进入中断。 发现的问题: 24L01的自动应答机制并不能完全消除误码,甚至带来一些麻烦,如实际接收方已经收到数据,也发回了应答,但发送方未收到应答信号,此时该如何处理?还望有高手指点!