STM32-定时器实验

TIM(Timer)定时器

定时器可以对输入的时钟进行计数,并在计数值达到设定值时触发中断

16位计数器、预分频器、自动重装寄存器的时基单元,在72MHz计数时钟下可以实现最大59.65s的定时

不仅具备基本的定时中断功能,而且还包含内外时钟源选择、输入捕获、输出比较、编码器接口、主从触发模式等多种功能 根据复杂度和应用场景分为了高级定时器、通用定时器、基本定时器三种类型。

在STM32F103C8T6中只有TIM1,2,3,4没有基本定时器。

主要运用通用定时器,通用定时器的框图如下:

时钟源选择可以是内部时钟RCC,也可以是外部时钟ETR,以及来自其他定时器的信号ITR。

要想使用定时器中断做程序,需要将其信号输出打通,如下图定时器中断的基本结构:

首先开启时钟源,选择内外时钟,完成后选择时钟源模式,这样时钟源部分已经打通,接下来配置的是时基单元,这个在库函数中由TIMBase_Init()函数可以完成配置。

接下来配置其中断输出,是事件响应还是,进入中断(中断标志位变换后的去向),完成后,配置NVIC进行分组配置后。

开启时钟使其使能开始。这样其初始化就完成了,随后在中断函数中写入需求功能即可在执行完函数后一定要清楚中断标志位。

接下来做一组实验,定时中断计时程序

其Timer.c文件如下:

#include "stm32f10x.h"                  // Device header

extern uint16_t Numm;
void Timer_Init(void)
{
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
	
	TIM_InternalClockConfig(TIM2);
	
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
	TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInitStruct.TIM_Period = 10000 - 1;    // ARR
	TIM_TimeBaseInitStruct.TIM_Prescaler = 7200 - 1;  // PSC
	TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;  
	
	TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStruct);
	TIM_ClearFlag(TIM2, TIM_FLAG_Update);
	
	TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	
	NVIC_InitTypeDef NVIC_InitStruct;
	NVIC_InitStruct.NVIC_IRQChannel = TIM2_IRQn;
	NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;  
	NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;   
	NVIC_Init(&NVIC_InitStruct);
	
	TIM_Cmd(TIM2, ENABLE);
	
}
void TIM2_IRQHandler(void)
{
	if(TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)
	{
		Numm ++;
	
		TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
	}

}

从以上代码可以看到,首先开启了TIM定时器的时钟,第二部选择了时钟模式,接下来是时基单元的配置包括计数模式,psc,arr等的初始化配置。

TIM_ClearFlag(TIM2, TIM_FLAG_Update);这一步的作用是在结构体初始化配置后,其程序默认的将中断标志位置为一,那么在我们初始化这个函数之后他将直接进入中断一次,在这个程序中的现象就是,计数在重新运行的时候初始位是一,为了消除这个影响在其后面手动清除其标志位。

接下来是配置中断,然后NIVIC优先级分组,配置NVIC,最后使能TIM2,至此其初始化配置完成。

下面的是TIM2的中断函数,中断函数在初始化文件中已经被指定,用其指定的名称来写中断函数,中断函数尽可能快速的完成,不要在里面停留太长时间,尽可能是一些标志位的变化,在完成后及时清除中断标志位。

其Timer.h文件如下:

#ifndef __TIMER_H
#define __TIMER_H

void Timer_Init(void);
uint16_t Timer_GetCounter(void);
#endif

其主函数main.c如下:

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "Timer.h"
uint16_t Numm;

int main(void)
{
	OLED_Init();
	Timer_Init();
	OLED_ShowString(1, 1, "Num:");
	OLED_ShowString(1, 1, "cnt:");
	while (1)
	{
		OLED_ShowNum(1, 5, Numm, 5);
		OLED_ShowNum(2, 5, TIM_GetCounter(TIM2), 5);
	}
}

 至此内部时钟的定时器实验完成,实验现象为,oled屏幕上能够显示计数和计数器的实时值。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值