STM32CubeMX Tutorial Series: USART
Abstract: This chapter illustrates three different program models, HAL library polling, interrupt and DMA with the example of serial communication.
Review
In serial communication, data is transmitted in characters, and each character is transmitted in bytes. It always starts from start bit and end with stop bit. Before the transmission, please make sure the host and the slave using the same baud rate. Commonly, there are two basic serial communication modes, synchronous communication and asynchronous communication. For asynchronous communication, the transmitted data should be in a format of startbit + data bit + paritybit + stop bit.
Redefine the function printf
Open a new project on STM32CubeMX, then select the chip STMF746IGT6 and High Speed Clock (HSE). Select USART1 as asynchronous communication mode. Set PA10 as RX, and PA9 as TX.
Clock configuration Configure the system clock as 216MHz. You can configure the USART clock dependently. The default value is108Mhz.
Serial configuration Set the baud rate to 115200 Bits/s, transmission data length to 8 Bit. Parity: None, Stop bit: 1. Other parameters are in default settings.
You can regenerate a new report and a new code, then compile the program. In the file usart.c, you can find the initialization function MX_USART1_UART_Init(void) and pin configuration functionHAL_UART_MspInit().
For the standard output functions of the standard library in C language, the default output device is displayer. You should redefine the output functions in the standard library to implement serial output or LCD output. For example, to output the function printf to serial port, you should direct the output of the function fputc to the serial port (redirect). It is easy to do so. Add a function int fputc(int ch, FILE *f) and make sure the serial port can output character.
Add the following lines behind the fileusart.c. The macro definition #ifdef has been added to the code for conditional compilation. If using GUNC compiler, PUTCHAR_PROTOTYPE should be defined as the function int__io_putchar(int ch), or else it should be defined as the functionint fputc(int ch, FILE *f).
/* USER CODE BEGIN 1 */ #ifdef __GNUC__ /* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf set to 'Yes') calls __io_putchar() */ #define PUTCHAR_PROTOTYPE int __io_putchar(int ch) #else #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f) #endif /* __GNUC__ */ /** * @brief Retargets the C library printf function to the USART. * @param None * @retval None */ PUTCHAR_PROTOTYPE { /* Place your implementation of fputc here */ /* e.g. write a character to the EVAL_COM1 and Loop until the end of transmission */ HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF); return ch; } /* USER CODE END 1 */
In which, the statement HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF) means transmitting a character via serial port 1. ch is the address for storing the character, 0xFFFF is the timeout period. In the file stm32f7xx_hal_uart.c, you can find the function HAL_UART_Transmit.
In the filemain.c, add application functions.
/* USER CODE BEGIN 2 */ printf("\n\r UART Printf Example: retarget the C library printf function to the UART\n\r"); /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ printf("\n\r welcome to www.waveshere.com !!!\n\r"); HAL_Delay(1000); } /* USER CODE END 3 */
Compile the program and download it to the development board. Connect the board to your PC with a USB cable, and run the serial assistant on the PC. Select the corresponding serial port number, and set the baud rate to 115200. Pressed the Reset button, you may receive the information as the figure shows below.
Open the header stm32f7xx_hal_uart.h. At the end of the file, you can find a serial function with the IO operationsshown below.
The TX/RX function of USART:
HAL_UART_Transmit(); data transmission under serial polling mode, using timeout management system. HAL_UART_Receive(); data reception under serial polling mode, using timeout management system. HAL_UART_Transmit_IT(); data transmission under serial interrupt mode HAL_UART_Receive_IT(); data reception under serial interrupt mode HAL_UART_Transmit_DMA(); data transmission under serial DMA mode HAL_UART_Receive_DMA(); data reception under serial DMA mode
Relative interrupt function of serial port: HAL_UART_TxHalfCpltCallback():When half data transmission (half transfer) is completed, it will be called by interrupt handle function. HAL_UART_TxCpltCallback(): When data transmission is finished, it will be called by interrupt handle function. HAL_UART_RxHalfCpltCallback(): When half data reception (half transfer) is completed, it will be called by interrupt handle function. HAL_UART_RxCpltCallback(): When data reception is finished, it will be called by interrupt handle function. HAL_UART_ErrorCallback():When there is error in the course of data transfer, When data transmission is finished, it will be called by interrupt handle function.
There are three communicationmodes for serial transmission, polling mode, interrupt control mode and DMA mode:
Polling mode: CPU continuallyqueries the IO device, and handles the requirement from the device. For example, CPU is querying the serial port whether the data transmission has finished. If transmission is over time, the timeout error will be returned. The polling is an inefficient method, because it may occupy CPU time.
Interrupt control mode: When the IO operation is finished, the IO device controller transmits an interrupt signal to the processor via the IRQ line. The processor receives the signal and switches to interrupt handle programto deal with the data transmission.
DMA: Direct memory accessallows data block to be transmitted between memory and IO device without CPU intermediate intervention.It only requires CPU send the data block transmission command to the device at the beginning and employs interrupt to judge whether the transmission is finished and whether the next operation is ready.
Interrupt mode
Open anew project on STM32CubeMX, and make the same configuration as the previous chapters presented. The only different is that serial interrupt is enable in this project.
You can regenerate a new report and a new code, then compile the program. Add two array variables before the main routine.
/* Private variables ---------------------------------------------------------*/ /* USER CODE BEGIN PV */ /* Private variables ---------------------------------------------------------*/ uint8_t aTxStartMessage[] = "\r\n****UART-Hyperterminal communication based on IT ****\r\nEnter 10 characters using keyboard :\r\n"; /* Buffer used for reception */ uint8_t aRxBuffer[20]; /* USER CODE END PV */
Add two lines in the main routine,to transmit and receive the data of the array aTxStartMessage (10 characters in total) and save the data to the array aRxBuffer by serial interrupt.
/* USER CODE BEGIN 2 */ HAL_UART_Transmit_IT(&huart1, (uint8_t *)aTxStartMessage, sizeof(aTxStartMessage)); HAL_UART_Receive_IT(&huart1, (uint8_t *)aRxBuffer, 10); /* USER CODE END 2 */
Add interrupt received callback function behind the file main.c. In this function, the received data will be returned via the serial interface.
/* USER CODE BEGIN 4 */ /** * @brief Rx Transfer completed callbacks * @param huart: uart handle * @retval None */ void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { /* Prevent unused argument(s) compilation warning */ UNUSED(huart); /* NOTE : This function should not be modified, when the callback is needed, the HAL_UART_RxCpltCallback can be implemented in the user file */ HAL_UART_Transmit(&huart1, (uint8_t *)aRxBuffer, 10,0xFFFF); } /* USER CODE END 4 */
Compile the program and download it to the development board. Connect the development board to your PC via a USB cable, and run the serial debugging assistant on your PC. Select the corresponding serial port number, and set the baud rate to 115200. Pressing the reset button, you can receive the data of the array aTxStartMessage. When serial assistant has sent out 10 characters, it may display back the transmitted data.Notices: The interrupt event is triggered only when 10 character strings are sent out. In case of less than 10 characters, interrupt will not be triggered and no data will be displayed back in the serial assistant. For more than 10 characters transmitted, only 10 characters will be sent back for display.