完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
前面章节中,中断相关的内容时不时提到,这节详细说一下。
因为前面有过铺垫,所以就不按部就班的啰嗦前戏了,直接进入正题吧。 nrf24l01一共3种中断: TX_DS / RX_DR / MAX_RT
当任意一个或多个中断发生时,IRQ管脚都会被【nrf24l01主动】拉低,即IRQ管脚低电平触发。 程序知道了IRQ脚变成低电平,只能知道有中断发生了,但并不知道到底是哪个或哪些中断,所以nrf24l01通过STATUS寄存器记录了具体的中断源: 如上图,标出的每个bit表示对应的中断,bit=0表示当前没有此中断,bit=1表示当前此中断已经触发。 当IRQ拉低之后,程序读取这个寄存器,就能知道到底是哪个或哪些中断被触发了。 IRQ管脚被拉低之后,即使我们程序读取了STATUS,管脚【也不会自动地】回归高电平,即nrf24l01不会主动清理中断。 清理中断的工作必须由我们的程序亲自来操作,做法是: 【往STATUS寄存器对应bit位上写1】(不要觉得奇怪,这里我没写错,就是写1而不是写0) 只有当前【所有】被触发的中断【都】被清理了,IRQ管脚才会回归高电平。 除此之外,程序可以通过配置寄存器的方式来【分别禁用/屏蔽】这些中断: 如上图,nrf24l01将中断屏蔽位整合到了CONFIG寄存器中,给bit位写1则屏蔽对应中断,写0保持开启。 个人认为,这个屏蔽设计有些轻微脑残,我实在想不出需要把中断屏蔽掉的理由。 之所以在这儿添上这些内容,是为了提醒大家不要【误操作】: 在修改CONFIG其他bit位的时候,不要将中断屏蔽位给误写了,不然程序就再也收不到对应的中断通知了。 本节上面的描述中,暗含了一个意思: IRQ管脚拉低时,可能是某中断单独发生,也可能是多个中断同时发生。 在【Enhanced ShockBurst】工作模式下: PTX 存在TX_DS/RX_DR/MAX_RT这全部的3种类型的中断。 PRX 只存在TX_DS/RX_DR这2种类型的中断,MAX_RT永远不会出现在PRX端。 列一下中断可能出现的【所有的】组合情况: 如果上面表格中"说明"一栏你看了之后觉得更"说不明",那么继续往下看。 MAX_RT的含义以及什么时候出现,前面章节已经详细说过了,这里略过。 只说 TX_DS 和 RX_DR,nrf24l01具体满足什么条件时,这两个中断才会触发? 上面这张图原型来自datasheet的第7章第8节(第39页)。 描述的是在【Enhanced ShockBurst】工作模式下,PTX和PRX之间一次通信过程的详细时序。 通信的最终结果是数据传输完毕,两端分别触发了各自的IRQ。 我加了很多标注,非常详细,这里就不再解说过程了,我相信看这个标注图要比看大段文字更直观。 先去看图,确保看明白之后再往下看,不然也会很晕^_^ OK,标注图看明白了,我们继续。 现在从这张图中提炼一些有用的信息: - 针对PTX发送的数据,PRX端的RX_DR在时间上要早于PTX端的TX_DS 这个结论也许让你有点意外,但确实是这样。 因为PTX端对通信管控负有更多的责任,必须收到对方的ACK之后才能确认自己发的数据被PRX收到了,才能放心的触发TX_DS。 而PRX不管这些,只要收到数据就触发RX_DR。 - PRX端的程序要好好利用回复ACK之前的这130微秒时间段 这句话里的【130微秒】指的是: 从【PRX触发IRQ】那一刻 到 【开始发送ACK包】那一刻之间的【PLL Lock】时间段。 我把这个时间段叫做【PRX的黄金时刻】。 这个时间段有什么特殊的地方? 如果PRX在这个时间段内,能把一些数据及时地塞进自己的TX FIFO里,那么Auto-ACK时,ACK包里就能带上这些数据! 这意味着,就在PTX端触发自己这边TX_DS的时候,就会收到这些数据,RX_DR必定会触发。 而如果PRX错过了机会,例如当ACK开始发送的时候,SPI上的数据还没写完,那么这次Auto-ACK就没机会捎上这些数据了。 这样的话,PTX想收到这些数据,必须等到下次通信了,时间被大大延后了。 假设这样一种应用场景: PTX端是遥控设备(比如无线手柄),PRX端是受控设备(比如遥控小车/机械臂)。 遥控器时常发送一些指令(本质是一些约定好协议格式的数据),用来 查询/修改/操作 受控设备; 受控设备收到指令后,读取/解析/执行 指令,而且必须回复遥控器,例如回传查询结果/确认动作执行完成/参数修改成功等。 注意受控设备的工作逻辑,它是收到指令之后才去执行的,而且要及时回复数据给遥控器。 我们假设这些指令都很短,最长也不超过32字节,所以nrf24l01单包传送就能搞定。 这样的场景很常见吧? 受控设备(PRX)的工作逻辑决定了: 只有本端RX_DR IRQ触发以后,PRX才能知道该回复什么数据给PTX。 由此可知,想要最高效的回传数据,必须好好利用上文的【130微秒黄金时段】。 我们先看一下在上述场景中程序对RX_DR IRQ的一般化的处理过程: (1)IRQ触发中断处理程序 (2)SPI访问STATUS寄存器,确认中断源为RX_DR (其实这步可以省略,PRX端IRQ响了,里面必定会有RX_DR的) (3)SPI读取RX FIFO得到指令数据,读入RAM (4)SPI写STATUS寄存器,清理中断源 (5)识别/解析/执行指令,然后生成回复数据 (6)SPI将回复数据写入TX FIFO (7)处理结束 只要以上(1)-(6)步骤能在130微秒内全部完成,程序就能做到理论上的最快回复。 在回复数据长达32字节(当然要讨论最坏的情况)的情况下,能实现130微秒全部搞定么? 假设步骤1非常快,时间忽略。 步骤2/3/4/6的耗时和SPI的时钟速度有直接关系。 步骤5的耗时和nrf24l01无关,只和具体的程序逻辑有关。 步骤2使用NOP指令最快,SPI上要走2个字节。 步骤3根据【9. nrf24l01的数据缓冲区】这节中的内容可知,一对一通信SPI上【最多】要走大约2+33=35字节。 步骤4,SPI上要走2个字节。 步骤6,最长回复时,SPI上要走33字节。 加起来是2+35+2+33=72字节。 如果SPI的时钟速度是8MHz(对nrf24l01来说基本就是安全上限了,不要再高了),那么耗时72微秒。 还有各条命令中间CSN电平保持间隔以及杂七杂八的开销,估算10微秒应该够了。 这样就已经消耗了82微秒了。 这里提醒一下,就算你用的不是arduino,而是CPU时钟高达72M的stm32f103,这80多微秒是无法再减少的。 你的单片机再快(往往其片上SPI也会很快)也得适应nrf24l01上SPI接口的要求不是? 留给步骤5的时间:130-82=48微秒,约50微秒。 如果程序设计合理的话,我认为这些时间足够可以计算出回复数据了。 除此之外,还要考虑整个过程被其他中断打断的情况,这会增加额外的耗时。 如果SPI的时钟为6M甚至更低,130微秒几乎就不够了。 - PRX端TX_DS IRQ对分包传输的影响 再假设另外一个应用场景: PRX作为环境数据采集终端,有一堆传感器,实时监测温度/湿度/光照等一些物理参数,每隔一分钟采集一次传感器数据; PTX作为这些数据的接收终端,每隔十分钟从PRX取走它积攒的数据,后续用于存储/显示/统计/分析等用途。 在这里我们先不纠结【采集终端作为PTX还是作为PRX哪个更合理】以及【为啥不每隔一分钟就取走一次数据】的问题, 只关注在上面已设定好的方案中【数据传输】方面的问题。 十多次采集积攒的数据量肯定不少。 把这个场景提炼一下,其实就是: 怎样把大量的数据(大于32字节)从PRX端完整传输到PTX端? 结合本节前面的内容,方案就很明显了: PRX端将数据拆包,然后通过多次Auto-ACK的方式,把数据传给PTX,PTX端再把分包数据还原。 假设要传输70字节有效数据,则需要拆分成3个数据包,列一下基本流程: (1)PTX向PRX查询有多少数据要传送 (2)PRX通过查询包的Auto-ACK将长度信息回复给PTX (3)分包依次传输这些数据,总共3次 (长度拿到了,PTX自然知道会有几包数据) (4)PTX收到最后一包有效数据后,还必须给PRX发一个确认包,通知PRX:你的数据我已全部收取。 步骤4是必要的: PRX【必须】要知道它的最后一包数据到底有没有被PTX收到,这样才能确认数据全部发完了。 PRX【只能】通过本端 TX_DS 中断才能确认某次数据传输(附带在Auto-ACK中的有效数据)OK。 PRX端的 TX_DS 触发依赖于 PTX端 【再多启动一次】通信,这就是上面所说的【确认包】。 我把完整的过程做了一张时序图: - 【PRX对PTX的分包传输机制】对PTX端【应用数据】传输效率的影响 先定义一下什么是【应用数据】: 双方传输的那些数据中,和具体通信手段无关的那些数据被称为【应用数据】。 这里先声明一下,"应用数据"这个词是我为了描述方面而自造的词,不是标准的术语。 有一个更简单的辨别方式:就算通信模块被替换了,双方依然要传输的那些数据就是应用数据。 比如我们用串口或者蓝牙替代nrf24l01来通信,通信双方依然需要传输某些数据,且数据格式是不变的。 在【遥控器和小车】的场景里,控制指令就是应用数据,小车响应查询指令回复的查询结果也是应用数据。 在【环境数据采集】的场景里,采集到的温度湿度光照等也是应用数据。 再回到PTX/PRX,上面那个时序图中,【查询数据长度】【取数据】【确认结束】这些包不是应用数据。它们仅仅是【为了分包传输应用数据】而衍生出来的,这里我给他们起个自造的名字:【传输控制数据】。如果你用串口线把无线模块替换掉,那就没有这些东西了。 也就是说,在nrf24l01眼中的,【有效数据】其实分为两种:【应用数据】和【传输控制数据】。 【传输控制数据】是属于【传输层】(这个是标准术语^^)层面的东西,和具体的应用无关。 【应用数据】是属于【应用层】(这个也是标准术语^^)层面的东西,和具体的通信媒介/通信手段无关。 好了,现在铺垫内容介绍完毕,开始说正题: 对传输效率的影响第1项: 一些冗余数据(【传输控制数据】) 的加入会降低【应用数据】的平均传输速度。 对传输效率的影响第2项: PTX在发送应用数据时,TX FIFO的32字节不能都用掉,必须留一部分空间给协议控制使用。 解释一下第2项: PTX端程序在写入TX FIFO时,当然知道写入的数据是应用数据,PRX收到后通知程序,PRX端的程序读出数据。 但PRX端的程序只知道这是有效数据,却不知道这到底是应用数据还是传输控制数据。 数据的属性是必须区分的,应用数据要送去上层处理,而传输控制数据不能往上层送,要内部处理掉。 因此,一包最长32字节的有效数据中,要至少留出一个字节的位置来标识数据的属性:即到底是【应用数据】还是仅仅是【传输控制数据】。 例如PTX在写TX FIFO时,如果写的是应用数据,TX FIFO第1个字节写0x00,表示后面31字节数据均是应用数据; 而如果写入的是传输控制数据,那么TX FIFO的第1个字节要写0x01,表示后面的31字节数据是传输控制数据。 PRX端的程序在读出这份数据后,发现第1字节为0x00,那么就知道是应用数据,取出后送往上层,否则当传输控制数据去解析处理。 当然,这个额外要求只是针对PTX的,PRX在回复数据的时候不需要这样做,32字节空间随便用就好。 因为PRX是【主接收端】,只是被动响应,主动权在PTX手里,PRX回复什么完全是应PTX的要求。 所以PTX对于收到的Auto-ACK数据是什么非常清楚。 【 温馨提示: 最后关于多包传输的这部分内容,仅仅是我自己根据对nrf24l01 IRQ的了解推演出的一些关于编程方面的东西,只是一个尽量通用的方案。这部分不是官方datasheet的内容。大家编程时仅参考即可,不必拘泥。对于你自己的项目,可以在这些内容的基础上进行简化/改造/升级。 适合自己的才是最好的! 】 【把和IRQ有关的,能想到的东西都写了,此节完^_^】 |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1810 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1631 浏览 1 评论
1098 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
737 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1687 浏览 2 评论
1944浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
749浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
584浏览 3评论
604浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
567浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-29 09:13 , Processed in 0.718363 second(s), Total 45, Slave 39 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号