STM32F103C8T6 HAL库串口收发实验

STM32F103C8T6 HAL库串口收发实验

实验目的

  1. 熟悉STM32F103C8T6微控制器的USART(通用同步异步收发传输器)模块的基本操作
  2. 掌握使用STM32CubeMX进行项目配置和初始化代码生成的方法
  3. 实现通过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_TransmitHAL_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_ConfigMX_USART1_UART_InitMX_GPIO_Init函数中,如果配置失败,会调用Error_Handler()函数。但需要注意的是,Error_Handler()函数在代码中没有定义,通常需要在用户代码中实现该函数以处理错误情况,比如通过无限循环来停止程序执行。

9. 注意事项

  • RX引脚配置错误,应配置在GPIOA上,而不是GPIOB。
  • Error_Handler()函数需要用户自行实现。
  • 发送和接收数据时使用HAL_MAX_DELAY作为超时时间,这在实际应用中可能不是最佳选择,因为它会阻塞程序直到操作完成或超时。在实时性要求较高的应用中,可能需要考虑使用中断或DMA来处理USART通信。
  • 6
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

科创工作室li

你的鼓励将是大学生的创作动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值