掌握STM32串口一重映射技术
简介:STM32串口一重映射是嵌入式开发中的关键技术,用于实现STM32微控制器中USART1的灵活引脚配置。通过配置映射寄存器,可以根据项目需求自由选择GPIO引脚来实现串口通信,以适应不同的板卡布局和接口资源需求。本技术要点包括初始化GPIO端口、时钟使能、USART配置、重映射寄存器配置以及USART启用等步骤。理解并掌握STM32串口一重映射有助于在设计嵌入式系统时灵活调整硬件接口,优化系统设计并提高可靠性。 
1. STM32串口一重映射概念
1.1 串口重映射背景
串口重映射是微控制器设计中的一个高级功能,它允许开发者将微控制器上的硬件资源重新分配到不同的物理引脚。这种技术特别适用于STM32这类复杂微控制器,它们拥有多个串口以及其他外设,当标准的引脚分配不符合特定项目要求时,通过重映射可以灵活调整。
1.2 串口重映射的必要性
在某些应用场景中,物理空间有限或对电路板布线有特定要求,标准的硬件接口可能无法满足需求。这时,开发者可以利用STM32的重映射功能,将串口或其他外设如I2C、SPI等映射到不同的引脚上,从而优化硬件布局,降低设计复杂度。
1.3 重映射的优势与挑战
重映射的优势显而易见,它提高了硬件资源的灵活性,为电路设计提供更多的自由度。然而,这也带来了编程上的挑战,如需对代码进行适配以确保通信等外设功能正常工作。了解如何配置和管理这些重映射功能,对于STM32开发者来说是一项重要的技能。
2. STM32微控制器及其应用领域
2.1 STM32微控制器概述
STM32微控制器是由STMicroelectronics(意法半导体)生产的一系列32位ARM Cortex-M微控制器产品线。这一系列微控制器以其高性能、低功耗、丰富的集成外设和灵活的配置选项而广受青睐,非常适合各种嵌入式系统应用。接下来,将详细介绍STM32微控制器的架构特点和系列分类。
2.1.1 STM32架构特点
STM32微控制器基于ARM Cortex-M处理器内核构建,具有以下显著特点:
- 高性能处理能力 :Cortex-M内核专为实时控制应用而设计,提供了包括中断响应和执行时间在内的多项性能改进。
- 低功耗设计 :支持多种省电模式,能够根据任务需求调整功耗,延长电池寿命。
- 丰富的外设选择 :集成多种外设,如定时器、ADC、DAC、通信接口(USART, SPI, I2C等)。
- 灵活的内存配置 :支持内部和外部存储器接口,允许灵活扩展存储空间。
- 安全性和加密支持 :提供多种安全特性,包括硬件加密引擎和随机数生成器。
2.1.2 STM32系列分类
STM32家族庞大,根据性能、内存容量、外设集成度、价格等因素,提供了多种系列的产品。主要分为以下几个系列:
- STM32F0 :入门级微控制器,适用于简单控制任务。
- STM32F1 :中等性能,针对常规应用。
- STM32F4 :高性能系列,具有高级数字信号处理(DSP)功能和图形显示能力。
- STM32L :低功耗系列,专为能效优化设计。
- STM32H7 :高端高性能系列,带有更多的内存和外设。
2.2 STM32在各领域的应用
随着微控制器技术的不断进步,STM32的应用领域不断扩展。以下是一些主流的应用领域。
2.2.1 工业自动化
在工业自动化领域,STM32被广泛用于控制传感器、执行器、驱动器和通信接口。其出色的实时性能和丰富的外设接口满足了工业应用对稳定性和精确性的要求。
2.2.2 医疗设备
医疗设备制造商依赖STM32的低功耗特点和高效的处理能力,用于开发血糖监测器、心电图仪、超声波成像设备等产品。安全性和稳定性是这些应用中的首要考虑因素。
2.2.3 消费电子
在消费电子市场,STM32微控制器以其小尺寸和集成化的特性被用于智能手表、智能家居设备、手持游戏机等产品中,提供了强大的功能和出色的用户体验。
2.2.4 汽车电子
在汽车电子领域,STM32微控制器提供多种汽车级产品,用于控制车身电子、发动机管理系统、信息娱乐系统和安全系统。它们需要满足极端温度和可靠性要求。
在下一章节中,我们将讨论STM32微控制器在串口通信方面的基础知识,特别是USART1的特性及其应用场景,以及如何通过这一通信接口与其他设备进行有效交互。
3. 串口通信基础与USART1
3.1 串口通信基础
3.1.1 串口通信原理
串口通信(Serial Communication)是一种在电子设备之间进行数据传输的方式,广泛应用于微控制器、计算机外设、通信设备等领域。串口通信通过单根数据线(通常是TX和RX)和一根地线来传输数据,数据以位(bit)为单位依次发送。
在串口通信中,数据帧是由起始位、数据位、可选的奇偶校验位、停止位组成,有时还包含控制信息。起始位用于标志一个新字节的开始,后面跟着数据位,数据位的个数通常有5位、6位、7位或8位等。奇偶校验位用于数据错误检测,而停止位用来标志数据传输的结束。数据传输可以是同步的,也可以是异步的,其中异步通信是最常见的形式。
3.1.2 串口通信协议
串口通信协议是指双方在进行数据传输时所遵循的规范和约定,它包括了信号电平、数据格式、通信速率、校验方法等细节。在通用串行总线(Universal Serial Bus,简称USB)和RS-232等协议中,尽管它们使用了串口通信的方式,但在信号电平、接口形式、电气特性等方面有所不同。
以RS-232为例,它是一种广泛用于电脑和设备通信的串口标准,使用-15V到+15V的电压水平代表逻辑“0”和“1”,适合于传输速率较低、距离较短的情况。RS-232可以实现全双工通信,并且具有较高的抗干扰能力。相比较之下,TTL(晶体管-晶体管逻辑电平)串口通信使用0V和+5V表示逻辑“0”和“1”,在信号电平上更加适用于微控制器之间的通信。
3.2 USART1概述
3.2.1 USART1的特点
通用同步/异步收发传输器(USART)是微控制器中常见的通信接口之一,具有全双工通信能力,支持同步和异步模式,是STM32微控制器中的一种强大的串口通信接口。USART1是其中的实例,具有以下特点:
- 具有独立的波特率生成器。
- 支持多种数据格式,包括数据位、停止位和校验位的多种组合。
- 支持硬件流控制,例如RTS/CTS。
- 具有中断功能,可用于接收和发送操作。
- 提供DMA功能,可用于高吞吐量的通信。
3.2.2 USART1的应用场景
由于USART1具有诸多优点,它被广泛应用于多种场景中,包括:
- 调试信息输出:开发人员可以使用USART1将调试信息发送到电脑终端进行监控。
- 设备间通信:例如使用USART1进行STM32与PC、其他微控制器或其他通信设备之间的数据交换。
- 低速网络:利用USART1可以构建简单的低速网络,用于远程设备的数据交换。
- 配置外围设备:例如通过USART1与传感器、EEPROM等进行通信,以配置工作参数或读取测量数据。
3.2.3 USART1的物理连接
在物理连接方面,USART1的TX(发送)和RX(接收)引脚必须分别连接到通信伙伴的RX和TX引脚上。在一些应用中,如需要硬件流控制,则还需要连接RTS(请求发送)和CTS(清除发送)信号线。连接时应考虑到电平兼容性问题,因为STM32的TX和RX通常是TTL电平,而某些设备可能使用RS-232电平。在必要时,需要通过电平转换器来匹配不同设备的电平标准。
3.2.4 USART1的配置步骤
配置USART1通常包括以下几个步骤:
- 初始化GPIO引脚:配置GPIO为复用功能模式,以用于USART1的TX和RX功能。
- 设置波特率:通过配置USART的波特率寄存器来设定通信速率。
- 设置数据格式:配置数据位数、停止位、奇偶校验位等参数。
- 使能中断或DMA:根据需要选择是否使用中断或DMA传输方式。
- 使能USART1:最后,通过设置控制寄存器中的使能位来启动USART1。
3.2.5 USART1的编程示例
以下是一个使用STM32 HAL库编写的简单串口通信程序片段,展示了如何初始化USART1以及发送和接收数据的基本方法:
#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();
char *msg = "Hello USART!\r\n";
uint8_t rxBuffer[1];
while (1)
{
// 发送数据
HAL_UART_Transmit(&huart1, (uint8_t*)msg, strlen(msg), 100);
// 接收数据
HAL_UART_Receive(&huart1, rxBuffer, sizeof(rxBuffer), 100);
// 简单的处理接收到的数据
if (rxBuffer[0] == 'A') {
// 根据接收到的数据执行特定操作
}
HAL_Delay(1000);
}
}
static void MX_USART1_UART_Init(void)
{
huart1.Instance = USART1;
huart1.Init.BaudRate = 9600;
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;
HAL_UART_Init(&huart1);
}
在上述代码中,首先通过MX_USART1_UART_Init函数完成USART1的初始化,然后在主循环中使用HAL_UART_Transmit函数发送字符串,并使用HAL_UART_Receive函数接收数据。这里我们没有使用中断或DMA,而是使用了阻塞模式,意味着程序会等待每个操作完成后才继续执行。在实际应用中,为了不阻塞主循环,通常会采用中断或DMA来进行非阻塞的串口通信。
4. STM32的GPIO端口初始化与时钟配置
4.1 STM32 GPIO端口初始化
4.1.1 GPIO端口基本结构
通用输入输出(GPIO)端口是STM32微控制器中用于进行数据输入输出的基本组件。STM32的GPIO端口是由多个引脚组成的,每个引脚可以配置为输入或输出模式,并且可以具有不同的特性,如上拉/下拉电阻、输出类型(推挽或开漏)、速度、中断能力和模拟输入等。
GPIO端口通常具有以下特点:
- 可编程:每个引脚的模式(输入、输出、模拟)、输出类型(推挽或开漏)、速度、上拉/下拉配置等都可以通过软件进行配置。
- 多功能:一个GPIO引脚可以有多个功能,如复用为外设的信号输入输出。
- 外设复用:GPIO引脚除了基本的输入输出功能外,还可以复用为微控制器内部外设的接口。
4.1.2 GPIO初始化流程
为了使STM32的GPIO端口正常工作,需要进行一系列的初始化配置。初始化流程包括以下几个基本步骤:
- 时钟使能 :首先需要使能GPIO端口的时钟,因为只有时钟使能之后,端口才能被配置和操作。
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOxEN; // 使能GPIOx端口时钟,其中x表示不同的端口号
- 配置引脚模式和参数 :配置GPIO引脚的模式(输入、输出、模拟等)、输出类型、速度和上下拉等参数。
GPIOx->MODER &= ~(GPIO_MODER_MODERx); // 清除对应引脚的模式设置
GPIOx->MODER |= GPIO_MODER_MODERx_0; // 设置引脚为输入/输出/模拟模式,具体设置依赖于MODERx_0的值
- 上拉/下拉配置 :根据需要选择是否启用内部上拉或下拉电阻。
GPIOx->PUPDR &= ~(GPIO_PUPDR_PUPDRx); // 清除对应引脚的上下拉设置
GPIOx->PUPDR |= GPIO_PUPDR_PUPDRx_0; // 设置引脚为无上拉下拉/上拉/下拉,具体设置依赖于PUPDRx_0的值
- 输出类型配置 :配置GPIO引脚的输出类型,是否为推挽或开漏输出。
GPIOx->OTYPER &= ~(GPIO_OTYPER_OTx); // 清除对应引脚的输出类型设置
- 输出速度配置 :设置GPIO引脚的输出速度。
GPIOx->OSPEEDR &= ~(GPIO_OSPEEDR_OSPEEDRx); // 清除对应引脚的输出速度设置
GPIOx->OSPEEDR |= GPIO_OSPEEDR_OSPEEDRx_0; // 设置引脚的输出速度
- 使用引脚 :配置完成后,即可使用引脚进行相应的输入输出操作。
4.2 STM32时钟配置
STM32的时钟系统是其运行的核心,涉及到内部时钟源和外部时钟源的配置,以及时钟树和分频器的设置,这些配置决定了微控制器的运行速度和外设的工作频率。
4.2.1 内部时钟源
STM32内部有高速内部时钟源(HSI)和低速内部时钟源(LSI),HSI是系统启动后默认的时钟源。内部时钟源不需要外部电路支持,方便在没有外部晶振的情况下使用。
RCC->CR |= RCC_CR_HSION; // 启动HSI,HSI的使能位为HSION
4.2.2 外部时钟源
外部时钟源(HSE)通常由外部晶振提供,与内部时钟源相比,通常能提供更高的精度和稳定性。使用外部时钟源时,需要在时钟控制寄存器中选择外部时钟源,并等待其稳定。
RCC->CR |= RCC_CR_HSEON; // 启动HSE
while((RCC->CR & RCC_CR_HSERDY) == 0) { // 等待HSE就绪
; // 空操作,等待HSE稳定
}
4.2.3 时钟树和分频器配置
在STM32中,系统时钟(SYSCLK)可以通过内部时钟源或外部时钟源得到,并且可以通过不同的分频器配置来得到外设时钟。如APB总线、AHB总线时钟以及各种外设的时钟。
RCC->CFGR |= RCC_CFGR_SW_HSE; // 设置系统时钟源为HSE
RCC->CFGR |= RCC_CFGR_PPRE1_DIV2 | RCC_CFGR_PPRE2_DIV1; // 设置APB1和APB2分频因子,APB1分频因子为2,APB2分频因子为1
通过上述配置,STM32的GPIO端口初始化和时钟配置可以得到精确的控制,为后续的应用开发提供了稳定的运行环境。
5. USART1工作参数配置与重映射配置步骤
5.1 USART1工作参数配置
波特率设置
在串口通信中,波特率是决定数据传输速率的关键参数。STM32的USART1允许用户设置不同的波特率以匹配不同的通信需求。波特率的配置涉及到时钟源的选择、分频系数的确定以及USART的时钟配置。
void USART1_BaudRate_Config(uint32_t baudrate) {
RCCispersizer = 8; // 设置APB时钟分频值
USART1->BRR = (uint16_t) (SystemCoreClock / baudrate); // 计算波特率寄存器的值
}
在上述代码示例中,我们首先设置了APB1总线的时钟分频值。这是因为USART1通常挂在APB1总线上。接下来,我们计算了波特率寄存器的值,这个值是根据系统时钟频率除以所期望的波特率得到的。系统核心时钟(SystemCoreClock)是预先定义好的系统时钟频率值, baudrate 是我们想要设置的波特率。
数据位、停止位和校验位配置
在进行串口通信时,除了波特率,还需要设置数据位、停止位和校验位。这些参数共同定义了通信的数据帧格式。
void USART1_Framing_Config(uint8_t data_bits, uint8_t stop_bits, uint8_t parity) {
USART1->CR1 &= ~(USART_CR1_M | USART_CR1_PCE | USART_CR1_PS);
USART1->CR2 &= ~USART_CR2_STOP;
USART1->CR1 |= data_bits; // 设置数据位
USART1->CR1 |= parity; // 设置校验位
USART1->CR2 |= (stop_bits << USART_CR2_STOPPos); // 设置停止位
}
在这段代码中,我们首先清除了相关的CR1和CR2寄存器中的配置位,然后根据传入的参数重新配置。 data_bits 参数可以设置为 USART_CR1_M0 或 USART_CR1_M1 来选择8位或9位数据帧长度; parity 参数可以配置为无校验、偶校验或奇校验; stop_bits 参数决定了停止位的位数,通常是1位或2位。
5.2 重映射配置步骤
重映射前的准备工作
在STM32中,重映射是指将外设(比如USART1)的引脚映射到不同的GPIO引脚上。这在电路板设计中非常有用,特别是在空间受限的情况下,可以灵活地使用不同的引脚。
void USART1_Remap_Prepare(void) {
RCC->APB2ENR |= RCC_APB2ENR_AFIOEN; // 启用AFIO时钟
AFIO->MAPR &= ~(AFIO_MAPR_USART1_REMAP); // 清除重映射位
}
在这段代码中,我们首先启用了高级定时器的复用功能时钟(AFIO)。AFIO时钟是必须的,因为它负责管理外设的重映射功能。然后,我们清除了与USART1相关的重映射位,以便我们可以重新设置它。
重映射的具体步骤
重映射的具体步骤依赖于STM32系列和引脚的实际布局。例如,STM32F103系列的USART1默认连接到PA9(TX)和PA10(RX),但可以通过AFIO_MAPR寄存器将其重映射到其他引脚。
void USART1_Remap_Config(uint8_t remap_type) {
USART1_Remap_Prepare(); // 执行准备工作
AFIO->MAPR |= remap_type; // 根据重映射类型设置相应位
}
在 USART1_Remap_Config 函数中,我们首先调用 USART1_Remap_Prepare 函数来准备重映射。然后根据 remap_type 参数来设置AFIO_MAPR寄存器的相应位。 remap_type 可以被设置为不同的值,来实现不同的引脚映射配置。
重映射的测试验证
配置完成重映射后,需要进行测试验证以确保一切按预期工作。这通常涉及到发送一个已知的数据帧并验证它是否被正确接收。
void USART1_Remap_Test(void) {
// 初始化USART1
// 配置GPIO
// 配置USART1工作参数
// 配置重映射
// ...
// 发送数据帧
uint8_t test_data[] = "Hello USART1!";
for (int i = 0; i < sizeof(test_data); i++) {
while (!(USART1->SR & USART_SR_TXE)); // 等待发送缓冲区为空
USART1->DR = test_data[i]; // 发送数据
}
// 接收数据帧并验证
// ...
}
在测试函数 USART1_Remap_Test 中,我们首先进行初始化,包括GPIO和USART1的工作参数配置以及重映射。接着,我们通过循环发送已知数据帧,并检查USART状态寄存器中的TXE(发送缓冲区为空)位来确保数据被逐字节发送。在实际应用中,接收验证部分应当通过检查接收到的数据帧是否与发送的完全一致来完成。
通过这些步骤的精确配置与测试,我们可以确保STM32的USART1重映射配置正确无误,并在实际项目中稳定运行。这为灵活设计PCB和优化信号连接提供了可能性。
6. 防止信号冲突及中断/DMA配置与实际应用意义
6.1 防止信号冲突和中断/DMA配置
在处理多任务的嵌入式系统中,防止信号冲突是确保系统稳定运行的关键。当中断和直接内存访问(DMA)被配置使用时,这种冲突的可能性尤其需要考虑。
6.1.1 中断优先级配置
中断优先级配置允许系统根据紧急程度和重要性对中断进行排序。STM32微控制器中,可以通过编写相应的代码来设置中断优先级。例如,在处理USART1接收中断时,通过设置NVIC(嵌套向量中断控制器)的优先级寄存器来确保关键任务不会被低优先级中断所干扰。
void USART1_IRQHandler(void) {
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) {
// 处理接收到的数据
}
}
int main(void) {
NVIC_InitTypeDef NVIC_InitStructure;
// 配置NVIC优先级分组
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
// 配置USART1接收中断优先级
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; // 抢占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; // 响应优先级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
// 其他初始化代码...
}
在上面的代码中,我们通过 NVIC_Init 函数配置了USART1接收中断的优先级。需要注意的是,抢占优先级高于响应优先级,所以数值越小,优先级越高。
6.1.2 DMA传输机制
直接内存访问(DMA)是一种允许硬件子系统直接读写系统内存的技术,而无需CPU的干预。这样可以减少CPU的负载,并且提高数据传输的效率。在STM32中,配置DMA非常简单,首先需要启用DMA时钟,然后配置相应的DMA通道和传输参数。
void DMA_Configuration(void) {
DMA_InitTypeDef DMA_InitStructure;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); // 启用DMA1时钟
// 配置DMA1 Channel5以传输数据到USART1的数据寄存器
DMA_DeInit(DMA1_Channel5);
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&USART1->DR;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)buffer; // buffer是数据源
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
DMA_InitStructure.DMA_BufferSize = sizeof(buffer);
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel5, &DMA_InitStructure);
DMA_Cmd(DMA1_Channel5, ENABLE); // 启用DMA通道
}
在上述示例代码中,我们配置了DMA1的Channel5,使其负责将buffer中的数据通过USART1传输出去。通过设置DMA循环模式和传输大小,我们可以实现连续的数据传输,无需CPU干预。
6.2 重映射技术的实际应用意义
6.2.1 系统性能优化
重映射技术允许开发者根据应用需求对硬件资源进行重新配置,从而优化系统性能。以STM32为例,通过软件重映射,可以在不更改物理连接的情况下改变某个功能的硬件接口,这为资源受限的嵌入式应用提供了极大的灵活性。
例如,如果一个应用需要使用多个串口通信,而STM32的硬件资源有限,开发者可以将一个不需要的接口(如TIM的PWM输出)重映射为USART接口,这样就可以在不增加硬件成本的情况下,实现额外的串口通信功能。
6.2.2 功能扩展及案例分析
在某些应用场景中,如工业控制、医疗设备等,系统的功能扩展需求可能非常复杂。通过重映射技术,开发者不仅可以扩展系统的通信能力,还可以通过软件配置来优化特定的应用模块。
考虑以下案例:在一个医疗设备中,需要实现多种传感器数据的采集和实时传输。通常,这样的设备会同时使用多个串口来连接不同类型的传感器。在设备设计之初,开发者可能没有预见到所有未来的扩展需求。但通过重映射技术,可以在软件层面对STM32的GPIO和外设接口进行重配置,以适应新的需求,避免了硬件改动,降低了成本。
此外,重映射还允许将某个外设的中断信号映射到不同的中断线,这有助于更好地管理中断信号,减少冲突,并允许系统更灵活地处理多任务。对于处理大量数据或者实时性要求较高的应用,这样的灵活性至关重要。
通过对重映射技术的实际应用进行分析,我们可以看出它在功能扩展和系统性能优化方面起到了关键作用。在今后的嵌入式系统设计中,重映射技术将持续发挥其强大的作用。
简介:STM32串口一重映射是嵌入式开发中的关键技术,用于实现STM32微控制器中USART1的灵活引脚配置。通过配置映射寄存器,可以根据项目需求自由选择GPIO引脚来实现串口通信,以适应不同的板卡布局和接口资源需求。本技术要点包括初始化GPIO端口、时钟使能、USART配置、重映射寄存器配置以及USART启用等步骤。理解并掌握STM32串口一重映射有助于在设计嵌入式系统时灵活调整硬件接口,优化系统设计并提高可靠性。
更多推荐


所有评论(0)