1、硬件电路
2、设置RCC,选择高速外部时钟HSE,时钟设置为180MHz
3、配置USART1引脚
4、生成工程配置
5、部分代码
/* USER CODE BEGIN 0 */
volatile uint8_t rx_len = 0; //接收一帧数据的长度
volatile uint8_t recv_end_flag = 0; //一帧数据接收完成标志
uint8_t rx_buffer[20]={0}; //接收数据缓存数组
uint8_t rx_buffer2[20]={0}; //接收数据缓存数组2
/* USER CODE END 0 */
void MX_USART1_UART_Init(void)
{
/* USER CODE BEGIN USART1_Init 0 */
/* USER CODE END USART1_Init 0 */
/* USER CODE BEGIN USART1_Init 1 */
/* USER CODE END USART1_Init 1 */
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN USART1_Init 2 */
__HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE); //使能串口空闲中断
HAL_UART_Receive_DMA(&huart1,rx_buffer,BUFFER_SIZE); //设置DMA传输,将串口1的数据搬运到rx_buffer中,每次BUFFER_SIZE个字节
/* USER CODE END USART1_Init 2 */
}
void USART1_IRQHandler(void)
{
/* USER CODE BEGIN USART1_IRQn 0 */
uint8_t temp_flag = 0; // 数据传输完成标志位
uint8_t temp; // DMA未传输的数据个数
temp_flag = __HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE); //获取串口1是否处于空闲状态
if (RESET != temp_flag)
{
memset(rx_buffer2, 0, BUFFER_SIZE);
__HAL_UART_CLEAR_IDLEFLAG(&huart1); // 清除空闲中断标志位
HAL_UART_DMAStop(&huart1); // 停止DMA传输
memcpy(rx_buffer2, rx_buffer, BUFFER_SIZE);
temp = __HAL_DMA_GET_COUNTER(&hdma_usart1_rx); //获取DMA传输期间剩余的数据量
rx_len = BUFFER_SIZE - temp; // 接收到的字节数
recv_end_flag = 1; // 置位接收完成标志位
}
/* USER CODE END USART1_IRQn 0 */
HAL_UART_IRQHandler(&huart1);
/* USER CODE BEGIN USART1_IRQn 1 */
/* USER CODE END USART1_IRQn 1 */
}
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
if (1 == recv_end_flag)
{
HAL_UART_Transmit(&huart1, rx_buffer2, rx_len, 0xffff);
printf("\r\n");
HAL_UART_Transmit_DMA(&huart1, rx_buffer2, rx_len); // 之前此函数(DMA模式)在执行时还没有发送完数据数据就被下面的memset函数清零了(CPU清零),所以增加一个二级缓存数组rx_buffer2用来打印数据
// 当DMA再次接收到数据触发中断进入中断服务函数时,把rx_buffer2数组清空,这样就能保证代码正常运行。
printf("\r\n");
rx_len = 0;
recv_end_flag = 0;
memset(rx_buffer, 0, BUFFER_SIZE);
}
HAL_UART_Receive_DMA(&huart1, rx_buffer, BUFFER_SIZE); // 设置DMA传输,将串口1的数据搬运到rx_buffer中,每次BUFFER_SIZE个字节
LED_TIME();
}
/* USER CODE END 3 */
6、实验现象