微商城网站建设哪家好,网页设计公司官网功能图,cmseasy破解版,海外永久不收费的加速器文章目录 TIM简介定时器类型 通用定时器预分频器时序计数器时序定时中断基本结构TIM内部中断工程TIM外部中断工程 TIM简介
STM32的TIM#xff08;定时器#xff09;是一种非常常用的外设#xff0c;用于实现各种定时和计数功能。它是基于时钟信号进行计数#xff0c;并在计… 文章目录 TIM简介定时器类型 通用定时器预分频器时序计数器时序定时中断基本结构TIM内部中断工程TIM外部中断工程 TIM简介
STM32的TIM定时器是一种非常常用的外设用于实现各种定时和计数功能。它是基于时钟信号进行计数并在计数值达到设定值时触发中断执行相应的操作。
定时器类型
一般来说STM32中有三类定时器 在我们这款STM32F03C9T6有4种定时器资源TIM1TIM2,TIM3,TIM4;
对于定时器类型越高级拥有的功能越多且向下兼容 我们将以通用定时器进行讲解。
通用定时器
通用定时器是一个通过可编程预分频器驱动的16位自动装载计数器构成。 它适用于多种场合包括测量输入信号的脉冲长度输入捕获或者产生输出波形输出比较和PWM。 使用定时器预分频器和RCC时钟控制器预分频器脉冲信号长度和波形周期可以在几个微妙到几个毫秒间调整。 每个定时器都是完全独立的没有互相共享任何资源。它们可以同步操作。 这是通用定时器的总框图我将会分为几部分进行讲解。 这是定时器最基本的结构通过RCC内部时钟产生的脉冲频率通向预分频器频率分频后到计数器当达到自动重装载寄存器的值将会发出信号或者触发中断。
RCC的TIMxCLK会产生一个72MHz的脉冲频率 这一部分称为时基单元是TIM计时器最主要的计数计时结构。 PSC预分频器会将72MHZ进行分频可以按1到65536之间的任意值分频将输入频率除以预分频器值就得到分频结果 通过频率会在计数器中计数通过传输的频率的上升沿计数器将加一 计数器取值范围为0到65535所以计数的快慢由输入频率决定 对于通用计数器来说计数器是有多种模式进行计数的。 向上计数模式计数器从0计数到自动加载值(TIMx_ARR计数器的内容)然后重新从0开始计数并且产生一个计数器溢出事件。 向下计数模式计数器从自动装入的值(TIMx_ARR计数器的值)开始向下计数到0然后从自动装入的值重新开始并且产生一个计数器向下溢出事件。 中央对齐模式计数器从0开始计数到自动加载的值(TIMx_ARR寄存器)−1产生一个计数器 溢出事件然后向下计数到1并且产生一个计数器下溢事件然后再从0开始重新计数。 自动重装载寄存器相当就是给计数器一个周期值当计数器达到这个值就会产生中断并清零计数器计数器溢出中断后会产生更新中断传到NVIC中最后传到CPU那么定时器就能产生中断了。也会产生更新事件它会触发内部其他电路的工作。 这部分是定时器时钟频率的来源在通用定时器中不止有内部时钟还有外部时钟。 第一个外部时钟TIMx_ETR如果在引脚上默认有该功能就能直接使用作为外部时钟的连接引脚 传输进来的方波信号会通过极性选择边沿检测滤波等进行整形处理掉一些毛刺滤波后的信号兵分两路第一路是走到ETRF通过触发控制器走到复位使能这种走法称为“外部时钟模式2”。(TRIGO是映射功能能够从主模式触发DAC)。第二路是TRGI主要用作触发使用的可以走到从模式当然也可以走复位使能那里那么这样的外部时钟称为“外部时钟模式1”。
第二个的来源就是ITRTRIGO可以通向其他定时器其他定时器就是通过ITR引脚来连接的。 这是内部定时器连接的方式。可以允许4种定时器进行连接到定时器上但是只允许一个定时器连接着一个定时器。
第三个一个是TIIF_ED,这里连接着输入捕获单元的CH1ED为Edge边沿的意思触发方式上升沿和下降沿都有效。
最后一个是TI1FP1和TI2FP2 后续将会讲解。 下边的左半部分为输入捕获电路右半部分为输出比较部分每部分都有4个通道可以进入且输入和输出共用一个寄存器意味着不能边输入边输出具体功能将会后续讲解。
预分频器时序 这是一个预分频器从1变到2的时序图。 CK_PSC是时钟频率一般都为72MHZ CNT_EN是计时器使能只有在使能高电平状态下才能运行。 CK_CNT是计时器时钟它既是预分频器的时钟输出也是计数器的时钟输入当使能为高电平时CNT开始运行前半段频率跟时钟一样后半段预分频器从1变到2CNT让定时器上升沿减半即一个周期有效一个周期无效保持低电平。 在计时器时钟的驱动下计时器寄存器也不断增加当达到FC时与自动重转载寄存器的值一样将会从0开始 更新事件UEV当计数器寄存器到FC时更新事件将会触发。 下面三个时序将一起看这是预分频控制寄存器的缓冲机制我们写入的值会到预分频控制寄存器上当在计数器未归零之前写入时为了保持完整性将会在更新事件后才会进行分频。所以到预分频缓冲器上才是所读的正确结果而预分频计数器会在1时保持定时器时钟为低电平为0时保持原先状态。
计数器计数频率CK_CNT CK_PSC / (PSC 1) PSC相对我们输入者来说就是0开始的当对于PSC来说是从1开始的。就像一块蛋糕不切时它就是1份完整的切一刀时就会被分成两份。
计数器时序 大体来说与预分频器一致当计数器寄存器满时将会使计数器溢出更新事件发生更新中断标志。
计数器溢出频率CK_CNT_OV CK_CNT / (ARR 1) CK_PSC / (PSC 1) / (ARR 1)
定时中断基本结构
对于我们来说由于有库函数的提供不需要管哪些寄存器我们需要了解一些代码逻辑结构。 通过外部引脚GPIO就可连接外部时钟然后选择时钟模式接着对时基单元初始化接上NVIC即可。
TIM内部中断工程
连接方式 OLED函数可以点击连接 该工程将会实现走秒的例子。 Timer.h
#ifndef __TIMER_H__
#define __TIMER_H__void Timer_Init();#endif
Timer.c
#include stm32f10x.h // Device headervoid Timer_Init()
{//开启APB1外设开关RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);//配置TIM2为内部时钟TIM_InternalClockConfig(TIM2);//时钟结构体初始化TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;TIM_TimeBaseInitStructure.TIM_ClockDivisionTIM_CKD_DIV1; //划分TIM2TIM_TimeBaseInitStructure.TIM_CounterModeTIM_CounterMode_Up; //计时器模式上升沿计时TIM_TimeBaseInitStructure.TIM_Period10000-1; //自动加载寄存器周期值TIM_TimeBaseInitStructure.TIM_Prescaler7200-1; //预分频值TIM_TimeBaseInitStructure.TIM_RepetitionCounter0; //指定重复计时器的值这里不用到TIM_TimeBaseInit(TIM2,TIM_TimeBaseInitStructure);//清除标志位TIM_ClearFlag(TIM2, TIM_FLAG_Update);//启用TIM2中断TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);//配置优先级分组NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//NVIC初始化NVIC_InitTypeDef NVIC_InitStructure;NVIC_InitStructure.NVIC_IRQChannelTIM2_IRQn;NVIC_InitStructure.NVIC_IRQChannelCmdENABLE;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority2;NVIC_InitStructure.NVIC_IRQChannelSubPriority1;NVIC_Init(NVIC_InitStructure);//启用TIM2外设控制TIM_Cmd(TIM2,ENABLE);
} 对于内部时钟没有外部引脚的使用记住TIM所在总线是APB1先开启外设开关接着配置TIM2的内部时钟然后对时基单元结构体成员进行初始化对于预分频器值通过公式可知需要-1才能达到我们想要的数字重复计时器是高级计时器的操作这里不需要用到。 在初始化完将会生成一个更新事件立即重新加载预分频和计时器的计算。在更新一个事件后同时也会产生中断标志为了让计时时从0开始就采用了清除标志的函数。 最后记得启用TIM2的外设否则无效。 main.c
#include stm32f10x.h // Device header
#include Delay.h
#include Buzzer.h
#include LightSensor.h
#include OLED.h
#include Timer.huint16_t Count;
int main()
{OLED_Init();Timer_Init();while(1){OLED_ShowNum(1,1,Count,4);}
}//中断函数
void TIM2_IRQHandler()
{
//表示已经触发中断了if(TIM_GetITStatus(TIM2,TIM_IT_Update)SET){Count;//中断挂起位中断结束后需要将中断位挂起让下一个能进入中断TIM_ClearITPendingBit(TIM2,TIM_IT_Update);}
}
TIM外部中断工程
接线方式 通过对射式红外传感器的电平变化作为CNT的触发条件然后通过10次的电平变化让计时器溢出进1
Timer.h
#ifndef __TIMER_H__
#define __TIMER_H__void Timer_Init();#endif
Timer.c
#include stm32f10x.h // Device headervoid Timer_Init()
{//开启APB1外设开关RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_ModeGPIO_Mode_IPU;GPIO_InitStructure.GPIO_PinGPIO_Pin_0;GPIO_InitStructure.GPIO_SpeedGPIO_Speed_50MHz;GPIO_Init(GPIOA,GPIO_InitStructure);//配置TIM2为外部时钟模式2TIM_ETRClockMode2Config(TIM2,TIM_ExtTRGPSC_OFF,TIM_ExtTRGPolarity_NonInverted,0x0F);//时钟结构体初始化TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;TIM_TimeBaseInitStructure.TIM_ClockDivisionTIM_CKD_DIV1; //表示不分频TIM_TimeBaseInitStructure.TIM_CounterModeTIM_CounterMode_Up; //计时器模式TIM_TimeBaseInitStructure.TIM_Period10-1; //自动加载寄存器周期值TIM_TimeBaseInitStructure.TIM_Prescaler1-1; //预分频值TIM_TimeBaseInitStructure.TIM_RepetitionCounter0; //指定重复计时器的值这里不用到TIM_TimeBaseInit(TIM2,TIM_TimeBaseInitStructure);//TIM_ClearFlag(TIM2, TIM_FLAG_Update);//启用TIM2中断TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);//配置优先级分组NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//NVIC初始化NVIC_InitTypeDef NVIC_InitStructure;NVIC_InitStructure.NVIC_IRQChannelTIM2_IRQn;NVIC_InitStructure.NVIC_IRQChannelCmdENABLE;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority2;NVIC_InitStructure.NVIC_IRQChannelSubPriority1;NVIC_Init(NVIC_InitStructure);//启用TIM2外设控制TIM_Cmd(TIM2,ENABLE);
} 外部时钟模式2 TIM_ExtTRGPrescaler:外部触发预分频器 TIM_ExtTRGPolarity_NonInverted:触发极性为上升沿或高电平 ExtTRGFilter:最后一个参数表示滤波频率高低可选范围0x00 and 0x0F一般来说滤波频率越高毛刺与不规则信号处理的越干净。 main.c
#include stm32f10x.h // Device header
#include Delay.h
#include Buzzer.h
#include LightSensor.h
#include OLED.h
#include Timer.huint16_t Count;
int main()
{OLED_Init();Timer_Init();while(1){OLED_ShowNum(1,1,Count,4);OLED_ShowNum(2,1,TIM_GetCounter(TIM2),5);}
}void TIM2_IRQHandler()
{if(TIM_GetITStatus(TIM2,TIM_IT_Update)SET){Count;TIM_ClearITPendingBit(TIM2,TIM_IT_Update);}
}