STM32
直播中

石玉兰

7年用户 1411经验值
私信 关注
[问答]

STM32F4物理串口UART7bit校验位停止位数据设置问题怎么解决?

STM32F4物理串口UART7bit校验位停止位数据设置问题怎么解决?

回帖(1)

张雯雯

2021-12-3 10:54:53
关于STM32使用7位数据收发的问题,网上找了一些资料,但是 都不是特别清楚,现在结合目前的项目对这个问题做一些探讨。
STM32我们在使用数据位是7并且使能了校验位的时候,字长我们需要设置成8bit,这样对单片机来说,就是7bit数据+1bit的校验位。这个可以从技术文档中查看:





7bit Even 1 stop具体配置如下:
USART_StructInit(&USART_InitStructure); USART_InitStructure.USART_BaudRate = 9600; USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_Parity = USART_Parity_Even; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
PC端的上位机串口我们设置成对应的,如下:





我们通过串口发送数据到pc端的时候,会发现是正常的。但是PC端发送数据到STM32是错的。
如下:





发送. 11 55 AA FF
接收. 11 55 2A 7F
为什么接收和发送的数据不一样呢?
一、 这是因为,PC发数据到单片机的时候,如果设置数据位7位或者8位,那就是单纯的数据长度为7或8,但是STM32的文档里说,串口设置的数据长度包含校验位。若使能了校验位,数据位设置了8,就是7位数据+1位校验位。若设置了9,就是8位数据+1位校验
所以,第一种解决方式出来了。就是发送的时候,必须设置成8位数据位,然后单片机才能识别到,但是,一旦设置成8位,PC这边接收的就不对了















二、回到前面的收发问题。





发送. 11 55 AA FF
接收. 11 55 2A 7F
当PC端设置成7bit的时候产生这个深层的原因其实是:
若PC设置发送数据位7bit,MCU实际上接收到了8bit数据,只不过最高位是被设置成了校验位。
例如,发送字符1,对应MCU收到的B1,二进制为 1011 0001;偶校验,因此最高位0被置成了1,如果只取前7位有效,就变成了0011 0001,对应0x31,也就是字符1;

如图:










上面的两个图可以很好说明这种原因

最好的解决方法:
如果PC端也需要设置成7bit的话
最好的处理方式就是对收到的数据进行反奇偶校验处理,但是有一个问题,MCU对接收的数据的处理是根据奇偶校验结果将最高位重置的,没有将校验位单独放一位。
所以,每个收到的数据,反奇偶校验的结果都有两个。我们不知道应该怎么判断哪个是正确的。就像0xf0,MCU收到的正确结果应该是1111 0000,如果是偶校验,那么最高位1就会被重置成0,变成了0111 0000 ,对应是的0x70,我测试下来,应该是这样的。不知道这个校验是PC端做的还是单片机端做的,如果是PC端并且知道pc端是什么校验方式的话,还可以算出来真实结果,如果是单片机端,需要知道单片机的校验方式,才能知道结果,但是如果不知道的话,MCU端就没法判断了。
另外上面所说的第一种解决方式,PC设置成8bit,如果PC端设置成8bit,MCU是可以识别的,我认为PC设置成8bit,实际上发送的是8bit数据+1bit校验位,而MCU端的设置是7,even,1,字长设置成了8bit,因此PC发过来的第9位,也就是校验位被丢掉了,只接收了8bit的数据。因此能够识别。具体我没有验证,理论上应该是这样的。
第三种解决方式:
当第二种解决方式不行的时候,也就是你不知道PC端发送数据的方式,即校验方式。那么如果你发送的数据大小都不超过0x7F的话,MCU端可以通过将接受的数据&0x7f,直接丢掉最高位校验位的方式,来获取收到的真实数据。
这种方式,对于仅仅用来获取可显示字符(ASCII的0x21-0x7e)是完全没有任何问题的。
举报

更多回帖

发帖
×
20
完善资料,
赚取积分