打印
[STM32WB]

STM32定时器中断配置步骤_影子寄存器_时钟_时钟树_固件库

[复制链接]
545|29
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
前言
本文分两大部分:

一、定时器中断

这部主要是简单的介绍了一下定时器,给出了定时器中断的配置步骤及实例代码。如果只是想实现定时器中断代码,则只需参考本部分即可。

二、补充&深入

在这一部分中,简单介绍了一下定时器的框图、影子寄存器、时钟、时钟树。另外还讲解了使用固件库编写定时器相关代码时,需要对固件库中默认参数进行更改的地方

—————————————————————————————

定时器中断
定时器是什么
定时器是 单片机中用来 “定时” 的器件

定时器可以根据计数到来的时钟脉冲周期的个数,来实现定时功能 =》 计数值 * 时钟周期 = 定时时间

定时器的类型
在STM32F103C8T6芯片中



当采用RCC内部时钟作为定时器时钟源输入时,三者配置代码步骤基本相同

使用特权

评论回复
沙发
纠结的那些年|  楼主 | 2024-7-31 13:07 | 只看该作者
计数器模式


递增计数:从0计数到设定值ARR后,再来一个脉冲就溢出。
递减计数:从ARR计数到0后,再来一个脉冲就溢出。
中心对齐计数模式1:交替计数,在向下计数溢出时会产生中断。
中心对齐计数模式2:交替计数,在向上计数溢出时会产生中断。
中心对齐计数模式3:交替计数,在向下和向上计数溢出时均会产生中断。

注:

所有定时器都支持递增计数。
TIM6/TIM7/TIM9/TIM10/TIM11/TIM12/TIM13/TIM14只支持递增 (参考芯片中文手册)

使用特权

评论回复
板凳
纠结的那些年|  楼主 | 2024-7-31 13:08 | 只看该作者
时基单元
时基单元分为3个部分:

① 预分频器TIMx_PSC

② 计数器TIMx_CNT

③ 自动重装器TIMx_ARR

使用特权

评论回复
地板
纠结的那些年|  楼主 | 2024-7-31 13:08 | 只看该作者
工作原理:

​ 通过PSC预分频器将定时器从总线上获取的输入频率CK_PSC分频为一个合适的计数频率CK_CNT。每来一个脉冲周期,定时器中的计数CNT加1,当计数器计数溢出时,就可以向NVIC上报一个定时器溢出中断请求,以此来实现定时。

计数器计数频率:
CK_CNT = CK_PSC / (PSC + 1)

计数器溢出频率:
CK_CNT_OV = CK_CNT / (ARR + 1)
= CK_PSC / (PSC + 1) / (ARR + 1)

注意事项:

1.预分频器的设定值与实际预分频系数是有一个1的差值:

因为预分频器的取值是从0开始的,当设置预分频值为0时,对应1分频,即:CK_PSC / 1

2.自动重装载的设定值与实际溢出值也有一个1的差值:

当计数到设定值ARR时,并不会产生溢出中断,还需要再来一个脉冲后才产生中断

这就是为什么上面公式中PSC、ARR都要加1的原因

使用特权

评论回复
5
纠结的那些年|  楼主 | 2024-7-31 13:10 | 只看该作者
例子:

TIM9位于APB2总线上,则其输入频率CK_PSC = 84M*2 = 168M。

设置:

PSC = 168 - 1;

ARR = 1000 - 1;

使用特权

评论回复
6
纠结的那些年|  楼主 | 2024-7-31 13:10 | 只看该作者
定时器的时钟源
定时器的时钟来源有4个:



①RCC内部时钟:即定时器所在总线的定时器时钟。

②ETR外部时钟:即通过GPIO引脚输入的脉冲时钟。

③ITRx其他定时器时钟:即以其他定时器溢出更新事件作为时钟源,用于实现定时器的级联。

④TIx捕获通道:定时器输入捕获功能从GPIO口捕获的脉冲作为时钟源。

一般情况下都采用RCC内部时钟作为定时器的时钟源。

使用RCC内部时钟时,CK_PSC 的频率由定时器所在总线决定。

例如:定时器TIM9位于APB2总线上,则CK_PSC = 168M

注:基本定时器只能使用RCC内部时钟

使用特权

评论回复
7
纠结的那些年|  楼主 | 2024-7-31 13:11 | 只看该作者
定时中断-固件库实现步骤
定时中断的基本结构框图、

使用特权

评论回复
8
纠结的那些年|  楼主 | 2024-7-31 13:11 | 只看该作者
要实现定时中断,则只需 “打通” 上面这个框图的线路即可:

1.使能时钟
使能TIMx定时器时钟
2.配置时钟源
选择RCC内部时钟
3.配置时基单元
选择计数模式
计数重装值ARR
预分频PSC
...
4.配置中断输出控制
允许更新中断输出到NVIC
5.配置嵌套中断向量控制器NVIC
① 配置优先级分组

② 配置NVIC

中断请求线
抢占优先级
响应优先级
使能

6.启动定时器
void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState);

使用特权

评论回复
9
纠结的那些年|  楼主 | 2024-7-31 13:12 | 只看该作者
实例代码
STM32F407芯片

使用定时器TIM4、内部时钟RCC 实现定时器中断
//配置定时器中断
void TIM4_Init(void)
{
        TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
        NVIC_InitTypeDef NVIC_InitStruct;
        //1.使能时钟
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);

        //2.选择时钟源
        TIM_InternalClockConfig(TIM4); //选择内部时钟源作为TIM4时基单元驱动

        //3.配置时基单元
        TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up; //递增计数
        TIM_TimeBaseInitStruct.TIM_Period = 10000 - 1; //计数重装值ARR
        TIM_TimeBaseInitStruct.TIM_Prescaler = 8400 - 1; //预分频PSC
        //TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1; //选择外部时钟时,时钟源处的预分频
        //TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0; //重复计数器的值,高级定时器才用到,这里给0即可
        TIM_TimeBaseInit(TIM4, &TIM_TimeBaseInitStruct);

        //清除中断标志(不清除则会在启动定时器前先产生一次更新中断事件)
        //(自动重装载器机制是通过产生一次更新中断事件来装载的,所以初次给ARR值时,即便定时器还没有启动,也会产生一次更新中断事件)
        TIM_ClearFlag(TIM4, TIM_FLAG_Update);
        //4.配置输出中断控制,允许更新中断输出到NVIC
        TIM_ITConfig(TIM4, TIM_IT_Update,  ENABLE);

        //5.配置NVIC(嵌套中断向量控制器)
        // ① NVIC优先级分组
        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
        // ② NVIC
        NVIC_InitStruct.NVIC_IRQChannel = TIM4_IRQn; //选择NVIC通道
        NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
        NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 2;
        NVIC_InitStruct.NVIC_IRQChannelSubPriority = 2;
        NVIC_Init(&NVIC_InitStruct);

        //启动定时器
        TIM_Cmd(TIM4, ENABLE);
}

//定时器4中断处理函数(函数位置任意,但函数名必须以中断向量表中的函数名为准,可在启动文件中找到)
void TIM4_IRQHandler(void)
{
        //1.先判断TIM4中断标志位
        if(TIM_GetITStatus(TIM4, TIM_IT_Update) == SET)
        {
                //2.处理中断的代码
               
               
                //3.软件清除中断标志
                TIM_ClearFlag(TIM4, TIM_FLAG_Update);
        }
}

//主函数
int main()
{
        TIM4_Init();
        while(1);
}

使用特权

评论回复
10
纠结的那些年|  楼主 | 2024-7-31 13:12 | 只看该作者
补充&深入
一、基本定时器框图

使用特权

评论回复
11
纠结的那些年|  楼主 | 2024-7-31 13:12 | 只看该作者
通用定时器框图
高级定时器框图与基本定时器差不多,且通用定时器更常用,故不再列出

使用特权

评论回复
12
纠结的那些年|  楼主 | 2024-7-31 13:12 | 只看该作者
由上面两个框图可以看出来

基本定时器的定时器时钟源只有RCC内部时钟

而通用定时器有四个定时器时钟源

使用特权

评论回复
13
纠结的那些年|  楼主 | 2024-7-31 13:12 | 只看该作者
影子寄存器
在上面框图中,预分频器、自动重装载器的框图后都有一个 “影子” ,这些寄存器都有一个影子寄存器。

这些寄存器实际上是有两个的:

一个供我们读写用的,他并不直接决定分频系数

另外一个是缓冲寄存器(影子寄存器),这才是真正起作用的寄存器

使用特权

评论回复
14
纠结的那些年|  楼主 | 2024-7-31 13:13 | 只看该作者
参考上面这个时序图,红线②对应的分频器值为0(即分频系数为1),之后在①处改变分频系数,但②-③的定时器时钟并没有立即改变,且此时缓冲寄存器中的值仍然是0。直到红线③处,计数器计数溢出产生更新事件后,预分频控制寄存器的值才传递到缓冲寄存器中,此时定时器的时钟才变成输入时钟的2分频

影子寄存器的作用:同步。同步更新ARR、PSC、CCR。
防止在一个计数周期(从开始计数到溢出)内更改ARR、PSC、RCC而导致波形频率变化/计数出错等问题。

使用特权

评论回复
15
纠结的那些年|  楼主 | 2024-7-31 13:13 | 只看该作者
例如:

如果上图更改的重装值ARR立即生效,由于当前计数值计数已经大于新的重装值,则计数器就会一直计数,直到达到计数上限65535。导致计数错误。

使用特权

评论回复
16
纠结的那些年|  楼主 | 2024-7-31 13:13 | 只看该作者
时钟
一)时钟是什么
时钟是数字电路的灵魂,是用来使系统相关的电子组件实现 同步运行

时钟本质上是一个周期性变化的矩形波(方波)



两个与时钟息息相关的概念:

时钟周期T:指 时钟信号的最小重复单位,即一个低电平+一个高电平,基本单位 秒s。
时钟频率f:指 时钟信号在1s内重复的周期个数,基本单位 Hz。
f = 1 / T f = 1/T
f=1/T

使用特权

评论回复
17
纠结的那些年|  楼主 | 2024-7-31 13:13 | 只看该作者
拓展讲解:

晶振:石英晶体振荡器,石英晶体是自然存在的一种能够通过压电效应产生周期性振荡波形的物质,只需要给石英晶体通电,就能够得到一个周期性变化的信号,在当下的电子产品中,通常会采用晶振来为系统提供基础时钟频率

RC振荡电路:通过电阻和电容按特定电路结构连接后,通过电容的充放电也可以产生周期性变化的信号,在数字电路中经常也会被用来作为 基础时钟使用,只不过 RC振荡电路产生的时钟频率较低,稳定性比晶振要差

PLL:锁相环电路,可以通过电路设计,对输入时钟信号进行 倍频/分频处理

倍频:放大时钟频率

分频:减小时钟频率

DIVIDER:分频器 Prescale:预分频器

使用特权

评论回复
18
纠结的那些年|  楼主 | 2024-7-31 13:14 | 只看该作者
STM32F4xx有四个时钟源
HSI :High Speed Internal 高速内部RC时钟,频率16MHz

HSE :High Speed External 高速外部晶振时钟,频率范围为4MHz~26MHz,频率取决于PH0和PH1连接的外部晶振电路


GEC-M4采用的是8MHz晶振。


使用特权

评论回复
19
纠结的那些年|  楼主 | 2024-7-31 13:14 | 只看该作者
LSI :Low Speed Internal 低速内部RC时钟,频率32KHz

LSE:Low Speed External 低速外部晶振时钟,频率32.768KHz,连接在PC14和PC15引脚的晶振电路提供

使用特权

评论回复
20
纠结的那些年|  楼主 | 2024-7-31 13:14 | 只看该作者
STM32F4xx的时钟树

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

38

主题

632

帖子

0

粉丝