STM32F1 DMA串口接收数据

本文介绍了如何通过串口接收空闲中断和DMA技术,实现在USART1中接收不确定长度的数据。代码展示了初始化过程、配置DMA以及中断服务函数的工作原理。
摘要由CSDN通过智能技术生成

本实验利用串口的接收空闲中断(IDLE)实现DMA接收串口不定长数据。

usart.c

UART_HandleTypeDef UART1_Handler;
u8 buffer[100];//数据缓冲区
u8 len;//已存储数据长度
  

void uart_init(u32 bound)
{	
	UART1_Handler.Instance=USART1;					   
	UART1_Handler.Init.BaudRate=bound;				   
	UART1_Handler.Init.WordLength=UART_WORDLENGTH_8B;   
	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);					    //初始化UART1
	
	
	HAL_NVIC_EnableIRQ(USART1_IRQn);				    //使能UART1中断通道
	HAL_NVIC_SetPriority(USART1_IRQn,3,3);			    //抢占优先级3 子优先级3
  __HAL_UART_ENABLE_IT(&UART1_Handler, UART_IT_IDLE);   //开启接收空闲中断 当串口接收空闲时 
                                                        // 状态寄存器SR的IDLE为将被置1 并产 
                                                        // 生中断
}


void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{

	GPIO_InitTypeDef GPIO_Initure;
	
	if(huart->Instance==USART1)
	{
		__HAL_RCC_GPIOA_CLK_ENABLE();			
		__HAL_RCC_USART1_CLK_ENABLE();			
		__HAL_RCC_AFIO_CLK_ENABLE();
	
		GPIO_Initure.Pin=GPIO_PIN_9;			
		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);	   

		GPIO_Initure.Pin=GPIO_PIN_10;			
		GPIO_Initure.Mode=GPIO_MODE_AF_INPUT;		
		HAL_GPIO_Init(GPIOA,&GPIO_Initure);	 
	}
}


//UART1中断服务函数
void USART1_IRQHandler(void)                	
{ 
	if (__HAL_UART_GET_FLAG(&UART1_Handler,UART_FLAG_IDLE)!=RESET)
   { 
		 HAL_UART_DMAStop(&UART1_Handler);                       //停止DMA搬运
       __HAL_UART_CLEAR_IDLEFLAG(&UART1_Handler);                //清除IDLE中断标志位           
         len = 100 - __HAL_DMA_GET_COUNTER(&UART1TxDMA_Handler); //已搬运数据长度=缓冲区长度-缓冲区剩余长度
         HAL_UART_Receive_DMA(&UART1_Handler,buffer,100);        //重新开启DMA搬运
		 
		 HAL_UART_Transmit(&UART1_Handler,buffer,len,1000);      //将缓冲区数据发送
   }
} 

dma.c

DMA_HandleTypeDef UART1TxDMA_Handler;

void MYDMA_Config(void){
	__HAL_RCC_DMA1_CLK_ENABLE();
	
	__HAL_LINKDMA(&UART1_Handler,hdmarx,UART1TxDMA_Handler);
//将DMA的句柄地址赋值给串口句柄的hdmarx  注意这里因为数据是从串口到内存,
//所以是hdmarx而不是hdmatx!!!
	
	
	UART1TxDMA_Handler.Instance=DMA1_Channel5;//UART1—RX在DMA1的通道5
	UART1TxDMA_Handler.Init.Direction=DMA_PERIPH_TO_MEMORY;//外设到内存
	UART1TxDMA_Handler.Init.PeriphInc=DMA_PINC_DISABLE;//外设非增量模式
	UART1TxDMA_Handler.Init.MemInc=DMA_MINC_ENABLE;//内存增量模式
	UART1TxDMA_Handler.Init.PeriphDataAlignment=DMA_PDATAALIGN_BYTE;//外设数据格式1字节
	UART1TxDMA_Handler.Init.MemDataAlignment=DMA_MDATAALIGN_BYTE;//内存数据格式1字节
	UART1TxDMA_Handler.Init.Mode=DMA_CIRCULAR;//循环模式
	UART1TxDMA_Handler.Init.Priority=DMA_PRIORITY_MEDIUM;//中等优先级
	
	HAL_DMA_Init(&UART1TxDMA_Handler);//初始化DMA
	HAL_UART_Receive_DMA(&UART1_Handler,buffer,100);//开启串口接收DMA传输
}

main.c

#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "dma.h"

int main(void)
{

    HAL_Init();                    	
    Stm32_Clock_Init(RCC_PLL_MUL9); 
    delay_init(72);                 
	
    uart_init(115200);	 	      //初始化串口
	MYDMA_Config();               //初始化DMA
	
	while(1){}
	
}

本人是初学者,有错误欢迎指教!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值