定时器
STM32F4 定时器分类(共14个):
高级定时器:TIM1 、TIM8 (有4个独立通道)
通用定时器: TIM2-TIM5,TIM9-TIM14
基本定时器: TIM6 、 TIM7
控制器上所有定时器都是彼此独立的,不共享任何资源。就功能上来说通用定时器包含所有基本定时器功能,而高级控制定时器包含通用定时器所有功能。所以高级控制定时器功能繁多,但也是最难理解的。
预分频系数PSC:用来降低频率,操作:时钟总线频率除(PSC + 1)
最大接口时钟:APB2:84MHz;APB1:42MHz
基本定时器
功能:第一就是基本定时功能,生成时基。第二就是 专门用于驱动数模转换器(DAC)
特性(TIM6 和 TIM7):
● 16 位自动重载递增计数器(eg:0~ARR+1~0)当计数值ARR太大可以分段计时
(ARR_max = 65535(2^16-1)) (PSC+1)* (ARR+1) 微秒 尽可能接近或等于计时值
● 16 位可编程预分频器,用于对计数器时钟频率进行分频(即运行时修改),分频系数PSC介于 1 和 65536 之间
● 用于触发 DAC 的同步电路
● 发生如下更新事件时会生成中断/DMA 请求:计数器上溢
框图
-
CK_PSC是定时器时钟TIMxCLK,经APB1预分频器后分频提供,我们的芯片为42Mhz,×2为84Mhz

-
定时器时钟经过PSC 预分频器之后,即CK_CNT,用来驱动计数器计数。
-
计数器CNT 是一个16 位的计数器,向上,向下,向上/下计数模式(基本定时器只能递增计数),最大计数值为65535(2的16次方)。当计数达到自动重装载寄存器的时候产生更新事件,并清零从头开始计数。
-
自动重装载寄存器ARR 是一个16位的寄存器,这里面装着计数器能计数的最大数值。当计数到这个值的时候,如果使能了中断的话,定时器就产生溢出中断。
编程
题目
编程实现定时器定时1s触发中断,通过LED灯闪烁验证实验现象。
定时器结构体参数:
(1) TIM_Prescaler:定时器预分频器设置,时钟源经该预分频器才是定时器时钟,它设定TIMx_PSC
寄存器的值。可设置范围为0 至65535,实现1 至65536 分频。
(2) TIM_CounterMode:定时器计数方式,可是在为向上计数、向下计数以及三种中心对齐模式。
基本定时器只能是向上计数,即TIMx_CNT 只能从0 开始递增,并且无需初始化。
(3) TIM_Period:定时器周期,实际就是设定自动重载寄存器的值,在事件生成时更新到影子寄存器。可设置范围为0 至65535。
(4) TIM_ClockDivision:时钟分频,设置定时器时钟CK_INT 频率与数字滤波器采样时钟频率分频比,基本定时器没有此功能,不用设置。
(5) TIM_RepetitionCounter:重复计数器,属于高级控制寄存器专用寄存器位,利用它可以非常容易控制输出PWM 的个数。这里不用设置。
思路
(1) 初始化LED的GPIO口;
(2) 开启基本定时器时钟(TIM6);
(3) 设置定时器周期、预分频器和计数最大值;
(4) 启动定时器更新中断,并开启定时器;
(5) 定时器中断服务函数实现LED翻转。
/*
代码思路:
1.时钟使能
2.定时器配置
a.结构体申明 TIM_TimeBaseInitTypeDef
b.结构体配置 计数模式,PSC、ARR值
c.初始化 TIM_TimeBaseInit
3.定时器中断
a.确定中断触发方式:定时器更新中断
b.结构体配置,定时器6为TIM6_DAC_IRQn频道
c.重写中断服务函数
4.定时器使能
TIM_Cmd
*/
//led.c
void LED_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);//通电还是断电
//开始配置F端口下的9号跟10号引脚。
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9|GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode= GPIO_Mode_OUT; //输出模式
GPIO_InitStructure.GPIO_OType=GPIO_OType_PP; //推挽输出
GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP; //上拉模式,暂时没讲
GPIO_InitStructure.GPIO_Speed=GPIO_High_Speed; //引脚响应速度
GPIO_Init(GPIOF, &GPIO_InitStructure);
GPIO_SetBits(GPIOF,GPIO_Pin_9|GPIO_Pin_10);//初始化不亮
}
//timer.h
#ifndef __TIMER_H
#define __TIMER_H
#include "stm32f4xx.h"
void Timer6_Init(uint16_t psc, uint32_t arr);
#endif
//timer.c
#include "timer.h"
void Timer6_Init(uint16_t psc, uint32_t arr)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE); //时钟使能
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM6向上计数,递增
TIM_TimeBaseStructure.TIM_Prescaler = psc-1;//PSC值
TIM_TimeBaseStructure.TIM_Period = arr-1;//ARR值
TIM_TimeBaseInit(TIM6, &TIM_TimeBaseStructure);
TIM_ITConfig(TIM6, TIM_IT_Update, ENABLE);//中断使能
NVIC_InitStructure.NVIC_IRQChannel = TIM6_DAC_IRQn;//定时器6中断频道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01;//抢占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;//响应优先级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//启用中断通道
NVIC_Init(&NVIC_InitStructure);//中断初始化
TIM_Cmd(TIM6, ENABLE); //定时器使能
}
定时器中断服务函数
void TIM6_DAC_IRQHandler(void)
{
static int a = 0;
if(TIM_GetITStatus(TIM6, TIM_IT_Update) == SET)
{
if(a == 2)
{
//反转灯的状态
GPIO_ToggleBits(GPIOF, GPIO_Pin_9 | GPIO_Pin_10);
a = 0;
}
a++;
}
TIM_ClearITPendingBit(TIM6, TIM_IT_Update);
}
main.c
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
LED_Init();
Timer6_Init(8400, 10000);
while(1)
{
}
}
1583

被折叠的 条评论
为什么被折叠?



