【蓝桥杯嵌入式】流水灯(TIM)

STM32G431RBT6上有高级定时器TIM1/8、通用定时器TIM2~4、基本定时器TIM6/7。经常用到的是通用定时器TIM2~4,可以选择其中一个作为一个总控定时器(定时20ms),在这个总控上去安排不同的任务(比较像分时复用?)。

复制下上次的LED工程,重命名为TIM,加入定时器的控制,做一个流水灯效果。

这里我们选用TIM4做为总控定时器。

一、在STM32CubeMX中打开TEST.ios,进行定时器的配置

在比赛资源包中的STM32G4系列微控制器参考手册资料中可以找到定时器所使用的时钟线。

可以看到TIM4是挂在APB1下(按之前设置,时钟频率为80MHz)

设置计数参数,TIM4定时器定时10ms,作为基准。

TIM4的设置完成,更新工程。

二、编程实现流水灯

在Keil 5中打开工程,先编译一次,无错误再进行下一步。

新建一对interrupt文件,用来放置用户编写的有关中断的函数,如定时器、串口中断。

将文件导入到工程中,操作详见上一章“蓝桥杯嵌入式之点灯”。

interrupt.h中先写:

#ifndef __INTERRUPT_H
#define __INTERRUPT_H

#include "main.h"



#endif

接着编写interrupt.c

#include "interrupt.h"

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{//10ms
	if(htim->Instance == TIM4)
	{
		
	}
}


在使用定时器(TIM)时,HAL库提供了一些回调函数(Callback Function),这些函数在定时器事件发生时被调用。其中,HAL_TIM_PeriodElapsedCallback() 是当定时器的定时周期结束时被调用的回调函数。

  • "Period":定时周期,指定时器的时间间隔。
  • "Elapsed":已过,表示指定的时间间隔已经流逝。
  • "Callback":回调,指一个函数,在某个事件发生时自动被调用。

当定时器的定时周期结束时,HAL库会自动调用 HAL_TIM_PeriodElapsedCallback() 函数,并将指向定时器句柄的指针 TIM_HandleTypeDef 作为参数传递给它。通过这个回调函数,用户可以实现自定义的操作,例如在定时器周期结束时执行一些特定的任务、更新计数器或重新加载计时器的值等。

其中的if语句为判断中断来源是否来自TIM4,这样就可以使用多个定时器中断任务而不会冲突。

添加流水灯函数:

#include "interrupt.h"
#include "led.h"

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{//10ms
    // 声明静态变量用于计时和记录LED位置
    static unsigned int tim4_count = 0; // 用于TIM4计数,实现分时复用
    static unsigned char led_addr = 0;  // 用于记录亮灯的位置,随时间移动形成流水灯效果
    
    // 判断中断来源是否是TIM4
    if(htim->Instance == TIM4)
    {
        tim4_count++; // TIM4计数递增
        
        // 每500ms进行一次灯的移位
        if(tim4_count == 50)
        {
            tim4_count = 0; // 重置计数变量,很重要
            led_addr = (led_addr + 1) % 8; // 移位操作
            led_disp(0x01 << led_addr); // LED显示函数,根据新的LED位置控制LED灯亮灭
        }
    }
}

static:这个关键字用于声明一个静态变量。静态变量在程序的整个生命周期内都存在,并且只会被初始化一次。它的作用域限定在当前文件中,因此在其他文件中无法直接访问。在函数内部声明的静态变量,其生命周期也是整个程序的运行期间,但是作用域限定在声明的函数内部。

(led_addr + 1) % 8:这是一个表达式,它由两部分组成。首先,led_addr + 1led_addr 的值加1,即将 LED 地址递增1。然后,% 8 将结果对8取模,即计算余数,使得 led_addr 在取值范围0到7之间循环。

综合起来,这行语句的作用是将 led_addr 的值加1,并且如果超过了7,则将其重置为0,从而实现了在LED地址范围内循环递增。

在interrupt.h中声明函数

把头文件包含到main.c中

在main()函数中加入代码

led_disp()函数详见上一章“蓝桥杯嵌入式之点灯”。

最后编译下载到板子上。

三、演示效果

流水灯(20ms间隔版)

  • 38
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值