1. 引言
STM32是一款广泛使用的32位微控制器,以其高性能、低功耗和丰富的外设而著称。串口通信(UART/USART)是STM32中最常用的通信方式之一,用于实现与计算机或其他设备的简单数据交换。本文将详细介绍如何在STM32上配置和使用串口通信。
2. 基本概念
2.1 UART vs USART•UART(Universal Asynchronous Receiver-Transmitter):
通用异步收发传输器,是一种简单的串行通信协议,支持单端信号。
•USART(Universal Synchronous Asynchronous Receiver-Transmitter):通用同步异步收发传输器,支持同步和异步通信,可以使用差分信号提高抗干扰能力。
2.2 串口参数•波特率(Baud Rate):
每秒传输的位数,常见的波特率有9600、115200等。
•数据位(Data Bits):每个字符的位数,通常为8位。
•停止位(Stop Bits):表示一个字符结束的位数,通常为1位。
•校验位(Parity Bit):用于检测传输错误,可以是偶校验、奇校验或无校验。
3. 硬件连接
3.1 串口引脚STM32的串口引脚通常包括:
•TX(传输):发送数据的引脚。•RX(接收):接收数据的引脚。•GND(地线):接地线。
3.2 连接示例假设使用STM32F103C8T6的USART1,连接到PC的USB转串口适配器:
•STM32 TX (PA9) → USB转串口 RX•STM32 RX (PA10) → USB转串口 TX•STM32 GND → USB转串口 GND
4. 软件配置
4.1 使用HAL库配置串口STM32 HAL库提供了方便的API来配置和使用串口。以下是一个基本的配置示例:
4.1.1 初始化函数#include "stm32f1xx_hal.h"
UART_HandleTypeDef huart1;
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();
}
}
4.1.2 发送数据
void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(uartHandle->Instance==USART1)
{
__HAL_RCC_USART1_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
HAL_NVIC_SetPriority(USART1_IRQn, 0, 1);
HAL_NVIC_EnableIRQ(USART1_IRQn);
}
}
void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle)
{
if(uartHandle->Instance==USART1)
{
HAL_NVIC_DisableIRQ(USART1_IRQn);
__HAL_RCC_USART1_FORCE_RESET();
__HAL_RCC_USART1_RELEASE_RESET();
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9 | GPIO_PIN_10);
}
}
void SendData(const char *data)
{
HAL_UART_Transmit(&huart1, (uint8_t *)data, strlen(data), HAL_MAX_DELAY);
}
4.1.3 接收数据
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if (huart->Instance == USART1)
{
// 处理接收到的数据
uint8_t received_data;
HAL_UART_Receive(&huart1, &received_data, 1, HAL_MAX_DELAY);
// 处理 received_data
}
}
4.2 使用CubeMX生成代码
1. 打开STM32CubeMX,选择相应的STM32型号。
2. 配置USART1,设置波特率、数据位、停止位和校验位。
3. 生成初始化代码,导入到项目中。
5. 示例代码
5.1 主函数
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USART1_UART_Init();
while (1)
{
SendData("Hello, STM32!\r\n");
HAL_Delay(1000);
}
}
5.2 系统时钟配置
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Initializes the CPU, AHB and APB busses clocks
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB busses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
Error_Handler();
}
}
6. 常见问题及解决方案
6.1 通信不稳定•检查硬件连接:确保TX和RX引脚连接正确,无短路或断路。•调整波特率:尝试使用不同的波特率,找到最稳定的设置。
6.2 接收数据错误•校验位设置:确保发送方和接收方的校验位设置一致。•数据长度:确保发送和接收的数据长度一致。
6.3 发送数据失败•缓冲区溢出:检查发送缓冲区是否已满,避免溢出。•中断优先级:确保UART中断的优先级设置合理,避免被其他中断抢占。