本文中介绍USART编程涵盖了三种主要方法,详细介绍STM32F407微控制器结合HAL库,通过UART的查询方式来实现一个实用的密码验证程序。提示用户键入一个字符作为密码。只有当用户精准地输入字符'6'时,系统才会反馈“密码正确”的确认信息。反之,若输入的字符非'6',则会立即显示“密码错误,请重新输入”的提示。
一、USART编程主要三种方法
1. 查询方式
查询方式是最基础、最简单的UART编程方法。其基本原理是:主程序通过不断查询UART的状态寄存器,以确定是否可以进行数据的发送或接收。
- 发送数据:在发送数据之前,程序可以首先检查TDR寄存器是否为空(即发送缓冲区是否空闲)。如果TDR为空,则可以将数据写入TDR寄存器,并等待发送完成(通常通过查询相关状态位来判断)。为了简化编程,也可以先写入数据,然后再检查发送状态。
- 接收数据:在接收数据时,程序需要不断查询RDR寄存器是否为非空(即接收缓冲区是否有数据)。如果RDR非空,则可以读取RDR寄存器中的数据,并进行相应的处理。
查询方式的优点是编程简单、直观,但缺点是CPU利用率较低,因为主程序需要不断轮询UART状态寄存器。
2. 中断方式
中断方式是一种更加高效的UART编程方法。它利用中断机制,在UART状态发生变化时自动触发中断处理函数,从而减轻CPU的负担。
- 发送数据:在发送数据时,程序可以配置UART以在发送缓冲区空(TXE)时产生中断。在TXE中断处理函数中,程序从发送缓冲区中取出一个数据,并写入TDR寄存器。当TDR中的数据发送完成后,UART会再次触发TXE中断,程序可以继续发送下一个数据。
- 接收数据:在接收数据时,程序可以配置UART以在接收缓冲区有数据(RXNE)时产生中断。在RXNE中断处理函数中,程序读取RDR寄存器中的数据,并将其存储到接收缓冲区中。如果接收缓冲区未满,则UART会继续接收数据并触发RXNE中断。
中断方式的优点是CPU利用率高、实时性好,但缺点是编程相对复杂,需要处理中断优先级和中断嵌套等问题。
3. DMA方式
DMA方式是一种更加高级的UART编程方法。它利用DMA控制器,在UART和内存之间直接传输数据,无需CPU的参与。
- 发送数据:在发送数据时,程序可以将发送缓冲区的地址和长度配置给DMA控制器,并启动DMA传输。DMA控制器会自动从发送缓冲区中读取数据,并写入UART的TDR寄存器。当TDR中的数据发送完成后,DMA控制器会自动从发送缓冲区中读取下一个数据,并继续发送。整个过程无需CPU的干预。
- 接收数据:在接收数据时,程序可以将接收缓冲区的地址和长度配置给DMA控制器,并启动DMA接收。DMA控制器会自动从UART的RDR寄存器中读取数据,并存储到接收缓冲区中。当接收缓冲区满或接收到特定数量的数据时,DMA控制器可以触发一个中断或事件,通知CPU进行后续处理。
DMA方式的优点是数据传输效率高、CPU负担轻,但缺点是编程相对复杂,需要了解DMA控制器的配置和使用方法。
二、USART 查询方式具体实现
下面介绍STM32F407 HAL库下的UART查询方式编程。 在STM32F407微控制器上,通过HAL库使用UART的查询方式来实现一个简单的密码验证程序,程序将提示用户输入一个字符作为密码,只有当用户输入字符'6'时,才会显示密码正确“The password is correct”,否则将提示密码错误重新输入“The password is incorrect, please re-enter it”,并允许用户重新输入。
0.开发环境
硬件:正点原子探索者 V3 STM32F407开发板
单片机:STM32F407ZGT6
Keil版本:5.32
STM32CubeMX版本:6.9.2
STM32Cube MCU Packges版本:STM32F4xx_DFP.2.14.0
串口:USART1(PA9,PA10)
1.STM32CubeMX配置
参考利用STM32 HAL库实现USART串口通信,并通过printf重定向输出“Hello World“
2.编写主程序
在生成的项目基础上,编写主程序main.c。
int main(void)
{
/* USER CODE BEGIN 1 */
char c;
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
HAL_UART_Transmit(&huart1, "Please enter a char for password: \r\n", strlen("Please enter a char for password: \r\n"), 1000);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
while (HAL_OK != HAL_UART_Receive(&huart1, &c, 1, 100));
if('6'==c)
{
HAL_UART_Transmit(&huart1, "The password is correct\r\n", strlen("The password is correct\r\n"), 1000);
}
else
{
HAL_UART_Transmit(&huart1, "The password is incorrect, please re-enter it\r\n", strlen("The password is incorrect, please re-enter it\r\n"), 1000);
};
}
/* USER CODE END 3 */
}
3.运行结果
串口打印Please enter a char for password: 只有当用户输入字符'6'时,才会显示“The password is correct”,否则将提示“The password is incorrect, please re-enter it”,并允许用户重新输入。
下一篇再来介绍中断和DMA方式。