STM32串口空闲中断DMA的实现

7 篇文章 0 订阅
//**********************************************************
//结构体实例初始化
//**********************************************************
T_COMOptr COM1 ={
	 .isReFinish          = FALSE,
	 .renum               = 0,
	 .ComInit             = uart1_init,
	 .SendByte            = uart1_send,
	 .SendBuf             = uart1_sendbuf,
};

T_COMOptr COM2 ={
	 .isReFinish          = FALSE,
	 .renum               = 0,
	 .ComInit             = uart2_init,
	 .SendByte            = uart2_send,
	 .SendBuf             = uart2_sendbuf,
};

T_COMOptr COM3 ={
	 .isReFinish          = FALSE,
	 .renum               = 0,
	 .ComInit             = uart3_init,
	 .SendByte            = uart3_send,
	 .SendBuf             = uart3_sendbuf,
};

T_COMOptr COM4 ={
	 .isReFinish          = FALSE,
	 .renum               = 0,
	 .ComInit             = uart4_init,
	 .SendByte            = uart4_send,
	 .SendBuf             = uart4_sendbuf,
};
//**********************************************************
//UART句柄
//**********************************************************
UART_HandleTypeDef UART1_Handler; //UART句柄
DMA_HandleTypeDef  hdma_usart1_rx;

UART_HandleTypeDef UART2_Handler; //UART句柄
DMA_HandleTypeDef  hdma_usart2_rx;

UART_HandleTypeDef UART3_Handler; //UART句柄
DMA_HandleTypeDef  hdma_usart3_rx;

UART_HandleTypeDef UART4_Handler; //UART4句柄
DMA_HandleTypeDef  hdma_uart4_rx; 
//**********************************************************
//支持printf函数,而不需要选择use MicroLIB
//********************************************************** 
#if 1
#pragma import(__use_no_semihosting)             
//标准库需要的支持函数                 
struct __FILE 
{ 
	int handle; 

}; 

FILE __stdout;       
//定义_sys_exit()以避免使用半主机模式    
void _sys_exit(int x) 
{ 
	x = x; 
} 
//重定义fputc函数 
int fputc(int ch, FILE *f)
{      
	while((USART3->SR&0X40)==0);//循环发送,直到发送完毕   
    USART3->DR = (u8) ch;      
	return ch;
}
#endif 

//**********************************************************
//名称:uart1_send函数
//功能:串口1发送
//**********************************************************
static void uart1_send(u8 dat)
{	
	USART1->DR = dat;
  while((USART1->SR&0X40)==0);
}

//**********************************************************
//名称:uart1_sendbuf函数
//功能:串口1发送
//**********************************************************
static void uart1_sendbuf(u8 *pdata,u8 num)
{
	u8 i;
	for(i = 0;i < num;i++)
	{
		uart1_send(*(pdata+i));
	}
}
//**********************************************************
//名称:uart2_send函数
//功能:串口2发送
//**********************************************************
static void uart2_send(u8 dat)
{	
	USART2->DR = dat;
  while((USART2->SR&0X40)==0);
}

//**********************************************************
//名称:uart2_sendbuf函数
//功能:串口2发送
//**********************************************************
static void uart2_sendbuf(u8 *pdata,u8 num)
{
	u8 i;
	for(i = 0;i < num;i++)
	{
		uart2_send(*(pdata+i));
	}
}
//**********************************************************
//名称:uart3_send函数
//功能:串口1发送
//**********************************************************
static void uart3_send(u8 dat)
{  
	while((USART3->SR&0X40)==0);  
	USART3->DR = dat;	
}

//**********************************************************
//名称:uart3_sendbuf函数
//功能:串口1发送
//**********************************************************
static void uart3_sendbuf(u8 *pdata,u8 num)
{
	u8 i;
	for(i = 0;i < num;i++)
	{
		uart3_send(*(pdata+i));
	}
}

/************************************************
名    称: uart4_send
功    能: 串口4单字节发送函数
************************************************/
static void uart4_send(u8 dat)
{
	while((UART4->SR&0X40)==0);//循环发送,直到发送完毕   
	UART4->DR = dat;      
}

/************************************************
名    称: uart4_sendbuf
功    能: 串口4多字节发送函数
************************************************/
static void uart4_sendbuf(u8 *pdata,u8 num)
{
	u8 i;
	for(i = 0;i < num;i++)
	{
		uart4_send(*(pdata+i));
	}
}
//**********************************************************
//名称:uart1_init函数
//功能:用于串口1的初始化,bound:波特率
//**********************************************************
static void uart1_init(u32 bound)
{	
	//UART 初始化设置
	UART1_Handler.Instance=USART1;					    //USART1
	UART1_Handler.Init.BaudRate=bound;				    //波特率
	UART1_Handler.Init.WordLength=UART_WORDLENGTH_8B;   //字长为8位数据格式
	UART1_Handler.Init.StopBits=UART_STOPBITS_1;	    //一个停止位
	UART1_Handler.Init.Parity=UART_PARITY_NONE;		    //无奇偶校验位
	UART1_Handler.Init.HwFlowCtl=UART_HWCONTROL_NONE;   //无硬件流控
	UART1_Handler.Init.Mode=UART_MODE_TX_RX;		    //收发模式
	HAL_UART_Init(&UART1_Handler);					    //HAL_UART_Init()会使能UART1

	HAL_DMA_Start_IT(&hdma_usart1_rx, (uint32_t)&UART1_Handler.Instance->DR, (uint32_t)(COM1.rxbuf), UART_MAX_LEN);
	SET_BIT(UART1_Handler.Instance->CR3, USART_CR3_DMAR);
}
//**********************************************************
//名称:uart2_init函数
//功能:用于串口2的初始化,bound:波特率
//**********************************************************
static void uart2_init(u32 bound)
{	
	//UART 初始化设置
	UART2_Handler.Instance=USART2;					    //USART2
	UART2_Handler.Init.BaudRate=bound;				    //波特率
	UART2_Handler.Init.WordLength=UART_WORDLENGTH_8B;   //字长为8位数据格式
	UART2_Handler.Init.StopBits=UART_STOPBITS_1;	    //一个停止位
	UART2_Handler.Init.Parity=UART_PARITY_NONE;		    //无奇偶校验位
	UART2_Handler.Init.HwFlowCtl=UART_HWCONTROL_NONE;   //无硬件流控
	UART2_Handler.Init.Mode=UART_MODE_TX_RX;		    //收发模式
	HAL_UART_Init(&UART2_Handler);					    //HAL_UART_Init()会使能UART2

	HAL_DMA_Start_IT(&hdma_usart2_rx, (uint32_t)&UART2_Handler.Instance->DR, (uint32_t)(COM2.rxbuf), UART_MAX_LEN);
	SET_BIT(UART2_Handler.Instance->CR3, USART_CR3_DMAR);
}
/************************************************
名    称: uart3_init
功    能: 串口3初始化函数
输入参数: bound--无符号32位整型指针 波特率
输出参数: 无
返回值:   void
************************************************/
static void uart3_init(u32 bound)
{	
	//UART 初始化设置
	UART3_Handler.Instance=USART3;					    //USART3
	UART3_Handler.Init.BaudRate=bound;				    //波特率
	UART3_Handler.Init.WordLength=UART_WORDLENGTH_8B;   //字长为8位数据格式
	UART3_Handler.Init.StopBits=UART_STOPBITS_1;	    //一个停止位
	UART3_Handler.Init.Parity=UART_PARITY_NONE;		    //无奇偶校验位
	UART3_Handler.Init.HwFlowCtl=UART_HWCONTROL_NONE;   //无硬件流控
	UART3_Handler.Init.Mode=UART_MODE_TX_RX;		    //收发模式
	HAL_UART_Init(&UART3_Handler);					    //HAL_UART_Init()会使能USART1
	
	HAL_DMA_Start_IT(&hdma_usart3_rx, (uint32_t)&UART3_Handler.Instance->DR, (uint32_t)(COM3.rxbuf), UART_MAX_LEN);
	SET_BIT(UART3_Handler.Instance->CR3, USART_CR3_DMAR);
}

/************************************************
名    称: uart4_init
功    能: 串口4初始化函数
输入参数: bound--无符号32位整型指针 波特率
输出参数: 无
返回值:   void
************************************************/
static void uart4_init(u32 bound)
{	
	//UART 初始化设置
	UART4_Handler.Instance=UART4;					    //UART4
	UART4_Handler.Init.BaudRate=bound;				    //波特率
	UART4_Handler.Init.WordLength=UART_WORDLENGTH_8B;   //字长为8位数据格式
	UART4_Handler.Init.StopBits=UART_STOPBITS_1;	    //一个停止位
	UART4_Handler.Init.Parity=UART_PARITY_NONE;		    //无奇偶校验位
	UART4_Handler.Init.HwFlowCtl=UART_HWCONTROL_NONE;   //无硬件流控
	UART4_Handler.Init.Mode=UART_MODE_TX_RX;		    //收发模式
	HAL_UART_Init(&UART4_Handler);					    //HAL_UART_Init()会使能USART1
	
	HAL_DMA_Start_IT(&hdma_uart4_rx, (uint32_t)&UART4_Handler.Instance->DR, (uint32_t)(COM4.rxbuf), UART_MAX_LEN);
	SET_BIT(UART4_Handler.Instance->CR3, USART_CR3_DMAR);
}

//**********************************************************
//名称:HAL_UART_MspInit函数
//功能:UART底层初始化,时钟使能,引脚配置,中断配置
//			此函数会被HAL_UART_Init()调用。huart:串口句柄
//**********************************************************
void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{
  //GPIO端口设置
	GPIO_InitTypeDef GPIO_Initure;

	/**********************串口1*************************/
	if(huart->Instance==USART1)//如果是串口1,进行串口1 MSP初始化
	{
		__HAL_RCC_USART1_CLK_ENABLE();					//使能USART1时钟
		__HAL_RCC_DMA1_CLK_ENABLE();
	
		GPIO_Initure.Pin=GPIO_PIN_9;						//PA9
		GPIO_Initure.Mode=GPIO_MODE_AF_PP;			//复用推挽输出
		GPIO_Initure.Pull=GPIO_PULLUP;					//上拉
		GPIO_Initure.Speed=GPIO_SPEED_FREQ_HIGH;//高速
		HAL_GPIO_Init(GPIOA,&GPIO_Initure);	   	//初始化PA9

		GPIO_Initure.Pin=GPIO_PIN_10;						
		GPIO_Initure.Mode=GPIO_MODE_AF_INPUT;
		HAL_GPIO_Init(GPIOA,&GPIO_Initure);	   	//初始化PA10
    
		
		hdma_usart1_rx.Instance = DMA1_Channel5;
    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_CIRCULAR;
    hdma_usart1_rx.Init.Priority = DMA_PRIORITY_HIGH;
    HAL_DMA_Init(&hdma_usart1_rx);

    __HAL_LINKDMA(huart,hdmarx,hdma_usart1_rx);
	  	 
		HAL_NVIC_EnableIRQ(USART1_IRQn);						//使能USART1中断通道
		HAL_NVIC_SetPriority(USART1_IRQn,2,1);			//抢占优先级2,子优先级1
		__HAL_UART_ENABLE_IT(huart, UART_IT_IDLE);	//使能空闲中断
	}
		/**********************串口2*************************/
	if(huart->Instance==USART2)//如果是串口2,进行串口2 MSP初始化
	{
		__HAL_RCC_USART2_CLK_ENABLE();					//使能USART2时钟
		__HAL_RCC_DMA1_CLK_ENABLE();
	
		GPIO_Initure.Pin=GPIO_PIN_2;						//PA2
		GPIO_Initure.Mode=GPIO_MODE_AF_PP;			//复用推挽输出
		GPIO_Initure.Pull=GPIO_PULLUP;					//上拉
		GPIO_Initure.Speed=GPIO_SPEED_FREQ_HIGH;//高速
		HAL_GPIO_Init(GPIOA,&GPIO_Initure);	   	//初始化PA2

		GPIO_Initure.Pin=GPIO_PIN_3;						
		GPIO_Initure.Mode=GPIO_MODE_AF_INPUT;
		HAL_GPIO_Init(GPIOA,&GPIO_Initure);	   	//初始化PA3
    
		
		hdma_usart2_rx.Instance = DMA1_Channel6;
    hdma_usart2_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_usart2_rx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_usart2_rx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_usart2_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_usart2_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_usart2_rx.Init.Mode = DMA_CIRCULAR;
    hdma_usart2_rx.Init.Priority = DMA_PRIORITY_HIGH;
    HAL_DMA_Init(&hdma_usart2_rx);

    __HAL_LINKDMA(huart,hdmarx,hdma_usart2_rx);
	  	 
		HAL_NVIC_EnableIRQ(USART2_IRQn);						//使能USART1中断通道
		HAL_NVIC_SetPriority(USART2_IRQn,2,2);			//抢占优先级2,子优先级1
		__HAL_UART_ENABLE_IT(huart, UART_IT_IDLE);	//使能空闲中断
	}
	/**********************串口3*************************/
	if(huart->Instance==USART3)//如果是串口3,进行串口3 MSP初始化
	{
		__HAL_RCC_USART3_CLK_ENABLE();					//使能USART3时钟
		__HAL_RCC_DMA1_CLK_ENABLE();
	
		GPIO_Initure.Pin=GPIO_PIN_10;			
		GPIO_Initure.Mode=GPIO_MODE_AF_PP;			//复用推挽输出
		GPIO_Initure.Pull=GPIO_PULLUP;					//上拉
		GPIO_Initure.Speed=GPIO_SPEED_FREQ_HIGH;//高速
		HAL_GPIO_Init(GPIOB,&GPIO_Initure);	   	//初始化PB10

		GPIO_Initure.Pin=GPIO_PIN_11;			
		GPIO_Initure.Mode=GPIO_MODE_AF_INPUT;
		HAL_GPIO_Init(GPIOB,&GPIO_Initure);	   	//初始化PB11
    
		hdma_usart3_rx.Instance = DMA1_Channel3;
    hdma_usart3_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_usart3_rx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_usart3_rx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_usart3_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_usart3_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_usart3_rx.Init.Mode = DMA_CIRCULAR;
    hdma_usart3_rx.Init.Priority = DMA_PRIORITY_HIGH;
    HAL_DMA_Init(&hdma_usart3_rx);

    __HAL_LINKDMA(huart,hdmarx,hdma_usart3_rx);

		HAL_NVIC_EnableIRQ(USART3_IRQn);				
		HAL_NVIC_SetPriority(USART3_IRQn,3,1);			
		
		__HAL_UART_ENABLE_IT(huart, UART_IT_IDLE);	
	}
	/**********************串口4*************************/
	if(huart->Instance==UART4)
	{
		__HAL_RCC_UART4_CLK_ENABLE();			//使能USART4时钟
		__HAL_RCC_DMA2_CLK_ENABLE();
		
		GPIO_Initure.Pin=GPIO_PIN_10;			
		GPIO_Initure.Mode=GPIO_MODE_AF_PP;			//复用推挽输出
		GPIO_Initure.Pull=GPIO_PULLUP;					//上拉
		GPIO_Initure.Speed=GPIO_SPEED_FREQ_HIGH;//高速
		HAL_GPIO_Init(GPIOC,&GPIO_Initure);	   	//初始化PC10

		GPIO_Initure.Pin=GPIO_PIN_11;			
		GPIO_Initure.Mode=GPIO_MODE_AF_INPUT;
		HAL_GPIO_Init(GPIOC,&GPIO_Initure);	   	//初始化PC11
		
		hdma_uart4_rx.Instance = DMA2_Channel3;
    hdma_uart4_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_uart4_rx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_uart4_rx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_uart4_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_uart4_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_uart4_rx.Init.Mode = DMA_CIRCULAR;
    hdma_uart4_rx.Init.Priority = DMA_PRIORITY_HIGH;
    HAL_DMA_Init(&hdma_uart4_rx);

    __HAL_LINKDMA(huart,hdmarx,hdma_uart4_rx);
   
		HAL_NVIC_EnableIRQ(UART4_IRQn);				//使能UART4断通道
		HAL_NVIC_SetPriority(UART4_IRQn,2,0);			//抢占优先级3,子优先级1
		__HAL_UART_ENABLE_IT(huart, UART_IT_IDLE);
	}
}

//**********************************************************
//名称:USART1_IRQHandler函数
//功能:串口1中断处理函数
//**********************************************************
void USART1_IRQHandler(void)                	
{ 
	u8 re_dat = 0;
	re_dat = re_dat; //消除警告
#if SYSTEM_SUPPORT_OS	 	//使用OS
	OSIntEnter();    
#endif
	
	if((__HAL_UART_GET_FLAG(&UART1_Handler,UART_FLAG_IDLE)!=RESET)) 
	{
		//__HAL_UART_CLEAR_IDLEFLAG(&UART1_Handler);
		re_dat = USART1->SR;
		re_dat = USART1->DR;	
	  COM1.renum = UART_MAX_LEN - hdma_usart1_rx.Instance->CNDTR;
	  COM1.isReFinish = TRUE;
	  __HAL_UNLOCK(&hdma_usart1_rx);
	  HAL_DMA_Start_IT(&hdma_usart1_rx, (uint32_t)&UART1_Handler.Instance->DR, (uint32_t)(COM1.rxbuf), UART_MAX_LEN);
		COM1_Data_Rev();
	}	
	
#if SYSTEM_SUPPORT_OS	 	//使用OS
	OSIntExit();  											 
#endif
}
//**********************************************************
//名称:USART2_IRQHandler函数
//功能:串口1中断处理函数
//FPGA通信
//**********************************************************
void USART2_IRQHandler(void)                	
{ 
	u8 re_dat = 0;
	re_dat = re_dat; //消除警告
#if SYSTEM_SUPPORT_OS	 	//使用OS
	OSIntEnter();    
#endif
	if((__HAL_UART_GET_FLAG(&UART2_Handler,UART_FLAG_IDLE)!=RESET)) 
	{
		re_dat = USART2->SR;
		re_dat = USART2->DR;	
	  COM2.renum = UART_MAX_LEN - hdma_usart2_rx.Instance->CNDTR;
	  COM2.isReFinish = TRUE;
	  __HAL_UNLOCK(&hdma_usart2_rx);
	  HAL_DMA_Start_IT(&hdma_usart2_rx, (uint32_t)&UART2_Handler.Instance->DR, (uint32_t)(COM2.rxbuf), UART_MAX_LEN);
		COM2_Data_Rev();
	}	
	
#if SYSTEM_SUPPORT_OS	 	//使用OS
	OSIntExit();  											 
#endif
}
//**********************************************************
//名称:USART3_IRQHandler函数
//功能:串口3中断处理函数
//TEST
//**********************************************************
void USART3_IRQHandler(void)                	
{ 
	u8 re_dat = 0;
	re_dat = re_dat; //消除警告
	
#if SYSTEM_SUPPORT_OS	 	//使用OS
	OSIntEnter();    
#endif
	
	if((__HAL_UART_GET_FLAG(&UART3_Handler,UART_FLAG_IDLE)!=RESET)) 
	{
		re_dat = USART3->SR;
		re_dat = USART3->DR;
		COM3.renum = UART_MAX_LEN - hdma_usart3_rx.Instance->CNDTR;
		COM3.isReFinish = TRUE;
		__HAL_UNLOCK(&hdma_usart3_rx);
		HAL_DMA_Start_IT(&hdma_usart3_rx, (uint32_t)&UART3_Handler.Instance->DR, (uint32_t)(COM3.rxbuf), UART_MAX_LEN);
		COM3_Data_Rev();
	}
	
#if SYSTEM_SUPPORT_OS	 	//使用OS
	OSIntExit();  											 
#endif
}	

//**********************************************************
//名称:USART4_IRQHandler函数
//功能:串口4中断处理函数
//WIFI
//**********************************************************
void UART4_IRQHandler(void)                	
{ 
	u8 re_dat = 0;
	re_dat = re_dat; //消除警告
	
#if SYSTEM_SUPPORT_OS	 	//使用OS
	OSIntEnter();    
#endif
	
	if((__HAL_UART_GET_FLAG(&UART4_Handler,UART_FLAG_IDLE)!=RESET)) 
	{
		re_dat = UART4->SR;
		re_dat = UART4->DR;
		COM4.renum = UART_MAX_LEN - hdma_uart4_rx.Instance->CNDTR;
		COM4.isReFinish = TRUE;
		__HAL_UNLOCK(&hdma_uart4_rx);
		HAL_DMA_Start_IT(&hdma_uart4_rx, (uint32_t)&UART4_Handler.Instance->DR, (uint32_t)(COM4.rxbuf), UART_MAX_LEN);
		COM4_Data_Rev();
	}
	
#if SYSTEM_SUPPORT_OS	 	//使用OS
	OSIntExit();  											 
#endif
}	

STM32中,可以使用空闲中断DMA接收来实现串口数据的接收。下面是一个基本的流程: 1. 配置串口的硬件参数,包括波特率、数据位、停止位、校验等。 2. 配置DMA通道,使其能够接收串口数据并将其存储到指定的缓冲区中。 3. 配置空闲中断,当串口接收到数据后触发,并在中断处理函数中进行处理。 4. 在主程序中启动DMA传输和空闲中断,使其能够接收串口数据并进行处理。 下面是一个简单的例子,用于演示如何使用空闲中断DMA接收来实现串口数据的接收: ```c #include "stm32f4xx.h" #include <stdio.h> #define BUFFER_SIZE 256 volatile uint8_t buffer[BUFFER_SIZE]; volatile uint16_t buffer_head = 0; volatile uint16_t buffer_tail = 0; void USART2_IRQHandler(void) { if (USART_GetITStatus(USART2, USART_IT_IDLE) != RESET) { // 空闲中断触发,表示接收到了完整的数据帧 DMA_Cmd(DMA1_Stream5, DISABLE); uint16_t len = BUFFER_SIZE - DMA_GetCurrDataCounter(DMA1_Stream5); buffer_tail = (buffer_head + len) % BUFFER_SIZE; DMA_SetCurrDataCounter(DMA1_Stream5, BUFFER_SIZE); DMA_Cmd(DMA1_Stream5, ENABLE); USART_ClearITPendingBit(USART2, USART_IT_IDLE); } } int main(void) { // 初始化串口2 USART_InitTypeDef USART_InitStructure; USART_InitStructure.USART_BaudRate = 115200; USART_InitStructure.USART_WordLength = USART_WordLength_8b; 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_Init(USART2, &USART_InitStructure); USART_ITConfig(USART2, USART_IT_IDLE, ENABLE); USART_Cmd(USART2, ENABLE); // 初始化DMA1 Stream5,用于接收串口2数据 DMA_InitTypeDef DMA_InitStructure; DMA_DeInit(DMA1_Stream5); DMA_InitStructure.DMA_Channel = DMA_Channel_4; DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&(USART2->DR); DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)buffer; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory; DMA_InitStructure.DMA_BufferSize = BUFFER_SIZE; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; DMA_InitStructure.DMA_Priority = DMA_Priority_High; DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull; DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; DMA_Init(DMA1_Stream5, &DMA_InitStructure); // 启动DMA传输和空闲中断 DMA_Cmd(DMA1_Stream5, ENABLE); NVIC_EnableIRQ(USART2_IRQn); while (1) { if (buffer_head != buffer_tail) { // 有数据需要处理,这里只是简单地将其打印出来 uint16_t len = (buffer_tail > buffer_head) ? (buffer_tail - buffer_head) : (BUFFER_SIZE - buffer_head); printf("%.*s", len, buffer + buffer_head); buffer_head = buffer_tail; } } } ``` 在上面的代码中,我们将DMA设置为循环模式,这样可以不断地接收串口数据。当空闲中断触发时,说明接收到了完整的数据帧,此时我们停止DMA传输,并记录下接收到的数据的长度。然后将缓冲区的读指针向后移动相应的长度,以便下一次处理。在主程序中,我们不断检查缓冲区的读指针和写指针是否相同,如果不同,则说明有新的数据需要处理,这里只是简单地将其打印出来,实际应用中可以根据需要进行其他的处理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

glassine

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值