基于STM32F103ZET6实现定时器中断

为了实现定时器中断的判断,将利用 TIM3 的定时器中断来控制 DS1 的翻转,在主函数用 DS0的常亮转来提示程序正在运行。
STM32F1 的定时器功能很多,有 TIME1 和 TIME8 等高级定时器,也有TIME2~TIME5 等通用定时器,还有 TIME6和 TIME7 等基本定时器。STM32F1 的通用定时器是一个通过可编程预分频器(PSC)驱动的 16 位自动装载计数器(CNT)构成。
STM32 的通用定时器可以被用于:
(1)测量输入信号的脉冲长度(输入捕获)
(2)产生输出波形(输出比较和 PWM)等。
使用定时器预分频器RCC 时钟控制器预分频器,脉冲长度和波形周期可以在几个微秒到几个毫秒间调整。每个通用定时器都是完全独立的,没有互相共享的任何资源。
那么什么时候可以出发定时器中断呢?
(1)更新:计数器向上溢出/向下溢出,计数器初始化(通过软件或者内部/外部触发)
(2)输入捕获
(3)输出比较
(4)计数器启动、停止、初始化或者由内部/外部触发计数
讲这么多,我们该如何配置可编程的寄存器呢?
1.控制寄存器
在这里插入图片描述
最低位是使能位,该位必须置 1,第 4 位 DIR 可以看出默认的计数方式是向上计数,同时也可以向下计数,第 5,6位是设置计数对齐方式的。从第 8 和第 9 位可以看出,我们还可以设置定时器的时钟分频因子为 1,2,4。
2.DMA/中断使能寄存器
在这里插入图片描述
只需要配置第 0 位,该位是更新中断允许位,我们用到的是定时器的更新中断,所以该位要设置为 1,来允许由于更新事件所产生的中断。
3.预分频寄存器(TIMx_PSC)
该寄存器用设置对时钟进行分频,然后提供给计数器,作为计数器的时钟。
高级定时器的时钟不是来自 APB1,而是来自 APB2 的。
4. TIMx_CNT 寄存器
该寄存器是定时器的计数器,该寄存器存储了当前定时器的计数值。
5.自动重装载寄存器(TIMx_ARR)
在这里插入图片描述
该寄存器在物理上实际对应着 2 个寄存器。一个是程序员可以直接操作的,另外一个是程序员看不到的,被叫做影子寄存器。
寄存器介绍完了,直接开始实践我为我们的代码!
定时器中断头文件timer.h

#ifndef TIMER_H
#define TIMER_H
extern void timer_init(void);
#endif

定时器中断源文件timer.c

#include "timer.h"
#include "sys.h"
#include "led.h"
void timer_init(void)
{
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	LED_Init();
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
	TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
	TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;
	TIM_TimeBaseInitStructure.TIM_Period= 5000;
	TIM_TimeBaseInitStructure.TIM_Prescaler=7199;
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure);
	TIM_Cmd(TIM3, ENABLE);
	TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE );
	NVIC_InitStructure.NVIC_IRQChannel=TIM3_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority=3;
	NVIC_Init(&NVIC_InitStructure);
	
}
void TIM3_IRQHandler(void)
{
	if(TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)
	{
		LED1=!LED1;
		TIM_ClearITPendingBit(TIM3, TIM_IT_Update );	
	}
}

主要就是定时器的初始化,有的读者就要问了,这样初始化那样初始化,到底怎么才能比较全面的初始化流程呢?
打个比方:定时器中断
包含
定时器:想要用到定时器,必须有提供的时钟,初始化定时器参数设置好了(TIM_TimeBaseInit()),我们就要去打开定时器(TIM_Cmd(TIM3, ENABLE)),然后(打开)使能更新中断(TIM_ITConfig( )
中断:中断初始化(包括优先级,中断类型NVIC_Init()),中断开启**(TIM_Cmd())**,
定时器中断主函数main.c

#include "led.h"
#include "sys.h"
#include "wwdg.h"
#include "timer.h"
int main(void)
{
	LED_Init();
	timer_init();
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); 
	 while(1)
	 { 
		 LED0=0;
	 }
}

现象
TIM3 的定时器中断来控制 DS1 的翻转,在主函数用 DS0的常亮

程序格式比较固定,希望大家能在以后的工作中举一反三,清楚原理就可以了。

发布了10 篇原创文章 · 获赞 14 · 访问量 4086

猜你喜欢

转载自blog.csdn.net/weixin_42271802/article/details/104525027