cancel
Showing results for 
Search instead for 
Did you mean: 

only 1 byte RS485 received on STM32L051

_alaBaster
Associate III

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
9 REPLIES 9
Pavel A.
Evangelist III

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.

 

TDK
Guru

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

If you feel a post has answered your question, please click "Accept as Solution".
Chris21
Senior

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?

_alaBaster
Associate III

@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

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.

If you feel a post has answered your question, please click "Accept as Solution".

Do you enable interrupt on RX errors? If overrun occurs, the normal RXNE interrupt flag won't be set, this is the problem. 

 

 

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)
  {
  }
}

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!

Hi @Pavel A. 

yes, interrupt on RX errors is dealt along within the init function.

According to documentation (RM0377 Rev 10, page 719/905), with respect to ORE (Overrun error) in the USART_ISR register:
"An interrupt is generated if RXNEIE=1 or EIE = 1 in the USART_CR1 register."

Thanks, will keep an eye on this error while developing