UART receiving 3 bytes using STM32cubeMX libraries

Thread Starter

zazas321

Joined Nov 29, 2015
432
Hey. Is anyone here familliar with stm32cubeMX generated libraries for USART? I am working with MIDI data and just need to receive MIDI messages send from a MIDI keyboard that is connected to a microcontroller through USART using simmilar hardware just changed to +3.3V:



Everytime the keyboard button is pressed, I am expecting to receive 3 bytes of data:

C:
__IO ITStatus UartReady = RESET;

void READ_3_BYTES(){

UART_HandleTypeDef huart1;
uint8_t byte[3];

int i = 1
//Buffer used for reception
uint8_t aRxBuffer[16];

  if(HAL_UART_Receive_IT(&huart1, (uint8_t *)aRxBuffer, sizeof(RXBUFFERSIZE) != HAL_OK)
  {
    Error_Handler();
  }
  if(aRxBuffer && 0xff) == channel_number){
    //valid MIDI
    while(i<3)
    {
    byte[i++]=aRxBuffer;
    }
   }
  /*##-3- Wait for the end of the transfer ###################################*/ 
    while (UartReady != SET)
    {

    }

  /* Reset transmission flag */
  UartReady = RESET;
  }



void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart1)
{
  /* Set transmission flag: transfer complete */
  UartReady = SET;


}


I am struggling to understand how to properly write a code to receive 3 bytes of data. I have written the code above, would that work? I dont have the hardware yet so I cannot test it yet.
 
Last edited:

bertus

Joined Apr 5, 2008
20,051
Hello,

What speed for the UART is set?

MIDI messages are made up of 8-bit words (commonly called bytes) that are transmitted serially at a rate of 31.25 kbit/s. This rate was chosen because it is an exact division of 1 MHz, the operational speed of many early microprocessors.[10]:286 The first bit of each word identifies whether the word is a status byte or a data byte, and is followed by seven bits of information.[2]:13–14 A start bit and a stop bit are added to each byte for framing purposes, so a MIDI byte requires ten bits for transmission.[10]:286

https://en.wikipedia.org/wiki/MIDI

Bertus
 

Thread Starter

zazas321

Joined Nov 29, 2015
432
The baud rate was currently set to 9600, but chaning that is not a problem as the library handles everything. My concern is reading the MIDI data using the USART interrupt mode. As far as I understand, the receive interrupt is triggered every one byte, therefore assuming that typical MIDI message contains 3 bytes of data, I would need to build a loop and store the data in the buffer 3 times as I have attempted to do in my function.

I am also not 100% sure how does the stm32cubeMX generated library handles the start and stop bit and how does it acknowledge when to start receiving data bytes.

If a typical midi byte requires 10 bits, does that mean that I cannot receive a message using a uint8_t variable?
 

bertus

Joined Apr 5, 2008
20,051
Hello,

When the baudrate is not correct, you will read garbage.

Bertus
 

Thread Starter

zazas321

Joined Nov 29, 2015
432
Please ignore the baudrate for now. It is set to 31250 now but as I said - I dont hardware to test anything.
 

MrChips

Joined Oct 2, 2009
19,274
STM32CubeMX generates code to initialize MCU modules, not to handle UART transmission.

Do you have access to an oscilloscope?
 

Thread Starter

zazas321

Joined Nov 29, 2015
432
Yes. I have an access to oscilloscope. I have been digging into the STM32cubeMX generated UART functions such as :

C:
static HAL_StatusTypeDef UART_Receive_IT(UART_HandleTypeDef *huart)
{
  uint16_t *tmp;

  /* Check that a Rx process is ongoing */
  if (huart->RxState == HAL_UART_STATE_BUSY_RX)
  {
    if (huart->Init.WordLength == UART_WORDLENGTH_9B)
    {
      tmp = (uint16_t *) huart->pRxBuffPtr;
      if (huart->Init.Parity == UART_PARITY_NONE)
      {
        *tmp = (uint16_t)(huart->Instance->DR & (uint16_t)0x01FF);
        huart->pRxBuffPtr += 2U;
      }
      else
      {
        *tmp = (uint16_t)(huart->Instance->DR & (uint16_t)0x00FF);
        huart->pRxBuffPtr += 1U;
      }
    }
    else
    {
      if (huart->Init.Parity == UART_PARITY_NONE)
      {
        *huart->pRxBuffPtr++ = (uint8_t)(huart->Instance->DR & (uint8_t)0x00FF);
      }
      else
      {
        *huart->pRxBuffPtr++ = (uint8_t)(huart->Instance->DR & (uint8_t)0x007F);
      }
    }

    if (--huart->RxXferCount == 0U)
    {
      /* Disable the UART Data Register not empty Interrupt */
      __HAL_UART_DISABLE_IT(huart, UART_IT_RXNE);

      /* Disable the UART Parity Error Interrupt */
      __HAL_UART_DISABLE_IT(huart, UART_IT_PE);

      /* Disable the UART Error Interrupt: (Frame error, noise error, overrun error) */
      __HAL_UART_DISABLE_IT(huart, UART_IT_ERR);

      /* Rx process is completed, restore huart->RxState to Ready */
      huart->RxState = HAL_UART_STATE_READY;

#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
      /*Call registered Rx complete callback*/
      huart->RxCpltCallback(huart);
#else
      /*Call legacy weak Rx complete callback*/
      HAL_UART_RxCpltCallback(huart);
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */

      return HAL_OK;
    }
    return HAL_OK;
  }
  else
  {
    return HAL_BUSY;
  }
}


And another function:

C:
HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
{
  /* Check that a Rx process is not already ongoing */
  if (huart->RxState == HAL_UART_STATE_READY)
  {
    if ((pData == NULL) || (Size == 0U))
    {
      return HAL_ERROR;
    }

    /* Process Locked */
    __HAL_LOCK(huart);

    huart->pRxBuffPtr = pData;
    huart->RxXferSize = Size;
    huart->RxXferCount = Size;

    huart->ErrorCode = HAL_UART_ERROR_NONE;
    huart->RxState = HAL_UART_STATE_BUSY_RX;

    /* Process Unlocked */
    __HAL_UNLOCK(huart);

    /* Enable the UART Parity Error Interrupt */
    __HAL_UART_ENABLE_IT(huart, UART_IT_PE);

    /* Enable the UART Error Interrupt: (Frame error, noise error, overrun error) */
    __HAL_UART_ENABLE_IT(huart, UART_IT_ERR);

    /* Enable the UART Data Register not empty Interrupt */
    __HAL_UART_ENABLE_IT(huart, UART_IT_RXNE);

    return HAL_OK;
  }
  else
  {
    return HAL_BUSY;
  }
}

The library suggest to use the HAL functions, however, the HAL receive function itself does not shift the data bits from the data register to receive buffer - UART_Receive_IT does. My guess is that by calling the HAL_UART_Receive_IT, the UART_Receive_IT function is somehow automatically executed. From what I understand, after the UART initialization, I can just call the receive functions with the correct variables(Usart handle , receive buffer and size) and I should be able to get the UART data.
 

MrChips

Joined Oct 2, 2009
19,274
The first step would be to confirm that the UART transmitter is working properly.

Start off by writing the shortest program to send the letter "U" continuously with a short delay (20ms) in between characters. Confirm the proper transmission and baud on the oscilloscope.
 

Thread Starter

zazas321

Joined Nov 29, 2015
432
Thanks for your replies. I will test uart transmission as soon as I get PCB - should be monday..
 
Top