STM32 HAL库学习(二) 串口收发数据

   上一篇实现了LED的点亮和串口轮询发送数据,这章想着实现串口接收数据,不得不说,在开始使用STM32的外设才对HAL库的框架有更准确的理解。之前一直不懂HAL库的优越性在哪,这次对它的msp层有了一定认识。

   简单来说,HAL库有一个特点就是对于许多外设的初始化以及功能操作,都提供有一个weak版本的函数,例如串口的HAL_UART_MspInit()函数和HAL_UART_MspDeInit()函数等,这些都可以供用户在需要时在stm32f0xx_hal_msp.c中进行重写实现功能。

   用串口初始化来举例子,用Cube配置UART1使能并生成代码后可以看到有三个关键函数:

1、void MX_USART1_UART_Init(void)

      这个函数是Cube配置完成后自动帮我们生成的,存在于用户文件usart.c中(如果Cube中有配置选项生成用户.c文件,否则在main函数中)。里面主要是将USART的结构体初始化成USART1以及我们设置好的参数),并且在最后有一个语句:if (HAL_UART_Init(&huart1) != HAL_OK)通过这个来调用HAL_UART_Init函数。

2、HAL_StatusTypeDef HAL_UART_Init(UART_HandleTypeDef *huart)

     这个函数在HAL库文件stm32f0xx_hal_uart.c中,在上一个函数 MX_USART1_UART_Init(void)中有被调用,这个函数将初始化UART1,使能UART1,而重点是里面有调用一个函数HAL_UART_MspInit(huart)

3、__weak void HAL_UART_MspInit(UART_HandleTypeDef *huart)

     这个函数也在HAL库文件stm32f0xx_hal_uart.c中,它是weak修饰的,也就是可以重写。我们发现在Cube生成的用户文件usart.c文件中有对这个函数进行重写,主要实现对UART1的TX、RX引脚的IO口配置,以及开启串口中断等设置。

由此,HAL库的串口外设初始化操作就清晰了,也就是说如果我们使用Cube生成代码,要完成对串口的初始化,就要自行对串口的结构体参数进行配置,并对HAL_UART_MspInit函数进行重写。到这里,也能看书HAL库的优越性,用户只需在msp.c中对要实现的函数进行重写,调用相关函数既可实现。

串口初始化完成后,下一步就是实现串口的收发数据,轮询发送很简单,上一篇就实现了。这里主要研究下串口的中断接收,和中断接收有关的函数有下面几个:

1、HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)

     函数有是三个参数,分别是串口结构体,要传输的数据指针以及待传输数据的大小,这其实是对中断接收的一个配置函数,指定当接收到Size大小的字节后就产生一次中断进入中断处理。对比以前的库函数的串口接收协议,可以将这里的Size设置为1,也就是每次接收一个字节就产生一次中断,并将数据存储到pData指向的地址中。这就类似于库函数中的每次中断将数据赋值给临时变量res。需要注意的是,这个函数调用一次只适用于一次中断,如果要连续接收数据的话应该在重写函数中调用它。

2、USART1_IRQHandler(void)、HAL_UART_IRQHandler(&huart1)

     第一个是在it.c中的通用的硬件中断入口函数,其中在里面调用了HAL_UART_IRQHandler(&huart1),也就进入了UART1的中断处理,HAL_UART_IRQHandler函数在stm32f0xx_hal_uart.c文件中,主要进行中断标志的判定,当判定接收到数据时,调用UART_Receive_IT(huart)函数。

3、HAL_StatusTypeDef UART_Receive_IT(UART_HandleTypeDef *huart)

     这个函数也在stm32f0xx_hal_uart.c中,这才是真正的处理数据的函数,读取接收寄存器,将数据赋值给结构体huart的pRxBuffer并清除中断标志,而在里面还调用了一个函数HAL_UART_RxCpltCallback(huart);

4、__weak void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)

    这个是用户真正可以进行重写实现自己所需功能的函数,在msp.c中将其重写。前面我们设置了参数使得每接收一个字节就产生中断,于是可以重写这个函数,在里面将每次接收到的数据存放在自己定义的UART1RXBuffer中。另外,上面有提到配置中断参数的函数 HAL_UART_Receive_IT()每次调用仅适用于一次中断,如果要实现连续采用中断接收数据,也要这个函数中调用HAL_UART_Receive_IT()。因为这个回调函数是每次中断发生都会调用,也就相当于每次发生中断处理完数据后又将中断打开,从而实现连续中断接收数据。

总结下整个逻辑就是:

1、初始化UART1

2、调用HAL_UART_Receive_IT(&huart1,&RxData,1)

3、在msp.c中重写HAL_UART_RxCpltCallback

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	UART1RxBuffer[receive_count++] = RxData;
	HAL_UART_Transmit(huart,&RxData,1,10);
	HAL_UART_Receive_IT(huart,&RxData,1);
}

实验时如何保证HAL库的完整性是一个值得重视的问题。 

猜你喜欢

转载自blog.csdn.net/yhl_sophia/article/details/83541111