欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

STM32F103定时器中断(库函数)

程序员文章站 2024-02-21 21:14:04
...

三种定时器

STM32F103定时器中断(库函数)

定时器的时基

计数器寄存器(TIMx_CNT)、预分频器寄存器(TIMx_PSC)、自动转载寄存器(TIMx_ARR)。可通过配置这三个寄存器可配置计数周期。
STM32F103定时器中断(库函数)
参考stm32中文手册
1.CNT_EN在TIMx_CR1寄存器 的最低位当高电平时将定时器使能。
STM32F103定时器中断(库函数)
2.预分频寄存器(TIMx_PSC)。该寄存器用设置对时钟进行分频,然后提供给计数器,作为计数器的时钟。
STM32F103定时器中断(库函数)
这里的 CK_INT时钟是从 APB1 倍频的来的,除非 APB1 的时钟分频数设置为 1,否则通用定时器 TIMx 的时钟是 APB1 时钟的 2 倍。

3.状态寄存器(TIMx_SR)。该寄存器用来标记当前与定时器相关的各种事件/中断是否发生。置1时代表发生
STM32F103定时器中断(库函数)
4.自动重装载寄存器(TIMx_ARR),该寄存器在物理上实际对应着 2 个寄存器。一个是程序员可以直接操作的,另外一个是程序员看不到的,这个看不到的寄存器在《STM32参考手册》里面被叫做影子寄存器。事实上真正起作用的是影子寄存器。根据 TIMx_CR1 寄存器中 APRE 位的设置:APRE=0 时,预装载寄存器的内容可以随时传送到影子寄存器,此时 2者是连通的;而 APRE=1 时,在每一次更新事件(UEV)时,才把预装在寄存器的内容传送到影子寄存器。
STM32F103定时器中断(库函数)
5.计算公式
时钟频率公式:CK_CNT = fCK_PSC/(PSC[15:0]+1) (在默认情况下fCK_PSC为72MHz,AHB时钟=72M,APB1时钟=3M,所以APB1的分频系数=AHB/APB1=2,所以,通用定时器时钟CK_INT=36M2=72M)
时间公式:T = (PSC[15:0]+1)
( ARR[15:0]+1)/ fCK_PSC

例如,ARR[15:0]值为 5,则定时时长为6 * (1/CK_CNT)

通用定时器功能特点描述

STM3 的通用TIMx (TIM2、TIM3、TIM4和TIM5)定 时器功能特点包括:位于低速的APB1总线上(APB1)
16位向上、向下、向上/向下(中心对齐)计数模式,自动装载计数器(TIMx CNT)。16位可编程(可以实时修改)预分频器(TIMx_ PSC),计数器时钟频率的分频系数为1~65535之间的任意数值。
4个独立通道(TIMx CH1~4),这些通道可以用来作为:
①输入捕获
②输出比较
③PWM生成(边缘或中间对齐模式)
④单脉冲模式输出

以下事件发生时产生中断

①更新事件:计数器向上溢出向下溢出,计数器初始化(通过软件或者内部/外部触发)
②触发事件(计数器启动、停止、初始化或者由内部/外部触发计数)
③输入捕获
④输出比较

STM32的通用定时器可以被用于:测量输入信号的脉冲长度(输入捕获)或者产生输出波形(输出比较和PWM)等。
使用定时器预分频器和RCC时钟控制器预分频器,脉冲长度和波形周期可以在几个微秒到几个毫秒间调整。STM32的每个通用定时器都是完全独立的,没有互相共享的任何资源。

计数器模式

通用定时器可以向上计数、向下计数、向上向下双向计数模式。
①向上计数模式:计数器从0计数到自动加载值(TIMx _ARR),然后重新从0开始计数并且产生一个计数器溢出事件。
②向下计数模式:计数器从自动装入的值(TIMx ARR)开始向下计数到0,然后从自动装入的值重新开始,并产生个计数器向下溢出事件。
③*对齐模式(向上/向下计数) :计数器从0开始计数到自动装入的值-1,产生一个计数器溢出事件,然后向下计数到1并且产生个计数器溢出事件:然后再从0开始重新计数。
STM32F103定时器中断(库函数)

代码配置

1.使能定时器时钟
RCC_APB1PeriphClockCmd()
2.初始化定时器配置,arr,psc
TIM_TimeBaseInitStrue.TIM_Period
TIM_TimeBaseInitStrue.TIM_Prescaler
TIM_TimeBaseInitStrue.TIM_CounterMode
TIM_TimeBaseInitStrue.TIM_ClockDivision
3.开启定时器中断,配置NVIC
TIM_ITConfig()
NVIC_InitStructure.NVIC_IRQChannel
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority
NVIC_InitStructure.NVIC_IRQChannelSubPriority
NVIC_InitStructure.NVIC_IRQChannelCmd
4.使能定时器
TIM_Cmd()
5.编写中断服务函数
TIMx_IRQHandler()

void TIM3_Int_Iint(u16 arr,u16 psc)
{
 TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStrue;
 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);//使能定时器时钟
 TIM_TimeBaseInitStrue.TIM_Period=arr;//自动装载值
 TIM_TimeBaseInitStrue.TIM_Prescaler=psc; //预分频系数
 TIM_TimeBaseInitStrue.TIM_CounterMode=TIM_CounterMode_Up;//向上计数
 TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStrue);//初始化
  TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);//开启定时器中断 更新中断当计数溢出时进入中断,更新指的是更新计数器的值,中断是指更新数值的时候会进入中断
  NVIC_InitTypeDef NVIC_InitStructure;
 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);  // 设置NVIC中断分组2,其中2位抢占优先级,2位响应优先级
  NVIC_InitStructure.NVIC_IRQChannel                   = TIM3_IRQn;//中断通道
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;//抢占优先级
  NVIC_InitStructure.NVIC_IRQChannelSubPriority        = 0;//响应优先级
  NVIC_InitStructure.NVIC_IRQChannelCmd                = ENABLE;//使能
  NVIC_Init(&NVIC_InitStructure);//初始化NVIC
  TIM_Cmd(TIM3,ENABLE);//使能定时器
}
void TIM3_IRQHandler(void)//服务函数
{
 if (TIM_GetITStatus(TIM3,TIM_IT_Update) != RESET)//判断是否中断
 {
  LED1_Toggle;//控制led反转
  LED2_Toggle;
  TIM_ClearITPendingBit(TIM3,TIM_IT_Update);//清除中断
 }
}

注意:
1.通用定时器在APB1里面,高级定时器在APB2里面
2.根据时间公式,当我们设置一个100ms时,例如应设置arr=999,psc=7199;因为72M/(7199+1)=10KHz为0.1ms,时间=(999+1)*0.1=100ms;arr和psc都是16位 应设置在1~65535;
3.可在服务函数里编写自己想要的功能