cancel
Showing results for 
Search instead for 
Did you mean: 

How can I use UART manually, without HAL_UART_***() functions?

Louie88
Associate III

NUCLEO-H723ZG dev. kit.

I need take over the full control of the USARTx. I need a TX interrupt and the RX interrupt handled manually independently the HAL_UART_*** functions. The HAL_UART_Receive_IT() and the HAL_UART_Transmit_IT() is useless for me.

During initialization I need to enable the receiver. When one byte is received then I need an interrupt and I will store the received bytes in the RXBuffer. The main() loop periodically checks the received bytes. If it finds a complete message in the RXBuffer[] then it processes the message, then creates the answer into the TXBuffer[], enables the TX interrupt and sends back answer.

To do this I need a TX interrupt when the TX buffer becomes empty. I simply send the next byte. When I get the TX buffer empty interrupt and I have no more bytes to send I disable the TX interrupt, clear the RXBuffer and re-enable the RX interrupt. 

I am sure it is possible to do with STM32H723ZG MCU but I could not find such an example. How can I do this? Thanks for your help.

Louis

1 ACCEPTED SOLUTION

Accepted Solutions

At a register level the Reference Manual has the detail, the source to the libraries is also available.

For the L0 for example I have this

void USART2_IRQHandler(void)
{
  uint32_t isr = USART2->ISR;
 
  if (isr & USART_ISR_RXNE) // Received character?
  {
    uint16_t Data = USART2->RDR;
 
    Fifo_Insert(FifoIn2, 1, (void *)&Data);
  }
 
  if (isr & (USART_ISR_ORE | USART_ISR_NE | USART_ISR_FE)) // Pending Errors
  {
    if (isr & USART_ISR_ORE)
      USART2->ICR = USART_ICR_ORECF;
 
    if (isr & USART_ISR_NE)
      USART2->ICR = USART_ICR_NCF;
 
    if (isr & USART_ISR_FE)
      USART2->ICR = USART_ICR_FECF;
  }
 
  if (isr & USART_ISR_TXE) // Transmit empty
  {
    uint32_t Used = Fifo_Used(FifoOut2);
 
    if (Used)
    {
      uint16_t Data = 0;
 
      if (Fifo_Extract(FifoOut2, 1, (void *)&Data))
        USART2->TDR = Data;
 
      if (Used > 1)
        USART2->CR1 |= USART_CR1_TXEIE;
      else
        USART2->CR1 &= ~USART_CR1_TXEIE; // Disable as empty
    }
    else
      USART2->CR1 &= ~USART_CR1_TXEIE; // Disable as empty
  }
}

When pushing data into the output FIFO you enable the TXE interrupt, and it will fire immediately. You disable it so it doesn't saturate/loop with interrupts when there's not data available to push into the TDR

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

View solution in original post

2 REPLIES 2

At a register level the Reference Manual has the detail, the source to the libraries is also available.

For the L0 for example I have this

void USART2_IRQHandler(void)
{
  uint32_t isr = USART2->ISR;
 
  if (isr & USART_ISR_RXNE) // Received character?
  {
    uint16_t Data = USART2->RDR;
 
    Fifo_Insert(FifoIn2, 1, (void *)&Data);
  }
 
  if (isr & (USART_ISR_ORE | USART_ISR_NE | USART_ISR_FE)) // Pending Errors
  {
    if (isr & USART_ISR_ORE)
      USART2->ICR = USART_ICR_ORECF;
 
    if (isr & USART_ISR_NE)
      USART2->ICR = USART_ICR_NCF;
 
    if (isr & USART_ISR_FE)
      USART2->ICR = USART_ICR_FECF;
  }
 
  if (isr & USART_ISR_TXE) // Transmit empty
  {
    uint32_t Used = Fifo_Used(FifoOut2);
 
    if (Used)
    {
      uint16_t Data = 0;
 
      if (Fifo_Extract(FifoOut2, 1, (void *)&Data))
        USART2->TDR = Data;
 
      if (Used > 1)
        USART2->CR1 |= USART_CR1_TXEIE;
      else
        USART2->CR1 &= ~USART_CR1_TXEIE; // Disable as empty
    }
    else
      USART2->CR1 &= ~USART_CR1_TXEIE; // Disable as empty
  }
}

When pushing data into the output FIFO you enable the TXE interrupt, and it will fire immediately. You disable it so it doesn't saturate/loop with interrupts when there's not data available to push into the TDR

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Louie88
Associate III

Dear Tesla DeLorean,

Excellent, thank you!

Best regards,

Louis