Skip to main content
Graduate
August 13, 2024
Question

only 1 byte RS485 received on STM32L051

  • August 13, 2024
  • 4 replies
  • 2072 views

Hi there I am using STM32L051 to talk to a RS485 transceiver and I am having problem with the receive part.

System is as follow: laptop->FTDI USB converter-> Renesas transceiver -> STM32

I want to update the single byte buffer when a character is detected on the RX line by means of an interrupt.

Interrupt is detected the first time then microcontroller does not go into interrupt any longer on subsequent send of byte from the terminal. I can see that byte is on the uC pin with oscilloscope.

The main does nothing other than enabling the interrupt with __HAL_UART_ENABLE_IT, see below:

/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <string.h>
#include <stdio.h>
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
UART_HandleTypeDef huart2;

/* USER CODE BEGIN PV */
uint8_t r;

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART2_UART_Init(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */

/* USER CODE END 1 */

/* MCU Configuration--------------------------------------------------------*/

/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();

/* USER CODE BEGIN Init */

/* USER CODE END Init */

/* Configure the system clock */
SystemClock_Config();

/* USER CODE BEGIN SysInit */

/* USER CODE END SysInit */

/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART2_UART_Init();

/* USER CODE BEGIN 2 */
__HAL_UART_ENABLE_IT(&huart2, UART_IT_RXNE);

HAL_GPIO_WritePin(RS485_DE_GPIO_Port, RS485_DE_Pin, GPIO_PIN_SET); //Pull DE high, enable transmit,

// The /RE pin is permanently low
/* USER CODE END 2 */

/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */

/* USER CODE BEGIN 3 */

}
/* USER CODE END 3 */
}

 

The USART2_IRQHandler in stm32l0xx_it.c is modified, such that is actually receiving the byte:

void USART2_IRQHandler(void)
{
  /* USER CODE BEGIN USART2_IRQn 0 */
 
/* USER CODE END USART2_IRQn 0 */
  HAL_UART_IRQHandler(&huart2);
  /* USER CODE BEGIN USART2_IRQn 1 */
  HAL_UART_Receive_IT(&huart2, &r, 1);
  /* USER CODE END USART2_IRQn 1 */
}
 
Any hint, I appreciate! Thanx
    This topic has been closed for replies.

    4 replies

    Super User
    August 13, 2024

    Interrupt is detected the first time then microcontroller does not go into interrupt any longer on subsequent send of byte from the terminal.

    Symptom of receiver overrun. Check for overrun and clear if it occurs.

     

    Super User
    August 13, 2024

    You should be calling HAL_UART_Receive_IT before the main loop to start things off. Enabling RXNE interrupt isn't what HAL wants.

    Graduate
    August 13, 2024

    You have:

    HAL_GPIO_WritePin(RS485_DE_GPIO_Port, RS485_DE_Pin, GPIO_PIN_SET); // Pull DE high, enable transmit,

    but you want to receive?

    Graduate
    August 14, 2024

    Hi @Chris21

    indeed, the issue was related to that. The external transceiver is going weird when both TX and RX are active. So solution is: activate only RX path when receiving  :)

    Thank you!

    Graduate
    August 13, 2024

    @TDK 

    in main I use now:


    /* Initialize all configured peripherals */
    MX_GPIO_Init();
    MX_USART2_UART_Init();

    /* USER CODE BEGIN 2 */
    HAL_UART_Receive_IT(&huart2, &r, 1);

     

    @Pavel A. 

    interrupt handler is accessing RDR register to clean potential overrun, I also tried to explicitly lcear OREF before calling again the HAL_UART_Receive_IT:

    void USART2_IRQHandler(void)
    {
      HAL_UART_IRQHandler(&huart2);
      volatile uint8_t temp = USART2->RDR;
      (void)temp;
      memset(&r,'\0',1);
      __HAL_UART_CLEAR_FLAG(&huart2, UART_CLEAR_OREF);
      HAL_UART_Receive_IT(&huart2, &r, 1);
     }
     
    After reading the first byte, a subsequent byte is not raising interrupt on USART2.
    Why the HAL_UART_Receive_IT is not taking care of preparing for next interrupt?
    It seems there are several posts on the topic, but not clear solution/explanation.
    Thanks
    Super User
    August 13, 2024

    Shouldn't be messing with anything in USART2_IRQHandler other than to restart the reception. Did you implement HAL_UART_RxCpltCallback to read in the data?

     

    The HAL-correct way to clear ORE would be within the HAL_UART_ErrorCallback callback handler.

     

    As a rule, if you are getting an overrun error, you have a code bug. It's not something you should be experiencing on a regular basis. If you're debugging and the cpu is paused, it could explain why you're getting it, but if your program is running and you get ORE, there's a bug somewhere that needs fixed.

    Graduate
    August 14, 2024

    Hi @TDK thanks

    OK I received your point on rather working with HAL_UART_RxCpltCallBack.

    Anyway with the following basic code it works, I am receiving subsequent bytes.

    Issue was:

    • I was setting my Renesas transceiver to transmit  and receive at the same time. In this state apparently the device is "sometimes" distorting the received signal (from laptop). So I do need to deactivate the TX path while receiving, as it should be :)

    Below the basic code I am working with. Question, do I need to clear the content of the RxBuffer? Apparently not needed actually, as long as RDR content is reset.

    It was quite silly thing in the end, but your guidance helped in understanding better how UART works so thank you!

     

    void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
    {
    HAL_UART_Receive_IT(&huart2, &r, 1);
    memset(huart->pRxBuffPtr,'\0',1);
    }
     
    int main(void)
    {
      HAL_Init();
      SystemClock_Config();
      MX_GPIO_Init();
      MX_USART2_UART_Init();
      HAL_UART_Receive_IT(&huart2, &r, 1);
      while (1)
      {
      }
    }