问题描述
我们有一个带IP的网口转串口的小设备,用在现场,接在路由器上,从网络来和485设备来通讯。
现场有很多485设备,如果是9600/n/8/1, 通讯没问题;如果校验不是无校验,我们做好的应用,就无法和设备通讯。
这设备固件是2017年写的,现在没人维护了。用起来没发现问题。
以前遇到过有校验的情况,当时是联系设备厂商,让他们指导如何将设备通讯参数改为无校验,就能通讯了。
这次在现场的设备是台空调,现场工程师在仪表面板中提供的功能中,并没有发现如何将空调的通讯参数改为无校验的UI界面。正在和厂家联系。
我从研发的角度看,公司有网转串设备的同型号现货,我可以先验证一下,是否真的是网转串设备本身不支持有校验的通讯方式。
我和同事做了测试,他从一台计算机上,从网口向设备的输入端网口发数据,我从设备的485输出端口接一个485转串口,在电脑上等着他发的数据。
当通讯参数为9600/n/8/1时,可以收到他发来的原样数据。
当通讯参数为9600/偶校验/8/1时,我这边的电脑调试助手收到的是乱码,他发来3个16进制字节,我收到4个16进制字节乱码。乱码和原样数据没人任何关系。
尝试解决
既然确定是设备有问题,从svn上迁出这个设备的固件工程看了一下。
我第一感觉是串口初始化参数有问题。
连上仿真器,单步一下,看下在校验方式设置时,是否有区别?
没看出区别。
去网上查STM32接收乱码的问题,网上说到一个上位机(e.g. 串口助手)数据长度为8,下位机(e.g. STM32固件)的数据长度要设为9。说是数据长度是数据位长度 + 停止位的和。
试了一下,将数据位设置位9, 可以通讯了。
去查一下,这个上位机数据长度为8,下位机数据长度必须设置为9,这个说法是从哪来的?没查到。
官方文档没说法。官方F1固件库中串口的例子工程,都是直接给串口通讯参数赋值,并没有根据上位机通讯参数来设置下位机通讯参数的例子。
那我估计,可能是前面的同学,自己试出来的。比如8位不行,又没有其他解决方法,那还有个9位可以用一下,试了一下好使这样子。
我们工程中,通讯参数是通过udp通讯,先设置到设备中,设备重启后,读通讯参数,然后串口初始化。
void STM32_UART1_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_USART1,ENABLE); //UART时钟配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_Init(GPIOA, &GPIO_InitStructure);
USART_InitStructure.USART_BaudRate = setinfo.Device_Baudrate; //比特率设定
if(setinfo.USART_WordLength==7)
{
USART_InitStructure.USART_WordLength = USART_WordLength_8b; //8数据位长度
}
else if(setinfo.USART_WordLength==8)
{
USART_InitStructure.USART_WordLength = USART_WordLength_9b; //9数据位长度
}
我们实施的同事,以前遇到这种有校验的方式,都是请厂家工程师指导我们改设备通讯参数,甚至跪求厂家工程师帮我们直接刷无校验的实现 😛
其实应用方面的问题,前面的同学大多都解决掉了。做一下实验,查一下资料,再做一下实验搞定:)
真的很少问题是确实前面的同学从来没解决过,没分享过,非要自己亲自操刀来解决,这种特殊情况很少的。