STM32F103入门 | 9.定时器简述

STM32F103系列的单片机一共有11个定时器:

2个高级定时器

4个通用定时器

2个基本定时器

2个看门狗定时器

1个系统滴答定时器

除去看门狗定时器和滴答定时器,其他8个定时器列表:

其中,

TIM1和TIM8是高级定时器

TIM2 - TIM5是通用定时器

TIM6和TIM7是基本定时器

这8个定时器都是16位的,它们计数的类型除了基本定时器TIM6和TIM7,都支持向上、向下、向上/向下3种计数模式。

 

计数器的3种计数模式:

向上计数模式:从0开始,计到arr预设值,产生溢出事件,返回重新计时;

向下计数模式:从arr预设值开始,计到0,产生溢出事件,返回重新计时;

中央对齐模式:从0开始向上计数,计到arr产生溢出事件,然后向下计数,计数到1以后,又产生溢出,然后再从0开始向上计数(这种计数方式也叫向上/向下计数)。

 

基本定时器(TIM6和TIM7)主要功能:

只有最基本的定时功能。基本定时器TIM6和TIM7各包含一个16位自动装载计数器,由各自的可编程预分频器驱动。

 

通用定时器(TIM2 - TIM5)主要功能:

除了基本的定时器的功能外,还可以测量输入信号的脉冲长度( 输入捕获) 或者产生输出波形( 输出比较和PWM)。

 

高级定时器(TIM1和TIM8)主要功能:

高级定时器不但具有基本、通用定时器的所有的功能,还具有控制交直流电动机的所有功能。比如它可以输出6路互补带死区的信号,刹车功能等等。

 

通用定时器的时钟来源:

a. 内部时钟(CK_INT)

b. 外部时钟模式1:外部输入脚(TIx)

c. 外部时钟模式2:外部触发输入(ETR)

d. 内部触发输入(ITRx):使用一个定时器作为另一个定时器的预分频器

 

自动装载寄存器arr值得计算:

Tout = ((arr + 1)*(psc + 1))/Tclk;

Tclk:TIMx的输入时钟频率(单位:MHz)

Tout:TIMx的溢出时间(单位:us)

eg: 计时1秒,输入时钟频率为72MHz,psc预分频的值为35999,那么,((arr + 1)*(psc + 1))/72M = ((arr + 1)*(35999 + 1))/72M = 1s,就可以求解出自动预装载寄存器arr = 1999。

 

定时器每次计数到预设值后,会产生一次中断更新事件,进入中断服务函数。因此,每个定时器有一个或者多个对应的中断处理函数的入口。

 

对于STM32F103C8T6,需要注意的是,这款芯片没有基本定时器TIM6和TIM7。它的中断服务函数名如下:

 

不知小伙伴们还记不记得上一篇的精准延时?没错啦,精准延时那里就用到了系统滴答定时器。

ARM Cortex-M3内核中有一个Systick定时器,它是一个24位(0~(2^24-1))的倒计数定时器,这个脉冲计数值保存在当前计数值寄存器STK_VAL(Systick current value register)中,当计数到0时,它就会从Load寄存器中自动重装定时初值,只要不把CTRL寄存器中的ENABLE清0,它就永不停。

Systick定时器只能向下计数,每接收到一个时钟脉冲,STK_VAL的值就会向下减1,当减到0时,硬件会自动把重装载寄存器STK_LOAD(Systick reload value register)中保存的数据加载到STK_VAL,重新开始向下计数。如果STK_VAL的值被减至0时,会触发异常产生中断。所以,小伙伴们不要因为好玩,在程序里写一句 delay_ms(0) 或 delay_us(0)。这样会触发异常产生中断,到时你就找不着北啦~

既然提到了精准延时,那这次小R给小伙伴们分享更加准确的LED灯闪烁时间,我们使用通用定时器中断来实现LED灯闪烁:

 

1. 新建两个文件,tim.c 和 tim.h

 

2. 在头文件 tim.h 添加下面代码:

#ifndef _TIM_H
#define _TIM_H
#include "stm32f10x.h"

void TIMx_Init(u16 arr, u16 psc);

#endif

 

3. 把 tim.c 添加到工程中

 

4. 在 tim.c 中添加以下代码:

#include “tim.h”

void TIMx_Init(u16 arr,u16 psc)
{
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;         //声明TIMx定时器结构体
    NVIC_InitTypeDef NVIC_InitStructure;                   //声明中断优先级结构体
    
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);        //配置中断优先级分组
    
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);    //使能APB1总线上的TIM3时钟
    
    TIM_TimeBaseStructure.TIM_Period = arr;                       //设置在下一个更新事件活动的自动装载寄存器周期的值
    TIM_TimeBaseStructure.TIM_Prescaler = psc;                    //设置用来作为TIMx时钟频率除数的预分频值
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;       //设置时钟分割:TDTS = Tck_tim
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;   //TIM向上计数
    TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStructure);                //根据指定的参数初始化TIMx的时间基数单位
    
    TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);                      //允许TIM3中断更新
    
    NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;               //配置外部中断通道
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;     //设置抢先优先级为0
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;            //设置子优先级为3
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;               //使能外部中断通道
    NVIC_Init(&NVIC_InitStructure);                               //初始化中断优先级
    
    TIM_Cmd(TIM3,ENABLE);                                         //使能TIM3
}


void TIM3_IRQHandler(void)                                        //TIM3中断服务函数
{
    if(TIM_GetITStatus(TIM3,TIM_IT_Update) != RESET)              //检查TIM3更新中断
    {
        GPIOC->ODR ^= 0X0001<<13;                                 //PC13高低电平交替翻转
        TIM_ClearITPendingBit(TIM3,TIM_IT_Update);                //清除TIM3中断标志位
    }
}

定时器中断配置步骤:

1. NVIC优先级组配置

2. 使能定时器时钟

3. 初始化定时器

4. 设置定时器允许更新中断

5. 设置定时器中断优先级

6. 使能定时器

7. 编写中断服务函数

 

5. 实现定时器更新中断LED灯闪烁功能

#include "stm32f10x.h"
#include "delay.h"
#include "led.h"
#include "tim.h"

int mian(void)
{
    led_init();
    TIMx_Init(1999, 35999);

    while(1)
    {
    }
}

 

需要注意的是:在中断函数中需要检验一下标志位,因为定时器的所有事件共用一个中断。但只使用更新中断不用检验也是没有问题滴。

 

欢迎关注微信公众号『OpenSSR』

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值