STM32F103C8T6 HAL库串口收发实验
实验目的
- 熟悉STM32F103C8T6微控制器的USART(通用同步异步收发传输器)模块的基本操作。
- 掌握使用STM32CubeMX进行项目配置和初始化代码生成的方法。
- 实现通过USART模块进行数据的发送与接收功能。
实验器材
- STM32F103C8T6开发板
- USB转串口模块(用于与PC机通信)
- 杜邦线
- STM32CubeIDE(或其他支持的IDE)
- STM32CubeMX(用于项目配置和初始化代码生成)
- PC机及串口调试助手软件(如PuTTY, Termite等)
实验原理
USART是STM32F103C8T6微控制器内置的一个全双工通用同步/异步串行收发模块,它可以实现数据的发送与接收功能。在通信过程中,USART模块可以通过配置不同的波特率、数据位、停止位和校验位等参数来适应不同的通信协议。
实验步骤
1. 硬件连接
- 将STM32F103C8T6开发板的USART1(通常为PA9作为TX,PA10作为RX)通过杜邦线连接到USB转串口模块的对应引脚。
- 将USB转串口模块连接到PC机的USB端口。
2. 项目配置(使用STM32CubeMX)
- 打开STM32CubeMX,创建一个新项目,选择STM32F103C8T6作为目标MCU。
- 在Pinout视图中,找到USART1对应的引脚(PA9和PA10),将其配置为USART TX和RX。
- 在Configuration视图中,配置USART1的参数,如波特率、数据位、停止位和校验位等,确保与PC端串口调试助手软件的设置相匹配。
- 启用USART1的中断(如果需要)或DMA(如果需要高速数据传输)。
- 生成初始化代码,选择STM32CubeIDE作为IDE,并导出项目。
3. 编写代码(在STM32CubeIDE中)
- 在主函数(
main.c
)中,初始化USART1并配置相关参数。 - 编写数据发送和接收的函数。可以使用HAL库提供的
HAL_UART_Transmit
和HAL_UART_Receive
等函数进行数据的发送和接收。 - 如果启用了中断或DMA,还需要编写相应的中断服务程序或DMA回调函数来处理数据。
- 在
main
函数的循环中,调用数据发送函数,并可以通过轮询或中断的方式接收数据。
4. 编译和下载代码
- 在STM32CubeIDE中编译整个项目,确保没有编译错误。
- 使用ST-LINK或其他支持的调试器将编译好的代码下载到STM32F103C8T6开发板上。
5. 观察结果
- 打开PC端的串口调试助手软件,设置与STM32F103C8T6开发板USART1相同的通信参数。
- 在串口调试助手软件中发送数据,观察开发板是否能够通过USART1接收并正确响应(如回显发送的数据)。
- 同时,也可以通过STM32F103C8T6开发板发送数据,观察串口调试助手软件是否能够接收并显示。
实验结果与分析
通过实验,我们成功实现了STM32F103C8T6开发板与PC机之间的USART通信。通过串口调试助手软件发送数据,开发板能够接收并正确响应(如回显数据),同时开发板也能主动发送数据给PC机,并在串口调试助手软件中显示。这证明了USART模块的发送与接收功能正常,且通信参数配置正确。
实验总结
本次实验通过STM32F103C8T6开发板和USART模块实现了数据的发送与接收功能,加深了对STM32F103C8T6微控制器USART模块操作的理解。同时,掌握了使用STM32CubeMX进行项目配置和初始化代码生成的方法,以及STM32CubeIDE的使用。此外,还学会了如何通过串口调试助手软件进行USART通信的调试与测试。这些知识和技能将为后续更复杂的嵌入式系统开发打下坚实的基础。
#include "stm32f1xx_hal.h"
UART_HandleTypeDef huart1;
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART1_UART_Init(void);
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USART1_UART_Init();
uint8_t txData[] = "Hello, STM32F103C8T6!
";
uint8_t rxData[32] = {0};
while (1)
{
HAL_UART_Transmit(&huart1, txData, sizeof(txData) - 1, HAL_MAX_DELAY);
HAL_Delay(1000);
if (HAL_UART_Receive(&huart1, rxData, sizeof(rxData) - 1, HAL_MAX_DELAY) == HAL_OK)
{
HAL_UART_Transmit(&huart1, rxData, sizeof(rxData) - 1, HAL_MAX_DELAY);
}
}
}
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
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();
}
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();
}
}
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};
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
GPIO_InitStruct.Pin = GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
上面的代码是一个基于STM32F103C8T6微控制器的简单USART(通用同步异步收发传输器)通信示例,使用了HAL库进行开发。代码主要实现了USART1的初始化、系统时钟的配置、GPIO端口的配置,以及通过USART1发送和接收数据的基本功能。下面是对代码的详细解释:
1. 引入头文件
#include "stm32f1xx_hal.h"
这行代码引入了STM32F1系列的HAL库头文件,使得程序可以使用HAL库提供的函数和宏定义。
2. 变量定义
UART_HandleTypeDef huart1;
定义了一个UART_HandleTypeDef
类型的变量huart1
,用于存储USART1的配置信息和状态。
3. 函数声明
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART1_UART_Init(void);
声明了三个函数,分别用于系统时钟配置、GPIO初始化、USART1初始化。
4. 主函数 main
int main(void)
{
// 初始化HAL库
HAL_Init();
// 配置系统时钟
SystemClock_Config();
// 初始化GPIO
MX_GPIO_Init();
// 初始化USART1
MX_USART1_UART_Init();
// 发送和接收数据的循环
while (1)
{
// 发送数据
HAL_UART_Transmit(&huart1, txData, sizeof(txData) - 1, HAL_MAX_DELAY);
HAL_Delay(1000);
// 接收数据并回显
if (HAL_UART_Receive(&huart1, rxData, sizeof(rxData) - 1, HAL_MAX_DELAY) == HAL_OK)
{
HAL_UART_Transmit(&huart1, rxData, sizeof(rxData) - 1, HAL_MAX_DELAY);
}
}
}
主函数中,首先进行HAL库、系统时钟、GPIO和USART1的初始化。然后进入一个无限循环,不断发送数据到USART1,并等待接收数据(如果有的话),然后将接收到的数据回显回去。
5. 系统时钟配置 SystemClock_Config
该函数配置了系统的时钟源为HSE(高速外部时钟),并启用了PLL(相位锁定环)进行时钟倍频,最终将系统时钟(SYSCLK)设置为HSE的9倍。同时,配置了AHB总线、APB1总线和APB2总线的时钟分频系数。
6. USART1初始化 MX_USART1_UART_Init
该函数配置了USART1的波特率为115200,数据位为8位,停止位为1位,无奇偶校验,支持收发模式,并启用了16倍过采样。
7. GPIO初始化 MX_GPIO_Init
该函数配置了USART1的TX(发送)引脚(PA9)为复用推挽输出模式,并配置了高速输出速度。然而,对于RX(接收)引脚(PA10),代码错误地将其配置在了GPIOB上,并且设置为输入模式,没有复用功能。正确的配置应该是将PA10配置为浮空输入模式(或上拉/下拉输入模式,取决于具体需求),并启用复用功能。
8. 错误处理
在SystemClock_Config
、MX_USART1_UART_Init
和MX_GPIO_Init
函数中,如果配置失败,会调用Error_Handler()
函数。但需要注意的是,Error_Handler()
函数在代码中没有定义,通常需要在用户代码中实现该函数以处理错误情况,比如通过无限循环来停止程序执行。
9. 注意事项
- RX引脚配置错误,应配置在GPIOA上,而不是GPIOB。
Error_Handler()
函数需要用户自行实现。- 发送和接收数据时使用
HAL_MAX_DELAY
作为超时时间,这在实际应用中可能不是最佳选择,因为它会阻塞程序直到操作完成或超时。在实时性要求较高的应用中,可能需要考虑使用中断或DMA来处理USART通信。