stm32F103C8T6标准库串口接收轮询方式1

目录

1.串口模式配置

c 复制代码
/**
  * @brief  配置 DEBUG 串口模式
  * @param  无
  * @retval 无
  */
  
void DEBUG_USART_MODEConfig(void)
{
    USART_InitTypeDef usart_InitStruct = { 0 };
    
    /* 开启 DEBUG 相关的GPIO外设/端口时钟 */
    DEBUG_APBXCLKCMD(DEBUG_USARTX_CLK_PORT, ENABLE); //开启 端口时钟
    
    /* 配置串口的工作参数 */
    
    //波特率配置:115200
    usart_InitStruct.USART_BaudRate            = DEBUG_BAUDRATE;
    //硬件流控开关配置:无
    usart_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    //配置工作模式:发送模式
    usart_InitStruct.USART_Mode                = USART_Mode_Tx | USART_Mode_Rx;
    //校验:无校验位
    usart_InitStruct.USART_Parity              = USART_Parity_No;
    //停止位:1个停止位
    usart_InitStruct.USART_StopBits            = USART_StopBits_1;
    //数据帧长度:8位
    usart_InitStruct.USART_WordLength          = USART_WordLength_8b;
    
    USART_Init(DEBUG_USARTX, &usart_InitStruct);
    
}

需要注意的地方是,在配置模式的时候可以写成这样

c 复制代码
usart_InitStruct.USART_Mode                = USART_Mode_Tx | USART_Mode_Rx;

这里将发送模式和接收模式可以或运算起来,并不冲突的,这是因为

一个是0x00004,另外一个是0x00008

而这个4是0100,而这个8是1000,或运算就是1100,所以并不会相互冲突影响的。

2.串口IO配置

2.1 串口头文件

c 复制代码
#ifndef __BSP_DEBUG_H
#define __BSP_DEBUG_H

#include "stm32f10x.h"

#define DEBUG_USART_NUM 1

#if(DEBUG_USART_NUM == 1)

    #define DEBUG_TX_GPIO_PORT      GPIOA                       /* GPIO 端口 */
    #define DEBUG_TX_GPIO_CLK_PORT  RCC_APB2Periph_GPIOA        /* GPIO 端口时钟 */
    #define DEBUG_TX_GPIO_PIN       GPIO_Pin_9                  /* 对应PIN脚 */
    #define DEBUG_RX_GPIO_PORT      GPIOA                       /* GPIO 端口 */
    #define DEBUG_RX_GPIO_CLK_PORT  RCC_APB2Periph_GPIOA        /* GPIO 端口时钟 */
    #define DEBUG_RX_GPIO_PIN       GPIO_Pin_10                  /*对应PIN脚 */
    
    #define DEBUG_USARTX            USART1                      /* 串口号 */
    #define DEBUG_USARTX_CLK_PORT   RCC_APB2Periph_USART1       /* 串口外设时钟位 */
    #define DEBUG_APBXCLKCMD        RCC_APB2PeriphClockCmd      /* 串口外设时钟 */
    #define DEBUG_BAUDRATE          115200                      /* 波特率 */

#elif(DEBUG_USART_NUM == 2)

    #define DEBUG_TX_GPIO_PORT      GPIOA                       /* GPIO 端口 */
    #define DEBUG_TX_GPIO_CLK_PORT  RCC_APB2Periph_GPIOA        /* GPIO 端口时钟 */
    #define DEBUG_TX_GPIO_PIN       GPIO_Pin_2                 /* 对应PIN脚 */
    #define DEBUG_RX_GPIO_PORT      GPIOA                       /* GPIO 端口 */
    #define DEBUG_RX_GPIO_CLK_PORT  RCC_APB2Periph_GPIOA        /* GPIO 端口时钟 */
    #define DEBUG_RX_GPIO_PIN       GPIO_Pin_3                 /* 对应PIN脚 */
    
    #define DEBUG_USARTX            USART2                      /* 串口号 */
    #define DEBUG_USARTX_CLK_PORT   RCC_APB1Periph_USART2       /* 串口外设时钟位 */
    #define DEBUG_APBXCLKCMD        RCC_APB1PeriphClockCmd      /* 串口外设时钟 */
    #define DEBUG_BAUDRATE          115200                      /* 波特率 */

#elif(DEBUG_USART_NUM == 3)

    #define DEBUG_TX_GPIO_PORT      GPIOB                       /* GPIO 端口 */
    #define DEBUG_TX_GPIO_CLK_PORT  RCC_APB2Periph_GPIOB        /* GPIO 端口时钟 */
    #define DEBUG_TX_GPIO_PIN       GPIO_Pin_10                 /* 对应PIN脚 */
    #define DEBUG_RX_GPIO_PORT      GPIOB                       /* GPIO 端口 */
    #define DEBUG_RX_GPIO_CLK_PORT  RCC_APB2Periph_GPIOB        /* GPIO 端口时钟 */
    #define DEBUG_RX_GPIO_PIN       GPIO_Pin_11                 /* 对应PIN脚 */
    
    #define DEBUG_USARTX            USART3                      /* 串口号 */
    #define DEBUG_USARTX_CLK_PORT   RCC_APB1Periph_USART3       /* 串口外设时钟位 */
    #define DEBUG_APBXCLKCMD        RCC_APB1PeriphClockCmd      /* 串口外设时钟 */
    #define DEBUG_BAUDRATE          115200                      /* 波特率 */

#endif

void DEBUG_USART_PinConfig(void);
void DEBUG_USART_MODEConfig(void);
void DEBUG_USART_Init(void);
#endif /*__BSP_DEBUG_H*/
引脚 APB2总线 USART1 APB1总线 USART2 APB1总线 USART3 APB1总线 UART4 APB1总线 UART5
TX PA9 PA2 PB10 PC10 PC12
RX PA10 PA3 PB11 PC11 PD2
SCLK PA8 PA4 PB12
nCTS PA11 PA0 PB13
nRTS PA12 PA1 PB14

可以看到串口1的发送引脚在PA9,接收是PA10,串口2的发送引脚在PA2,接收是PA3,串口3的发送引脚是在PB10,接收引脚在PB11

2.2 串口io发送/接收配置

c 复制代码
/**
  * @brief  初始化控制 DEBUG 串口 的IO
  * @param  无
  * @retval 无
  */
  
void DEBUG_USART_PinConfig(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = { 0 };

#if 1    
    /* 开启 DEBUG 相关的GPIO外设/端口时钟 */
    RCC_APB2PeriphClockCmd(DEBUG_TX_GPIO_CLK_PORT, ENABLE); //开启GPIOA 端口时钟
    
    // 配置引脚:选择GPIOA的Pin9
    GPIO_InitStruct.GPIO_Pin = DEBUG_TX_GPIO_PIN;
    // 配置输出速度:50MHz
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    // 配置工作模式:推挽复用
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_Init(DEBUG_TX_GPIO_PORT, &GPIO_InitStruct);
#endif
    
#if 1    
    /* 开启 DEBUG 相关的GPIO外设/端口时钟 */
    RCC_APB2PeriphClockCmd(DEBUG_RX_GPIO_CLK_PORT, ENABLE); //开启GPIOA 端口时钟
    
    // 配置引脚:选择GPIOA的Pin10
    GPIO_InitStruct.GPIO_Pin = DEBUG_RX_GPIO_PIN;
    // 配置输出速度:50MHz
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    // 配置工作模式:上拉输入/浮空输入
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_Init(DEBUG_RX_GPIO_PORT, &GPIO_InitStruct);
#endif
    
}

在数据手册可以看到,串口的发送 IO 口模式配置的是推挽复用输出模式,串口的接收 IO 口模式配置的是浮空输入模式 / 上拉输入模式

3.数据接收与发送

发送数据过程:数据寄存器 DR → 移位寄存器 → TX 引脚 (PA9)

接收数据过程:RX引脚 → 接收移位寄存器 → 接收数据寄存器DR → CPU读取

当接收移位寄存器采集完一整个字节的串行bit,将数据转移到接收数据寄存器DR之后,硬件自动将RXNE标志置1。

接收数据部分:

RXNE=1含义:接收数据寄存器DR里面已经存放了新收到的有效数据,也就是说移位寄存器全部转移到数据寄存器(DR)中,等待CPU读取。

发送数据部分:

TXE = 1 理解:

当数据寄存器 DR里面的数据,全部转移到发送移位寄存器之后,硬件自动把 TXE 置 1。

TC = 1理解:

TC=1:移位寄存器里面所有 bit,全部通过 TXD 引脚发送出去,一整个字节发送全部完成。

当CPU读取DR寄存器拿到数据之后,硬件自动将RXNE标志清零,准备接收下一个字节。

这个自动清除0的理解:

当调用这个函数的时候,通过return DR(数据寄存器)的值,就会触发自动清除RXNE的标志位

代码部分

c 复制代码
/* 数据回显 */
if (USART_GetFlagStatus(DEBUG_USARTX, USART_FLAG_RXNE) == SET)
{
	uint8_t data_temp = USART_ReceiveData(DEBUG_USARTX); //读取数据寄存器,读取后对应的寄存器会被复位 
	USART_SenByte(DEBUG_USARTX, data_temp);
	USART_ClearFlag(DEBUG_USARTX, USART_FLAG_RXNE);      //清除接收标志位
}

当上位机发送数据,RXD引脚接收数据,接收到的数据到移位寄存器,然后移位寄存器转移到数据寄存器,通过if判断RXNE是否置1,如果置1,就可以直接在DR(数据寄存器)读取了,而这个if用来检测移位寄存器是否全部转移到数据寄存器中了,如果转移成功标志这RXNE置1,最后可以直接读取数据寄存器的值。

读取数据调用函数

c 复制代码
uint8_t data_temp = USART_ReceiveData(DEBUG_USARTX);

这个函数是直接return DR的值

相当于当调用这个读取DR寄存器值的函数,就自动将RXNE标志位清0

如果不放心也可以手动清0,调用该函数

c 复制代码
USART_ClearFlag(DEBUG_USARTX, USART_FLAG_RXNE);      //清除接收标志位

当数据成功读取到临时变量data_temp中,此时可以调用自己编写的串口发送数据函数,直接发送。

相关推荐
国科安芯1 小时前
寄存器级 Flash 擦除与六轮迭代踩坑实录
嵌入式硬件·mcu·架构·flash·抗辐射·eflash
艾芯微科技2 小时前
B16WS SOD-323 肖特基二极管参数、应用电路与选型踩坑指南
网络·单片机·嵌入式硬件·集成测试·51单片机
天空'之城2 小时前
单片机基础核心知识点汇总(三十七)
单片机·嵌入式硬件
Groundwork Explorer2 小时前
ESP32-C3 SuperMini 排查WIFI收发故障
python·单片机·嵌入式硬件·mcu
索端阳2 小时前
初识 ARM Cortex-A7,嵌入式底层入门总结
汇编·嵌入式硬件
糖糖单片机设计2 小时前
基于STM32的远程宠物自动投喂系统
人工智能·stm32·51单片机·语音识别·智能硬件
wixzjsh2 小时前
基于STC89C52的温度采集与监控系统设计与实现
单片机
H_oRIZoN_3 小时前
Linux入门DAY42【51 单片机】DS18B20 数字温度传感器完整解析(单总线原理 + 时序 + 读取流程)
linux·单片机·linux应用编程
智购无人售货机厂家3 小时前
2026自动售货机品类拓展逻辑:从饮料零食到鲜食药品文创的工程实践~YH
服务器·人工智能·单片机·线性代数·矩阵