打印
[应用相关]

STM32应用定时器

[复制链接]
241|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
yyller|  楼主 | 2020-9-3 18:47 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
                                    

        一、定时器分类

        STM32F1 系列中,除了互联型的产品,共有 8 个定时器,分为基本定时器,通用定时器和高级定时器。基本定时器 TIM6 和 TIM7 是一个 16 位的只能向上计数的定时器,只能定时,没有外部 IO。通用定时器 TIM2/3/4/5 是一个 16 位的可以向上/下计数的定时器,可以定时,可以输出比较,可以输入捕捉,每个定时器有四个外部 IO。高级定时器 TIM1/8是一个 16 位的可以向上/下计数的定时器,可以定时,可以输出比较,可以输入捕捉,还可以有三相电机互补输出信号,每个定时器有 8 个外部 IO。

        基本定时器的核心是时基,通用计时器和高级定时器也有。

        1、时钟

        定时器时钟TIMxCLK,即内部时钟CK_INT,经APB1预分频器后分频提供,如果APB1 预分频系数等于 1,则频率不变,否则频率乘以 2,库函数中 APB1 预分频的系数是 2,即 PCLK1=36M,所以定时器时钟 TIMxCLK=36*2=72M 。

        2、计数器时钟

        定时器时钟经过 PSC 预分频器之后,即 CK_CNT,用来驱动计数器计数。PSC 是一个16 位的预分频器,可以对定时器时钟 TIMxCLK 进行 1~65536 之间的任何一个数进行分频。

        具体计算方式为:CK_CNT=TIMxCLK/(PSC+1)。

        3.计数器

        计数器 CNT 是一个 16 位的计数器,只能往上计数,最大计数值为 65535。当计数达到自动重装载寄存器的时候产生更新事件,并清零从头开始计数。

        4、自动重装载寄存器

        自动重装载寄存器 ARR 是一个 16 位的寄存器,这里面装着计数器能计数的最大数值。当计数到这个值的时候,如果使能了中断的话,定时器就产生溢出中断。

        5. 定时时间的计算

        定时器的定时时间等于计数器的中断周期乘以中断的次数。计数器在 CK_CNT 的驱动下,计一个数的时间则是 CK_CLK 的倒数,等于:1/(TIMxCLK/(PSC+1)),产生一次中断的时间则等于:1/(CK_CLK * ARR)。如果在中断服务程序里面设置一个变量 time,用来记录中断的次数,那么就可以计算出我们需要的定时时间等于: 1/CK_CLK *(ARR+1)*time。

        1.定义

        设置等待时间,到达等待时间之后执行指定的硬件操作。

        定时器最基本的功能就是定时,比如说定时发送串口数据,定时采集AD数据,也可以产生PWM方波等,定时器产生PWM控制电机状态是工业控制的普通。

        2、STM32F4xx系列的芯片:2个高级控制定时器(TIM1和TIM8)、10个通用定时器(10TIM2-TIM5,TIM9-TIM14)、2个基本定时器(TIM6和TIM7)、2个看门狗定时器

        具体可参考中文参考手册了解其特性及原理

       

        3、定时器计数模式:

        通用定时器可以向上计数、向下计数、向上向下双向计数模式。

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

        ②向下计数模式:计数器从自动装入的值(TIMx_ARR)开始向下计数到0,然后从自动装入的值重新开始,并产生一个计数器向下溢出事件。

        ③中央对齐模式(向上/向下计数):计数器从0开始计数到自动装入的值-1,产生一个计数器溢出事件,然后向下计数到1并且产生一个计数器溢出事件;然后再从0开始重新计数。

        如图:

       

        4、通用定时器工作原理:

        ● 计数器寄存器 (TIMx_CNT)

        ● 预分频器寄存器 (TIMx_PSC)

        ● 自动重载寄存器 (TIMx_ARR)

        假如是向上增长模式,计数器(CNT)从0加到自动重载值(ARR),预分频器(PSC)减一次。

        时间计算方式:

        假设频率为:42M*2 == 84M == 84000000 == 1s //42根据定时器时钟数可知 并且一般都是*2

        定时器定时1s产生中断:

        ARR = 84000; // 1ms

        PSC = 1000; // 1000*1ms == 1s

       

        如图:可知基本定时器的时钟是42M,那么对应*2就是84M=84000000=1S(ARR*PSC)

        高级的既是84*2=96M=96000000=1S

        -----------------------------------------------------------------------------------------------------------------------------------------------------------

        5、定时器中断实现步骤

        //5.1、能定时器时钟。

        RCC_APB1PeriphClockCmd();

        //5.2、初始化定时器,配置ARR,PSC。(申明结构体)

        TIM_TimeBaseInit();

        typedef struct

        {

        uint16_t TIM_Prescaler;

        uint16_t TIM_CounterMode;

        uint16_t TIM_Period;

        uint16_t TIM_ClockDivision;

        uint8_t TIM_RepetitionCounter;

        } TIM_TimeBaseInitTypeDef;

        //5.3、启定时器中断,配置NVIC(申明结构体)

        NVIC_Init();

        进行NVIC中断配置

        NVIC_InitStructure.NVIC_IRQChannel=TIM3_IRQn; //定时器 3 中断

        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x01; //抢占优先级 1

        NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x03; //响应优先级 3

        NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;

        NVIC_Init(&NVIC_InitStructure);// ④初始化 NVIC

        TIM_Cmd(TIM3,ENABLE); //⑤使能定时器 3

        //5.4、设置 TIM3_DIER 允许更新中断

        TIM_ITConfig();

        //5.5、使能定时器。

        TIM_Cmd();

        //5.6、编写中断服务函数。

        TIMx_IRQHandler();

        //定时器 3 中断服务函数

        void TIM3_IRQHandler(void)

        {

        if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET) //溢出中断

        {

        /*处理的程序段*/

        }

        TIM_ClearITPendingBit(TIM3,TIM_IT_Update); //清除中断标志位

        }

        TIM3_Int_Init(5000-1,8400-1); //定时器时钟84M,分频系数8400,所以84M/8400=10Khz的计数频率,计数5000次为500ms

        void TIM3_Int_Init(u16 arr,u16 psc)

        {

        TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;

        NVIC_InitTypeDef NVIC_InitStructure;

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

        TIM_TimeBaseInitStructure.TIM_Period = arr; //自动重装载值

        TIM_TimeBaseInitStructure.TIM_Prescaler=psc; //定时器分频

        TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式

        TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;

        TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure);//初始化TIM3

        TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE); //允许定时器3更新中断

        TIM_Cmd(TIM3,ENABLE); //使能定时器3

        NVIC_InitStructure.NVIC_IRQChannel=TIM3_IRQn; //定时器3中断

        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x01; //抢占优先级1

        NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x03; //子优先级3

        NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;

        NVIC_Init(&NVIC_InitStructure);

        }

        //定时器3中断服务函数

        void TIM3_IRQHandler(void)

        {

        if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET) //溢出中断

        {

        LED1=!LED1;//DS1翻转

        }

        TIM_ClearITPendingBit(TIM3,TIM_IT_Update); //清除中断标志位

        }

        定时器初始化结构体详解

        在标准库函数头文件stm32f10x_tim.h中对定时器外设建立了四个初始化结构体,基本定时器只用到其中一个即TIM_TimeBaseInitTypeDef,其他三个在高级定时器章节讲解。

        typedef struct {

        uint16_t TIM_Prescaler; // 预分频器

        uint16_t TIM_CounterMode; // 计数模式

        uint32_t TIM_Period; // 定时器周期

        uint16_t TIM_ClockDivision; // 时钟分频

        uint8_t TIM_RepetitionCounter; // 重复计算器

        } TIM_TimeBaseInitTypeDef;1234567

        (1) TIM_Prescaler:定时器预分频器设置,时钟源经该预分频器才是定时器时钟,它设定TIMx_PSC 寄存器的值。可设置范围为 0 至 65535,实现 1至 65536 分频。

        (2) TIM_CounterMode:定时器计数方式,可是在为向上计数、向下计数以及三种中心对齐模式。基本定时器只能是向上计数,即 TIMx_CNT只能从 0开始递增,并且无需初始化。

        (3) TIM_Period:定时器周期,实际就是设定自动重载寄存器的值,在事件生成时更新到影子寄存器。可设置范围为 0至 65535。

        (4) TIM_ClockDivision:时钟分频,设置定时器时钟 CK_INT 频率与数字滤波器采样时钟频率分频比,基本定时器没有此功能,不用设置。

        (5) TIM_RepetitionCounter:重复计数器,属于高级控制寄存器专用寄存器位,利用它可以非常容易控制输出 PWM 的个数。这里不用设置。

        虽然定时器基本初始化结构体有 5 个成员,但对于基本定时器只需设置其中两个就可以。

               
            

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

132

主题

241

帖子

1

粉丝