Skip to main content
Graduate
December 5, 2024
Solved

Framing error generated after RS485 plugging and unplugging

  • December 5, 2024
  • 4 replies
  • 2223 views

Hello everyone, I encountered a problem while using STM32L431 for RS485 development. I used the ISO7041 isolation chip, and in the initial state, the DE pin is low, while both TX and RX are high. The current issue is that when I turn on the power, reset, and plug in 485, both the transmission and reception of 485 are normal. However, when I unplugged and inserted 485 again, an FE error occurred. Why is this? Is it because the voltage level does not match after inserting 485?

微信图片_20241205083302.png

Debugging found errorsflags=2, which should be FE errors。

Here is some of my code:

 

int main()
{
	HAL_Init();
	SystemClock_Config();
	MX_GPIO_Init();
	MX_LPUART1_UART_Init();
	HAL_GPIO_WritePin(DE485_GPIO_Port, DE485_Pin, GPIO_PIN_RESET);
	initSqQueue(&uart[_LPCOM].Rx, lpuartRxBuff, sizeof(lpuartRxBuff));
	initSqQueue(&uart[_LPCOM].Tx, lpuartTxBuff, sizeof(lpuartTxBuff));
	__HAL_UART_ENABLE_IT(&hlpuart1, UART_IT_RXNE);
	__HAL_UART_ENABLE_IT(&hlpuart1, UART_IT_IDLE);
	while(1)
	{
		Process_Modbus_Receive(_LPCOM); // MODBUS
	}
}

void USER_LPUART1_IRQHandler(void)
{
 uint8_t lpuart1_data;
 if (__HAL_UART_GET_FLAG(&hlpuart1, UART_FLAG_RXNE) != RESET)
 {
 lpuart1_data = (uint8_t)hlpuart1.Instance->RDR & (uint8_t)0x00fff;
 wrEleQueue(&uart[_LPCOM].Rx, lpuart1_data);
 uart[_LPCOM].active = true;
 }
 if (__HAL_UART_GET_FLAG(&hlpuart1, UART_FLAG_IDLE) != RESET)
 {
 uart[_LPCOM].rxIdle = true;
 __HAL_UART_CLEAR_IDLEFLAG(&hlpuart1);
 }
 else
 {
 uart[_LPCOM].rxIdle = false;
 }
}

void LPUART1_IRQHandler(void)
{
 USER_LPUART1_IRQHandler();
 HAL_UART_IRQHandler(&hlpuart1);
}

 

My current solution is to modify the HAL library generated by CUBEMX, directly delete the judgment of CR3 EIE value and clear the flag bit. Is this correct? Will it affect the transmission and reception of other serial ports, or can this flag be detected elsewhere and cleared elsewhere.

 

 // if (((isrflags & USART_ISR_FE) != 0U) && ((cr3its & USART_CR3_EIE) != 0U))
 if (((isrflags & USART_ISR_FE) != 0U) )
 {
 __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_FEF);

 huart->ErrorCode |= HAL_UART_ERROR_FE;
 }

 

 微信图片_20241205084926.png

微信图片_20241205085038.png

    This topic has been closed for replies.
    Best answer by AlfRomeo

    @Techn @Andrew Neil @jiangfan 

    Hi, can I modify it like this?

    void USER_LPUART1_IRQHandler(void)
    {
     uint8_t lpuart1_data;
     if (__HAL_UART_GET_FLAG(&hlpuart1, UART_FLAG_RXNE) != RESET)
     {
     lpuart1_data = (uint8_t)hlpuart1.Instance->RDR & (uint8_t)0x00fff;
     wrEleQueue(&uart[_LPCOM].Rx, lpuart1_data);
     uart[_LPCOM].active = true;
     uart[_LPCOM].holdTmr = CONST_RS_485_HOLD_TMR;
     }
     if (__HAL_UART_GET_FLAG(&hlpuart1, UART_FLAG_FE))//Determine whether the FE flag is set
     {
     __HAL_UART_CLEAR_FLAG(&hlpuart1, UART_CLEAR_FEF);//Clear the FE flag
     openLpUart1();
     initSqQueue(&uart[_LPCOM].Rx, lpuartRxBuff, sizeof(lpuartRxBuff)); // Initialize the serial port receiving buffer
     memset(lpuartRxBuff, 0, sizeof(lpuartRxBuff));
     }
     if (__HAL_UART_GET_FLAG(&hlpuart1, UART_FLAG_IDLE) != RESET)
     {
     uart[_LPCOM].rxIdle = true;
     __HAL_UART_CLEAR_IDLEFLAG(&hlpuart1);
     }
     else
     {
     uart[_LPCOM].rxIdle = false;
     }
    }
    void LPUART1_IRQHandler(void)
    {
     USER_LPUART1_IRQHandler();
     HAL_UART_IRQHandler(&hlpuart1);
    }

    4 replies

    ST Employee
    December 5, 2024

    After a brief look, I suppose you may do:

    detect unplug of RS485, reset/re-init RS485 interface, then RS485 can work as if it is the same as power on of the board.

    AlfRomeoAuthor
    Graduate
    December 5, 2024

    Hi, how can I check if RS485 is unplugged? There are no other pins except for DE, RX, TX

    ST Employee
    December 5, 2024

    perhaps from low level, it is difficult to know if unplug state, you may define - from high level - protocol level that some traffic (heart break) exist timely (such as each second). so, unplug may be detected after unplug for ~1 second.

    Super User
    December 5, 2024

    @AlfRomeo wrote:

    when I unplugged and inserted 485 again, an FE error occurred. Why is this?


    Because you get a glitch on the unplugging and/or re-plugging.

    This is perfectly normal, and to be expected.

     

    PS:

    or the unplugging and/or re-plugging occurs during a frame

    Graduate II
    December 5, 2024

    if you get frame error, reset the uart errors and start afresh, it should be ok. RS485 is not auto recovery , you have to have routines to detect errors and take action.

    AlfRomeoAuthorAnswer
    Graduate
    December 6, 2024

    @Techn @Andrew Neil @jiangfan 

    Hi, can I modify it like this?

    void USER_LPUART1_IRQHandler(void)
    {
     uint8_t lpuart1_data;
     if (__HAL_UART_GET_FLAG(&hlpuart1, UART_FLAG_RXNE) != RESET)
     {
     lpuart1_data = (uint8_t)hlpuart1.Instance->RDR & (uint8_t)0x00fff;
     wrEleQueue(&uart[_LPCOM].Rx, lpuart1_data);
     uart[_LPCOM].active = true;
     uart[_LPCOM].holdTmr = CONST_RS_485_HOLD_TMR;
     }
     if (__HAL_UART_GET_FLAG(&hlpuart1, UART_FLAG_FE))//Determine whether the FE flag is set
     {
     __HAL_UART_CLEAR_FLAG(&hlpuart1, UART_CLEAR_FEF);//Clear the FE flag
     openLpUart1();
     initSqQueue(&uart[_LPCOM].Rx, lpuartRxBuff, sizeof(lpuartRxBuff)); // Initialize the serial port receiving buffer
     memset(lpuartRxBuff, 0, sizeof(lpuartRxBuff));
     }
     if (__HAL_UART_GET_FLAG(&hlpuart1, UART_FLAG_IDLE) != RESET)
     {
     uart[_LPCOM].rxIdle = true;
     __HAL_UART_CLEAR_IDLEFLAG(&hlpuart1);
     }
     else
     {
     uart[_LPCOM].rxIdle = false;
     }
    }
    void LPUART1_IRQHandler(void)
    {
     USER_LPUART1_IRQHandler();
     HAL_UART_IRQHandler(&hlpuart1);
    }
    Graduate II
    December 12, 2024

    In addition to the above, probably you have to have some routine at higher level to detect the break and re-start the query/reception based on your state machine. Normally we implement one master multiple slaves, so it should be easy.