4

I am using stm32f0 MCU.

I would like to transmit every single byte received from the uart out of the uart. I am enabling an interrupt on every byte received from uart.

My code is quite simple.

uint8_t Rx_data[5]; 

//Interrupt callback routine
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    if (huart->Instance == USART1)  //current UART
    {
        HAL_UART_Transmit(&huart1, &Rx_data[0], 1, 100);        
        HAL_UART_Receive_IT(&huart1, Rx_data, 1);   //activate UART receive interrupt every time on receiving 1 byte
    }
}

My PC transmits ASCII 12345678 to stm32. If things work as expected, the PC should be receiving 12345678 back. However, the PC receives 1357 instead. What is wrong with the code?

guagay_wk
  • 26,337
  • 54
  • 186
  • 295
  • I think you miss char while HAL reinit USART IRQ. Try to significantly decrease USART baudrate by power of 2. If problem will disappear so don't use HAL for desired MCU clock frequency and USART baudrate or change some of this clocks. – imbearr May 18 '16 at 14:28
  • Even with perfectly efficient code, it may not be possible to echo every character received. Baud rates are derived from the transmitter's clock, which can have error, and the division can also be inexact. Receivers typically oversample and so can tolerate data that arrives a little fast or slow. But data that arrives fast will generate words at a faster rate than the transmit half of the UART can repeate. In that case, sooner or later, if there are no pauses in the inflow, you will drop words - or if you have a multi-word buffer, you will start to fill it up and overflow it. – Chris Stratton Aug 05 '16 at 18:50

3 Answers3

6

Reenabling interrupts may be inefficient. With a couple of modifications it is possible to keep the interrupt active without needing to write the handler all over again. See the example below altered from the stm32cubemx generator.

/**
* @brief This function handles USART3 to USART6 global interrupts.
*/
void USART3_6_IRQHandler(void)
{
  InterruptGPS(&huart5);
}

void InterruptGPS(UART_HandleTypeDef *huart) {
    uint8_t rbyte;
    if (huart->Instance != USART5) {
        return;
    }
    /* UART in mode Receiver ---------------------------------------------------*/
    if((__HAL_UART_GET_IT(huart, UART_IT_RXNE) == RESET) || (__HAL_UART_GET_IT_SOURCE(huart, UART_IT_RXNE) == RESET)) {
        return;
    }
    rbyte = (uint8_t)(huart->Instance->RDR & (uint8_t)0xff);
    __HAL_UART_SEND_REQ(huart, UART_RXDATA_FLUSH_REQUEST);

    // do your stuff

}

static void init_gps() {
    __HAL_UART_ENABLE_IT(&huart5, UART_IT_RXNE);
}
Paulo Soares
  • 1,896
  • 8
  • 21
  • 19
  • Also there possible to use such solution without alter stm32cubemx generated code. I just add my code inside `/*USER CODE BEGIN irq name */` comments and add `return` after my code - so default HAL's handler never be executed. More over it ignored by compiler because it have no `static` keyword. – imbearr May 19 '16 at 12:52
  • where from the init_gps() static function come in ... is it required for any other purpose ?? – Aloy A Sen Mar 23 '17 at 10:36
  • init_gps() enables the interrupt to the uart5, it should be called at the start of main(). – Paulo Soares Mar 23 '17 at 15:14
2

You should make a tx array buffer as well, and use interrupt for writing as well (The first write if not enabled yet, should be sent immediately).

There should be examples of this for STM32 around.

Stian Skjelstad
  • 2,277
  • 1
  • 9
  • 19
  • Sorry, I do not quite catch it. Why is an interrupt for writing required? I test the code using HAL_UART_Transmit() which doesn't use interrupt and it works perfectly fine based on answer from wk_sg. – guagay_wk May 19 '16 at 13:46
  • Then you can receive and transmit without worrying about buffer overruns that happens if waiting for write inside read, and the other way around – Stian Skjelstad May 19 '16 at 15:40
  • Actually, no, this will not free you from worrying about overruns. – Chris Stratton Aug 05 '16 at 18:49
1

You should probably switch the two lines: Transmit and Receive. The Transmit function waits for a timeout to send the character, in meantime the next received character is missed.

veeman
  • 780
  • 1
  • 8
  • 17