✅作者简介:热爱科研的嵌入式开发者,修心和技术同步精进
❤欢迎关注我的知乎:对error视而不见
代码获取、问题探讨及文章转载可私信。
☁ 愿你的生命中有够多的云翳,来造就一个美丽的黄昏。
获取更多嵌入式资料可点击链接进群领取,谢谢支持!
点击领取更多详细资料
在嵌入式系统开发里,设备间的通信是关键环节。串口通信由于其实现简单、成本低廉等特性,被广泛应用于各类设备之间的数据传输。STM32系列微控制器具备强大的通信功能,其中USART(通用同步/异步收发传输器)是常用的串口通信接口,它能在同步和异步模式下工作,满足不同场景的通信需求。接下来,我们会详细阐述USART串口协议和STM32的串口外设,并给出相应代码示例。
USART是一种全双工的串行通信接口,它既支持异步通信,也支持同步通信。在异步通信中,通信双方不需要共享时钟信号,而是依靠预先约定好的波特率来实现数据的同步传输;而同步通信则需要一个额外的时钟信号来协调发送方和接收方的操作,确保数据准确无误地传输。
在异步通信里,数据是以帧为单位进行传输的,一个典型的数据帧包含以下几个部分:
波特率定义了数据传输的速率,即每秒传输的比特数。常见的波特率有9600、115200等。在进行串口通信时,发送方和接收方必须使用相同的波特率,否则会导致数据传输错误,接收方无法正确解析接收到的数据。
STM32的USART外设主要有两个重要的引脚:TX(发送)和RX(接收)。在异步通信模式下,只需要将发送方的TX引脚连接到接收方的RX引脚,接收方的TX引脚连接到发送方的RX引脚,就可以实现数据的双向传输。如果使用同步通信模式,还需要一个时钟引脚(CK)来提供同步时钟信号。
STM32通过一系列的寄存器来对USART外设进行配置和控制,主要的寄存器如下:
STM32的USART外设支持多种工作模式,主要包括:
以下是一个基于STM32Cube HAL库的USART串口通信代码示例,实现了简单的串口数据发送和接收功能。
#include "stm32f4xx_hal.h"
UART_HandleTypeDef huart1;
// 系统时钟配置函数
void SystemClock_Config(void);
// GPIO初始化函数
static void MX_GPIO_Init(void);
// USART1初始化函数
static void MX_USART1_UART_Init(void);
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USART1_UART_Init();
uint8_t tx_data[] = "Hello, STM32 USART!\r\n";
uint8_t rx_data[20];
while (1)
{
// 发送数据
HAL_UART_Transmit(&huart1, tx_data, sizeof(tx_data), HAL_MAX_DELAY);
// 接收数据
HAL_UART_Receive(&huart1, rx_data, sizeof(rx_data), HAL_MAX_DELAY);
// 可在此处添加对接收数据的处理逻辑
HAL_Delay(1000);
}
}
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
// 初始化RCC振荡器
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
// 初始化CPU、AHB和APB总线时钟
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK
| RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
{
Error_Handler();
}
}
static void MX_USART1_UART_Init(void)
{
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
Error_Handler();
}
}
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
// 使能GPIO端口时钟
__HAL_RCC_GPIOA_CLK_ENABLE();
// 配置GPIO引脚输出电平
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);
// 配置GPIO引脚: PA5
GPIO_InitStruct.Pin = GPIO_PIN_5;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
// 配置GPIO引脚: PA9 PA10
GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
void Error_Handler(void)
{
while (1)
{
}
}
#ifdef USE_FULL_ASSERT
/**
* @brief 报告发生断言错误的源文件名和行号
* @param file: 指向源文件名的指针
* @param line: 断言错误发生的行号
* @retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
// 用户可以添加自己的实现来报告文件名和行号
}
#endif
main
:程序的入口点。首先进行系统初始化,包括HAL库的初始化、系统时钟的配置、GPIO引脚的初始化以及USART1的初始化。然后进入一个无限循环,在循环中不断发送数据“Hello, STM32 USART!”,并接收数据。接收到的数据可以在后续添加处理逻辑。每次发送和接收操作后,程序会延迟1秒。SystemClock_Config
:该函数的作用是配置系统时钟。首先初始化RCC振荡器,选择内部高速时钟(HSI)作为时钟源,并设置相关参数。然后初始化CPU、AHB和APB总线时钟,设置时钟的分频系数。如果配置过程中出现错误,会调用Error_Handler
函数进入无限循环。MX_USART1_UART_Init
:初始化USART1外设。设置波特率为115200,数据位为8位,停止位为1位,无校验位,工作模式为发送和接收模式,不使用硬件流控制,过采样率为16。如果初始化过程中出现错误,会调用Error_Handler
函数。MX_GPIO_Init
:配置GPIO引脚。使能GPIOA端口的时钟,将PA5引脚配置为推挽输出模式,速度为低频。将PA9和PA10引脚配置为复用功能,复用为USART1的TX和RX引脚,速度为高频。USART串口通信在众多领域都有广泛的应用,例如:
本文详细介绍了USART串口协议和STM32的串口外设。USART协议提供了一种简单、可靠的串行通信方式,而STM32的串口外设则为开发者提供了丰富的配置选项和强大的功能。通过代码示例,我们展示了如何使用STM32Cube HAL库实现基本的串口通信功能。开发者可以根据实际需求对代码进行扩展和优化,以满足不同的应用场景。在实际开发过程中,要注意波特率设置、数据帧格式和缓冲区管理等问题,确保串口通信的稳定性和可靠性。