目录
一、基本定时器简介
1.STM32F1系列的基本定时器为TIM6与TIM7
2.基本定时器为16位计数器,只能向上计数
3.基本定时器没有外部GPIO,是内部资源,只能用于定时
二、时基
定时器最主要的部分为时基部分,包括了预分频器,计数器,自动重装载寄存器
三、基本定时器的使用
1.配置中断优先级
2..配置时基初始化结构体
3.开启定时器中断
4.使能定时器
5.编写中断服务程序
6.编写功能函数
四、中断优先级初始化结构体
typedef struct
{
uint8_t NVIC_IRQChannel; //中断源
uint8_t NVIC_IRQChannelPreemptionPriority; //中断主优先级
uint8_t NVIC_IRQChannelSubPriority; //中断次优先级
FunctionalState NVIC_IRQChannelCmd; //中断使能
} NVIC_InitTypeDef;
五、配置中断优先级初始化结构体
//配置定时器中断优先级
static void TIM_BASC_NVIC(void)
{
NVIC_InitTypeDef NVIC_InitStruct;
//配置中断优先级分组
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
//设置中断源
NVIC_InitStruct.NVIC_IRQChannel = TIM6_IRQn;
//设置主优先级为0
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
//设置次优先级
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 2;
//使能中断
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
//中断优先级初始化
NVIC_Init(&NVIC_InitStruct);
}
六、配置时基初始化结构体
void TIM_BASIC_Init(void)//1ms中断
{
TIM_TimeBaseInitTypeDef TIM_BaseInitstruct;
TIM_BASC_NVIC();
//开启定时器时钟APB1
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6,ENABLE);
//配置定时器电器属性
TIM_BaseInitstruct.TIM_Period = 1000-1; //定时器重装载寄存器的值
TIM_BaseInitstruct.TIM_Prescaler = 72 - 1;//定时器时钟预分频值
/*分频因子(基本定时器没有):TIM_Prescaler是计数器分频器,TIM_ClockDivision是在采样时使用
的时钟分频器,比如输入捕获时的采样时钟或计算互补输出的死区的时钟;*/
// TIM_BaseInitstruct.TIM_ClockDivision = TIM_CKD_DIV1;
//计数模式:基本定时器只能向上计数,没有计数模式的设置
// TIM_BaseInitstruct.TIM_CounterMode = TIM_CounterMode_Up;//向上计数
//重复计数的值,基本定时器没有
// TIM_BaseInitstruct.TIM_RepetitionCounter = 0;
//初始化定时器
TIM_TimeBaseInit(TIM6,&TIM_BaseInitstruct);
//清除计时器中断标志位
TIM_ClearFlag(TIM6,TIM_FLAG_Update);
//开启计数中断
TIM_ITConfig(TIM6,TIM_IT_Update,ENABLE);
//使能计数器
TIM_Cmd(TIM6,ENABLE);
}
tips:进入一次中断的时间=1/(72M/TIM_Period/TIM_Prescaler);
七、按键为何要消抖
通常的按键所用的开关为机械弹性开关,当机械触点断开、闭合时,由于机械触点得到弹性作用,一个按键开关在闭合时不会马上稳定的接通,在断开时也不会一下子断开。会在闭合及断开的瞬间均伴随有一连串的抖动,为了不让这段抖动影响程序判断,所以需要对该按键进行消抖处理,消抖的方式有软件消抖与硬件消抖。我们一般使用软件消抖的方式。
tips:软件消抖的原理即是将上图按键按下及断开时产生的抖动通过延时的方式将这一断抖动在宏观上消除掉。
八、定时器按键消抖
//定时器消抖
void TIM6_IRQHandler(void)
{
char i = 0;
tim_count++;
if(TIM_GetITStatus(TIM6,TIM_IT_Update) != RESET)
{
if(tim_count > 10)
{
key[0].key_state = GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0);
key[1].key_state = GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_13);
for(i=0;i<2;i++)
{
switch(key[i].switch_state)
{
case 0:
{
if(key[i].key_state == 0)
{
key[i].switch_state = 1;
key[i].key_time = 0;
}
}break;
case 1:
{
if(key[i].key_state == 0)
{
key[i].switch_state = 2;
}
else
{
key[i].switch_state = 0;
}
}break;
case 2:
{
if(key[i].key_state == 1)
{
key[i].switch_state = 0;
if(key[i].key_time < 70)
{
key[i].short_state = 1;
}
}
else
{
key[i].key_time++;
if(key[i].key_time > 70)
{
key[i].long_state = 1;
key[i].switch_state = 0;
}
}
}break;
}
}
}
if(led_flag == 1)
{
led_count++;
if(led_count >= 500)
{
// LED1_TOGGLE;
LED_RED;
}
else
{
LED_GREEN;
}
if(led_count > 1000)
{
led_count = 0;
}
}
//清除中断挂起位,让它进入下一次中断
TIM_ClearITPendingBit(TIM6,TIM_FLAG_Update);
}
}
tips:本实验作者使用的是野火霸道开发板,开发板上有硬件消抖措施,可直接读取IO口输入电平,但是本实验所写的按键消抖适用于其它没有硬件消抖的开发板。
九、通过按键控制LED灯的闪烁与停止
void KEY_Process(void)
{
if(key[0].short_state == 1)
{
key1_flag = !key1_flag;
key[0].short_state = 0;
}
if(key[1].short_state == 1)
{
key1_flag = 2;
key[1].short_state = 0;
}
}
void LED_Process(void)
{
if(key1_flag == 1)
{
led_flag = 1;
}
else
{
led_flag = 0;
}
}
十、实验现象
实验现象为:当按键按下时,LED灯从红色变成绿色500ms交替闪烁,按键再次按下LED闪烁停止,实验与程序所写一致。