目录

  • 一、前言
    • 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:本人也属于技术小白级别,本文如有写的不合适的地方,欢迎各位在评论区讨论。

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

  1. PHP开发之递归算法的三种实现方法

    递归算法对于任何一个编程人员来说,应该都不陌生.因为递归这个概念,无论是在PHP语言还是Java等其他编程语言中,都是大多数算法的灵魂.对于PHP新手来说,递归算法的实现原理可能不容易理解.但是只要你 ...

  2. 51单片机(二)流水灯的几种实现方法

    流水灯的几种实现方法 一.暴力法 二.数组法 三.循环左移法 一.暴力法 直接对P1寄存器的每一位进行重命名,然后点亮第一个-->延时-->熄灭第一个.点亮第二个-->延时--> ...

  3. 简单51单片机c语言编程流水灯,51单片机如何实现流水灯?51单片机实现流水灯的三种方法详细分析...

    描述 首先,介绍下原理.下图为主控芯片和流水灯模块的原理图.流水灯模块接在单片机的P1口,由原理图可以知道,在P1口给一个低电平即可点亮LED灯.相反,如果要LED灯熄灭,就要把P1口的电平变为高电平 ...

  4. 【单片机基础】stc89c52单片机实现流水灯的三种编程方式

    效果图 实现流水灯的第一种方式 /* 来回点亮LED的第一种方法 */ #include <reg52.h>//包含51一些特殊功能寄存器 #define uchar unsigned c ...

  5. 51单片机流水灯的三种实现方法

    首先,介绍下原理.下图为主控芯片和流水灯模块的原理图.流水灯模块接在单片机的P1口,由原理图可以知道,在P1口给一个低电平即可点亮LED灯.相反,如果要LED灯熄灭,就要把P1口的电平变为高电平即可. ...

  6. 51单片机制作花式流水灯的三种方式总结与仿真运行

    制作流水灯,一共有三种方式,分别是左右移位,延时,与定时器(计数器)方式 其中移位方式较为简便,常与简单的延时一同使用在各类工程中.除此之外,也可以直接操作寄存器改变灯的亮度. 延时方式通过改变占空比 ...

  7. keil5生成一个单片机led呼吸灯程序

    对于生成单片机 LED 呼吸灯程序,您可以以下这样做: 打开 Keil 5 软件,创建一个新项目. 选择您使用的单片机类型和板子,按照向导配置项目. 在程序代码中包含所需的头文件和定义. 使用 for ...

  8. 单片机长时间程序跑飞_单片机程序跑飞的三种现象、原因及解决方法

    今天在编写单片机程序的时候,由于中断服务程序写的不好,导致单片机程序总是跑飞,最后费了好长时间,花了很大功夫才找到问题原因,由此总结了单片机程序跑飞的三种现象.原因及解决方法. 一.数组越界(数组溢出 ...

  9. UG\NX二次开发 获取相切面的三种方法

    文章作者:里海 来源网站:https://blog.csdn.net/WangPaiFeiXingYuan 简介: UG\NX二次开发 获取相切面的三种方法 方法1: 使用NX Open C++ 的面 ...

最新文章

  1. android中menu菜单扩增_【已解决】Android添加Menu菜单
  2. MVC5+EF6 入门完整教程七
  3. (JAVA学习笔记) static关键字详解
  4. DCMTK:查询/检索服务类用户(C-FIND操作)
  5. java mvc 面试题_2018年java技术面试题整理
  6. POJ 3087 Shuffle'm Up (模拟+map)
  7. 【VB.NET】基于Visual Studio编写VB.NET程序的常见问题的解答
  8. Powerdesigner导出ORACLE形式sql文件遇到的问题总结
  9. 远程服务异常处理的实践之一:客户端
  10. IsPostBack深入探讨
  11. 计蒜客 17119 Trig Function(切比雪夫多项式)
  12. PandoraBox潘多拉无线桥接(中继)使用方法和无法使用解决----小米mini小米3路由
  13. 大数据之大数据技术架构
  14. 协议实例说明--租房
  15. 百度×TCL丨鸿鹄语音芯片首次在家电行业量产!
  16. 使用FTP进行主机与Linux的文件传输
  17. An error has occured.See the log file
  18. 计算机三个人的英语情景对话,求简单的三人英语情景对话对话 购物的老师要求要三人的英语对话 购物的 每人五句左右就行...
  19. 基于专家知识的决策树分类|以DEM+影像数据在ENVI操作为例
  20. 计算机无法显示移动硬盘,电脑不显示移动硬盘怎么办 检测不到移动硬盘的原因...

热门文章

  1. 调用matlab dll报错,c#调用MATLAB的dll时出错
  2. 【Python 实战】---- 批量修改文件名和将txt转excel
  3. [面试经历]偶最近做过的面试题~
  4. Mac抓包工具—— Charles相关总结
  5. 下载神器:axel aria2 mwget多线程快速下载取代curl和wget的多线程下载命令
  6. R语言和Rstudio下载 以及 R 包安装
  7. Linux中连接mysql执行sql文件
  8. JAVA2实用教程(第5版)第二章
  9. 服务器之间文件同步 go,基于golang文件实时监控并同步远端服务器工具
  10. Java权限管理|基于springBoot+springSecurity+jwt实现前后端分离用户权限认证