第五章、TIMER
1、基本概念:什么是定时器 ?作用 ?分类 ?
2、时基单元 ?组成 ?计数模式 ?溢出条件 ? 溢出时间计算 ?
3、systick原理 ?代码讲解 ?
4、systick与hal_delay的关系 ?为什么不能再中断里使用中断 ?
5、看门狗原理?独立看门狗 ? 窗口看门狗 (下限 0x3f)?
6、RTC ?
7、定时器框图 ?基础、通用、高级的区别 ?
1、定时器
定时->计数
1.定时器分类
三种: 高级定时器(TIM1,TIM8)、通用定时器(TIM2~TIM5)以及基本定时器(TIM6、TIM7)区别:高级定时器具有捕获/比较通道和互补输出,通用定时器只有捕获/比较通道,基本定时器没有以上两者。
计数器模式:通用定时器可以向上计数、向下计数、向上向下双向计数模式。
①向上计数模式:计数器从0计数到自动加载值(TIMx_ARR),然后重新从0开始计数并且产生一个计数器溢出事件。
②向下计数模式:计数器从自动装入的值(TIMx_ARR)开始向下计数到0,然后从自动装入的值重新开始,并产生一个计数器向下溢出事件。
③中央对齐模式(向上/向下计数):计数器从0开始计数到自动装入的值-1,产生一个计数器溢出事件,然后向下计数到1并且产生一个计数器溢出事件;然后再从0开始重新计数。
2.定时器框图
四个大的部分:时钟产生器部分、时基单元部分、输入捕获部分以及输出比较部分
时钟产生器:STM32的定时器有四种时钟源:
①内部时钟(CK_INT)
②外部时钟模式:外部触发输入(ETR)
③内部触发输入(ITRx):使用一个定时器作为另一个定时器的预分频器,如可以配置一个定时器Timer1而作为另一个定时器Timer2的预分频器。
④外部时钟模式:外部输入脚(TIx)
3.输出比较通道(PWM)
有两种模式:边沿对齐模式以及中心对齐模式
频率*周期=1
72MHz的时钟,代表它发射的方波,一秒钟发72000000个方波;
通过方波的个数去计时,就把计数和计时关联了起来;
一个方波的时间72*10的六次方之一秒,可以算出n个方波的时间;
如果某段时间经过了72个方波,就意味着已经经历了1M分之一秒
这样理解,就可以把计时和计数划一个等号
4.定时器
它的计数在某种意义上等于计时
核心组件:时基单元;
时基单元由三个部分组成,第一个部分是预分频器,作用都是对时钟做除法,就是进行分频;第二个是ARR,重装载寄存器;最后一个是CNT,也就是计数寄存器;这三个设备完成定时器的核心功能;
首先,给它一个初始的时钟源,给它一个72M的频率,想要得到1M的频率,那就用预分频器将初始的时钟源除以72;计数要计1M次,将这个1M的次数首先放在重装载寄存器中,计数寄存器进行计数的同时,不停地和ARR进行对比,次数正确的时候,就进行更新事件这么一个处理。
计算思路:比如问,8M的ALK,定时1ms
首先,单位化统一:s
列公式:1/CLK PSCARR=t
得出PSC*ARR等于? 最后合理分配:PSC/ARR
5.计数模式
第一种:向上计数模式:CNT++ ->ARR
CNT等于0,CNT一直加,直到和ARR一样大,最后更新事件,
它的溢出条件(也就是停止计数,触发更新事件:CNT=ARR);
第二种、计数方式是:向下计数:
首先让CNT等于ARR,然后让CNT去趋近于0,就是向下计数模式
在这个模式里,CNT初始值=ARR,对CNT进行–,直到CNT=0,触发更新事件;向下计数的溢出条件就是CNT==0;
第三种:中心对称计数
6.内核定时器
为系统提供时钟,和延时函数有关;
(滴答定时器),不管什么定时器,都离不开时基单元(PSC.ARR.CNT还需要加上一个更新中断)
代码当中寻找;内核定时器的时钟源是内部的一个高速时钟(16M),它的ARR是16000;CNT是0,向上计数;
更新中断:tick++(用来给hel_delay做延时)(每次tick++都代表过了1ms)两次gettick相当于毫秒级的延时,这是本质;
两个用法:第一个是通过修改systick handler的优先级(提高优先级)来实现中断嵌套,就可以在中断中使用延时函数;
第二个用法是自定义延时函数:重写ARR和CNT的代码,分别可以实现毫秒级延时和微秒级延时以及秒级延时;
第二个外设:
2、看门狗
(分为独立看门狗和窗口看门狗)
当代码出现异常或者跑飞的时候,让计算机自动复位
这里重点是,如何实现计算机的自动复位
一个时基单元,看门狗是向下计数的,看门狗启动的时候,CNT的初始值会等于ARR,喂狗的程序也是让CNT等于ARR,如果CNT==0,就会触发复位(程序正常的时候,CNT永远都不等于0)
当程序异常的时候,喂狗的代码就无法执行,此时必然会出现CNT==0的情况,触发条件让计算机进行复位;
1.窗口看门狗
0x3f(64) 它的上限是ARR,也就是我们自己设置的值,窗口看门狗的CNT也会从ARR向0减少,它的喂狗时间必须在窗口期内,0x3f这点设置为更新事件,这时会有一个中断产生,此时喂狗行为进行;
3、RTC
实时时钟:
外部时钟芯片:稳定
专供电供:纽扣电池
专供晶振:32.768k
反映的信息:年、月、日、时、分、秒
内部的时基单元,年月日时分秒不停累加,前提是不断电
需求:定时器每隔1s,打印或者闪烁一次
cubemx:选择一个定时器、
分频定时:clk,psc,arr怎么选择,设置一个合理的值
与定时器相关的nvic打开
uart/gpio
keil:定时器中断开关(只需要打开一次
更新回调函数)
4、定时器分类(三种)
第一种是内核定时器:systick
专用定时器有独立看门狗和窗口看门狗,只需要看代码和应用层,寄存器这儿不用看,只需要到应用层就足够了(应用层相关配置部分)(面试问,你说你用过uart,你用的时候,使用到了哪些:hal库中在使用uart时,在初始化uart时,需要配置的参数:答案都在keil的代码里面,自己课后去寻找)
专用看门狗还有讲到了一个RTC
常用定时器:基础定时器、通用定时器以及高级定时器
如果定时器只弄了时基单元,那就是基础定时器,
如果还有输入通道和输出通道,就是有输入捕获功能和输出比较功能(就是生成PWM波)主动向外发出一些方波,单片机有能力自己创造波形并且输出这个波;有以上两个额外功能的,就叫做通用定时器;
高级定时器,专门为电机服务;电机有专门的通道,实现“刹车”,如果电机要停止,会有一个瞬间的停止,电机具有刹车功能,芯片有意识地迎合这个功能(多一个接口)
此外,高级定时器还有一个死区功能,还能输出互补通道
5、PWM
脉冲宽度调制
每种波,都有自己的周期和频率,这两个可以决定这个波的高电平和低电平的时间
占空比:t1/t*100%,在整个方波的周期内,高电平所占时间的比值
脉冲:时基单元来确定一个波的周期t
周期可以由时基单元分配:分频定时去控制
宽度:高电平的时间t1
调制:动态地改变占空比->应用场景:呼吸灯的亮度,逐渐变亮再逐渐变暗 改变占空比就是改变高电平的持续时间,
比较值:计数为100个,PWM1模式:令CNT在0到x的时候,为高电平,x到100为低电平;;;PWM2模式:x到100的时候为高电平;0到x为低电平
应用:呼吸灯:本质:控制led灯高电平的时间(动态改变占空比)
6、实验
1、systick与han_delay 代码解析
2、RTC
HAL_RTC_GetTime()
HAL_RTC_GetDate()
3、独立看门狗
HAL_IWDG_Refresh()
4、窗口看门狗
HAL_WWDG_Refresh()
HAL_WWDG_IRQHandler()
HAL_WWDG_EarlyWakeupCallback()
#include <stdio.h>
void HAL_WWDG_EarlyWakeupCallback(WWDG_HandleTypeDef *hwwdg)
{
HAL_WWDG_Refresh(hwwdg);
printf(“dog eat now…\n”);
HAL_Delay(2000);
printf(“dog eat end…\n”);
}
( 不喂狗时,只会打印部分值,因为不喂狗时会触发中断,然后直接复位)
5、基础定时器 :1s延时
HAL_TIM_Base_Start_IT(&htim14)
HAL_TIM_PeriodElapsedCallback()
void delay_us(uint16_t nus){ // 利用CNT进行微秒延时
__HAL_TIM_SetCounter(&htim14,0);
__HAL_TIM_ENABLE(&htim14);
while( __HAL_TIM_GetCounter(&htim14)< nus);
__HAL_TIM_DISABLE(&htim14);
}
6、通用定时器 PWM : 呼吸灯 ( 微秒级延时 )
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_3);
__HAL_TIM_SetCompare();
6、通用定时器 PWM : 呼吸灯 ( 微秒级延时 )
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_3);
__HAL_TIM_SetCompare();