使用STM32定时器实现计数功能

  1. TIM简介
  2. 时基单元介绍
  3. 函数介绍
  4. 实现代码

一.TIM简介

1.TIM(Timer)定时器:可以对输入的时钟进行计数,并在计数值达到设定值时触发中断。不仅具备基本的定时中断功能,而且还包含内外时钟源选择、输入捕获、输出比较、编码器接口、主从触发模式等多种功能。

2.根据复杂度和应用场景分为了高级定时器、通用定时器、基本定时器三种类型。

  • 高级定时器(TIM1,TIM8):拥有通用定时器全部功能,并额外具有重复计数器、死区生成、互补输出、刹车输入等功能
  • 通用定时器(TIM2到5):拥有基本定时器全部功能,并额外具有内外时钟源选择、输入捕获、输出比较、编码器接口、主从触发模式等功能
  • 基本定时器(TIM6,TIM7):拥有定时中断、主模式触发DAC的功能
  • 3.基本结构:

    4.由图可知使用时只用配置好一条通路就可以使用了。

  • RCC开启时钟——选择时钟源——配置时基单元——配置中断控制输出——NVIC——启动定时器

  • 二.时基单元介绍

    1.PSC:将定时器时钟源进行分频输出,降低计数器的频率

  • 计数器频率:CK_CNT = CK_PSC / ( PSC + 1 )
  • 2.CNT:定时器溢出频率=CK_PSC / ( PSC + 1 )(ARR + 1)


    三.函数介绍

  • TIM_InternalClockConfig开启需要的定时器时钟
  • TIM_TimeBaseInit时基单元初始化
  • TIM_ITConfig:使能中断输出信号
  • TIM_Cmd:使能计数器,用于启动定时器

  • 四.实现代码

    1.首先新建一个关于TIM定时器的.c文件用来存放代码,之后按照上方的步骤配置就可以了。

  • RCC开始需要使用的时钟,这里使用的通用定时器TIM2,是APB1的外设,没用用到别的GPIO口,所以只用开启TIM2就可以了
  • RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
  • 之后开启定时器时钟,这里用的TIM2
  • TIM_InternalClockConfig(TIM2);
  • 配置时基单元, 由于时基单元需要结构体参数,也就需要配置结构体
  •     TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
    	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;//控制时钟分频
    	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;//选择计数器模式,这里是向        
        上计数
    	/*这3是时基单元里关键寄存器的参数,主要是给PSC和ARR一个初始值
    	关于时间的计算用上方的公式,对72MHz进行7200分频,得到10K再计1万个数,得到1s的时间
    	注意ARR和PSC范围最大65535*/
    	TIM_TimeBaseInitStructure.TIM_Period = 10000 - 1;//ARR自动重装器的值
    	TIM_TimeBaseInitStructure.TIM_Prescaler = 7200 - 1;//PSC预分频器值
    	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;//重复计数器的值,高级计时器用的
    	
    	TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);//需要结构体参数,记得取地址符
  • 之后配置中断控制输出
  • TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);//使能中断
  • 配置NVIC,NVIC的相关代码在上一节有介绍
  •     NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//模式选择
    	NVIC_InitTypeDef NVIC_InitStructure;//定义结构体,配置结构体
    	NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;//选择通道
    	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能
    	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;//优先级
    	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    	
    	NVIC_Init(&NVIC_InitStructure);
  • 最后启动定时器
  • TIM_Cmd(TIM2,ENABLE);
  • 然后就可以用中断函数实现定时中断了,函数名是void TIM2_IRQHandler(void)
  • 主函数如下,关于Delay和OLED部分在前两节有相关代码,Timer的代码上方都给了,再建一个.h文件就行了
  • #include "stm32f10x.h"                  // Device header
    #include "Delay.h"
    #include "OLED.h"
    #include "Timer.h"
    
    uint16_t num;
    
    int main(void)
    {
    	OLED_Init();
    	Timer_Init();
    	
    	OLED_ShowString(1,1,"Num:");
    	while(1)
    	{
    		OLED_ShowNum(1,5,num,5);//每1s(中断进入一次)加1
    //		OLED_ShowNum(2,5,TIM_GetCounter(TIM2),5);//显示计数器的值
    	}
    }
    
    void TIM2_IRQHandler(void)
    {
    	if( TIM_GetITStatus(TIM2,TIM_IT_Update) == SET)//经典判断
    	{
    		num++;
    		TIM_ClearITPendingBit(TIM2,TIM_IT_Update);//手动清除标志位
    	}
    }
    
  • 接线图如下,OELD的接线其实也在上一节有
  • 作者:numbers0410

    物联沃分享整理
    物联沃-IOTWORD物联网 » 使用STM32定时器实现计数功能

    发表评论