STM32串口通信校验
我就只讲讲我对串口的新的领悟:
原来串口按照帧来传输是真的,比如数据位是7个,那么收到的也是7个数据位,那问题就来了,不应该按照一个字节8个位来解码吗,我是不是应该等下一帧传过来,从里面取一位补齐8位?
实际上就是,不需要,如果设置的数据位是7个,那么接收到这7个数据位之后,就直接处理了,自动补一个最高位(这个我确实分不清是硬件做的还是软件做的),然后位数变成8位了,然后最高位补0,这样,
一个字节就齐了,然后就直接解析数据。所以说如果发送的是0XFF,收到之后就会变成0X7F,127以内的数据用7个数据位传输不会错,超了就会报错了。
然后再说说串口的硬件,你的MCU串口最大能发送几个数据位的是由硬件决定了的,软件配置硬件处理,然后就是发送数据时,是低位先发,再发高位,比如0XF1,那么发送的二进制顺序就是
10001111,加上起始位和停止位,发送的数据就成了0100011111,如果用示波器或者逻辑分析仪检测到的波形就是这样的(0代表低电平,1代表高电平):1 1 1 1 1 0 0 0 1 0;但是不管波形是怎么样的,
接收方收到这串帧数据之后,会自动处理,没错,又是硬件包揽了一切,然后你获取到的数据就是0XF1了,如果包没出错的话,否则这个包就要扔掉。
然后说说为什么串口通信加了一个校验位就变得可靠了:实际上不是因为加了校验位就可靠了,而是加了校验位再加上软件的校验就变得可靠了,先前我们说的都是发送一个字节,或者说至少处理之后
会变成一个字节,但是一般的校验位比如奇偶校验,只能检测这7个数据位中是否有一个位发生了翻转,若是两个四个六个位同时翻转,那么它是检测不出来的(虽然这种概率并不高)。也就是说,校验位只能
处理变了一个位的情况。然后问题来了,检测出来了之后呢,不会订正只会丢掉,那么对于我要执行的多字节串口指令来说,丢掉了不还是可以执行吗?比如我发送:今天不打游戏,传输途中校验丢了个不,
那收到的就是:今天打游戏。这不是影响更大吗。所以说,得把这几个字节再用一种协议封装一下,变成一个“包”。就比如说我要发送这句话之前,多加一个字节的长度放在一起发过来,那么当丢了个“不”的时候,我软件就能得知
字节长度不匹配,然后就可以直接整个包都丢掉了,要求再重新发一条新的过来。但是还是不够保险,假如我判断字节长度的也变了,数据字节也变了,恰好他们又对上了呢,我还是以为我收到的是正确的数据,
所以这个时候要加一种更强的校验方式,不仅仅是奇偶校验了,就比如CRC校验。他会根据你传入的数据长度+整串数据,输出两个字节的校验码,这个校验码只能说非常可靠。接收方收到数据之后,根据同样的CRC校验函数,将数据
再经过CRC校验一次,看看新的校验码是不是对得上,要是对得上那就没问题了,数据正常可信。
再总结一下上面的,总之就是把一串数据归纳到一起,双方定义一下数据长度,校验码,这个数据就会变得更加可信,这个也就是协议,协议加的越复杂,数据的可靠程度就越高,就比如MODBUS协议中,格式为:地址 + 功能码 + 数据 + CRC16,
甚至这个的功能码和地址码都只能是有限的几种组合,那可靠度确实就上去了。但是可靠度上去的同时,有效信息率就降低了,就比如我原本最基础的串口通信,8个数据位一个校验位,或者7个数据位1个校验位,那么信息密度就是8/9或者7/8,
反观这些加了各种校验的呢,如果数据位只有两三字节,那么信息密度可能只有3/8之类的了。所以对于一些普通的调试信息,直接使用串口就好了,速度最快,或者根据使用场景慢慢变复杂。
然后再讲讲怎么接收数据,如果能确定数据是隔一段时间一发还好,那么单缓存也可以使用,但是如果数据频繁,就要考虑双缓存或者环形缓存?这个环形缓存也是刚刚问AI跟我说的,没想到还有这么个东西,
我只是觉得双缓存也不够保险,需不需要在解析的时候锁住串口,这样当然可以解析正确,但是会丢包,感觉也不好,所以双缓存真的有必要吗,不如直接上环形缓存?
下面是关于缓存区如何选择,还未经试验,目前只是理论探讨。

下面是环形缓存区实质是什么:

对于这个环形缓冲区,我觉得有必要考虑下全局变量编译时在CPU中的存放,若是只设置了大小,初始化时应该是划分了1KB的空间在RAM区的.bss区域,flash中没有占多余的数据空间,应该是比较合理的选择。
根据这个缓存区的数据结构,我已经知道怎么用的了,存入或者读出数据一个字节一个字节地来,因为是有两个指针,可以判断两个指针的大小来判断缓存区是否还有数据需要读取,有了指针之后只需要存到最后一个位置的数据存完之后,如果有新的数据进来
,只需要把指针位置连接到数组的“0”号就实现了“环形”,指针原来这么好用吗!
浙公网安备 33010602011771号