单片机知多少之STM32F103-USART应用篇

     以下是一个基于STM32的串口应用示例,实现了通过串口发送和接收数据的基本功能。

一、控制逻辑

     将STM32的串口引脚(如USART1的TX引脚用于发送数据,RX引脚用于接收数据)与外部设备(如PC端的串口调试助手)相连。在STM32端,通过配置串口相关寄存器或使用库函数来设置串口的参数,如波特率、数据位、停止位、校验位等。然后,可以使用发送函数将数据从STM32的串口发送出去,同时通过接收中断或轮询的方式来获取从外部设备发送到STM32串口的数据。

二、编写代码

(第一步)变量定义

USART_InitTypeDef USART_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
uint8_t receive_data;
  • USART_InitTypeDef USART_InitStructure;:定义一个USART_InitTypeDef类型的结构体变量USART_InitStructure。这个结构体用于配置串口的参数,如波特率、字长、停止位等。
  • GPIO_InitTypeDef GPIO_InitStructure;:定义一个用于配置 GPIO 引脚(与串口相关引脚)的结构体变量GPIO_InitStructure
  • uint8_t receive_data;:定义一个无符号 8 位变量receive_data,用于存储接收到的串口数据。
  • (第二步)使能串口和相关 GPIO 端口的时钟

    // 使能USART1时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
    
    // 使能与USART1相关的GPIO端口时钟(假设USART1_TX为PA9,USART1_RX为PA10)
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

           这里分别使能了 USART1 串口的时钟以及与 USART1 相关的 GPIOA 端口的时钟(因为示例中假设串口的 TX 和 RX 引脚在 GPIOA 上)。通过调用RCC_APB2PeriphClockCmd函数,并传入相应的参数来实现时钟使能。RCC_APB2Periph_USART1RCC_APB2Periph_GPIOA是宏,表示对应的时钟域,ENABLE表示使能该时钟。

    (第三步)配置与串口相关的 GPIO 引脚

    // 配置USART1_TX引脚(PA9)
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    
    // 配置USART1_RX引脚(PA10)
    GPIO_InitStructure.GPIO_Pin = GPIO_PPin_10;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

        对于 USART1 的 TX 引脚(PA9):

  • 设置GPIO_InitStructure.GPIO_PinGPIO_Pin_9,指定要配置的引脚。
  • 设置GPIO_InitStructure.GPIO_ModeGPIO_Mode_AF_PP(复用推挽输出模式),因为 TX 引脚用于发送数据,需要这种模式来实现数据的有效输出。
  • 设置GPIO_InitStructure.GPIO_SpeedGPIO_Speed_50MHz,确定引脚的输出速度。
    然后通过GPIO_Init函数对 GPIOA 端口的 PA9 引脚进行初始化。
  •     对于 USART1 的 RX 引脚(PA10):

  • 设置GPIO_InitStructure.GPIO_PinGPIO_PPin_10,指定要配置的引脚。
  • 设置GPIO_InitStructure.GPIO_ModeGPIO_Mode_IN_FLOATING(浮空输入模式),因为 RX 引脚用于接收数据,这种模式适合接收外部设备发送过来的信号。
    然后通过GPIO_Init函数对 GPIOA 端口的 PA10 引脚进行初始化。
  • (第四步)配置串口参数

    // 配置USART1串口参数
    USART_InitStructure.USART_BaudRate = 9600;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No;
    USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
    USART_Init(USART1, &USART_InitStructure);
  • 设置USART_InitStructure.USART_BaudRate9600,指定串口的波特率为 9600bps。
  • 设置USART_InitStructure.USART_WordLengthUSART_WordLength_8b,表示数据字长为 8 位。
  • 设置USART_InitStructure.USART_StopBitsUSART_StopBits_1,表示停止位为 1 位。
  • 设置USART_InitStructure.USART_ParityUSART_Parity_No,表示不使用校验位。
  • 设置USART_InitStructure.USART_ModeUSART_Mode_Tx | USART_Mode_Rx,表示串口同时具备发送和接收模式。
    最后通过USART_Init函数对 USART1 串口进行初始化。
  • (第五步)使能串口

    USART_Cmd(USART1, ENABLE);

          调用USART_Cmd函数,将 USART1 串口使能,使其可以开始进行发送和接收操作。

    (第六步)发送数据函数(示例)

    void USART_SendData(uint8_t data)
    {
        USART_Send(USART1, data);
        while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
    }

           这个函数用于发送一个无符号 8 位数据。首先通过USART_Send函数将数据发送到 USART1 串口,然后通过while循环等待发送缓冲区为空(即USART_FLAG_TXE标志位为SET),确保数据已经成功发送出去。

    示例代码

    #include "stm32f10x.h"
    
    USART_InitTypeDef USART_InitStructure;
    GPIO_InitTypeDef GPIO_InitStructure;
    uint8_t receive_data;
    
    // 初始化串口函数
    void USART_InitFunction()
    {
        // 使能USART1时钟
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
    
        // 使能与USART1相关的GPIO端口时钟(假设USART1_TX为PA9,USART1_RX为PA10)
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    
        // 配置USART1_TX引脚(PA9)
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOA, &GPIO_InitStructure);
    
        // 配置USART1_RX引脚(PA10)
        GPIO_InitStructure.GPIO_Pin = GPIO_PPin_10;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
        GPIO_Init(GPIOA, &GPIO_InitStructure);
    
        // 配置USART1串口参数
        USART_InitStructure.USART_BaudRate = 9600;
        USART_InitStructure.USART_WordLength = USART_WordLength_8b;
        USART_InitStructure.USART_StopBits = USART_StopBits_1;
        USART_InitStructure.USART_Parity = USART_Parity_No;
        USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
        USART_Init(USART1, &USART_InitStructure);
    
        // 使能串口
        USART_Cmd(USART1, ENABLE);
    }
    
    // 发送数据函数
    void USART_SendData(uint8_t data)
    {
        USART_Send(USART1, data);
        while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
    }
    
    // 接收数据(轮询方式)函数
    void USART_ReceiveDataPolling()
    {
        if(USART_GetFlagStatus(USART1, USART_FLAG_RXE) == SET)
        {
            receive_data = USART_Receive(USART1);
        }
    }
    

    main.c

    #include "stm32f10x.h"
    
    int main()
    {
        // 初始化串口
        USART_InitFunction();
    
        // 发送一个字符 'A'
        USART_SendData('A');
    
        // 轮询接收数据
        while(1)
        {
            USART_ReceiveDataPolling();
            if(receive_data!= 0)
            {
                // 对接收的数据进行处理,这里简单打印出来
                printf("Received data: %c\n", receive_data);
                receive_data = 0;
            }
        }
    }

          在上述示例中,首先在main函数中调用USART_InitFunction函数对串口进行初始化,包括使能时钟、配置引脚、设置串口参数等操作。然后通过USART_SendData函数发送一个字符'A'。接着在一个无限循环中,通过USART_ReceiveDataPolling函数轮询接收数据,并对接收的数据进行简单处理(这里是打印出来)。请注意,这里的printf函数可能需要根据具体的开发环境进行适当的配置才能正确使用。

    作者:行知者也

    物联沃分享整理
    物联沃-IOTWORD物联网 » 单片机知多少之STM32F103-USART应用篇

    发表回复