目录
1、定时器时钟频率
STM32F405xx/07xx 和 STM32F415xx/17xx 的定时器时钟频率由硬件自动设置。分为两种情况: 如果 APB 预分频器为 1,定时器时钟频率等于 APB 域(APB1和APB2)的频率;否则,定时器时钟频率等于 APB 域(APB1和APB2)的频率的两倍 (×2)。
下图为定时器的分布以及时钟频率:
2、定时原理
以定时500ms为例:
TIM_TimeBaseStructure.TIM_Period = (10000/2)-1; //定时时间的配置,也就是配置计数值
TIM_TimeBaseStructure.TIM_Prescaler = 8400-1; //配置分频值,确定定时器的时钟频率
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//向上计数,0->TIM_Period就会触发中断请求
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
由上图已经知道,定时器3(TIM3)的时钟频率为84MHz,为了方便计算,我们设置分频值为8400,这样的话定时器3只要进行10000次计数,就是1s时间的到达。
3、代码思路
- 使能定时器硬件时钟
- 设置定时器分频值
- 确定定时器计数值
- 使能定时器工作
- 使能定时器更新中断触发
- 配置定时器中断优先级
- 编写定时器中断服务函数
#include "stm32f4xx.h"
static GPIO_InitTypeDef GPIO_InitStruct;//不加*
static TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
static NVIC_InitTypeDef NVIC_InitStructure;
#define PFout(x) *(volatile uint32_t *)(0x42000000+(GPIOF_BASE+0x14-0x40000000)*32+(x)*4)
#define PAin(x) *(volatile uint32_t *)(0x42000000+(GPIOA_BASE+0x10-0x40000000)*32+(x)*4)
void TIM3_Init()
{
//打开定时器3的硬件时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
//配置优先级
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
//配置定时器3分频值和计数值
TIM_TimeBaseStructure.TIM_Period = 10000-1; //10000次计数为1秒,0~9999
TIM_TimeBaseStructure.TIM_Prescaler = 8400-1; //默认加1,预分频值为8400-1+1
TIM_TimeBaseStructure.TIM_ClockDivision = 0; //F407不支持
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//上升计数
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
//配置中断触发方式:计数值更新
TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);
//使能定时器3工作
TIM_Cmd(TIM3, ENABLE);
}
int main()
{
//uint32_t * pf9 = (uint32_t *)(0x42000000+((uint32_t)&GPIOF->ODR-0x40000000)*32+9*4);
//打开端口F的硬件时钟,就是为端口F供电
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);
//配置引脚
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_9;
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_OUT;
GPIO_InitStruct.GPIO_Speed=GPIO_High_Speed;
GPIO_InitStruct.GPIO_OType=GPIO_OType_PP;
GPIO_InitStruct.GPIO_PuPd=GPIO_PuPd_NOPULL;
GPIO_Init(GPIOF,&GPIO_InitStruct);//为何传地址
PFout(9)=1;
TIM3_Init();
while(1)
{
} //为何用此循环
}
void TIM3_IRQHandler(void)
{
//设置标志位
if(SET==TIM_GetFlagStatus(TIM3,TIM_IT_Update))
{
PFout(9)^=1;
//清空标志位
TIM_ClearITPendingBit(TIM3,TIM_IT_Update);
}
}
4、思考题
参照上述代码,编写其他定时器的初始化配置代码。