STM32学习100步之第九十六步——定时器的其他应用

  • Post author:
  • Post category:其他




定时器的3种功能

1、捕获器:测量波形的频率和宽度

2、比较器:分为模拟比较器和输出比较器

模拟比较器:比较两组输入电压的大小(STM32F103无此功能)

输出比较器:产生可调频率和可调占空比的脉冲波形

3、PWM:脉宽调制器,产生固定频率但占空比可调的脉冲波形



其中PWM功能前面已经介绍,下面介绍其他功能



普通定时

定时器可以用于独立时间计时功能,原理和嘀嗒定时器、看门狗基本相同。

定时时间到时,可等待CPU检查标志位(查寻方式),或产生“定时器中断”

一般都是让定时器产生中断。

定时原理图如下(设置为向上加计数)

在这里插入图片描述



通过定义定时器的4个独立通道设置为输入或者输出即可完成下面介绍的功能。



捕获器

捕获什么?输入接口的电平变化 (. 上升沿或下降沿)

有什么用?可 测量脉冲的宽度,或者测量脉冲频率

工作过程! 当接口产生.上升沿或下降沿时,将当前定时器值保存。

主要捕获数字信号的方波。捕获方波对应的上升沿或者下降沿。



捕获高(低)电平宽度时序图

在这里插入图片描述

记录第一次捕获上升沿时间为T1(计数值C1),记录第二次捕获下降沿时间为T2(计数值C2),再相减计算,便得到高电平的时间宽度。

同理

记录第一次捕获下降沿时间为T1(计数值C1),记录第二次捕获上升沿时间为T2(计数值C2),再相减计算,便得到低电平的时间宽度。



测频原理图如下:

在这里插入图片描述

记录第一次捕获上升沿(下降沿)时间为T1(计数值C1),记录第二次捕获上升沿(下降沿)时间为T2(计数值C2),再相减计算,便得到一个周期的宽度,即可以完成测频。



输出比较器

可输出脉冲,可调占空比和频率。

PWM只能调占空比(也是可以通过程序调频率,但不方便随时调)输出比较器可随时调占空比和频率。

输出比较器主要用于步进电机、伺服电机的控制。

下面举一个例子:

在这里插入图片描述



定时中断功能的使用:

和前面产出PWM波相类似,比之前简单,时钟频率默认72MHZ。



定时器时间计算公式Tout = ((重装载值+1)*(预分频系数+1))/时钟频率;


例如:1秒定时,重装载值=9999,预分频系数=7199

调用该函数即可:

	TIM3_Init(9999,7199);//定时器初始化,定时1秒(9999,7199)

具体的初始化函数如下:

void TIM3_Init(u16 arr,u16 psc){  //TIM3 初始化 arr重装载值 psc预分频系数
    TIM_TimeBaseInitTypeDef     TIM_TimeBaseInitStrue;
    
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);//使能TIM3
    TIM3_NVIC_Init (); //开启TIM3中断向量
	      
    TIM_TimeBaseInitStrue.TIM_Period=arr; //设置自动重装载值
    TIM_TimeBaseInitStrue.TIM_Prescaler=psc; //预分频系数
    TIM_TimeBaseInitStrue.TIM_CounterMode=TIM_CounterMode_Up; //计数器向上溢出
    TIM_TimeBaseInitStrue.TIM_ClockDivision=TIM_CKD_DIV1; //时钟的分频因子,起到了一点点的延时作用,一般设为TIM_CKD_DIV1
    TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStrue); //TIM3初始化设置
    TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);//使能TIM3中断    
    TIM_Cmd(TIM3,ENABLE); //使能TIM3
}

将定时器3的中断向量写入中断控制向量器的函数(因为中断向量控制器直接和单片机相连,控制着单片机的中断)如下:

void TIM3_NVIC_Init (void){ //开启TIM3中断向量
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;	
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x3;	//设置抢占和子优先级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x3;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);
}

中断处理函数如下(

注意函数名称不可以修改,是固定的

):

void TIM3_IRQHandler(void){ //TIM3中断处理函数
    if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET){	//判断是否是TIM3中断
        TIM_ClearITPendingBit(TIM3, TIM_IT_Update);

        //此处写入用户自己的处理程序
		GPIO_WriteBit(LEDPORT,LED1,(BitAction)(1-GPIO_ReadOutputDataBit(LEDPORT,LED1))); //取反LED1
    }
}

刚进入中断时,需要判断中断标志位是否表示定时器的溢出,若确实为溢出,则清空标志位(为下次定时做准备),这时再if语句成立的条件下(即确定是定时器溢出产生中断),写入自己的处理程序。

所谓定时器中断在我看来,CPU和定时器独立工作,定时器计时,cpu做自己的事情,当定时器计满溢出之后,定时器被清零,产生中断信号给CPU,CPU立即放下手头的事情,然后处理中断函数中的内容,中断函数不能在主函数或者其他函数中调用,而是独立的,让CPU进入中断函数处理完成之后,再返回原来做原来的事情,当定时器再次溢出时,再产生中断,如此反复下去…

图中部分图片出自洋桃电子,仅用于学习目的。