GD32转RS422在115200下接收乱码
如果你的串口是用来转RS422、RS485、RS232等其它协议,我认为GD32的芯片可能不是一个好的选择,因为它的兼容能力太差了。
如果你只是串口间来回传输数据,那么乱码大概的时钟没配置对,请看我这两篇文章:
GD32F4(5):GD32F450时钟配置为200M过程分析
GD32F4(6):晶振引发串口乱码
本文讲述的乱码不是程序的原因,而是使用了部分品牌的转换芯片(如uart转RS422、485、232)导致的电平时常发生改变引发的乱码。

1. 知识储备
首先我们要知道,在定义UART协议的时候,我们都是以bit为单位的,比如起始位是一个bit的低电平,数据一位占据的是1个bit低或1个bit的高,停止位是1或1.5或2个bit。这里其实隐含了一个事情,那就是按理说每一个状态都是有时间规定的,即倍数于一个bit的时间,而bit的时间和波特率是一一对应的。
举个简单的例子:
当波特率为9600的时候,每一个bit的时间为1s/9600 = 104us,也就是说起始位应该是104us的低电平,一个0应该是104us的低电平,一个1应该是104us的高电平。
当波特率为115200的时候,每一个bit的时间为1s/115200 = 8.68us,也就是说起始位应该是8.68us的低电平,一个0应该是8.68us的低电平,一个1应该是8.68us的高电平。
可是对于通信来讲,我们都知道数据传输的时候0和1的表示时间难免和bit时间有一些误差,可能0的时间稍短些,1的时间电平稍长些,这些都是很正常的事情,只要在一个合理的范围内,应该都能识别,可是GD32对于这种兼容效果极差,就是就是这件事,直接导致了stm32换型GD32失败。
下面是我的遭遇:
2. 环境
我为GD32F450设计了一个UART转RS422,转换模块型号为CA-IS3086W,下面是它的设计图(声明:我的问题不是由于这个电路引发的,这里只是给个例子,这个CA-IS3086W很好用):

当我把GD32程序写完,用usb转RS422模块来进行测试,我用的是下面这个模块(这个模块就是坑的开始,我后面说):

这个是同时支持422和485的模块,我把这个蓝色外壳打开,这个芯片422是通过两个串口转485来实现的。
3. 操作
我用串口助手发送数据,通过usb转422发送给mcu:
当我发送的波特率为9600的时候,mcu可以正常接收到数据。
当我发送的波特率为115200的时候,mcu接收到数据会存在部分乱码,因为9600数据是正常的,所以首先排除了时钟的问题,于是我就发送0x55或0xaa,然后用示波器来看波形,如下:

要排除问题,于是我将电路图从UART处断开,在用USB转串口,分别接到两头,发现GD32可以正常和USB转串口收发数据,422侧也可以正常和USB转串口收发数据。所以我就怀疑可能是UART线阻抗不匹配的问题,于是我就把USB转串口的RX引脚直接焊接到了MCU的RX引脚,这样当422收到数据的时候,mcu和USB转串口应该收到一样的数据,结果是USB转串口正常收到数据,mcu收到的是乱码。我蒙了。
在GD32串口RX引脚处看到波形如上图,没有任何问题,上升沿和下降沿都很陡峭,也没有干扰的存在,那为什么呢,因此我就在网上找到了这样的一篇文章《GD32F450的USART接收数据错误问题》。
4. 分析
我大概解释一下《GD32F450的USART接收数据错误问题》这篇文章的意思。我们其实都知道,在配置mcu的UART的时候,其实有一个配置叫过采样(我们一般都是默认值,不配置),一般可以配置成8倍或16倍,其实写过FPGA的朋友应该很好理解UART的IP核的设计,过采样其实就是判断是高还是低的连续采样次数,我们以过采样为8来采集一次低电平为例,如下:

这里描述了UART怎样识别一个bit的低电平,采样的位置每家的设计各不相同,上面只是一个示意图,描述过采样大概就是这样实现的,当我使用过采样为8的时候,一般我设计UART的时候都会这样设计:
- 当采集到低电平>=5次的时候,说明这个bit为低电平。
- 当采集到低电平<=3次的时候,说明这个bit为高电平。
- 当采集到低电平=4次的时候,这说明干扰很大,这时候会报异常,触发串口接收异常中断。
这样的数据增加了容错率,即使有的时候这个bit稍微长一点,或者短一点也能正常识别到。对于16次过采样也大概是这种思路。
根据《GD32F450的USART接收数据错误问题》博主问FAE可知道,GD32的uart的IP核是GD自己自行设计的,在GD32在起始位进行采样的时候,必须全为0才会认为这是一帧的开始(这其实很不合理),那就会出现下面这种情况:

上图中,左边的采集成功,右面的采集失败。
现在将我的通信示波器采集的图像放大,如下:

这是比特率为115200的图像,标准下一个bit时间是8.68us,你会发现我的这个低电平只有8.0us,高电平9.5us,当我选择16倍过采样,采样间隔是8.68us/16 = 0.54us 。而 8.68us-8.0us>0.54,因此这16个采样至少有一次是不正常的,因此数据就会识别错误。
后来我反复的确认,这个bit出现低电平变短,高电平变长的原因是我的那个USB转rs422模块产生的,当我将我两个开发板的RS422互联,就不会出现问题,这就说明并不是所有品牌的RS485或422会出现bit时常低电平变短,高电平变长的现象。
下图是使用CA-IS3086W,会发现数据很正常,如下图:

现在有个非常尬的事:我们设计RS422是对接别人的接口,我们也不知道它用的什么芯片,而且到时候它接在STM32的串口就能用,接在你的设备上就不能,你说是他的电平不标准,谁信呀!
5. 总结
串口协议虽然有标准,可是貌似没有bit时间容错的标准,因此每家的mcu对此兼容性不同,我们不能说GD的uart做的不好,只能说它的兼容性比STM32差的有点多,更何况RS485和RS422转换芯片众多,兼容更多更广的设备,才能有更好的认可。
我的项目结果:
因为上面的问题根本没办法改善,我只能更换mcu厂家,所以现在我决定这个项目用小华半导体HC32FA0重做。
损失。