呼吸灯的三种实现方法

简介: 本文提供了三种实现呼吸灯的方法,分别是利用for循环实现、利用定时器中断实现和利用定时器输出PWM波实现。前两种方法平时接触的不多,所以贴出了程序,最后一种方法大家肯定都已熟悉,这里就没有详细介绍。


🎀 文章作者:二土电子
🐸 期待大家一起学习交流!


一、前言

提示:本文使用的芯片并非STM32系列,利用定时器实现呼吸灯是从寄存器层面讲解的,但是对于不同芯片以及是否使用库函数开发来说,基本原理是相同的。

1、什么是呼吸灯

顾名思义,呼吸灯是指灯能够像人的呼吸一样,实现由暗到亮或由亮到暗的变化,通常用于消息提示功能,或者作为系统正在运行的提示。

2、如何实现呼吸灯


其实无论哪种实现方法,基本思想都是通过脉冲宽度调制(PWM)实现,即通过调节占空比来对模拟信号电平进行数字编码。关于何为PWM,何为占空比,这里就不再赘述了,简单理解就是,占空比越高,LED两端电压越大,LED越亮。这里用一张图简单的介绍一下呼吸灯的实现原理。

人眼的分辨率为1秒24帧,即人眼看到的图像滞留时间为0.04s左右,就按40ms计算。也就是说,一个周期为40ms,人眼是看不出其中的亮灭变化的。但是为了让呼吸灯效果看起来更好,建议选则周期长度小于40ms,这里选则25ms。

二、利用for循环实现呼吸灯

利用for循环实现呼吸灯主要有两个关键变量,一个是周期T,一个是占空比的值t,他们的含义如下图所示:
be9603c3358a5a6675c3906f184b562e_f537cc90f86e48cea64dfa85f5d8143c.jpeg
图中T为一个周期(脉冲宽度),t为占空比。
利用for循环实现呼吸灯的程序如下:

int main(void)
{
   
   
    uint32 T = 1600;   // 周期(脉冲宽度)
    uint32 i=0,m=0,n=0,t=0;

    PT0OES_D9 = 1;   // 输出使能
    PT0DAT_D9 = 1;   // 灭

    while (1)
    {
   
   
        for (i=0;i<T;i++)
        {
   
   
            PT0DAT_D9 = 0;   // 亮
            for (m=0;m<t;m++);
            PT0DAT_D9 = 1;   // 灭
            for (n=0;n<T-t;n++);
            t++;

            if (t >= T)
            {
   
   
                for (i=0;i<T;i++)
                {
   
   
                    PT0DAT_D9 = 0;   // 亮
                    for (m=0;m<t;m++);
                    PT0DAT_D9 = 1;   // 灭
                    for (n=0;n<T-t;n++);
                    t--;
                }
            }
        }
    }
}

这里程序逻辑比较容易理解,就不再赘述,有需要讨论的小伙伴可以留言讨论。虽然利用for循环能够很简单的实现呼吸灯,但是这种方法是利用for循环来控制亮灭时间,时间控制并不精确。

三、利用定时器实现呼吸灯

1.利用定时器中断实现

利用定时器中断实现呼吸灯的程序如下:

uint32 count= 0;
uint32 flag = 0;
uint32 t = 0;

int main(void)
{
   
   
    Osc_Setup();   // 初始化系统时钟
    EnableGlobalInterrupt();   // 使能全局中断

    PT0OES_D9 = 1;   // 输出使能
    PT0DAT_D9 = 1;   // 灭

    TMR1_TCR_CRST = 1;   // 复位定时器计数值寄存器和预分频计数值寄存器
    while (TMR1_TCR_CRST);   // 等待复位完成
    TMR1_PR_PR = 49;   // 设置预分频系数
    TMR1_MCR_MR0I = 1;   // 产生匹配中断
    TMR1_MCR_MR0R = 1;   // 产生计数器复位
    TMR1_MCR_MR0S   = 0;   // 计数器不停止计数
    TMR1_MR0 = 250;   // 设置匹配值
    TMR1_IR = 0xffffffff;   // 清除匹配中断标志位
    NVIC_ISER_TMR1  = 1;
    TMR1_TCR_CEN = 1;   //定时器定时,捕捉功能启动

    while (1)
    {
   
   
        if (t <= count)
        {
   
   
            PT0DAT_D9 = 1;   // 灭
        }
        else if (t > count)
        {
   
   
            PT0DAT_D9 = 0;   // 亮
        }
    }
}

void __attribute__((isr)) ISR_TMR1(void)   // 匹配中断服务函数
{
   
   
    count = count + 1;

    if (count >= 100 && flag <= 100)   // 由暗到亮
    {
   
   
        count = 0;
        t = t + 1;
        flag = flag + 1;
    }
    if (count >= 100 && flag > 100)   // 由亮到暗
       {
   
   
           count = 0;
           t = t - 1;
           flag = flag + 1;
       }
    if (flag > 200)
    {
   
   
        count = 0;
        t = 0;
        flag = 0;
    }
    TMR1_IR = 0xffffffff;
}

配置TMR1来实现呼吸灯功能,配置TMR1时预分频系数设置为49,匹配值设置为250,配置产生匹配中断,中断后产生计数器复位,计数器不停止计数,然后开启定时器1。这里需要注意的是要配置中断后产生计数器复位,否则计数器会等到计数到最大值后才清零,此时的现象是LED依然可是像呼吸灯一样由暗变亮,再由亮变暗,但是期间会不断闪烁。

假设进入匹配中断的时间为t,系统主时钟频率为Fsys,预分频系数为PR,匹配值为n,那么进入一次匹配中断的时间t= ((PR + 1)/Fsys)*n。因为开头提到过,本程序设置的脉冲宽度为25ms,系统主时钟频率为50MHz,所以这里将预分频系数设置为49和匹配值设置为250,计算后可知,每0.25ms进入一次匹配中断,进入100次更改一次占空比,即25ms更改一次,总的脉冲宽度为25ms。如果想更改脉冲宽度只需要调整count的值即可。

2.利用定时器输出PWM波实现

相比于前两种方法来说,初学单片机的人更加熟悉的是利用定时器输出PWM波来实现呼吸灯,因为正点原子或普中科技等等教程中都有详细介绍,这里就不再赘述了。


四、总结

虽然利用for循环能够比较简单地实现呼吸灯,但是其时间控制没有利用定时器实现准确,建议使用定时器来实现呼吸灯功能。

当然,上面给出的程序存在不好的地方,在中断中执行了太多语句,这是平时开发需要注意的。可以只在中断中保留count自加操作,其他放在主函数地while(1)中进行,这样可以减少在中断中执行的程序。

PS:本人也属于技术小白级别,本文如有写的不合适的地方,欢迎各位在评论区讨论。

相关文章
|
6月前
学生开闭灯问题
学生开闭灯问题
84 4
|
6月前
|
JavaScript
闪烁的灯泡
闪烁的灯泡
38 0
|
传感器
Arduino光敏传感器控制LED灯亮度
Arduino光敏传感器控制LED灯亮度
|
3月前
|
Python
实例3:树莓派呼吸灯
本文是一个关于树莓派制作呼吸灯的实验教程,介绍了PWM(脉冲宽度调制)技术的原理和应用,详细讲解了如何通过RPi.GPIO库使用Python编程控制LED灯实现呼吸效果,包括实验目的、要求、相关知识点和完整的实验步骤。
37 1
实例3:树莓派呼吸灯
|
存储 芯片
人体感应太阳能灯原理图详细讲解
三河凡科科技飞讯教学,人体感应太阳能灯是一种利用太阳能源供电,通过人体红外线感应技术实现智能控制灯源开关的照明设备。其原理是利用太阳能板将太阳能转化为电能,通过对电池的储存和管理,将电能存储在电池中,作为灯源使用时的电力供应。同时,通过人体红外线感应技术,能够实现对灯源的智能控制。
人体感应太阳能灯原理图详细讲解
|
6月前
51单片机实现led灯亮度变化!
51单片机实现led灯亮度变化!
60 0
|
传感器 算法 API
无人机 LED 灯的闪烁
在 Python 中,可以使用 GPIO 库来控制树莓派(Raspberry Pi)上的 GPIO 引脚,从而实现对 LED 灯的控制。以下是一个简单的 Python 代码示例,可以实现 LED 灯的闪烁、显示文字和数值、循环播放文字等功能:
142 0
|
编解码 网络性能优化 芯片
如何用51单片机实现pwm调光+呼吸灯(超详细+源码)
如何用51单片机实现pwm调光+呼吸灯(超详细+源码)
868 0
如何用51单片机实现pwm调光+呼吸灯(超详细+源码)
|
C语言
圆曾经的小车梦,造一台智能小车(四)之QT上位机控制小车
圆曾经的小车梦,造一台智能小车(四)之QT上位机控制小车
245 0