STM32CubeMx——串口使用空闲中断和DMA收发数据
一、Cube设置
1、设置时钟和调试方式:

2、设置串口1:

3、在DMA Setting里点击Add添加USART1_TX,Mode有两种模式,一种是普通模式,使用一次发送语句就发一次,另一种是循环模式,使用一次发送会一直发送。这里发送我选择普通模式,接收选择循环模式。


4、在中断设置里打开串口1的中断:

二、代码编写
1、初始化打开空闲中断和DMA接收:
volatile uint8_t rx_len=0;
volatile uint8_t recv_end_flag=0;
uint8_t rx_buffer[200];
static void MX_USART1_UART_Init(void)
{
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(__FILE__, __LINE__);
}
//上面的usart配置代码为cubemx自动生成的,在下方添加使能idle中断和打开串口DMA接收语句
__HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);//使能idle中断
HAL_UART_Receive_DMA(&huart1,rx_buffer,BUFFER_SIZE);//打开DMA接收,数据存入rx_buffer数组中。
}
2、修改串口中断函数:
void USART1_IRQHandler(void)
{
uint32_t tmp_flag = 0;
uint32_t temp;
tmp_flag =__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE); //获取IDLE标志位
if((tmp_flag != RESET))//idle标志被置位
{
__HAL_UART_CLEAR_IDLEFLAG(&huart1);//清除标志位
temp = huart1.Instance->SR; //清除状态寄存器SR,读取SR寄存器可以实现清除SR寄存器的功能
temp = huart1.Instance->DR; //读取数据寄存器中的数据
HAL_UART_DMAStop(&huart1); //
temp = hdma_usart1_rx.Instance->NDTR;// 获取DMA中未传输的数据个数,NDTR寄存器分析见下面
rx_len = BUFFER_SIZE - temp; //总计数减去未传输的数据个数,得到已经接收的数据个数
recv_end_flag = 1; // 接受完成标志位置1
}
HAL_UART_IRQHandler(&huart1);
}
3、主函数中串口中断的处理函数:
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_DMA_Init();
MX_USART1_UART_Init();
while (1)
{
if(recv_end_flag ==1)
{
printf("rx_len=%d\r\n",rx_len);//打印接收长度
HAL_UART_Transmit(&huart1,rx_buffer, rx_len,200);接收数据打印出来
for(uint8_t i=0;i<rx_len;i++)
{
rx_buffer[i]=0;//清接收缓存
}
rx_len=0;//清除计数
recv_end_flag=0;//清除接收结束标志位
}
HAL_UART_Receive_DMA(&huart1,rx_buffer,BUFFER_SIZE);//重新打开DMA接收
}
}

浙公网安备 33010602011771号