stm32串口数据中断接收(DMA、IDLE中断)
对于stm32串口程序的编写,最好的方式还是看寄存器手册,了解寄存器的配置。对于常规的一些应用,自己设置了个模板,在此记录下来。因个人习惯,本人不喜欢在串口收发数据中定义特殊字段,如结束字符,故,串口数据接收完成均由IDLE中断实现。
一、基于HAL库的串口1的DMA中断接收
1、环境配置:
工程模板直接使用cubMax导出的keil工程,对dma.c中内容不做更改,保留函数:
void MX_DMA_Init(void)
{
/* DMA controller clock enable */
/* DMA interrupt init */
/* DMA2_Stream5_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA2_Stream5_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA2_Stream5_IRQn);
/* DMA2_Stream7_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA2_Stream7_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA2_Stream7_IRQn);
}
2、串口相关配置代码如下:
UART_HandleTypeDef huart1;
DMA_HandleTypeDef hdma_usart1_rx;
DMA_HandleTypeDef hdma_usart1_tx;
uint8_t get_data=0;
uint8_t rx_buffer[USART_REC_LEN];
/* USART1 init function */
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_MultiProcessor_Init(&huart1, 0, UART_WAKEUPMETHOD_IDLELINE) != HAL_OK)
{
Error_Handler();
}
__HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE);
__HAL_UART_ENABLE_IT(&huart1,UART_IT_RXNE);
__HAL_UART_CLEAR_FLAG(&huart1,UART_IT_IDLE);
// __HAL_UART_ENABLE_IT(&huart1,UART_IT_TXE);
}
void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(uartHandle->Instance==USART1)
{
__HAL_RCC_USART1_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/**USART1 GPIO Configuration
PA9 ------> USART1_TX
PA10 ------> USART1_RX
*/
GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* USART1 DMA Init */
__HAL_RCC_DMA2_CLK_ENABLE();
/* USART1_RX Init */
hdma_usart1_rx.Instance = DMA2_Stream5;
hdma_usart1_rx.Init.Channel = DMA_CHANNEL_4;
hdma_usart1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_usart1_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_usart1_rx.Init.MemInc = DMA_MINC_ENABLE;
hdma_usart1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_usart1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_usart1_rx.Init.Mode = DMA_NORMAL;
hdma_usart1_rx.Init.Priority = DMA_PRIORITY_MEDIUM;
hdma_usart1_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
hdma_usart1_rx.Init.FIFOThreshold=DMA_FIFO_THRESHOLD_FULL;
hdma_usart1_rx.Init.MemBurst=DMA_MBURST_SINGLE; //?????????
hdma_usart1_rx.Init.PeriphBurst=DMA_PBURST_SINGLE; //????????
HAL_DMA_DeInit(&hdma_usart1_rx);
if (HAL_DMA_Init(&hdma_usart1_rx) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(uartHandle,hdmarx,hdma_usart1_rx);
hdma_usart1_tx.Instance = DMA2_Stream7;
hdma_usart1_tx.Init.Channel = DMA_CHANNEL_4;
hdma_usart1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_usart1_tx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_usart1_tx.Init.MemInc = DMA_MINC_ENABLE;
hdma_usart1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_usart1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_usart1_tx.Init.Mode = DMA_NORMAL;
hdma_usart1_tx.Init.Priority = DMA_PRIORITY_LOW;
hdma_usart1_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
if (HAL_DMA_Init(&hdma_usart1_tx) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(uartHandle,hdmatx,hdma_usart1_tx);
HAL_NVIC_SetPriority(USART1_IRQn, 2, 2);
HAL_NVIC_EnableIRQ(USART1_IRQn);
__HAL_DMA_ENABLE_IT(&hdma_usart1_tx,DMA_IT_TC);
HAL_NVIC_SetPriority(DMA2_Stream7_IRQn , 0, 1);
HAL_NVIC_EnableIRQ(DMA2_Stream7_IRQn );
__HAL_DMA_ENABLE_IT(&hdma_usart1_rx,DMA_IT_TC);
HAL_NVIC_SetPriority(DMA2_Stream5_IRQn , 0, 1);
HAL_NVIC_EnableIRQ(DMA2_Stream5_IRQn);
HAL_UART_Receive_DMA(&huart1,rx_buffer,256);
}
}
void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle)
{
if(uartHandle->Instance==USART1)
{
/* Peripheral clock disable */
__HAL_RCC_USART1_CLK_DISABLE();
/**USART1 GPIO Configuration
PA9 ------> USART1_TX
PA10 ------> USART1_RX
*/
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10);
HAL_DMA_DeInit(uartHandle->hdmarx);
HAL_DMA_DeInit(uartHandle->hdmatx);
HAL_NVIC_DisableIRQ(USART1_IRQn);
}
}
void USART1_IRQHandler(void)
{
// HAL_UART_IRQHandler(&huart1); //??HAL?????????
if(__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE)!=RESET) //??IDLE???
{
__HAL_UART_CLEAR_IDLEFLAG(&huart1);
HAL_UART_DMAStopRx(&huart1);
//------------------------------------------------------------------------------------
get_data=USART_REC_LEN-__HAL_DMA_GET_COUNTER(&hdma_usart1_rx);
HAL_UART_Transmit_DMA(&huart1,(uint8_t*)rx_buffer,get_data);
//------------------------------------------------------------------------------------
HAL_UART_Receive_DMA(&huart1,(uint8_t*)rx_buffer,USART_REC_LEN); //??????
//------------------------------------------------------------------------------------
printf("dma Rx\r\n");
//------------------------------------------------------------------------------------
}
}
void DMA2_Stream7_IRQHandler(void)
{
if(__HAL_DMA_GET_FLAG(&hdma_usart1_tx,DMA_FLAG_TCIF3_7))//�ȴ�DMA2_Steam7�������
{
__HAL_DMA_CLEAR_FLAG(&hdma_usart1_tx,DMA_FLAG_TCIF3_7);//���DMA2_Steam7������ɱ�־
HAL_UART_DMAStopTx(&huart1); //��������Ժ�رմ���DMA
//------------------------------------------------------------------------------------
printf("dma Tx\r\n");
//------------------------------------------------------------------------------------
}
}
void DMA2_Stream5_IRQHandler(void)
{
printf("get data\r\n");
HAL_DMA_IRQHandler(&hdma_usart1_rx);
}
3、main函数内容如下:
int main(void)
{
uint8_t len,len_new;
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USART1_UART_Init();
HAL_UART_Receive_DMA(&huart1,rx_buffer,256);
while (1)
{
// HAL_UART_Transmit_DMA(&huart1,TEXT_TO_SEND,sizeof(TEXT_TO_SEND));//��������
// HAL_Delay(1000);
}
}
二、基于标准库的串口1的DMA中断接收
1、基本环境:基于原子代码修改
u8 ReceiveBuff[RECEIVE_BUF_SIZE]; //????
u8 SendBuff[SEND_BUF_SIZE]; //???????
u16 UART1_ReceiveSize = 0;
void uart_init(u32 bound)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
DMA_InitTypeDef DMA_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); //??GPIOA??
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//??USART1??
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2,ENABLE);//DMA2????
GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1); //GPIOA9???USART1
GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1); //GPIOA10???USART1
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10; //GPIOA9?GPIOA10
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//????
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //??50MHz
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //??????
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //??
GPIO_Init(GPIOA,&GPIO_InitStructure); //???PA9,PA10
//USART1 ?????
USART_InitStructure.USART_BaudRate = bound;//?????
USART_InitStructure.USART_WordLength = USART_WordLength_8b;//???8?????
USART_InitStructure.USART_StopBits = USART_StopBits_1;//?????
USART_InitStructure.USART_Parity = USART_Parity_No;//??????
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//????????
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //????
USART_Init(USART1, &USART_InitStructure); //?????1
USART_Cmd(USART1, ENABLE); //????1
//USART_ClearFlag(USART1, USART_FLAG_TC);
USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);//??????
//Usart1 NVIC ??
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;//??1????
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;//?????3
NVIC_InitStructure.NVIC_IRQChannelSubPriority =3; //????3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ????
NVIC_Init(&NVIC_InitStructure); //??????????VIC????
USART_DMACmd(USART1,USART_DMAReq_Tx,ENABLE); //????1?DMA??
USART_DMACmd(USART1,USART_DMAReq_Rx,ENABLE); //????1?DMA??
//****************************??UART1??
DMA_DeInit(DMA2_Stream7);
while (DMA_GetCmdStatus(DMA2_Stream7) != DISABLE);//??DMA???
/* ?? DMA Stream */
DMA_InitStructure.DMA_Channel = DMA_Channel_4; //????
DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&USART1->DR;//DMA????
DMA_InitStructure.DMA_Memory0BaseAddr = (u32)SendBuff;//DMA ???0??
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;//????????
DMA_InitStructure.DMA_BufferSize = SEND_BUF_SIZE;//?????
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//???????
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//???????
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//??????:8?
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;//???????:8?
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;// ??????
DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;//?????
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;//?????????
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;//????????
DMA_Init(DMA2_Stream7, &DMA_InitStructure);//???DMA Stream
//DMA NVIC
NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream7_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
DMA_ITConfig(DMA2_Stream7,DMA_IT_TC,ENABLE);
//****************************??UART1??
DMA_DeInit(DMA2_Stream5);
while (DMA_GetCmdStatus(DMA2_Stream5) != DISABLE);//??DMA???
/* ?? DMA Stream */
DMA_InitStructure.DMA_Channel = DMA_Channel_4; //????
DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&USART1->DR;//DMA????
DMA_InitStructure.DMA_Memory0BaseAddr = (u32)ReceiveBuff;//DMA ???0??
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory ;//????????
DMA_InitStructure.DMA_BufferSize = RECEIVE_BUF_SIZE;//?????
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//???????
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//???????
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//??????:8?
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;//???????:8?
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;// ??????
DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;//?????
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;//?????????
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;//????????
DMA_Init(DMA2_Stream5, &DMA_InitStructure);//???DMA Stream
//DMA NVIC
NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream5_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
DMA_Cmd(DMA2_Stream5, ENABLE); //??DMA??
DMA_ITConfig(DMA2_Stream5,DMA_IT_TC,ENABLE);
}
void DmaSendDataProc(DMA_Stream_TypeDef *DMA_Streamx,u16 ndtr)
{
DMA_Cmd(DMA_Streamx, DISABLE); //??DMA??
while (DMA_GetCmdStatus(DMA_Streamx) != DISABLE){} //??DMA?????
DMA_SetCurrDataCounter(DMA_Streamx,ndtr); //?????
DMA_Cmd(DMA_Streamx, ENABLE); //??DMA??
}
//��������ֱ��װ�뷢��buffer�У��˴�ֻ�Ǵ���DMA����
//��ο�USB����cdc����÷���Ϊд��buffer����ʽ��
void Uart1_DMATranmist(u16 nSendCount)
{
USART_DMACmd(USART1,USART_DMAReq_Tx,ENABLE); //ʹ�ܴ���1��DMA����
DmaSendDataProc(DMA2_Stream7,nSendCount); //????DMA??!
}
void DMA2_Stream7_IRQHandler(void)//DMA �����������
{
if(DMA_GetFlagStatus(DMA2_Stream7,DMA_FLAG_TCIF7)!=RESET)
{
DMA_ClearFlag(DMA2_Stream7,DMA_FLAG_TCIF7);//DMA ������������жϱ�־���
}
}
void DMA2_Stream5_IRQHandler(void)
{
if(DMA_GetFlagStatus(DMA2_Stream5,DMA_FLAG_TCIF5)!=RESET)//��������ж�
{
DMA_Cmd(DMA2_Stream5, DISABLE);
UART1_ReceiveSize =RECEIVE_BUF_SIZE - DMA_GetCurrDataCounter(DMA2_Stream5);//��ȡ�������ݵĴ�С
if(UART1_ReceiveSize !=0)
{
//�ڴ˴����ӽ������ݴ���
printf("get data=%s=%d\r\n",ReceiveBuff,UART1_ReceiveSize);
}
DMA_ClearFlag(DMA2_Stream5,DMA_FLAG_TCIF5 | DMA_FLAG_FEIF5 | DMA_FLAG_DMEIF5 | DMA_FLAG_TEIF5 | DMA_FLAG_HTIF5);//??DMA2_Steam7??????
DMA_SetCurrDataCounter(DMA2_Stream5, RECEIVE_BUF_SIZE);
DMA_Cmd(DMA2_Stream5, ENABLE);
}
}
void USART1_IRQHandler(void)
{
u16 data;
if(USART_GetITStatus(USART1,USART_IT_IDLE) != RESET)
{
DMA_Cmd(DMA2_Stream5, DISABLE); //??DMA,?????????
data = USART1->SR;
data = USART1->DR;
UART1_ReceiveSize =RECEIVE_BUF_SIZE - DMA_GetCurrDataCounter(DMA2_Stream5);
if(UART1_ReceiveSize !=0)
{
//�����������ݲ������˴�
//printf("hello=%s\r\n",ReceiveBuff);
}
DMA_ClearFlag(DMA2_Stream5,DMA_FLAG_TCIF5 | DMA_FLAG_FEIF5 | DMA_FLAG_DMEIF5 | DMA_FLAG_TEIF5 | DMA_FLAG_HTIF5);//??DMA2_Steam7??????
DMA_SetCurrDataCounter(DMA2_Stream5, RECEIVE_BUF_SIZE);
DMA_Cmd(DMA2_Stream5, ENABLE); //??DMA,
}
}
2、main函数:
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//����ϵͳ�ж����ȼ�����2
delay_init(168); //��ʱ��ʼ��
uart_init(115200); //���ڳ�ʼ��������Ϊ115200
j=sizeof(TEXT_TO_SEND);
for(i=0;i<SEND_BUF_SIZE;i++)//���ASCII�ַ�������
{
if(t>=j)//���뻻�з�
{
if(mask)
{
SendBuff[i]=0x0a;
t=0;
}else
{
SendBuff[i]=0x0d;
mask++;
}
}else//����TEXT_TO_SEND���
{
mask=0;
SendBuff[i]=TEXT_TO_SEND[t];
t++;
}
}
while(1)
{
//SendBytesInfoProc(SEND_BUF_SIZE);
delay_ms(3000);
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了