STM32 Note 01 How to use CubeMX to configure serial port interrupt to receive variable length data

Article directory

I. Introduction

  • The MCU used in the test is: STM32F103C8Tx
  • The CubeMX version used in the test is: 6.1

2. CubeMX configuration

1. [Serial port] configuration

2. Clock Configuration

3. Main code

1. Define the serial port control class in .h, and related macros

/* code begin define */ 
# define    USART_2_RECV_DATA_BUF_ROW_NUM 2   // Serial port 2 data receiving buffer row number. 
# define    USART_2_RECV_DATA_BUF_COL_NUM 10 // Serial port 2 data receiving buffer column number. 
/* code end define */

/* code begin data type */ 
typedef     struct 
{ 
    UART_HandleTypeDef* huart;       // serial port handle

    uint8_t indexForRecvDataBufRow; // The row index of the data receiving buffer.                                                   
    uint8_t indexForRecvDataBufCol; // Column index of data receiving buffer.   

    uint8_t recvDataBuf[USART_2_RECV_DATA_BUF_ROW_NUM][USART_2_RECV_DATA_BUF_COL_NUM]; // Data receiving buffer.

    void (*sendData)( uint8_t * data, uint16_t data_len); // Send data. 
    void (*recvDataInIntrrupt)( void );                   // Receive data in interrupt. This method needs to be placed in the USART2_IRQHandler function. 
    void (*processData)( void );                          // To process data, you need to fill in how to parse and process the data yourself. This method can be placed in a while loop or recvDataInIntrrupt.      
}objUsart2; // Serial port 2 control class. 
/* code end data type */

[2. Create a serial port control class object] in .c and declare the related methods to be implemented

/* code begin variable definition */
objUsart2 userUsart2;
/* code end variable definition */

/* code begin function statement */
void initUserUsart2(void);                                        
static void userUsart2_sendData(uint8_t* data, uint16_t data_len);
static void userUsart2_recvDataInIntrrupt(void);                
static void userUsart2_processData(void);                   
/* code end function statement */

3. Implement concrete methods in .c

/* code begin function body */
void initUserUsart2(void)
{
    userUser2.field = &field2;
    userUsart2.indexForRecvDataBufRow = 0;
    userUsart2.indexForRecvDataBufCol = 0;

    memset (userUsart2.recvDataBuf, 0 , USART_2_RECV_DATA_BUF_ROW_NUM * USART_2_RECV_DATA_BUF_COL_NUM);         // Clear the cache.

    userUsart2.sendData = userUsart2_sendData;
    userUsart2.recvDataInIntrrupt = userUsart2_recvDataInIntrrupt;
    userUsart2.processData        = userUsart2_processData;

  __HAL_UART_ENABLE_IT(userUsart2.huart, UART_IT_RXNE); // Enable receive interrupt. 
  __HAL_UART_ENABLE_IT(userUsart2.huart, UART_IT_IDLE); // Enable idle interrupt.
}
static void userUsart2_sendData(uint8_t* data, uint16_t data_len)
{
  HAL_UART_Transmit(userUsart2.huart, data, data_len, 0xff);
}
static  void  userUsart2_recvDataInIntrrupt ( void )
 {
     // Determine if there is still space in the cache. 
    if (userUsart2.indexForRecvDataBufRow < USART_2_RECV_DATA_BUF_ROW_NUM && userUsart2.indexForRecvDataBufCol < USART_2_RECV_DATA_BUF_COL_NUM)
    {   
        if (__HAL_UART_GET_FLAG(userUsart2.huart, UART_FLAG_RXNE) != RESET) // Determine whether the receive interrupt is triggered.
        {
            // Read a byte from the serial port register and save it to ch. Note that the following code must be placed in the receive interrupt. 
            uint8_t ch;
            HAL_UART_Receive(userUsart2.huart, &ch, 1, 1000);

            userUsart2.recvDataBuf[userUsart2.indexForRecvDataBufRow][userUsart2.indexForRecvDataBufCol++] = ch;

            __HAL_UART_CLEAR_FLAG(userUsart2.huart, UART_FLAG_RXNE);
        }

        if (__HAL_UART_GET_FLAG(userUsart2.huart, UART_FLAG_IDLE) != RESET) // Determine whether the idle interrupt is triggered.
    {
            userUsart2.indexForRecvDataBufRow++;
      userUsart2.indexForRecvDataBufCol = 0;

      __HAL_UART_CLEAR_IDLEFLAG(userUsart2.huart);
    }
    }
}
static  void  userUsart2_processData ( void )
 {
     if (userUsart2.indexForRecvDataBufRow > 0 ) // If there is data in the cache, process it.
    {
        uint8_t row = userUsart2.indexForRecvDataBufRow - 1;
        userUsart2.sendData(&userUsart2.recvDataBuf[row][0], USART_2_RECV_DATA_BUF_COL_NUM);

        memset(&userUsart2.recvDataBuf[row][0], 0, USART_2_RECV_DATA_BUF_COL_NUM);
        userUsart2.indexForRecvDataBufRow--;
    }
}
/* code end function body */

4. Declare the serial port control class object in .h, and the serial port initialization function

/* code begin variable statement */ 
extern objUsart2 userUsart2; // Serial port 2 control class object. 
/* code end variable statement */

/* code begin function statement */ 
void  initUserUsart2 ( void ) ; // Initial serial port 2. 
/* code end function statement */

Leave a Comment

Your email address will not be published. Required fields are marked *