本帖最后由 黑夜之狼 于 2016-11-11 16:02 编辑
在前面的两个帖子当中,我们介绍了GPIO和UART通信,这次,我们来介绍单片机里面比较重要的一个外设——定时器。
STM32的定时器功能十分强大,F0系列的定时器分了高级定时器(TIM1)、通用定时器(TIM3/14/15/16/17)、基本定时器(TIM6/TIM7)三种。在参考手册里面,定时器占了1/3篇幅(P220~467),可见其重要性。在这次中,我们将利用通用定时器TIM3中断来实现闪烁灯这个实验。
STM32F0的通用定时器是一个通过可编程预分频器(PSC)驱动的 16 位自动装载计数器(CNT)构成。可以被用于:测量输入信号的脉冲长度(输入捕获)或者产
生输出波形(输出比较和 PWM)等。 使用定时器预分频器和 RCC 时钟控制器预分频器,脉冲长度和波形周期可以在几个微秒到几个毫秒间调整。每个通用定时器都是完全独立的,没有互相共享的任何资源。
主要功能可看下面截图(参考手册P29),这里就不一一描述了
本次实验主要完成以下几个步骤:
1)TIM3时钟使能
TIM3是挂载在APB1上的,所以我们通过APB1总线下的使能时钟函数来使能TIM3
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //使能TIM3时钟
2)初始化定时器参数,设置自动重装载值,分频系数,计数方式等 可以通过库函数里面的初始化函数TIM_TimeBaseInit来实现:
void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct)
我们可以再keil里面追踪TIM_TimeBaseInitTypeDef这个结构体(在stm32f0xx_tim.h文件),查看其成员
typedef struct
{
uint16_t TIM_Prescaler;
uint16_t TIM_CounterMode;
uint16_t TIM_Period;
uint16_t TIM_ClockDivision;
uint8_t TIM_RepetitionCounter;
} TIM_TimeBaseInitTypeDef;
从上面代码可见,这个结构体有5个成员变量,但是,对于通用定时器来说,只有前面4个成员才有用,最后一个成员Tim_TimeBaseInitTypeDef只对高级定时器才有用的,这里就不多解释了,等到用高级定时器的时候才来分析吧。
针对TIM3初始化,具体的配置代码如下:TIM_TimeBaseStructure.TIM_Period = arr;//设置在下一个更新事件装入活动的自动重装载寄存器周期的值
TIM_TimeBaseStructure.TIM_Prescaler = psc; //设置用来作为TIMx时钟频率除数的预分频值
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);//根据指定的参数初始化TIMx的时间基数单位
这里有arr和psc这两个形参,可以通过在main函数调用的时候作为输入形参使用。
中断时间的计算公式如下:
Tout = ( (arr + 1) * (psc + 1) ) / Tclk
Tclk:TIM3的输入时钟频率(单位:MHz)
Tout:TIM3溢出时间(单位:us)
我们这里定时500ms,可以令arr = 4999,psc = 4799,Tclk = 48MHz
即:Tout = ( (4999 + 1) * (4799 + 1) ) / 48 = 500000us = 500ms
3)设置TIM3允许更新中断
因为这里我们需要利用TIM3的中断来实现闪烁灯,所以要允许TIM3产生中断更新,库函数如下:
TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE); //使能指定的TIM3中断,允许更新中断
4)TIM3中断优先级设置
既然使能了TIM3中断,那肯定要配置它的中断优先级了,具体代码如下:
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
5)使能TIM3
这一步实在太熟悉了,众所周知,STM32的所有外设,用哪个都要先使能的,库函数如下:
TIM_Cmd(TIM3, ENABLE); //使能TIM3
6)编写中断服务函数
最后一步,千万不要忘了写中断服务函数(当然,你可以用查询方式,不用中断)!我们这里是更新(溢出)中断,在中断服务函数开头,首先要判断是否溢出,然后执行相关操作,最后清除中断标志。具体代码如下:
void TIM3_IRQHandler(void)
{
if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)
{
TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
LED2_Toggle();
}
}
通过以上几个步骤,我们就可以通过TIM3的更新中断,来控制LED的亮灭了。
上传工程代码:
STM32F030_TIM3.rar
(2.04 MB)
|