STM32/GD32使用RS485收发数据方向切换时需加延时的问题解决与分析
RS485作为常用的通信方式,在软件实现上和RS232使用基本类似,只需增加一个数据收发的方向切换引脚即可。然后,在使用这个方向切换的时候,如果对MCU底层驱动库理解不够的话,会出现各种奇怪的问题。下文将对方向切换时,需要在发送或者接收函数后增加一个延时的问题加以说明。事实上,只要发送函数写的合适,此延时函数是不需要的。
以GD32为例
RS485电路可以设计成自收发电路或者引脚可以收发电路,如果是自收发电路则不需要进行方向切换,对于MCU来说,当做RS232来用即可,但是自收发电路的收发控制脚的电容会影响到收发时序,还跟通信波特率用关。而使用MCU控制收发的方式则可以避免这个问题。
- 电路实例 ,下图给出了我们常见的最简单的485电路,使用的是MAX485芯片;;
- 代码很简单,如下:``此处为发送函数,判断TBE发送数据缓冲区为空即认为发送完成;
void uart_data_transmit_wait(uint32_t usart_periph, uint8_t data)
{
usart_data_transmit(usart_periph, data);
while (RESET == usart_flag_get(usart_periph, USART_FLAG_TBE));
}
此为发送函数,当发送数据缓冲区TBE置1时,即认为发送完成;
if(RS485_User_Group.Rx_Completed_Flag == true)
{
RS485_User_Group.Rx_Completed_Flag = false;
RS485_Transmit
uart_data_transmit_wait(MCU_COM2, 0x55);
delay_ms(1);
RS485_Receive
}
此为中断接收到数据后,紧接着向外发送一个0x55字节的操作。
代码测试发现:必须在发送函数后面加一个delay_ms(1)的延时函数后,数据才能正常的发送出去,若没有这个延时,则发送不出去,用示波器会发现一个字节的8个bit位还没发送完,方向已经切换成了收的状态,自然剩下的位就发送不出去了;
3. 原因为在发送函数中使用了USART_FLAG_TBE作为判断发送完成的标志,即认为数据已发送至移位寄存器之后就认为发送完成了,事实上数据到了移位寄存器了,并不代表数据已经送MCU发送出来了。需使用USART_FLAG_TC寄存器作为判断数据已经从MCU发送出去的标志,寄存器说明如下:
4. 修改并测试OK的代码如下:
void uart_data_transmit_wait(uint32_t usart_periph, uint8_t data)
{
usart_data_transmit(usart_periph, data);
//此处需要注意:若为485,需使用发送完成标志USART_FLAG_TC;若使用232,则可以使用发送数据缓冲区空USART_FLAG_TBE
while (RESET == usart_flag_get(usart_periph, USART_FLAG_TC));
}
if(RS485_User_Group.Rx_Completed_Flag == true)
{
RS485_User_Group.Rx_Completed_Flag = false;
RS485_Transmit
uart_data_transmit_wait(MCU_COM2, 0x55);
RS485_Receive
}
- 代码测试OK,不再需要延时,不会阻塞主程序的执行;
- 总结如下:使用485时最好使用USART_FLAG_TC作为判断发送完成的标志,使用232时,则可以使用USART_FLAG_TBE作为发送完成的标志。