STM32的定时器是个强大的模块,定时器使用的频率也是很高的,定时器可以做一些基本的定时,还可以做PWM输出或者输入捕获功能。 先看个图:
上图说明了,STM32中相关模块的总线结构,而这里用于测试的tiM3是接在了APB1上,APB1最大频率是36MHz,是算个低速的总线。 当APB1 的预分频系数为1 时,这个倍频器不起作用,定时器的时钟频率等于APB1 的频率;当APB1的预分频系数为其它数值(即预分频系数为2、4、8 或16)时,这个倍频器起作用,定时器的时钟频率等于APB1 的频率两倍。 也就是,当APB1不分频,TIM3的时钟速度为36MHz,当2分频是,APB1变成18MHz,但是TIM又会倍频,即TIM时钟等于18*2=36MHz。 好了,参考编程一般步骤: 1.系统初始化,主要初始化时钟等。 2.GPIO初始化,用于LED,有了灯就便于观察了。 3.TIM3的配置。 4.NVIC的配置。 5.编写中断服务函数。 首先,系统初始化直接使用SystemInit()函数即可,但是分析汇编启动代码,发现已经做了初始化了!所以就不去瞎凑热闹了。可以省去。 Reset_Handler PROC
EXPORT Reset_Handler [WEAK]
IMPORT __main
IMPORT SystemInit
LDR R0, =SystemInit
BLX R0
LDR R0, =__main
BX R0
ENDP 当然别忘记了先把GPIO和TIM模块的时钟给使能了!TIM3在APB1上,GPIO在APB2上。 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE); 第二步就是编写GPIO了,参考前面的点灯文章就明白了。代码如下: /**led**/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_WriteBit(GPIOA,GPIO_Pin_8,Bit_SET); 第三步,编写TIM3的配置。这里说一下定时频率的计算方法:Frequency=(SYSCLK/(Prescaler+1)) /(Period+1); SYSCLK即为系统时钟,这里使用72MHz,Prescaler为时钟预分频数,Period即为计数器值。 所以要得到1S的定时,即1Hz的频率,Period=1999,Prescaler= 35999,计算得出正好是1Hz,当然这里的配置关系不是随便来的。 /**tim3**/
TIM_DeInit(TIM3);
TIM_TimeBaseStructure.TIM_Period=1999; //自动重装载寄存器的值
TIM_TimeBaseStructure.TIM_Prescaler= 35999; //时钟预分频数
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1; //采样分频
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;//计数方式
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
TIM_ClearFlag(TIM3, TIM_FLAG_Update); //清除溢出中断标志
TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);
TIM_Cmd(TIM3, ENABLE); //开启时钟 第四步,配置NVIC。 /*nvic*/
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; //通道TIM2
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;//占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //副优先级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure); 最后呢编写个终端服务函数,每一次中断就变换一次LED的电平,也就是亮灭,这里用软件仿真一下看看LED端口波形即可。 void TIM3_IRQHandler(void)
{
static u8 sign = 1;
if ( TIM_GetITStatus(TIM3 , TIM_IT_Update) == SET)
{
TIM_ClearITPendingBit(TIM3 , TIM_FLAG_Update);
if(sign)
{
sign = 0;
GPIO_WriteBit(GPIOA,GPIO_Pin_8,Bit_RESET);
}
else
{
sign = 1;
GPIO_WriteBit(GPIOA,GPIO_Pin_8,Bit_SET);
}
}
} 实际,仿真波形如下:
|