2021-04-21 通用定时器第二节(定时器中断实验)

定时器中断实验

一. 通用定时器的回顾

二. 常用寄存器和库函数配置

三. 编写定时器中断实验

1.1 内部时钟选择

在这里插入图片描述
内部时钟来源由AHB经过APB1的预分频产生时钟供定时器来用即产生内部时钟
在这里插入图片描述
除非APB1的分频系数是1,否则通用定时器的时钟等于APB1时钟的2倍。
默认调用SystemInit函数情况下:
SYSCLK = 72M
AHB时钟=72M
APB1时钟=36M
所以APB1的分频系数=AHB/APB1时钟=2
所以,通用定时器时钟CK_INT = 2*36M = 72M

1.2 计数器模式

向上计数模式(时钟分频因子=1)
在这里插入图片描述
首先使能定时器,由图看出自动重装载的值为36,当计数器寄存器读取到36时,会产生溢出事件,同时产生更新事件和更新中断标志。

2.1 定时器常用寄存器

1. 计数器当前值寄存器CNT

在这里插入图片描述
16位

2. 预分频寄存器TIMx_PSC

在这里插入图片描述

3. 自动重装载寄存器TIMx_ARR

在这里插入图片描述

4. 控制寄存器TIMx_CR1

在这里插入图片描述
主要用到位4和位0,位4控制方向;位0控制使能。

5. DMA中断使能寄存器TIMx_DIER

在这里插入图片描述

2.2 常用库函数

定时器参数初始化

  void TIM_TimeBaseInit(TIM_TypeDef* TIMx,TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);
   typedef struct
                  {
                     uint16_t TIM_Prescaler;        
                     uint16_t TIM_CounterMode;     
                     uint16_t TIM_Period;        
                     uint16_t TIM_ClockDivision;  
                     uint8_t TIM_RepetitionCounter;
                  } TIM_TimeBaseInitTypeDef;


             TIM_TimeBaseStructure.TIM_Period = 4999;
             TIM_TimeBaseStructure.TIM_Prescaler =7199;
             TIM_TimeBaseStructure.TIM_ClockDivision =   TIM_CKD_DIV1; T
             IM_TimeBaseStructure.TIM_CounterMode =   TIM_CounterMode_Up;
             TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);

·定时器使能函数:

 void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState)

·定时器中断使能函数:

 void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState);

·状态标志位获取和清除

     FlagStatus TIM_GetFlagStatus(TIM_TypeDef* TIMx, uint16_t TIM_FLAG);
                void TIM_ClearFlag(TIM_TypeDef* TIMx, uint16_t TIM_FLAG);
                ITStatus TIM_GetITStatus(TIM_TypeDef* TIMx, uint16_t TIM_IT);
                void TIM_ClearITPendingBit(TIM_TypeDef* TIMx, uint16_t TIM_IT);

2.3 定时器中断实现步骤

1. 使能定时器时钟
RCC_APB1PeriphClockCmd();

2. 初始化定时器,配置ARR,PSC
TIM_TimeBaseInit();

3. 开启定时器中断,配置NVIC
void TIM_ITConfig();
NVIC_Init();

4. 使能定时器
TIM_Cmd();

5. 编写中断服务函数
TIMx_IRQHandler();

3.1 编写

程序要求

通过定时器中断配置,每500ms中断一次,然后中断服务函数中控制LED实现LED1状态取反(闪烁)。

Tout(溢出时间)=(ARR+1)(PSC+1)/Tclk

编写timer.c

#include "timer.h"
#include "led.h"

//通用定时器中断初始化
//这里时钟选择为APB1的2倍,而APB1为36M
//arr:自动重装值。
//psc:时钟预分频数
//这里使用的是定时器3!

void TIM3_Int_Init(u16 arr,u16 psc)
{
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	NVIC_InitTypeDef NVIC_InitStructure;

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能

	TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值	 计数到5000为500ms
	TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值  10Khz的计数频率  
	TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
 
	TIM_ITConfig(  //使能或者失能指定的TIM中断
		TIM3, //TIM2
		TIM_IT_Update ,
		ENABLE  //使能
		);
	NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;  //TIM3中断
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  //先占优先级0级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;  //从优先级3级
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
	NVIC_Init(&NVIC_InitStructure);  //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器

	TIM_Cmd(TIM3, ENABLE);  //使能TIMx外设
							 
}

void TIM3_IRQHandler(void)   //TIM3中断
{
	if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //检查指定的TIM中断发生与否:TIM 中断源 
		{
		TIM_ClearITPendingBit(TIM3, TIM_IT_Update  );  //清除TIMx的中断待处理位:TIM 中断源 
		LED1=!LED1;
		}
}

编写led.c

#include "led.h"

//初始化PB5和PE5为输出口.并使能这两个口的时钟		    
//LED IO初始化

void LED_Init(void)
{
 
 GPIO_InitTypeDef  GPIO_InitStructure;
 	
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOD, ENABLE);	 //使能PA,PD端口时钟
	
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;				 //LED0-->PA.8 端口配置
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 //推挽输出
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		 //IO口速度为50MHz
 GPIO_Init(GPIOA, &GPIO_InitStructure);					 //根据设定参数初始化GPIOA.8
 GPIO_SetBits(GPIOA,GPIO_Pin_8);						 //PA.8 输出高

 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;	    		 //LED1-->PD.2 端口配置, 推挽输出
 GPIO_Init(GPIOD, &GPIO_InitStructure);	  				 //推挽输出 ,IO口速度为50MHz
 GPIO_SetBits(GPIOD,GPIO_Pin_2); 						 //PD.2 输出高 
} 

编写main.c

#include "led.h"
#include "delay.h"
#include "sys.h"
#include "timer.h"

 int main(void)
 {	
	delay_init();	    	 //延时函数初始化
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);// 设置中断优先级分组2
	LED_Init();		  	//初始化与LED连接的硬件接口
	TIM3_Int_Init(4999,7199);//10Khz的计数频率,计数到5000为500ms  
   	while(1)
	{
		LED0=!LED0;
		delay_ms(200);		   
	}
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值