STM32——定时器中断实验

一、内部时钟选择

(计数器时钟可以有多个时钟源提供:内部时钟、外部时钟模式1、外部时钟模式2、内部触发模式。本次以内部时钟为时钟源,进行学习)

1、选择内部时钟  2、设置预分频系数、自动重装载值  3、使能定时器,写中断服务函数

 

通用定时器来源时APB1时钟,经过一个倍频系数产生CK_PSC,再通过一个分频产生CK_CNT。

如果APB1的分频系数为1,则通用定时器时钟就等于APB1时钟,否则通用定时器时钟就为APB1时钟的2倍。

例如:默认调用Systemlnit函数情况下:SYSCLK=168M  AHB时钟=168M   APB1时钟=42M  

APB1的分频系数=AHB/APB1时钟=4  所以,通用定时器时钟CK_INT=2*42M=84M

二、计数模式详细工作原理

1、向下计数模式:计数器从0计数到自动加载值(TIMx_ARR),然后重新从0开始计数并且产生一个计数器溢出事件。

假设时钟分频因子为1,则CK_INT与APB1相同,定时器时钟=CK_INT。首先使能定时器(CNT_EN),向上计数到重装载值36,计数到36之后会产生一个溢出事件并溢出,产生更新事件,接着计数器再次从0开始计数到36后再次产生更新事件。第一次向上计数到ARR产生一个中断,然后又从0开始第二次向上计数到ARR产生中断,即计时的长度就是从第一次计数开始到第二次计数开始(0~ARR之间)。

2、向下计数模式

同向上计数模式差不多,只是向下计数是从初值开始递减计数直到0

3、中央对齐计数模式

从自动重装载值计数到0会产生更新事件,然后再从0开始计数到ARR再次产生更新事件。

三、向上计数模式使用通用定时器

1、计数器当前值寄存器(TIMx_CNT)16位计数器

2、预分频寄存器(TIMx_PSC)16位设置预分频值

3、自动重装载寄存器(TIMx_ARR)16位寄存器

4、控制寄存器1(TIMx_CR1)位4控制计数方向(向上/向下),位0施恩计数器

5、DMA中断使能寄存器(TIMx_DIER)使能中断

四、常用库函数

1、定时器参数初始化:void TIM_TimeBaseInit(TIM_TypeDef* TIMx,TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);

typedef struct
{
  uint16_t TIM_Prescaler;  //预分频系数PSC

uint16_t TIM_CounterMode;//计数器模式DIR

uint32_t TIM_Period;//自动装载值

 uint16_t TIM_ClockDivision; //输入捕获

uint8_t TIM_RepetitionCounter;

}
TIM_TimeBaseStructure.TIM_Period=4999;//设置自动装载值

TIM_TimeBaseStructure.TIM_Prescaler=7199;//预分频系数

TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;

TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;//计数器计数模式

TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStructure);

2、定时器使能函数:

void TIM_Cmd(TIM_TypeDef* TIMx,FuctionalState NewState);

3、定时器中断使能函数:

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

4、状态标志位获取和清除:

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):

五、定时器中断使能步骤

1、使能定时器时钟:RCC_APB1PeriphClockCmd();

2、初始化定时器,配置ARR、PSC:TIM_YimeBaseInit();

3、开启定时器中断,配置NVIC:NVIC_Init();

4、使能定时器:TIM_Cmd();

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

6、代码(通过定时器中断配置,每500ms中断一次,然后中断服务函数中控制LED实现LED1状态取反闪烁,溢出时间:Tout=(ARR+1)(PSC+1)/Tclk)

int main(void)
{ 
 
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	delay_init(168);
	LED_Init();
	TIM3_Int_Init(4999,8399);
	while(1){
	LED0=!LED0;
		delay_ms(500);
		LED1=!LED1;
	}
}

void TIM3_Int_Init(u16 arr,u16 psc)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitABC;
NVIC_InitTypeDef NVIC_InitABC;
	
RCC_AHB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
	
	TIM_TimeBaseInitABC.TIM_Period=arr;
	TIM_TimeBaseInitABC.TIM_ClockDivision=TIM_CKD_DIV1;
	TIM_TimeBaseInitABC.TIM_CounterMode=TIM_CounterMode_Up;
	TIM_TimeBaseInitABC.TIM_Prescaler=psc;
	
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitABC);

TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);
	
	NVIC_InitABC.NVIC_IRQChannel=TIM3_IRQn;
	NVIC_InitABC.NVIC_IRQChannelCmd=0x01;
	NVIC_InitABC.NVIC_IRQChannelPreemptionPriority=0x03;
	NVIC_InitABC.NVIC_IRQChannelSubPriority=ENABLE;
	
NVIC_Init(&NVIC_InitABC);

TIM_Cmd(TIM3,ENABLE);
}
void TIM3_IRQHandler(void){

if(TIM_GetITStatus(TIM3,TIM_IT_Update)!=RESET)
{
  LED1=!LED1;
  TIM_ClearITPendingBit(TIM3,TIM_IT_Update);
}

}

#ifndef _TIMER_H
#define _TIMER_H

#include"sys.h"

void TIM3_Tin_Init(u16 arr,u16 psc);//16位寄存器,arr重装载值,psc预分频系数

#endif

定时器中断实验

  • 5
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值