stm32F4XX之UART&DMA HAL库

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/WZJwzj123456/article/details/83959748

1:串口相关的初始化操作

我们都知道stm32相关外设的初始化都需要打开相应的时钟,配置相应的IO,除此之外我们还需要对串口库中的相关成员变量赋值,这里我们就直接看一下这些结构体成员有哪些。

HAL_StatusTypeDef HAL_UART_Init(UART_HandleTypeDef *huart);这个函数就是对串口的初始化操作,形参是一个结构体指针,该结构体主要包含哪些部分,下面会做相应的介绍

typedef struct
{
 USART_TypeDef *Instance; 
 UART_InitTypeDef Init; 
 uint8_t *pTxBuffPtr; 
 uint16_t TxXferSize; 
 uint16_t TxXferCount; 
 uint8_t *pRxBuffPtr; 
 uint16_t RxXferSize; 
 uint16_t RxXferCount; 
 DMA_HandleTypeDef *hdmatx; 
 DMA_HandleTypeDef *hdmarx; 
 HAL_LockTypeDef Lock; 
 __IO HAL_UART_StateTypeDef State; 
 __IO uint32_t ErrorCode; 
}UART_HandleTypeDef;

在该成员中我们只需要对 USART_TypeDef *Instance;  UART_InitTypeDef Init; 这两个成员赋值就行了,首先我先来介绍一下 USART_TypeDef *Instance,这个成员表示的是具体串口号,它是执行寄存器基地址,实际上这个基地址 HAL 库已经定义好了,如果是串口 1,取值为 USART1 即可。

 UART_InitTypeDef Init这个变量主要包含如下的成员,它是用来设置串口的各个参数,包括波特率,停止位等

typedef struct
{
 uint32_t BaudRate; //波特率
 uint32_t WordLength; //字长
 uint32_t StopBits; //停止位
 uint32_t Parity; //奇偶校验
 uint32_t Mode; //收/发模式设置
 uint32_t HwFlowCtl; //硬件流设置
 uint32_t OverSampling; //过采样设置
}UART_InitTypeDef

pTxBuffPtr,TxXferSize 和 TxXferCount 三个变量分别用来设置串口发送的数据缓存指针,发送的数据量和还剩余的要发送的数据量。而接下来的三个变量 pRxBuffPtr,RxXferSize 和RxXferCount 则是用来设置接收的数据缓存指针,接收的最大数据量以及还剩余的要接收的数据量。这六个变量是 HAL 库处理中间变量。hdmatx 和 hdmarx 是串口 DMA 相关的变量,指向 DMA 句柄
函数 HAL_UART_Init 使用的一般格式为:
 

UART_HandleTypeDef UART1_Handler; //UART 句柄
UART1_Handler.Instance=USART1; //USART1
UART1_Handler.Init.BaudRate=115200; //波特率
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_UART_Init 内部会调用串口使能函数使能相应串口,所以调用了该函数之后我们就不需要重复使能串口了。当然,HAL 库也提供了具体的串口使能和关闭方法,具体使用方法如下:
__HAL_UART_ENABLE(handler); //使能句柄 handler 指定的串口
__HAL_UART_DISABLE(handler); //关闭句柄 handler 指定的串口

这里还需要提醒大家,串口作为一个重要外设,在调用的初始化函数 HAL_UART_Init 内部,会先调用 MSP 初始化回调函数进行 MCU 相关的初始化,函数为:void HAL_UART_MspInit(UART_HandleTypeDef *huart);我们在程序中,只需要重写该函数即可。一般情况下,该函数内部用来编写 IO 口初始化,时钟使能以及 NVIC 配置

void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{
    //GPIO端口设置
	GPIO_InitTypeDef GPIO_Initure;
	
	if(huart->Instance==USART1)//如果是串口1,进行串口1 MSP初始化
	{
		__HAL_RCC_GPIOA_CLK_ENABLE();			//使能GPIOA时钟
		__HAL_RCC_USART1_CLK_ENABLE();			//使能USART1时钟
	
		GPIO_Initure.Pin=GPIO_PIN_9;			//PA9
		GPIO_Initure.Mode=GPIO_MODE_AF_PP;		//复用推挽输出
		GPIO_Initure.Pull=GPIO_PULLUP;			//上拉
		GPIO_Initure.Speed=GPIO_SPEED_FAST;		//高速
		GPIO_Initure.Alternate=GPIO_AF7_USART1;	//复用为USART1
		HAL_GPIO_Init(GPIOA,&GPIO_Initure);	   	//初始化PA9

		GPIO_Initure.Pin=GPIO_PIN_10;			//PA10
		HAL_GPIO_Init(GPIOA,&GPIO_Initure);	   	//初始化PA10
		
#if EN_USART1_RX
		HAL_NVIC_EnableIRQ(USART1_IRQn);		//使能USART1中断通道
		HAL_NVIC_SetPriority(USART1_IRQn,3,3);	//抢占优先级3,子优先级3
#endif	
	}

}

2:中断相关配置

 开启串口相关中断,配置串口中断优先级HAL 库中定义了一个使能串口中断的标识符__HAL_UART_ENABLE_IT,大家可以把它当一个函数来使用,具体定义请参考 HAL 库文件 stm32f4xx_hal_uart.h 中该标识符定义。例如我们要使能接收完成中断,方法如下:
__HAL_UART_ENABLE_IT(huart,UART_IT_RXNE); //开启接收完成中断第一个参数为串口句柄,类型为UART_HandleTypeDef 结构体类型。第二个参数为我们要开启的中断类型值,可选值在头文件 stm32f4xx_hal_uart.h 中有宏定义。

关闭串口中断,操作方法为:
__HAL_UART_DISABLE_IT(huart,UART_IT_RXNE); //关闭接收完成中断对于中断优先级配置,方法就非常简单

对于中断优先级配置,方法就非常简单
HAL_NVIC_EnableIRQ(USART1_IRQn); //使能 USART1 中断通道
HAL_NVIC_SetPriority(USART1_IRQn,3,3); //抢占优先级 3,子优先级 3

3:编写中断服务函数

我们在初始化串口之后,开启相应中断,在中断产生的时候我们要有相应的中断处理函数来相应此次的中断

//串口1中断服务程序
void USART1_IRQHandler(void)                	
{ 
	u32 timeout=0;
	u32 maxDelay=0x1FFFF;
	
	HAL_UART_IRQHandler(&UART1_Handler);	//调用HAL库中断处理公用函数
	
	timeout=0;
    while (HAL_UART_GetState(&UART1_Handler) != HAL_UART_STATE_READY)//等待就绪
	{
	 timeout++;////超时处理
     if(timeout>maxDelay) break;		
	}
     
	timeout=0;
	while(HAL_UART_Receive_IT(&UART1_Handler, (u8 *)aRxBuffer, RXBUFFERSIZE) != HAL_OK)//一次处理完成之后,重新开启中断并设置RxXferCount为1
	{
	 timeout++; //超时处理
	 if(timeout>maxDelay) break;	
	}

} 

HAL_UART_IRQHandler(&UART1_Handler);    该函数会清楚相应的中断标志位,然后调用HAL_UART_GetState等待uart恢复初始状态,处理完之后重新打开接受中断

4:串口的发送和接收


         STM32F4 的发送与接收是通过数据寄存器 USART_DR 来实现的,这是一个双寄存器,包含了 TDR 和 RDR。当向该寄存器写数据的时候,串口就会自动发送,当收到数据的时候,也是存在该寄存器内。HAL 库操作 USART_DR 寄存器发送数据的函数是:
HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout);
通过该函数向串口寄存器 USART_DR 写入一个数据。
HAL 库操作 USART_DR 寄存器读取串口接收到的数据的函数是:
HAL_StatusTypeDef HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout);
通过该函数可以读取串口接受到的数据。

猜你喜欢

转载自blog.csdn.net/WZJwzj123456/article/details/83959748