#define DEBUG_USARTx USART1
#define DEBUG_USART_CLK RCC_APB2Periph_USART1
#define DEBUG_USART_APBxClkCmd RCC_APB2PeriphClockCmd
#define DEBUG_USART_BAUDRATE 115200
// USART GPIO 引脚宏定义
#define DEBUG_USART_GPIO_CLK (RCC_APB2Periph_GPIOA)
#define DEBUG_USART_GPIO_APBxClkCmd RCC_APB2PeriphClockCmd
STM32的USART(通用同步/异步收发传输器)通信配置的宏定义。USART是一种全双工的串行通信接口,常用于微控制器与外部设备(如电脑、其他微控制器、传感器等)之间的数据交换。
- USART选择:
#define DEBUG_USARTx USART1
:这行代码定义了用于调试的USART接口为USART1。这意味着后续的所有USART配置都将针对USART1进行。
- USART时钟配置:
#define DEBUG_USART_CLK RCC_APB2Periph_USART1
:这行代码定义了USART1所使用的时钟源。在STM32中,不同的外设(包括USART)可能连接到不同的时钟源上。这里RCC_APB2Periph_USART1
指的是USART1连接到APB2总线上,并需要通过RCC(复位与时钟控制)模块来使能其时钟。#define DEBUG_USART_APBxClkCmd RCC_APB2PeriphClockCmd
:这行代码定义了用于使能或禁用USART1时钟的函数。在STM32的标准外设库中,RCC_APB2PeriphClockCmd
是用于控制APB2总线上外设时钟的函数。通过这个函数,可以开启或关闭USART1的时钟,从而控制USART1的使能或禁用。
- USART波特率设置:
#define DEBUG_USART_BAUDRATE 115200
:这行代码定义了USART通信的波特率为115200。波特率是衡量数据传输速率的单位,表示每秒传输的比特数(bit/s)。在这个例子中,USART将以115200bps的速率进行数据传输。
- USART GPIO引脚配置:
#define DEBUG_USART_GPIO_CLK (RCC_APB2Periph_GPIOA)
:这行代码定义了与USART1相关的GPIO端口(如TX和RX引脚)所使用的时钟源。在这个例子中,假设USART1的TX和RX引脚连接在GPIOA端口上,因此需要使用RCC_APB2Periph_GPIOA
来使能GPIOA端口的时钟。#define DEBUG_USART_GPIO_APBxClkCmd RCC_APB2PeriphClockCmd
:与DEBUG_USART_APBxClkCmd
类似,这行代码定义了用于使能或禁用与USART1相关的GPIO端口时钟的函数。在这里,它也是RCC_APB2PeriphClockCmd
,因为GPIOA也连接到APB2总线上。
在STM32中,USART(通用同步/异步收发传输器)的通信涉及到两个主要的硬件组件:USART外设本身和与之相连的GPIO(通用输入输出)引脚。USART外设负责处理数据的串行化/解串行化、错误检测等通信任务,而GPIO引脚则用于物理上连接USART的TX(发送)和RX(接收)线到外部设备或接口。
当你看到DEBUG_USART_GPIO_CLK
和DEBUG_USART_GPIO_APBxClkCmd
这样的宏定义时,它们实际上是在为与USART1相关的GPIO引脚(通常是TX和RX引脚)的时钟配置做准备。这些宏定义将USART1的GPIO端口(在这个例子中是GPIOA)的时钟配置与USART1的时钟配置区分开来,尽管它们在逻辑上紧密相关,但在硬件和配置层面上是独立的。
具体来说:
-
#define DEBUG_USART_GPIO_CLK (RCC_APB2Periph_GPIOA)
:这行代码定义了与USART1的TX和RX引脚相连的GPIO端口(在这个例子中是GPIOA)的时钟标识符。在STM32中,每个GPIO端口都有自己的时钟源,需要通过RCC(复位与时钟控制)模块来使能其时钟。在这个宏定义中,RCC_APB2Periph_GPIOA
是一个枚举值(或宏定义),用于标识GPIOA端口的时钟源位于APB2总线上。 -
#define DEBUG_USART_GPIO_APBxClkCmd RCC_APB2PeriphClockCmd
:这行代码定义了用于控制上面定义的GPIOA端口时钟使能或禁用的函数(实际上是宏定义)。RCC_APB2PeriphClockCmd
是一个宏定义,它根据提供的参数(外设的时钟标识符和使能/禁用标志)来展开为一个函数调用,从而控制APB2总线上特定外设(在这个例子中是GPIOA端口)的时钟使能或禁用。
为什么USART1和GPIO要联系在一起?因为USART1的TX和RX功能是通过特定的GPIO引脚来实现的。为了使USART1能够正常工作,不仅需要使能USART1外设的时钟,还需要使能与之相连的GPIO端口的时钟,并正确配置这些GPIO引脚为USART功能(而不是默认的GPIO输入/输出功能)。
因此,在配置USART1进行通信之前,你需要执行以下步骤:
- 使能USART1的时钟(通过
DEBUG_USART_APBxClkCmd
宏,但实际上是传递DEBUG_USART_CLK
作为参数)。 - 使能与USART1 TX和RX引脚相连的GPIO端口的时钟(在这个例子中是GPIOA,通过
DEBUG_USART_GPIO_APBxClkCmd
宏,但实际上是传递DEBUG_USART_GPIO_CLK
作为参数)。 - 配置GPIO引脚为USART功能(这通常涉及到设置GPIO的复用功能寄存器)。
- 配置USART1的参数(如波特率、数据位、停止位、校验位等)。
- 使能USART1的接收和/或发送功能。
// 打开串口GPIO的时钟
DEBUG_USART_GPIO_APBxClkCmd(DEBUG_USART_GPIO_CLK, ENABLE);
// 打开串口外设的时钟
DEBUG_USART_APBxClkCmd(DEBUG_USART_CLK, ENABLE);
DEBUG_USART_GPIO_APBxClkCmd(DEBUG_USART_GPIO_CLK, ENABLE);
和DEBUG_USART_APBxClkCmd(DEBUG_USART_CLK, ENABLE);
这两行代码分别用于使能与USART1相关的GPIO端口的时钟和USART1外设本身的时钟。这两行代码之间的主要区别在于它们针对的硬件组件不同,尽管它们都使用了相同的宏定义(在这个例子中是DEBUG_USART_APBxClkCmd
,它实际上是RCC_APB2PeriphClockCmd
的别名)来执行操作。
- 使能GPIO端口的时钟 (
DEBUG_USART_GPIO_APBxClkCmd(DEBUG_USART_GPIO_CLK, ENABLE);
):- 这行代码的目的是使能与USART1的TX和RX引脚(通常连接在特定的GPIO端口上,如GPIOA)相连的GPIO端口的时钟。在STM32中,每个GPIO端口都有一个独立的时钟源,需要通过RCC(复位与时钟控制)模块来使能。使能GPIO端口的时钟是配置GPIO引脚为特定功能(如USART的TX和RX)之前的必要步骤。
- 使能USART外设的时钟 (
DEBUG_USART_APBxClkCmd(DEBUG_USART_CLK, ENABLE);
):- 这行代码的目的是使能USART1外设本身的时钟。USART外设(如USART1)是STM32微控制器上的一个独立模块,用于处理串行通信。为了使USART1能够正常工作,需要通过RCC模块来使能其时钟。一旦USART1的时钟被使能,就可以配置其各种参数(如波特率、数据位、停止位等),并开始发送和接收数据。
区别总结:
- 目标不同:第一行代码针对的是GPIO端口(通常是GPIOA),它是USART通信所需的物理引脚所在的端口;第二行代码针对的是USART外设本身(如USART1),它是处理串行通信逻辑的核心。
- 作用不同:使能GPIO端口的时钟是为了能够配置GPIO引脚为USART功能;使能USART外设的时钟是为了使USART模块能够正常工作,并准备接收配置参数以进行通信。
- 顺序重要性:在配置USART进行通信之前,通常需要首先使能GPIO端口的时钟,然后配置GPIO引脚为USART功能,最后使能USART外设的时钟并配置其参数。这是因为GPIO引脚需要被正确配置为USART功能之后,USART外设才能通过这些引脚与外部设备进行通信。
void USART_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
// 打开串口GPIO的时钟
DEBUG_USART_GPIO_APBxClkCmd(DEBUG_USART_GPIO_CLK, ENABLE);
// 打开串口外设的时钟
DEBUG_USART_APBxClkCmd(DEBUG_USART_CLK, ENABLE);
// 将USART Tx的GPIO配置为推挽复用模式
GPIO_InitStructure.GPIO_Pin = DEBUG_USART_TX_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(DEBUG_USART_TX_GPIO_PORT, &GPIO_InitStructure);
// 将USART Rx的GPIO配置为浮空输入模式
GPIO_InitStructure.GPIO_Pin = DEBUG_USART_RX_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(DEBUG_USART_RX_GPIO_PORT, &GPIO_InitStructure);
// 配置串口的工作参数
// 配置波特率
USART_InitStructure.USART_BaudRate = DEBUG_USART_BAUDRATE;
// 配置 针数据字长
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
// 配置停止位
USART_InitStructure.USART_StopBits = USART_StopBits_1;
// 配置校验位
USART_InitStructure.USART_Parity = USART_Parity_No ;
// 配置硬件流控制
USART_InitStructure.USART_HardwareFlowControl =
USART_HardwareFlowControl_None;
// 配置工作模式,收发一起
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
// 完成串口的初始化配置
USART_Init(DEBUG_USARTx, &USART_InitStructure);
// 使能串口
USART_Cmd(DEBUG_USARTx, ENABLE);
}