单片机开发—呼吸灯的三种实现方法

article/2025/10/27 22:36:51

目录

  • 一、前言
    • 1、什么是呼吸灯
    • 2、如何实现呼吸灯
  • 二、利用for循环实现呼吸灯
  • 三、利用定时器实现呼吸灯
    • 1.利用定时器中断实现
    • 2.利用定时器输出PWM波实现
  • 四、总结


一、前言

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

1、什么是呼吸灯

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

2、如何实现呼吸灯


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

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

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

利用for循环实现呼吸灯主要有两个关键变量,一个是周期T,一个是占空比的值t,他们的含义如下图所示:
在这里插入图片描述
图中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:本人也属于技术小白级别,本文如有写的不合适的地方,欢迎各位在评论区讨论。


http://chatgpt.dhexx.cn/article/ANyRYSlM.shtml

相关文章

【STM32】8.简单呼吸灯的制作教程,附代码、效果视频

目的&#xff1a; 实现呼吸灯。逐渐亮&#xff0c;逐渐灭。 一&#xff0e;呼吸灯原理分析 外设工作靠电流&#xff0c;因此要改变电流大小&#xff0c;所以要动电阻或电压。 电阻&#xff1a;阻值固定&#xff0c;不可更改。 电压&#xff1a;怎么改变电压大小呢&#xff1…

自适应滤波C语言实现

这里写目录标题 原理代码结果 原理 自适应滤波是近年以来发展起来的一种最佳滤波方法。它是在维纳滤波,Kalman滤波等线性滤波基础上发展起来的一种最佳滤波方法。由于它具有更强的适应性和更优的滤波性能。从而在工程实际中,尤其在信息处理技术中得到了广泛的应用。自适应滤波…

c语言实现图像滤波处理

#include<stdio.h> #include<malloc.h> #include<stdlib.h> #include <math.h> /* 位图头结构 */ #pragma pack(1) typedef struct tagBITMAPFILEHEADER {unsigned char bfType[2];//文件格式unsigned long bfSize;//文件大小unsigned short bfReserve…

卡尔曼滤波一阶矩阵C语言实现

①估计时刻k的状态&#xff1a; ②误差相关矩阵P&#xff0c;度量估计值的精确程度 ③卡尔曼增益 ④更新误差相关矩阵 ⑤更新状态变量 ⑥最后输出 C语言代码&#xff1a; float X_pre,P_pre,X_kalman_last,P_kalman_last,X_kalman2500,P_kalman2; //赋初值 float H,Q…

卡尔曼滤波C语言实现

卡尔曼5条基本公式&#xff0c;参考https://wenku.baidu.com/view/8523cb6eaf1ffc4ffe47ac24.html #include "stdio.h" #include "stdlib.h" #include "math.h"#define kal_Q 0.001 /*过程噪声协方差,Q增大&#xff0c;动态响应变快&#xff0…

C语言实现简单卡尔曼滤波

https://www.bilibili.com/video/BV1ez4y1X7eR DR.CAN讲的真的很好 卡尔曼滤波的步骤 步骤说明Step 1计算卡尔曼增益Step 2更新本次迭代的估计值Step 3更新本次迭代的估计误差 具体请看上面DR.CAN的视频 代码 参数说明x_mea测量值x_est估计值e_mea固有的测量误差&#xf…

C语言实现双边滤波

参考博文 看不懂公式的先去看参考博文 一个3*3窗口的代码 /**双边法滤波 3*3窗口 *参数 data[][COL] 图像数据 *参数 row 图像数据行数 *参数 varD 空域核d的标准差 *参数 varR 值域核r的标准差 *需要引用头文件math.h *typedef unsi…

数字图像处理,读懂频域处理的“傅里叶变换”

转载自&#xff1a;https://blog.csdn.net/ebowtang/article/details/39004979 以下部分文字资料整合于网络&#xff0c;本文仅供自己学习用&#xff01; 这是一幅很绝的一维傅里叶变换动态图 一&#xff0c;读懂傅里叶变换 一个信号能表示成傅里叶级数的形式是有条件的&…

傅立叶变换和拉普拉斯变换

欧拉公式 证明过程如下 首先是泰勒展开 参考cosX和sinX的泰勒展开可以证明这个问题。 还有下面这个号称宇宙最美公式 “自然底数e&#xff0c;自然数1和0&#xff0c;虚数i还有圆周率pi&#xff0c;它是这么简洁&#xff0c;这么美丽啊&#xff01;” 傅立叶级数 傅立叶在…

Little’s Law 利特尔法则

1 A simple definition: Little’s Law states that the long-term average number of customers in a stable system L L L is equal to the long-term average effective arrival rate, λ \lambda λ, multiplied by the average time a customer spends in the system, …

勒让德符号的说明及作用

Legendre符号的用途 一、 二次剩余 勒让德符号的提出的意义是判断一个数是否是模n的二次剩余&#xff0c;所以研究勒让德符号之前应该了解一下二次剩余。 存在x使x的平方与a MOD (p)就称a为模p的二次剩余&#xff0c;其中p为素数&#xff0c;a>0且a<p。 通过勒让…

奈奎斯特准则的简洁证明

一般而言&#xff0c;发送滤波器和接收滤波器的冲激响应相同且关于原点对称&#xff0c;有用信号事实上经过了这两个滤波器&#xff0c;所以等效滤波器为&#xff1a; 为使无符号间干扰&#xff0c; 应满足&#xff1a; 奈奎斯特准则指出上式等价于&#xff1a; 其中 表示的傅里…

蒙蒂霍尔悖论

贝叶斯与频率主义对蒙蒂霍尔问题的解 在定义概率时&#xff0c;通常有两种思想流派&#xff1a;贝叶斯主义和频率主义。前者将概率视为我们对事件发生的信念程度&#xff0c;而后者则将其视为事件发生的相对频率。这篇文章介绍了使用贝叶斯和频率主义方法来解决著名的蒙蒂霍尔问…

信号 信号的线性放大

信号 1.信号 信号是信息的载体或表达形式 2. 信号的频谱 正弦信号 方波信号 满足狄里赫利条件&#xff0c;展开成傅里叶级数 附 狄里赫利条件: 1) 函数在任意有限区间内连续&#xff0c;或只有有限个第一类间断点&#xff08;当t从左或右趋于这个间断点时&#xff0c;函数有有限…

信号的频域描述

一、周期信号的频域描述 1. 狄里赫利条件 &#xff08;1&#xff09;函数在任意有限区间内连续&#xff0c;或只有有限个第一类间断点 &#xff08;2&#xff09;在一个周期内&#xff0c;函数有有限个 极大值或极小值 2. 傅里叶级数 &#xff08;1&#xff09;傅里叶级数…

【信号与系统】(十三)傅里叶变换与频域分析——周期信号的傅里叶级数

文章目录 周期信号的傅里叶级数1 周期信号三角形式的傅里叶级数1.1 三角形式的傅里叶级数1.2 狄里赫利(Dirichlet)条件1.3 .余弦形式的傅里叶级数1.4 吉布斯现象 2 周期信号波形对称性和谐波特性2.1 f ( t ) f(t) f(t)为偶函数2.2 f ( t ) f(t) f(t)为奇函数2.3 f ( t ) f(t…

连续时间傅立叶变换和拉普拉斯变换

连续时间傅里叶变换简称&#xff1a;CTFT 连续时间周期信号x(t)如果满足狄里赫利条件&#xff0c;则其存在傅立叶级数对&#xff1a; x(t)在任何有限区间内&#xff0c;有有限个不连续点&#xff0c;并且在每个不连续点都必须是有限值。 注意&#xff1a;狄里赫利条件是充分条…

狄利克雷条件

属于 傅里叶级数分析使用的条件&#xff1a; 傅里叶在提出 傅里叶级数时坚持认为&#xff0c;任何一个周期信号都可以展开成傅里叶级数&#xff0c;虽然这个结论在当时引起许多争议&#xff0c;但持异议者却不能给出有力的不同论据。直到20年后(1829年)狄里赫利才对这个问题作出…

从傅里叶变换到拉普拉斯变换

理解拉普拉斯变换&#xff0c;可以先从傅里叶变换开始。 傅里叶定律&#xff1a;只要一个函数满足如狄利赫里条件&#xff0c;都能分解为复指数函数之和。 狄利赫里条件&#xff1a; (1) 函数在任意有限区间内连续&#xff0c;或只有有限个第一类间断点&#xff1b; (2)在一…

周期信号的傅里叶级数

周期信号的傅里叶级数 周期信号三角形式的傅里叶级数 1.三角形式的傅里叶级数 系数an, bn称为傅里叶系数 2.狄里赫利(Dirichlet)条件&#xff1a; 条件1&#xff1a;在一个周期内&#xff0c;函数连续或只有有限个第一类间断点&#xff1b; 条件2&#xff1a;在一个周期内&…