STM32 HAL库 RS485发送遇到的问题及解决方法(STM32G030C8t6)

       MCU利用RS485与外部通信,由于RS485是半双工通信协议,所以,要进行收发控制,要将485接口芯片的RE#和DE引脚短接,作为一个控制端,当控制端接高电平,为发送状态,否则,为接收状态。通常情况下,每个连接到RS485网络的设备,只有在本设备发送时才能将控制端置为高电平,其余时间要置于低电平(处于接收或监听状态)。

      假设我们将MCU的GPIOC口的PC7作为控制端口,并定义如下宏,便于使用:

#define RS485_T   HAL_GPIO_WritePin(GPIOC,GPIO_PIN_7,GPIO_PIN_SET);
#define RS485_R   HAL_GPIO_WritePin(GPIOC, GPIO_PIN_7,GPIO_PIN_RESET);

     如果使用串口1,发送函数如下:

///
//函数名称:DMA_Usart_Send(uint8_t *buf, uint16_t len)
//功能描述:串口DMA方式发送数据帧
//参数说明:*buf 数据帧的指针,len数据帧的长度
//返 回 值: 无
//
void DMA_Usart_Send(uint8_t *buf, uint16_t len)
{
    if(HAL_UART_Transmit_DMA(&huart1,buf,len)!=HAL_OK   )
    {
        Error_Handler();
    }
}    

       从逻辑上讲,RS485发送,在调用DMA_Usart_Send前,调用RS485_T,拉高发送控制端,在HAL_UART_TxCpltCallback函数中调用 RS485_R即可完成一帧数据的发送,见下面的代码。

发送一帧数据代码:

        RS485_T;                //485控制端置高电平

        DMA_Usart_Send(buf,len);//发送数据帧,数据帧发送完成会触发发送完成中断

                                                         // 中断回调函数HAL_UART_TxCpltCallback 中将485

                                                        //控制端置为低电平(执行RS485_R;)

中断回调函数代码如下。

///
//函数名称:HAL_UART_TxCpltCallback (UART_HandleTypeDef *huart)
//功能描述:串口发送完成回调函数,使RS485芯片RE#/DE连在一起的引脚变低
//

void HAL_UART_TxCpltCallback (UART_HandleTypeDef *huart)
{
        RS485_R;  //串口发送完成将RS485芯片的发送控制端置为低电平——接收
}

       但是,上述过程在时序上就会出现不可靠的情况,使得系统不能正常工作。产生不可靠的原因是RS485_T执行并不是理想的阶跃上升,通常是有一个上升时间的,如果这个时间并未达到485控制端最低高电平要求,接下来的DMA_Usart_Send发送已经执行,就可能造成发送的数据帧不完整,甚至不能触发发送完成中断,则 HAL_UART_TxCpltCallback回调函数不能执行,485控制端总是处于高电平,若设备接入RS485网络,将使整个瘫痪。

        为了解决上述问题,应在执行宏RS485_T后,插入一个小的延时,约10微秒左右,用一个变量和while循环实现即可,DMA_Usart_Send后面是通过发送完成中断回调函数中,执行RS485_R;拉低485控制端。实测波形,已经有10us以上的时延,所以不需要再延时。改进后的RS485发送代码如下:

void RS485_Send_data(uint8_t *pdata,uint16_t data_size)
{
    uint8_t i=100;
    RS485_T;
    while(i--);
    DMA_Usart_Send(pdata,data_size);  //发送完成产生发送完成中断,在中断回调函数中

                                                                //执行RS485_R
}

      以上观点基于实验,有认识不妥之处请批评指正。

你可能感兴趣的:(stm32,嵌入式硬件,单片机)