STM32F407 的通用定时器与串口配置深度解析
在 STM32F407 芯片的开发过程中,通用定时器和串口的配置与使用是极为关键的技能点。本文将结合提供的代码示例,深入剖析这两个模块的配置流程、工作原理以及实际应用,助力开发者更好地掌握相关技术。
一、通用定时器
(一)定时器时钟频率规则
在使用 STM32F407 芯片的定时器时,其时钟频率的设定遵循特定规则。对于 STM32F405xx/07xx 和 STM32F415xx/17xx 系列,定时器时钟频率由硬件自动设置,具体分为两种情况:
-
当 APB 预分频器为 1 时,定时器时钟频率等于 APB 域的频率。
-
若 APB 预分频器不为 1,定时器时钟频率则是 APB 域频率的两倍。
(二)通用定时器配置步骤
-
使能定时器时钟:使用
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
语句开启定时器 3 的时钟。这是定时器工作的基础,只有使能时钟,后续操作才有意义。 -
配置定时器参数
-
TIM_TimeBaseStructure.TIM_Period
:用于设置自动重装载寄存器的值,也就是计数值。例如,期望定时时间为 1ms,若定时器分频后的工作频率为 10000Hz(对应 100us 计数周期),那么为实现 1ms 定时,需要计数 10 次,TIM_Period
的值应设置为 (10000/1000) - 1 = 9 (从 0 开始计数,所以减 1)。 -
TIM_TimeBaseStructure.TIM_Prescaler
:用于设置预分频器的值。如设置为 8400 - 1,意味着将定时器的输入时钟(假设为 84MHz)分频为 84MHz/(8400)=10kHz ,从而调整定时器的计数频率。 -
TIM_TimeBaseStructure.TIM_ClockDivision
:用于设置时钟分频。TIM_CKD_DIV1
表示不分频,它影响定时器内部某些信号的分频关系,在本示例中选择不分频,方便后续代码的移植和理解。 -
TIM_TimeBaseStructure.TIM_CounterMode
:设置计数模式,TIM_CounterMode_Up
表示向上计数模式,即从 0 开始计数,计数值达到TIM_Period
设定值时触发溢出事件。
-
- 配置 NVIC 参数
-
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
:用于设置中断优先级分组,这里选择分组 2,确定抢占优先级和子优先级的分配方式。 -
NVIC_InitStructure.NVIC_IRQChannel
:指定中断通道,如TIM3_IRQn
表示定时器 3 的中断通道。 -
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority
:设置抢占优先级,示例中设为 0 。 -
NVIC_InitStructure.NVIC_IRQChannelSubPriority
:设置子优先级,示例中设为 0 。 -
NVIC_InitStructure.NVIC_IRQChannelCmd
:使能中断通道。
-
-
定时器中断配置:
TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);
用于使能定时器 3 的更新中断,当定时器计数值达到TIM_Period
设定值并溢出时,会触发更新中断。 -
使能定时器工作:
TIM_Cmd(TIM3, ENABLE);
启动定时器 3,使其按照配置参数开始计数工作。 -
定义定时器中断函数:在
TIM3_IRQHandler
函数中,通过TIM_GetITStatus(TIM3,TIM_IT_Update)==SET
检测是否发生更新中断事件。若发生,进行相应处理,如示例中每 1000 次中断(即 1 秒)通过串口发送 "hello\r\n" 字符串,并使用TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
清空中断标志位,告知 CPU 中断已处理完毕。
二、串口配置
(一)串口配置目的及整体流程
配置串口的主要目的是为了方便调试定时器。在本代码示例中,对串口 1 进行了详细配置,主要步骤如下:
-
使能端口和串口时钟
-
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);
:使能 GPIOA 端口时钟,因为串口 1 的引脚复用在 GPIOA 上。 -
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
:使能串口 1 的时钟。
-
-
引脚复用功能映射:
GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1);
和GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1);
将 GPIOA9 和 GPIOA10 分别复用为串口 1 的 TX 和 RX 引脚。 -
端口配置
-
GPIO_InitStructure.GPIO_Pin
:设置为GPIO_Pin_9 | GPIO_Pin_10
,即配置 GPIOA9 和 GPIOA10 引脚。 -
GPIO_InitStructure.GPIO_Mode
:设置为GPIO_Mode_AF
,表示复用功能模式。 -
GPIO_InitStructure.GPIO_Speed
:设置为GPIO_Speed_50MHz
,满足串口通信速率要求。 -
GPIO_InitStructure.GPIO_OType
:设置为GPIO_OType_PP
,推挽复用输出模式。 -
GPIO_InitStructure.GPIO_PuPd
:设置为GPIO_PuPd_UP
,上拉模式,确保引脚在未输入时处于稳定的高电平状态。 -
GPIO_Init(GPIOA,&GPIO_InitStructure);
:初始化 GPIOA9 和 GPIOA10 引脚。
-
-
串口参数配置
-
USART_InitStructure.USART_BaudRate
:设置波特率为 115200。 -
USART_InitStructure.USART_WordLength
:设置字长为 8 位。 -
USART_InitStructure.USART_StopBits
:设置一个停止位。 -
USART_InitStructure.USART_Parity
:设置无奇偶校验位。 -
USART_InitStructure.USART_HardwareFlowControl
:设置无硬件数据流控制。 -
USART_InitStructure.USART_Mode
:设置为USART_Mode_Tx|USART_Mode_Rx
,即收发模式。 -
USART_Init(USART1, &USART_InitStructure);
:初始化串口 1。
-
-
中断配置
-
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
:设置中断优先级分组为 2 。 -
NVIC_InitStructure.NVIC_IRQChannel
:指定为USART1_IRQn
,即串口 1 的中断通道。 -
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority
:设置抢占优先级为 1 。 -
NVIC_InitStructure.NVIC_IRQChannelSubPriority
:设置子优先级为 1 。 -
NVIC_InitStructure.NVIC_IRQChannelCmd
:使能中断通道。 -
USART_Cmd(USART1, ENABLE);
:使能串口 1。
-
(二)重定向 printf 函数到串口
通过重定向fputc
函数,实现将printf
函数的输出重定向到串口。这样在代码中使用printf
函数时,输出内容会通过串口发送出去,方便调试信息的查看。
int fputc(int ch, FILE *f) {/* 发送一个字节数据到串口 */USART_SendData(USART1, (uint8_t)ch);/* 等待发送完毕 */while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET); return (ch);
}
三、注意事项
-
时钟配置修改:需要修改
system_stm32f4xx.c
中的时钟配置。在stm32f407.h
中,将HSE_VALUE
修改为实际使用的晶振频率,以确保系统时钟和定时器时钟等的准确性。例如,如果实际晶振频率为 8MHz,就需要将HSE_VALUE
的值设置为 8000000。 -
代码优化与扩展:在实际项目中,可根据需求进一步优化和扩展代码。比如,在定时器中断函数中,可以添加更多复杂的业务逻辑,而不仅仅是发送固定字符串;串口配置部分,可根据不同的通信需求调整波特率、数据位、停止位和校验位等参数。
通过上述对 STM32F407 通用定时器和串口配置的详细解析,开发者可以更加深入地理解这两个模块的工作机制和应用方法,为开发更复杂、更高效的嵌入式系统奠定坚实基础。希望本文能对大家在 STM32F407 开发过程中有所帮助