0385-841212726
当前位置:主页 > 新闻动态 > 热门新闻 >

串口吸收法式遇到的那些问题

发布时间:2023-05-03 00:16   浏览次数:次   作者:168体育登录入口
本文摘要:上两篇文章先容了设计串口协议的基础知识,接下来的几篇将先容在编写调试串口代码时可能遇到的一些问题。以下内容不会用太多的笔墨形貌如何写发送、吸收函数,而是重点关注串口吸收历程中可能遇到的一些问题,如果说形貌到了发送、吸收函数,别会错意,顺带的。 以下大部门问题都是因为接纳 RXNE(吸收不为空)中断方式导致的问题,只有一个问题是鱼鹰从前没有思量到,也是 IDLE + DMA 方式不行忽略的问题。

168体育登录入口

上两篇文章先容了设计串口协议的基础知识,接下来的几篇将先容在编写调试串口代码时可能遇到的一些问题。以下内容不会用太多的笔墨形貌如何写发送、吸收函数,而是重点关注串口吸收历程中可能遇到的一些问题,如果说形貌到了发送、吸收函数,别会错意,顺带的。

以下大部门问题都是因为接纳 RXNE(吸收不为空)中断方式导致的问题,只有一个问题是鱼鹰从前没有思量到,也是 IDLE + DMA 方式不行忽略的问题。这就是为什么鱼鹰建议接纳 IDLE + DMA 的原因,不仅是因为效率问题,更因为它能制止许多问题,固然水平足够高的话,接纳 RXNE 也是完全("完全"就未必,内里有一个问题是 RXNE 方式难以制止的问题)没有问题。

事实上,纵然鱼鹰接纳 RXNE 方式吸收数据,也能制止以下大部门的问题,因为鱼鹰的基础足够扎实,会在一开始编写代码的时候自然而然制止一些问题的泛起。可是看完以下内容后,相信列位道友写出一个高效且结实的串口吸收法式基础不是问题,因为这就是所谓的履历啊。1、 传入参数指针前面鱼鹰已经提到了需要一个指针作为函数的参数,这里说说这个指针问题。

我们知道,为了维护利便,也是为了节约空间,一般都市将类似的功效整合成一个函数,好比串口经常要用的发送、吸收功效,可是所发送的数据内存空间可能就处于五湖四海了,他们通过指针来指向将要发送的数据。为了节约 RAM 空间或者其它不为人知的原因,通报给发送函数的指针就是实际发送数据的地址,而且在盘算校验值的时候也是直接使用这个地址举行校验盘算,然后接纳循环查询的方式发送数据,这样一来,就不必拷贝一个数据的副本举行发送,而是直接从数据源的地址举行发送,节约了部门 RAM 空间。可是这样真的好吗?你是否思量过在盘算数据帧校验值的时候,数据源改变了的问题呢?好比说你接纳和校验,数据一开始是 0x55,盘算数据帧的校验和值为 tx_sum,然后被中断法式或者 DMA 修改了这个数据源,酿成了 0xAA,此时你再使用这个数据地址举行发送,吸收端吸收到了 0xAA,吸收端盘算校验和的时候是 rx_sum,那么 rx_sum 一定不即是 tx_sum,然后吸收端就认为该数据帧是错误的,然后丢失这帧数据,而这种情况是比力少见的,但确实是会偶然泛起吸收错误的情况(其时发现这个问题时始终不得其解,明显我发送的是这个校验值,为什么你盘算的校验值是另一个?开始怀疑是校验函数的问题,但其他数据帧盘算时没有问题,只有一种数据帧会泛起问题,然后鱼鹰怀疑是数据源的问题,是的,鱼鹰很快就怀疑数据源的问题,但其时验证时,只改了校验那部门地址,发送时的地址还是使用源地址,导致问题还是没解决,过了很久之后才发现这个发送地址没改,囧。

所以说,纵然你的思路是对的,但如果你解决时错了,问题也很严重)。如果说吸收端(从机)具有重发机制,那么问题不是很大,丢失一帧数据而已,再重发就是,但事实是,一般串口设计成主从模式,主时机在没有吸收到从机的应答数据时会举行重发,可是从机一般不会主动重发数据的,它无法判断主机是否乐成吸收,而从机一般会在乐成发送完数据后开始清除一些标志位(好比键盘按键数据清空,否则主机下次获取按键信息时还是同一个按键数据),事实上这个行动必须在对方乐成吸收才气举行(否则这次按键信息就丢失了),从这个角度来看,我们必须设计一个机制用于判断主机是否乐成吸收。

I2C、CAN 总线都有应答信号,但这是这些是总线自带的特性,我们不行能在吸收到一个字节后发送一个应答信号给主机,那么是否有其他措施呢。人们很容易想到的一个措施就是在主机收到正确数据后,主动发送一帧专用数据帧用于清除这个标志(这个帧和普通帧一样,所以可以确保主机数据能准确送达从机,因为如果超时没有送达,会触发重发机制)。

这样只要在获取完这帧数据后,再分外的发送一帧数据用于对方确认即可,从机吸收到后,即可开始着手清除一些标志位。但这样会有一个问题,因为这种特殊的需要从机确认的数据包(其他类型数据不需要确认是因为如果主机没有正确收到数据还可以继续获取,获取的数据是一样并没有关系,但这种需要从机确认,一旦从机认为发送乐成了,数据就被清除了这种情况就需要确认,典型的就是按键信息了),我们需要分外处置惩罚并占用发送带宽。

这是鱼鹰不愿忍受的。那么是否有更好的措施?或许我们可以从 USB 协议中获得启发(这是在写这篇条记的时候想到的,其时写按键板代码的时候没有想到过,但因为其时测试时传输乐成率 100%,所以就放弃处置惩罚这种情况了)。USB 协议是典型的主从机制,主机不主动获取数据,从机是无法主动发送数据的。

那么从机是如何确定对方乐成吸收数据了呢?一个 bit 的翻转位。每当主机乐成发送一帧数据后再发送下一帧数据时,就会翻转这个位,从机就可以凭据这个位判断主机是属于重发数据(重发数据表现主机吸收失败了)还是新数据了,这样从机就能从下一帧数据确定上一帧数据是否乐成发送了。而主机发送的数据是由从机发送应答包确定的,和上面的串口协议类似,所以这个偏向的数据是没有问题的。

那么我们该如何重新设计这个协议呢?可以尽可能的不改变原来协议的情况下实现吗?或许可以从功效字出发。为了保证对功效字的原有界说保持基本稳定,使用最高 bit 作为这个特殊的位,这个 bit 开始是 0,之后主机每吸收一个从机应答数据就举行翻转,如果因为没有吸收到从机的应答数据,就会使用相同的翻转位重复发送;而从机也凭据这个 bit 来确定自己的上一帧数据对方是否吸收(对比上一帧数据的翻转位),如果主机没有乐成吸收,就不清除标志位(之后主时机重发数据再次获取),否则清除标志位,。因为是鱼鹰刚想到的,就不多说了,仅提供一个思路。现在回到指针那块的问题。

现在已经知道,如果你在盘算校验和与发送的历程中泛起源数据改变的情况,就会导致数据帧校验失败,那么有什么解决措施?如果说你坚持使用查询方式发送来节约部门空间,那么只要在盘算校验值之前拷贝一份源数据,然后用这份数据盘算并发送即可。另一种方法就是,直接把整帧数据拷贝到一个数据缓存中,使用 DMA 发送。

现在另有一个问题,那就是如果我想发送一个数据域为空的数据该怎么发送?一般来说,在使用指针的时候,不会使用 NULL 空指针,可是在数据为空的情况下,就需要使用 NULL 指针了,并长度设置为 0,这个时候在检查指针的时候,不能看到空指针就退出函数,还要判断长度信息,当长度为 0 时在打包时就不拷贝源数据,但最终还是要发送数据帧的(其时别人写的代码将指针和长度判断同时放到了 for 循环的条件内里,鱼鹰以为效率太低,导致修改代码是没思量指针为空的情况,所以导致了一个小 bug)。下集精彩, 串口缓存互斥锁释放顺序,喜欢的话记得关注鱼鹰哦!。


本文关键词:串口,吸收,法式,遇到,168体育登录,的,那些,问题,上,两篇

本文来源:168体育登录入口-www.huaqiangpeixun.com