STM32——定时器定时中断、外部中断

1、首先是进行程序实验

对定时器进行定时中断:首先是对TIM进行初始化设置,之后为了使得定时器在复位时是从0开始计时,清除定时器标志位,再开启定时器的更新中断,对NVIC进行分组,初始化配制,最后设置TIM使能开启定时器。部分代码如下:

VID_20240723_123055

以上是定时器的定时中断,可以当作秒表计时

之后是定时器的理论知识

自动重装寄存器:计到某个值后引发一次中断或相应

因为以上三个数都是16位,因此当预分频器、自动重装寄存器都是2的16次方时,达到计数的最大值

其中65536是2的16次。。

通过以上公式可以计算出72MHz可实现最大59.65s定时,一开始并不理解这是什么意思,后来经过查资料明白了,这个定时器可以在59.62秒之后发生一次中断或者事件响应。

如果觉得59.32秒才引起一次中断时间跨度小,可以进行定时器级联,将59.62秒作为输入,×2的16次方×2的16次方,就是8千多年。(频率是除以以上两个数,因此计数器就是乘以以上两个数)

之后介绍了定时器的分类,主要学习通用定时器,本节采用TIM2

基本定时器只能连接内部时钟

主从触发DAC模式:

相当于事件响应,用DAC输出波形,当达到更新事件时就去触发DAC处输出波形。

首先内部时钟的频率为72MHz,当传到时基单元时,如果预分频器为0,则输出频率与输入频率相等都是72MHz,就是1分频

此时传给计数器的频率就是36MHz.以此类推为2时,就是三分频,输出频率为24MHz,由此可得:

上面也说了,预分频器的最大值是2的16次方,为65535(从0到65535,一共65536个数)

因此自动重装载寄存器的作用就是存储目标值,计数器与其不断进行比较,使得他们一致之后就引起一次中断或者事件响应。之后清零,开始下一次计时。

当计数器与自动重装载寄存器的值一致时,发生中断称为更新中断;发生事件,称为更新事件。

因此TIM2的ETR只能用PA0引脚。

以下是整体流程:

然后是预分频器的时序图:

当CK_CNT为1时,相当于实际分频器系数为1,此时输入频率依然是72MHz,周期和CK_PSC一致;

当CK_CNT为2时,此时输入频率为72/2MHz,周期为原来的两倍

自动重装载寄存器的值为FC,因为在此之后计数器开始重新计时(与自动重装载寄存器的值一致且下一个定时器时钟来临时,计数器开始重新计数),且产生一个更新事件

CK_PSC表示输入预分频器的输入时钟。

CK_CNT是计数器的输入时钟,也是预分频器的输出时钟,相当于预分频器实际系数。

因为当预分频控制寄存器由0改到1,此时预分频系数发生立马改变,会导致在一个计数周期内,前半部分和后半部分的计数器频率不一样,虽然没有太大影响,但是STM32严谨,设计了预分频缓冲器,使得在本次计数周期完全结束后,产生一个更新事件后,进入到下一轮计数时,计数器周期才会发生改变。

预分频器内部是靠预分频计数进行分频,当预分频值为0时,预分频器的输出频率与输入频率一致,直接输出,然后当预分频值为1时,预分频计数器是输出0,1,0,1,回到0时输出一个脉冲,此时预分频器的输出频率是输入频率的一半。

UIF为1时,会去申请中断,中断响应后,手动清除中断信号

ARR表示自动重装载寄存器的值

是否添加缓冲器可以自己决定,下面一个是没有缓冲器:

可以明显看出,在计数器计数时,自动加载寄存器突然从FF变到了36,本来计数器需要达到FF才能进行一个重新计数,但是在没有缓冲器的情况下,并不需要完成一个周期后再按照新的目标值进行中断,而是直接更改目标值。

因此这种方式容易出错,譬如当原目标值为FF时,突然改到36,但此时的计数器已经超过36,此时计数器将一直加到FFFF(计数器是16位),再回到0,这就很不合理。

这个是有缓冲器的情况:

这个图则是在存在缓冲器的情况下,一定要等到一个周期结束后,目标值才发生了变化

以上就是基本原理,下面是外部中断的实验:就是在定时中断的基础上,增加GPIO的程序,与之前的一样

VID_20240723_124031

这个学习比之前的要难,因此视频也是看了两遍才突然顿悟,有点开心终于听懂了!!!

以下是stm32高级定时器TIM1的定时中断配置代码示例: ``` // 定时器配置 TIM_HandleTypeDef htim1; TIM_OC_InitTypeDef sConfigOC; htim1.Instance = TIM1; htim1.Init.Prescaler = 0; htim1.Init.CounterMode = TIM_COUNTERMODE_UP; htim1.Init.Period = 999; htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; htim1.Init.RepetitionCounter = 0; if (HAL_TIM_Base_Init(&htim1) != HAL_OK) { Error_Handler(); } // 定时中断配置 HAL_NVIC_SetPriority(TIM1_UP_TIM10_IRQn, 0, 0); HAL_NVIC_EnableIRQ(TIM1_UP_TIM10_IRQn); HAL_TIM_Base_Start_IT(&htim1); // 中断处理函数 void TIM1_UP_TIM10_IRQHandler(void) { HAL_TIM_IRQHandler(&htim1); } void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if (htim->Instance == TIM1) { // 定时器中断处理代码 } } ``` 这个示例代码中,我们使用了STM32 HAL库进行定时器配置和定时中断配置。其中,`htim1`是一个`TIM_HandleTypeDef`结构体,用于存储定时器的相关配置信息。`sConfigOC`是一个`TIM_OC_InitTypeDef`结构体,用于存储定时器输出比较(PWM)的相关配置信息。 在定时中断配置部分,我们使用了HAL库提供的函数`HAL_NVIC_SetPriority()`和`HAL_NVIC_EnableIRQ()`来配置定时器中断优先级和使能定时中断。同时,我们也使用了HAL库提供的函数`HAL_TIM_Base_Start_IT()`来启动定时器,并且使能定时中断。 在中断处理函数`TIM1_UP_TIM10_IRQHandler()`中,我们调用了HAL库提供的函数`HAL_TIM_IRQHandler()`来处理定时器中断。在`HAL_TIM_PeriodElapsedCallback()`回调函数中,我们可以编写定时器中断处理代码。 需要注意的是,这个示例代码中的定时器时钟源为APB2总线,如果需要使用其他时钟源或者其他定时器,请根据具体情况进行修改。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hssfscv

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值