STM32 serial port transceiver function application [HAL version]

Posted by hasin on Thu, 23 Dec 2021 01:43:59 +0100

STM32 serial port data transceiver foundation - blocking and non blocking application understanding [HAL version]

Send data to serial port

  1. Blocking transmission (recommended)

    Features: the program command sending service starts sending, and will accompany the sending service until all bytes are sent at one time. Or the timeout limit is reached before the program will leave and continue to execute. Relatively speaking, this will take up too much program time and affect the system performance.

    • 1.API prototype
      HAL_UART_Transmit(UART_HandleTypeDef *huart, //Pointer to handle (address value of handle)
                        uint8_t *pData,  //u8 pointer
                        uint16_t Size,  //u16
                        uint32_t Timeout);//u32
      
      //----*huart: which serial port (address of peripheral handle) 
      //----*pData: address to send the content (to the cache of the content)
      //----Size: how many bytes need to be sent
      //----Timeout: timeout
      
      2. Application examples
      HAL_UART_Transmit(&huart1, (uint8_t *)"Hello\r\n", 7, 0xFFFF);  
      //Send "Hell0\r\n" to serial port 1. After sending 7 bytes or reaching the timeout of 0xFFFF, exit the sending and the program will run down. 
      
Remarks and thoughts:

1. How to understand Handle?

Handle type, which is similar to an "instance" of a structure object; (an instance of a "structure object"); everything is an object;

2. Why do I need timeout?

A: due to the blocking transmission, once the data transmission is wrong, based on the blocking characteristics, the program will be blocked here all the time, affecting the subsequent programs.
Setting the concept of timeout is equivalent to limiting the maximum allowable running time of the program.

3. How much overtime should I give?

A: in the absence of special performance requirements, the maximum 0xFFFF is generally enough.

2. Non blocking transmission (interrupted) (recommended)

  • **Process: * * the program command sending service starts sending, and the timeout time does not need to be considered. Then the program doesn't have to pay much attention and directly continues to do its own business. Only after all bytes are sent, Size bytes are sent, or half of the sending is completed (different API s and different Size parameters), it will come back to execute the interrupt callback function.)

  • Features: during the sending service of Size bytes, the program can continue to do its own things without stopping in place. In this way, there is no need to delay the time of the program, and the task execution of the system is smoother. Although this period of time is very small, once a lot of services are sent, the combined time will have a great impact on an ordinary system!!

  • 1.API prototype
    //Non blocking send function
    ~ HAL_UART_Transmit_IT(UART_HandleTypeDef *huart,
                      uint8_t *pData,
                      uint16_t Size);
    //Size interrupt after sending bytes
    void HAL_UART_TxCpItCallback(UART_HandleTypeDeef *huart); 
    
Remarks and thoughts:
1. HAL_UART_TxCpItCallback disassembly memory?
  • Tx: send;
  • Cp: Complete;
  • It: interrupt;
  • Callback: callback;

3. Illustrate the application of serial port sending function

  • Use the non blocking serial port sending function to send the cached value data_ The first five data in TX are sent to USART1. After the data transmission is completed, the output level of PB9 is reversed.
1. Declare cache values data_Rx
    ...
2. Call non blocking serial port sending function
    HAL_UART_Transmit_IT(&huart1, data_Tx, 5); //Size = 5 (i.e. the first 5 data in the value data_Tx)
3. Write the callback after sending the first 5 bytes
void HAL_UART_TxCpItCallback(UART_HandleTypeDeef *huart)
{
    if(huart -> instance) == USART1 //If there are multiple serial ports, you can use this statement to ensure that it is USART1
    {
        HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_9);
    }
}

Receive data from serial port

  1. Blocking receive function (highly deprecated)

    Reason for not recommending: the blocking function will block all the time, waiting for the data sent by the upper computer. Pay attention! And it is the data that meets the requirements of jumping out of blocking parameter conditions. Compared with normal data receiving requirements, this is unreasonable...

2. Non blocking receiving function (interrupt receiving) (recommended)

1.API prototype
//Non blocking send function
~ HAL_UART_Receive_IT(UART_HandleTypeDef *huart, //From which serial port (pointer to handle)
                  uint8_t *pData, //Where is the received data stored (address)
                  uint16_t Size); //How many bytes do you need to receive 
//Size is the interrupt callback after receiving bytes
void HAL_UART_RxCpItCallback(UART_HandleTypeDeef *huart);

3. Illustrate the application of serial port receiving function

  • Use the non blocking serial port receiving function to receive the first byte in UART1 and save it in data_ In Rx variable, after data reception, if the byte is 0x5a *, the output level of PB9 * * will be reversed.
1. statement data_Rx
    ...
2. Call non blocking serial port receiving function
    HAL_UART_Receive_IT(&huart1, &data_Tx, 1); //Size = 1 (that is, only the first byte of data sent is received)
3. Write a callback after all bytes are sent
void HAL_UART_RxCpItCallback(UART_HandleTypeDeef *huart)
{
    if(huart -> instance) == USART1 //If there are multiple serial ports, you can use this statement to ensure that it is USART1
    {
        if(data_Rx == 0x5a)
            HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_9);
    }
}

4. Pay attention to the difference in writing the second parameter between the non blocking serial port sending function and the receiving function?

  1. If you declare a variable to access data, fill in the address of the variable

    uint8_t data_Tx, data_Rx;
    HAL_UART_Transmit_IT(&huart1, &data_Tx, 5);
    HAL_UART_Receive_IT(&huart1, &data_Rx, 5);

  2. If you declare a value to access data, just write the value name itself.

    uint8_t arr_Tx[5], arr_Rx[5];
    HAL_UART_Transmit_IT(&huart1, arr_Tx, 5);
    HAL_UART_Receive_IT(&huart1, arr_Rx, 5);

Topics: Embedded system stm32