Serial communication based on interrupt/DMA mode

1. Introduction to serial port interrupts
1. Serial port sending/receiving function
HAL_UART_Transmit(); Serial port sends data, using timeout management mechanism
HAL_UART_Receive(); The serial port receives data and uses the timeout management mechanism
HAL_UART_Transmit_IT(); Serial port interrupt mode transmission
HAL_UART_Receive_IT(); Serial port interrupt mode reception
HAL_UART_Transmit_DMA(); Serial port DMA mode transmission
HAL_UART_Transmit_DMA(); Serial port DMA mode reception

2. Serial port interrupt function
HAL_UART_IRQHandler(UART_HandleTypeDef *huart); //Serial port interrupt processing function
HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart); //Serial port transmission interrupt callback function
HAL_UART_TxHalfCpltCallback(UART_HandleTypeDef *huart); //The serial port sends half of the interrupt callback function (less used)
HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart); //Serial port reception interrupt callback function
HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart);//The serial port receives half of the callback function (less used)
HAL_UART_ErrorCallback(); Serial port receiving error function

3. Serial port query function
HAL_UART_GetState(); Determine whether UART reception is completed or whether sending data is busy

2. Task requirements: Use interrupt mode and DMA mode to complete the following tasks:
The STM32 system continuously sends “hello windows!” to the host computer (win10); when the host computer sends the character “stop” to stm32, stm32 pauses sending “hello windows!”; after sending a character “start”, stm32 continues to send;
2. Project establishment
(1) In the main interface of STMCubeMX, create a new project and click ACCEE TO MCU SELECTOR

(2) Select your own chip in the part name (generally choose to directly search for the required chip). This article uses STM32F103C8T6. Click on the specific chip information in the information bar to select it, and click start project

(3) Set RRC, set high-speed external clock HSE, and select external clock source

(4) Set up the serial port

Clock settings:

Code writing:

#include “main.h”
#include “dma.h”
#include “usart.h”
#include “gpio.h”

void SystemClock_Config(void);
uint8_t flag=1;
uint8_t rx_buf[6];//array for receiving serial port data storage
int strEqual(char rcData[6],char rcData2[6])
{
for(uint8_t i = 0 ; i < 6 ; i + + ){
if (rcData[i] != rcData2[i]) return 0;
}
return 1;
}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
//When the input command is “stop!”, send a prompt and change flag=0
if(strEqual(rx_buf,”stop!”))
{
flag=0;
}

//When the input command is "start", send a prompt and change flag=1
else if(strEqual(rx_buf,"start"))
{
flag=1;
}
HAL_UART_Receive_DMA( & amp;huart1,(uint8_t*)rx_buf,5);

}
int main(void)
{
HAL_Init();
uint8_t message[] = “hello windows!\\
”; //Define the data sending array
SystemClock_Config();
MX_GPIO_Init();
MX_DMA_Init();
MX_USART1_UART_Init();
HAL_UART_Receive_DMA( & amp;huart1,(uint8_t*)rx_buf,5);//Set the data received by DMA to be stored in rx_buf
while (1)
{
if(flag==1)
{
HAL_UART_Transmit_DMA( & amp;huart1, (uint8_t *)message, sizeof(message));
HAL_Delay(600);
}
}
}

void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Initializes the RCC Oscillators according to the specified parameters

  • in the RCC_OscInitTypeDef structure.
    /
    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
    RCC_OscInitStruct.HSIState = RCC_HSI_ON;
    RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
    RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
    if (HAL_RCC_OscConfig( & amp;RCC_OscInitStruct) != HAL_OK)
    {
    Error_Handler();
    }
    /
    * Initializes the CPU, AHB and APB buses clocks
    */
    RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
    |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
    RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
    RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
    RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
    RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
    if (HAL_RCC_ClockConfig( & amp;RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
    {
    Error_Handler();
    }
    }

void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug /
/
User can add his own implementation to report the HAL error return state /
__disable_irq();
while (1)
{
}
/
USER CODE END Error_Handler_Debug /
}
#ifdef USE_FULL_ASSERT
/
*

  • @brief Reports the name of the source file and the source line number
  •  where the assert_param error has occurred.
    
  • @param file: pointer to the source file name
  • @param line: assert_param error line source number
  • @retval None
    */
    void assert_failed(uint8_t file, uint32_t line)
    {
    /
    USER CODE BEGIN 6 /
    /
    User can add his own implementation to report the file name and line number,
    ex: printf(“Wrong parameters value: file %s on line %d\r\\
    ”, file, line) /
    /
    USER CODE END 6 /
    }
    #endif /
    USE_FULL_ASSERT */


3. Burning results:

4. DMA serial communication
(1) Set RRC

(2) Set the serial port USART1 and check whether the baud rate and other settings are correct.

!](https://img-blog.csdnimg.cn/0a407d7fe17e41179ebde93e4b47dcee.png)
(3) Enable interrupt selection


(4) DMA settings

5) Click on the two channels respectively to check whether the mode setting is Normal and whether Memory on the right is selected.
6) Clock settings

2. Code writing
main function:
Test Results: