概述
1.时钟
时钟就是一个可以产生周期性信号的设备。
时钟信号就是周期性变化的信号。
T:时钟周期 最小重复的信号单元的时间长度,基本单元为s(秒)
F:时钟频率 1s内有多少个重复的信号单元,单位为Hz
--->T * F = 1
2.为什么需要时钟?
时钟的最主要的目的是为了同步信号。
设备之间的同步是通过时钟信号来进行的。
3.时钟信号是怎么产生的?
在自然界中有一些物体天生就会产生摆动(振动)–>石英晶体
如果想利用石英晶体规则地、周期性的产生方波信号,需要一些电路来保证,如 晶振电路:频率一般比较小,如:12M、8M…
但是晶振电路难以满足现代计算机的高频需求,如:CPU它的频率就会很高。
分频/倍频电路:
分频:把输入频率变小
倍频:把输入频率变大
4.STM32F4xx时钟树(时钟系统)
关键词:
HSE:High Speed External 高速外部时钟 (晶振电路8MHz)
HSI:High Speed Internal 高速内部时钟 (16MHz RC振荡器)
LSE:Low Speed External 低速外部时钟 (32.768KHz)
LSI:Low Speed Internal 低速内部时钟 (32KHz RC振荡器)
内部时钟:由内部集成的RC震荡电路产生
外部时钟:由晶振产生
SYSCLK(系统时钟频率168MHz) = PLLCLK(锁相环时钟)
位于APB1总线上的定时器的频率42M * 2 = 84MHZ
位于APB2总线上的定时器的频率84M * 2 = 168MHZ
*5.定时器(Timer)
定时器就是用来定时的器件
在STM32上,一般来说,定时器由三部分组成:
1)时基单元(Time Base Unit)
定时器的基本单元,所有的定时器都会具备的单元。
时基单元的工作原理:
将计数器设置为一个值按照一定的时钟频率递减到0,或者按照一定的时钟
频率从0递增到某个值,当计数器溢出后,可以产生一个溢出事件/中断以
此来达到定时的功能。
时基单元 = 计数器 + 重载计数值寄存器 + 定时器预分频器
a. 定时器预分频器Timex_PSC
用来将定时器的总线时钟进行分频,提供一个合适的频率给计数
器去计数。分频系数介于1到65536之间,是一个16位的寄存器。
b. 重载计数值寄存器Timx_ARR
用来设定计数值(N值)。如果自动重装载寄存器的值为0,则计数
器停止。
c. 计数器Timx_CNT
按照预分频器给它提供的频率,从0递增到N,或者从N递减到0,
并且可以在溢出后,产生定时器中断/事件。
比如:假设Timex是位于APB1总线上,那么Fin = 84MHz,一般情况下,为了方便计算,将Timex_PSC设置为83。
Tcnt = 1/Fcnt = (Timex_PSC + 1) / Fin = (83 + 1)/84M = (10^-6)s = 1us
产生定时器中断的时长t = (N + 1)us
2)输入捕获单元
可以对一个或者多个输入信号进行处理。
有些定时器不具备输入捕获单元。
具体能够捕获多少个输入信号需要看你的定时器有几个通道Channel。
功能:比如可以计算输入信号的频率
3)输出比较单元
可以输出一个或者多个信号
有些定时器是没有输出比较单元
具体能够输出多少个信号,就需要看你的定时器有几个通道Channel。
输出比较:
主要是用于输出PWM波。
定时器可以向对应的GPIO引脚(复用功能)输出一个电平状态。
并且可以根据输出比较寄存器的值,来翻转输出的电平状态。
6.STM32F4xx定时器概述
1)SysTick
时钟嘀嗒定时器–>系统定时器
在M3/M4中都会内置一个在NVIC中的SysTick定时器。这个定时器
只有时基单元。并且溢出的时候,会产生SysTick中断,执行中断处理函数
SysTick_Handler
为什么需要这样的一个定时器?
因为大多数的操作系统,都需要一个硬件定时器来产生操作系统需要
的时钟嘀嗒中断,主要用于操作系统计时。
SysTIck定时器作为整个系统的基本的时间单元。
SysTick被集成在NVIC中,他可以产生SysTick中断,其实就是一个简单的24bit的递减定时器,它可以运行在处理器的时钟主频(168MHz)上,也可以运行在外部时钟(8MHz)上。
寄存器配置步骤:
a. Disable SysTick(禁止SysTick)
将Control and Status寄存器中的bit0-->0
b. 选择时钟源
将Control and Status寄存器中的bit2:
1:168M的系统时钟 <--- 0:8M外部时钟
c. 使能中断
将Control and Status寄存器中的bit1:
1:SysTick中断使能 0:SysTick中断禁止
d. 设置N值和计数初值
e. Enable SysTick(使能SysTick)
2)基本定时器(TIM6/TIM7)
只有时基单元,没有输入捕获单元/输出比较单元(无输入输出引脚)。
16位自动重装载递增计数器
用途:只能用于定时器中断
3)通用定时器
TIM2~TIM5 / TIMT9 ~TIM14,共10个
TIM2~TIM5
TIM3/TIM4(16bit)、TIM2/TIM5(32bit)计数器。
计数模式可以由软件配置成:
递增(0-->N)、递减(N-->0)、先递增再递减(0-->N-->0)
多达4个独立通道(可以有4个GPIO引脚复用),可以由软件配置成:
— 输入捕获
— 输出比较
— PWM 生成(边沿和中心对齐模式)
— 单脉冲模式输出
TIM9~TIM14
16bit的计数器,只能递增计数。
2个独立通道,可以由软件配置成:
— 输入捕获
— 输出比较
— PWM 生成(边沿对齐模式)
— 单脉冲模式输出
用途:
a.用于定时器中断 --> 配置时基单元
b.用于捕获输入信号 --> 配置时基单元 + 输入捕获单元
c.用于输出特定的信号(PWM)--> 配置时基单元 + 输出比较单元
4)高级定时器(TIM1 TIM8)
16bit计数器,递增、递减、递增/递减计数。
多达 4 个独立通道,可用于:
— 输入捕获
— 输出比较
— PWM 生成(边沿和中心对齐模式)
— 单脉冲模式输出
重复计数器(Timx_RCR):Repeation Counter Register
如果使用了重复计数,则当计数器重复溢出次数达到了设定的重复
计数器的值+1后才会产生定时器溢出/中断。
如果不使用重复计数器,在每次计数器溢出后都会产生中断/事件。
此时就跟通用定时器没什么区别。
5)看门狗 Watch Dog
看门狗的作用就是当系统卡死(跑飞了)之后,会产生复位中断(Reset_Handler)。但是看门狗只不过是忽略了卡死的现象,它并不能帮你解决卡死的问题。
看门狗的原理:
相当于一个定时器,当定时器的计数溢出后,就会产生溢出中断,这
个中断产生后,就会去执行RESET复位中断服务函数。
看门狗的实现:
1.初始化配置看门狗,比如设置初始值为N
配置好之后,系统启动同时看门狗也开始运行,就会从N开始递减(从0
开始递增),当减到溢出的时候,就会CPU复位。所以正常情况下,不能让
看门狗减到0,那么为了避免在正常的情况下,看门狗减到0,需要喂狗。
2.周期性的喂狗(重置定时器计数值)
比如:假设看门狗的定时时间为50ms。
意味着如果不做任何处理的话,每过50ms产生复位中断。
你必须每隔 < 50ms的时间就必须喂狗一次,以避免它产生复位中断。
喂狗的话不能采用定时器中去喂狗:
因为定时器中断无论是CPU是否跑飞,都会在溢出后产生中断,用定时
器喂狗,会导致看门狗失去效果。
7.STMF4xx固件库中定时器相关的函数
1)定时器时基单元配置
a.使能定时器时钟总线(定时器都处于APB1或者APB2总线上)
RCC_APB1P...
RCC_APB2P...
b.初始化定时器时基单元
void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct)
2)定时器中断配置
当要使用定时器中断时,则需要配置由哪种方式触发定时器中断。
void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState)
//用于指定触发定时器中断的方式
3)NVIC配置
同时写一个定时器对应的中断服务函数
4)使能定时器
void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState)
输出比较
不同的定时器有2~4个独立的通道,每一个通道都是由GPIO复用而来。因此,如果需要使用输出比较(输入捕获)的话,则需要事先配置通道对应的GPIO(AF模式)口。输入捕获和输出比较因为使用的是同一个寄存器,所以两者不能同时使用。
输出比较的实现步骤:
1.初始化GPIO控制器
1.1 使能GPIO分组时钟
1.2 初始化GPIO口(AF模式)
1.3 配置GPIO复用功能
void GPIO_PinAFConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_PinSource, uint8_t GPIO_AF)
2.配置定时器时基单元
2.1 使能定时器时钟总线(定时器都处于APB1或者APB2总线上)
2.2 初始化定时器时基单元
3.配置输出比较器(各个通道是可以独立配置)
void TIM_OC1Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct)
void TIM_OC2Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct)
void TIM_OC3Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct)
void TIM_OC4Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct)
4.使能定时器
TIM_Cmd
设置输出比较寄存器的值:
void TIM_SetCompare1(TIM_TypeDef* TIMx, uint32_t Compare1);
void TIM_SetCompare2(TIM_TypeDef* TIMx, uint32_t Compare2);
void TIM_SetCompare3(TIM_TypeDef* TIMx, uint32_t Compare3);
void TIM_SetCompare4(TIM_TypeDef* TIMx, uint32_t Compare4);
最后
以上就是高贵水蜜桃为你收集整理的定时器(Timer)的全部内容,希望文章能够帮你解决定时器(Timer)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复