蓝桥杯-单片机组基础15——会呼吸的流水灯制作详解

蓝桥杯单片机组备赛指南请查看 :本专栏第1篇文章

本文章针对蓝桥杯-单片机组比赛开发板所写,代码可直接在比赛开发板上使用。

型号:国信天长4T开发板(绿板),芯片:IAP15F2K61S2

(使用国信天长蓝板也可以完美兼容,与绿板几乎无差别)


        关于pwm调制基本原理本文不细讲,请查看本专栏基础7文章。但本文难度不影响您直接阅读

        对于呼吸灯,我本采用IO编程,2天的调试效果仍然不如意。采用MM编程瞬间BUG全无。因此比赛时本人铁了心采用MM编程。

        本文末尾将放出IO编程的程序,希望有大佬可以为我解答应如何修改!

1. 代码目的

        程序目的,实现小蜜蜂老师的呼吸灯讲解题目。感兴趣的朋友可以去小蜜蜂老师的CSDN观看。本文程序与小蜜蜂老师略有不同,希望有助于理解,写出自己的代码。

        题目要求如下:

【1】初始时:板子启动,led3,led4常亮,其他灯全部熄灭。此时按下S7并松开,启动呼吸灯。按下S6不松开数码管显示当初始信息,松开后数码管熄灭。蜂鸣器等无用外设全部关闭。

【2】呼吸灯要求:当前led由灭变亮500ms,再由亮变灭500ms。完成后向左或向右,下一个led灯开始呼吸

【3】第一次开机:按下并松开S7后,从led0开始呼吸,并默认从左向右流水移动;

【4】呼吸运行时:按下S7不松开,则保持当前led当前亮度不变;松开S7后从当前亮度继续呼吸,并向相反反向进行流水变化

【5】呼吸运行时:按下S6不松开,则保持当前led亮度不变,且数码管显示当前为几号灯(1~8),与灯光亮度数值(0~99);松开S6后,呼吸灯继续运行

【6】数码管显示格式:“        X _ _ _ _ _ 0 0        ”,X为第几号灯,最后两位为数值

2. 实现思路

        需要在500ms内由灭变亮,又经过500ms由暗变灭

        因此我考虑将500ms分成100份,每份50ms。用于表示100个周期内的不同占空比

        将50ms分成100份,每份50us。用于中断产生变量自增,当自增的变量小于占空比就亮。

更详细的说明如下:(来源于chatgpt4.0)

关键变量

  • pwm_50us:用于计数每50微秒增加1,以实现定时器的基本计时功能。
  • pwm_5ms:基于pwm_50us实现的更长时间计数,每累计到100(即每5ms),pwm_5ms会增加1,用于控制呼吸灯亮度变化的时间间隔。
  • pwm_duty:PWM占空比的值,这个值决定了LED亮和灭的时间比例,从而控制LED的亮度。
  • pwm_location:当前亮起的LED位置,用于在多个LED中循环显示呼吸效果。
  • pwm_direction:控制呼吸灯方向的标志位,用于决定LED是顺序点亮还是逆序点亮。
  • pwm_bright:LED亮度变化的方向标志位,0表示变亮,1表示变暗。
  • pwm_stop:控制呼吸灯停止的标志位,用于暂停或继续呼吸灯效果。
  • sys_stop:系统启动停止标志,用于控制整个呼吸灯系统是否运行。

PWM调制整合实现呼吸灯

  1. 定时器初始化:通过init_timer0函数,定时器0被设置为50微秒溢出一次,实现基础的时间计数功能。
  2. 定时器中断服务:在timer0_service中断服务函数中,每50微秒pwm_50us变量递增。当累计到100(即每5ms),pwm_5ms变量递增,用于控制呼吸灯的亮度变化周期。
  3. PWM调制:在同一个中断服务函数中,通过比较pwm_50uspwm_duty的值来控制LED的亮与灭。如果pwm_50us小于pwm_duty,则LED亮;否则,LED灭。这实现了PWM调制,pwm_duty的值决定了LED的亮度。
  4. 亮度和方向控制:在ledrunning函数中,pwm_5ms用于控制每0.5秒改变LED的亮度方向,同时也根据pwm_direction更新LED的位置,实现了呼吸灯的循环亮度变化和位置变换。
  5. 按键输入keyrunning函数处理外部按键输入,允许用户改变呼吸方向和系统的启停,从而增加了呼吸灯的交互性。

3. 代码参考(MM编程)

        详细注释版本,如果不喜欢太多注释,可以用python先将代码中的中文清洗掉

#include <reg52.h> // 包含8051系列单片机的寄存器定义
#include <intrins.h> // 包含内置函数定义
#include <absacc.h> // 包含绝对访问函数定义// 定义辅助寄存器AUXR位地址和P3端口的位地址
sbit AUXR = 0x8e;
sbit S7 = P3^0; // 定义S7为P3.0引脚,用于按键输入
sbit S6 = P3^1; // 定义S6为P3.1引脚,用于按键输入// 定义全局变量
unsigned char pwm_50us = 0;    // 定时计数器50微秒的计数值
unsigned char pwm_5ms = 0;     // 定时计数器5毫秒的计数值
unsigned char pwm_duty = 0;    // PWM占空比的计数值
unsigned char pwm_location = 0;    // LED亮灯位置的计数值
bit pwm_direction = 1;   	// 控制呼吸灯方向的标志位,0向右,1向左.因为按键函数有一个取反操作,因此初始向左,按下启动后则向右
bit pwm_bright = 0;   	    // 控制LED亮度变化的标志位,0变亮,1变暗
bit pwm_stop = 0;            // 控制呼吸灯停止的标志位,0继续,1停止
bit sys_stop = 0;			//初始时系统不启动,0不启动,1启动呼吸// 函数声明
void SMGrunning (); // 数码管运行函数声明
void ledrunning (); // LED运行函数声明
void state_SMG_all ( unsigned char value_SMG_all );// 数码管显示的编码,代表不同的数字和符号
unsigned char code duanma[18] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xc0,0x86,0x8e,0xbf,0x7f};// 系统初始化函数
void init_sys ()
{XBYTE[0x8000] = 0xe7; // 初始化led的3,4亮,其他熄灭XBYTE[0xa000] = 0x00; // 初始化外部设备state_SMG_all ( 0xff );
}// 数码管状态设置函数
void state_SMG ( unsigned char pos_SMG , unsigned char value_SMG )
{XBYTE[0xc000] = 0xff; // 关闭所有数码管显示,用于消影XBYTE[0xc000] = 0x01 << pos_SMG ; // 根据pos_SMG选择一个数码管显示XBYTE[0xe000] = value_SMG; // 设置选中数码管的显示值
}// 设置所有数码管显示同一个值的函数
void state_SMG_all ( unsigned char value_SMG_all )
{XBYTE[0xc000] = 0xff; // 关闭所有数码管显示XBYTE[0xc000] = 0xff; // 选择所有数码管XBYTE[0xe000] = value_SMG_all; // 设置所有数码管的显示值
}// 定时器0初始化函数,设置定时器为50微秒溢出一次
void init_timer0 (void)
{AUXR |= 0x80; // 定时器时钟1T模式,提高定时器的计数速度TMOD &= 0xF0; // 清除定时器0的模式位TMOD |= 0x02; // 设置定时器0为模式2(自动重装载)TL0 = 0xC9;   // 设置定时器初始值,与TH0一起决定定时周期TH0 = 0xC9;   // 设置定时器重装载值TF0 = 0;      // 清除定时器0的溢出标志TR0 = 1;      // 启动定时器0EA = 1;  // 全局中断使能ET0 = 1; // 定时器0中断使能
}// 定时器0中断服务函数
void timer0_service () interrupt 1
{if ( sys_stop == 0 )//初始时系统不启动{return;    //到此程序终止,下面语句不执行}pwm_50us ++; // 50微秒计数器递增// 每5ms完成一次PWM周期的处理if(pwm_50us == 100){   pwm_50us = 0; // 重置50微秒计数器if (pwm_stop == 0){pwm_5ms++; // 5ms计数器递增}}// 根据PWM占空比控制LED亮暗if (pwm_50us < pwm_duty){XBYTE[0x8000] = ~(0x01 << pwm_location); // 根据pwm_location点亮对应LED}else{XBYTE[0x8000] = 0xff; // 关闭所有LED}
}// LED运行函数,控制LED的亮度和位置
void ledrunning ()
{// 每0.5秒改变亮度方向if (pwm_5ms == 100){pwm_5ms = 0; // 重置5ms计数器if (pwm_bright == 1) // 如果当前是变暗阶段{// 根据呼吸方向更新LED位置if (pwm_direction == 0) // 向右呼吸{if (++pwm_location == 8) // 到达边界,重置位置{pwm_location = 0;}}else // 向左呼吸{if (--pwm_location == 255) // 到达边界,重置位置{pwm_location = 7;}   }               }pwm_bright = ~pwm_bright; // 改变亮度方向}// 根据亮度方向调整PWM占空比if (pwm_bright == 1){pwm_duty = 99 - pwm_5ms;}else{pwm_duty = pwm_5ms;}}void Delay2ms()		//@11.0592MHz
{unsigned char i, j;_nop_();_nop_();i = 22;j = 128;do{while (--j);} while (--i);
}// 按键处理函数,实现对呼吸灯的控制
void keyrunning ()
{// S7按键控制呼吸灯的方向if (S7 == 0){Delay2ms(); // 去抖动if (S7 == 0){while (S7 == 0){pwm_stop = 1; // 暂停LED操作}sys_stop = 1;  //启动系统pwm_direction = ~pwm_direction; // 改变呼吸方向pwm_stop = 0; // 恢复LED操作}}// S6按键控制数码管的显示if (S6 == 0){Delay2ms(); // 去抖动if (S6 == 0){while (S6 == 0) // 等待按键释放{pwm_stop = 1; // 暂停LED操作SMGrunning (); // 更新数码管显示}pwm_stop = 0; // 恢复LED操作}}
}// 数码管运行函数,显示当前LED状态
void SMGrunning ()
{// 分别显示LED位置和占空比state_SMG (0, duanma[pwm_location]); // 显示LED位置Delay2ms(); // 短暂延时state_SMG (6, duanma[pwm_duty/10]); // 显示PWM占空比的十位Delay2ms(); // 短暂延时state_SMG (7, duanma[pwm_duty%10]); // 显示PWM占空比的个位Delay2ms(); // 短暂延时state_SMG_all(0xff); // 关闭所有数码管显示Delay2ms(); // 短暂延时
}// 主函数
void main ()
{init_sys (); // 系统初始化init_timer0 (); // 定时器0初始化while (1){ledrunning (); // LED运行控制keyrunning(); // 按键处理}
}

4. IO代码(有bug,欢迎指出如何修改)

        我调试了两天,基本确定问题出在led显示的消隐问题没有处理好。尝试了各种歪门邪道依旧不起效果。欢迎大佬为此代码debug!

#include <reg52.h>
#include <intrins.h>sbit AUXR = 0x8e;
sbit S7 = P3^0;
sbit S6 = P3^1;unsigned char pwm_50us = 0;    //定时计数器50us次数值
unsigned char pwm_5ms = 0;    //定时计数器5ms次数值
unsigned char pwm_location = 0;    //亮灯的位置数值
bit pwm_direction = 0;   	//0表示向右呼吸,1表示向左呼吸
bit pwm_bright = 0;   	 //0表示逐渐变亮,1表示逐渐变暗
bit pwm_stop = 0;    //0表示继续呼吸,1表示停止呼吸void SMGrunning ();
void ledrunning ();unsigned char code duanma[18]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xc0,0x86,0x8e,0xbf,0x7f};void select_HC573 ( unsigned char channal )
{switch ( channal ){case 4:P2 = ( P2 & 0x1f ) | 0x80;break;case 5:P2 = ( P2 & 0x1f ) | 0xa0;break;case 6:P2 = ( P2 & 0x1f ) | 0xc0;break;case 7:P2 = ( P2 & 0x1f ) | 0xe0;break;}
}void init_sys ()
{select_HC573 ( 5 );P0 = 0x00;select_HC573 ( 4 );P0 = 0xe7;
}void state_SMG ( unsigned char pos_SMG , unsigned char value_SMG )
{select_HC573 ( 7 );P0 = 0xff;select_HC573 ( 6 );P0 = 0x01 << pos_SMG;select_HC573 ( 7 );P0 = value_SMG;
}void state_SMG_all ( unsigned char value_SMG )
{select_HC573 ( 6 );P0 = 0xff;select_HC573 ( 7 );P0 = value_SMG;
}void state_led ( unsigned char pos_led , unsigned char pwm_duty )
{select_HC573 ( 4 );if ( pwm_50us < pwm_duty ){P0 = ~( 0x01 << pos_led );}else{P0 = 0xff;}
}void init_timer0 (void)		//5微秒@11.0592MHz
{AUXR |= 0x80;		//定时器时钟1T模式TMOD &= 0xF0;		//设置定时器模式TMOD |= 0x02;		//设置定时器模式TL0 = 0xC9;		//设置定时初始值TH0 = 0xC9;		//设置定时重载值TF0 = 0;		//清除TF0标志TR0 = 1;		//定时器0计时EA = 1;ET0 = 1;
}void timer0_service () interrupt 1
{pwm_50us ++;
}unsigned char pwm_duty = 0;
void ledrunning ()
{//一个周期5ms内的操作if( pwm_50us == 100 ){	pwm_50us = 0;if ( pwm_stop == 0 ){pwm_5ms++;    }}//定时时间达到0.5s,此时需要转变为由亮变暗if ( pwm_5ms == 100 ){pwm_5ms = 0;if ( pwm_bright == 1 )    //判定此时是否是在由亮变暗环节,计时达到0.5s且为1时,则为真{if ( pwm_direction == 0 )    //判定此时是否为向右呼吸,则location自增{if ( ++pwm_location == 8 )    //向右呼吸到达第7位,返回第0位{pwm_location = 0;}}else    //不是向右呼吸,则向左呼吸,则location自减{if ( --pwm_location == 255 )    //向左呼吸到达第0位,返回第7位。在unsigned char数中,0-1=255{pwm_location = 7;}	}				}pwm_bright = ~pwm_bright;}if ( pwm_bright == 1 ){pwm_duty = 99 - pwm_5ms;}else{pwm_duty = pwm_5ms;}state_led ( pwm_location , pwm_duty );}void Delay100us()		//@11.0592MHz
{unsigned char i, j;_nop_();_nop_();i = 2;j = 15;do{while (--j);} while (--i);
}bit open_SMG = 0;    //为0时关闭数码管,为1时打开数码管
void keyrunning ()
{if ( S7 == 0 ){Delay100us();if ( S7 == 0 ){while ( S7 == 0 ){pwm_stop = 1;ledrunning ();}pwm_stop = 0;pwm_direction = ~pwm_direction;}}if ( S6 == 0 ){Delay100us();if ( S6 == 0 ){while ( S6 == 0 ){pwm_stop = 1;
//				SMGrunning ();ledrunning ();}pwm_stop = 0;}}	
}void SMGrunning ()
{state_SMG ( 0 , duanma[pwm_location] );Delay100us();state_SMG ( 6 , duanma[pwm_duty/10] );Delay100us();state_SMG ( 7 , duanma[pwm_duty%10] );Delay100us();state_SMG ( 0 , 0xff );state_SMG ( 6 , 0xff );state_SMG ( 7 , 0xff );}void main ()
{init_sys ();init_timer0 ();while ( 1 ){ledrunning ();keyrunning();}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/819288.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

实验:数据结构(结构体在单链表中的增删改查)

#include<stdio.h> #include<stdlib.h> #include <string.h> #include <string> using std::string;//strcmp需要加这三行代码&#xff0c;因为标准库中没有 #include<malloc.h> typedef struct { char id[16]; char name[20]; dou…

OpenKylin设置root密码

前言 新安装的OpenKylin系统应该root用户没有设置密码&#xff0c;但是可以使用sudo -i 临时获取root权限&#xff0c;不影响正常使用 当前是root用户 1、终端输入passwd命令 passwd2、按照提示输入新密码和确认密码 当前非root用户 1、终端输入sudo passwd root 命令 s…

【计算机毕业设】智慧食堂管理系统——后附源码

&#x1f389;**欢迎来到我的技术世界&#xff01;**&#x1f389; &#x1f4d8; 博主小档案&#xff1a; 一名来自世界500强的资深程序媛&#xff0c;毕业于国内知名985高校。 &#x1f527; 技术专长&#xff1a; 在深度学习任务中展现出卓越的能力&#xff0c;包括但不限于…

cookie与session及其区别

一、cookie 1. 为什么需要cookie&#xff1f; web程序使用HTTP协议进行传输&#xff0c;而HTTP协议是无状态的协议&#xff08;即对事务处理无记忆性&#xff0c;如果后续处理需要使用前面的信息&#xff0c;只能重传&#xff0c;导致每次连接传送的数据量增大&#xff09;。c…

【VUE】Vue项目打包报告生成:让性能优化触手可及

Vue项目打包报告生成&#xff1a;让性能优化触手可及 Vue.js是一款流行的前端框架&#xff0c;开发者在使用Vue.js构建项目时&#xff0c;生产环境的性能优化尤为重要。为了帮助开发者分析和优化打包出来的资源&#xff0c;生成打包报告是一个不可或缺的步骤。本文将介绍几种在…

图深度学习(一):介绍与概念

目录 一、介绍 二、图的数据结构 三、图深度学习的基本模型 四、图深度学习的基本操作和概念 五、训练过程 六、主要应用场景 七、总结 一、介绍 图深度学习是将深度学习应用于图形数据结构的领域&#xff0c;它结合了图论的概念和深度学习的技术&#xff0c;用以处理和…

久菜盒子|留学|推荐信|结构抗震设计课、化工工艺设备设计

在众多学生当中&#xff0c;10这名学生给我留下了更深的印象&#xff0c;她对学习的认真态度、一丝不苟的精神&#xff0c;都让我感受到她的与众不同。因此&#xff0c;作为我校土木工程学院的前院长&#xff0c;我对于10申请贵校表示支持并毫无保留的推荐这位学生。 在结构抗震…

如何在浏览器Web前端在线编辑PPT幻灯片?

有时候在项目中我们会遇到需要在网页在线打开并编辑PPT文档保存到本地或者服务器指定位置&#xff0c;猿大师办公助手可以很方便的调用本机Office实现在网页上编辑PPT幻灯片&#xff0c;效果与本机Office打开PPT完全一样。 猿大师办公助手支持完整嵌入模式&#xff0c;也就是本…

pyskl手势/动作识别的实现与pytorch cuda环境部署保姆教程

恭喜你&#xff0c;找到这篇不需要翻墙就能够成功部署的方法。在国内布置这个挺麻烦的&#xff0c;其他帖子会出现各种问题不能完全贯通。便宜你了。。 实话5年前我用1080训练过一个基于卷积和ltsm的手势识别&#xff0c;实话实说感觉比现在效果好。是因为现在的注意力都在tra…

.NET 设计模式—命令模式(Command Pattern)

简介 命令模式&#xff08;Command Pattern&#xff09;是一种数据驱动的设计模式&#xff0c;它属于行为型模式。请求以命令的形式包裹在对象中&#xff0c;并传给调用对象。调用对象寻找可以处理该命令的合适的对象&#xff0c;并把该命令传给相应的对象&#xff0c;该对象执…

开源模型应用落地-chatglm3-6b-批量推理-入门篇(四)

一、前言 刚开始接触AI时&#xff0c;您可能会感到困惑&#xff0c;因为面对众多开源模型的选择&#xff0c;不知道应该选择哪个模型&#xff0c;也不知道如何调用最基本的模型。但是不用担心&#xff0c;我将陪伴您一起逐步入门&#xff0c;解决这些问题。 在信息时代&#xf…

Normalizing Flows

需要学的是神经网络 f f f, 用于完成从source distribution (Pz)&#xff08;latent space&#xff0c;一般为高斯分布&#xff09;到 target distribution (Px) 的映射。 Normalizing Flows 是一种强大的生成模型&#xff0c;它通过学习一个可逆且易于计算的转换来将复杂的概…

Maven 总结

文章目录 第一章 Maven概述第一节 为什么要学习Maven&#xff1f;1、从『构建』角度解释①个人开发流程②团队开发流程 2、从『依赖』角度解释①jar包的规模②jar包的来源③jar包之间的依赖关系 第二节 What&#xff1f;什么是Maven&#xff1f;第二节 什么是Maven&#xff1f;…

FANUC机器人单轴零点标定的具体方法(全轴零点标定不方便时可采用)

FANUC机器人单轴零点标定的具体方法(全轴零点标定不方便时可采用) 前面和大家分享了FANUC机器人进行零点标定的原因和方法,具体可参考以下链接中的内容:: FANUC机器人进行零点标定的目的和具体方法步骤详解

封装原生html的table处理方法【参数类似eltable】

直接跑html即可 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>封装原生talbe</title> </…

Centos7下docker的jenkins配置启动vue、springboot生产环境

个人记录 上篇 Centos7下docker安装jenkins / Gitee上传私有仓库 安装插件 新建任务 多分支流水线 任务名称&#xff1a;ks-springboot&#xff08;后端&#xff09;/ ks-vue3&#xff08;前端&#xff09; 分支源 增加源&#xff1a;Git gitee复制git链接 https://g…

用例设计-抖音视频上下滑动用例

功能 正向case&#xff1a; 1、正常速度下滑&#xff0c;视频类、图片类、直播类资源能够正常展示 2、快速下滑&#xff0c;资源能够正常加载不会出现卡顿 3、下滑没有可加载的资源时&#xff0c;提示用户无新的资源 4、下滑幅度较大&#xff0c;更新一批新的资源 5、本地资源…

ECMA进阶1之从0~1搭建react同构体系项目1

ECMA进阶 ES6项目实战前期介绍SSRpnpm 包管理工具package.json 项目搭建初始化配置引入encode-fe-lint 基础环境的配置修改package.jsonbabel相关tsconfig相关postcss相关补充scripts脚本webpack配置base.config.tsclient.config.tsserver.config.ts src环境server端&#xff1…

简单的车牌号识别

目录 处理流程与界面各接口编写时遇到的一些问题上传图片识别结果标签显示中文 处理流程与界面 首先点击“上传图片”按钮&#xff0c;可以选择文件夹中含有汽车车牌的图片&#xff0c;并显示在“图片框”中。 点击“检测车牌”按钮&#xff0c;会先对“图片框”中即含有汽车车…

解析数据科学,探索ChatGPT背后的奥秘

在当今这个由数据驱动和AI蓬勃发展的时代&#xff0c;数据科学作为一门融合多种学科的综合性领域&#xff0c;对于推动各行各业实现数字化转型升级起着至关重要的作用。近年来&#xff0c;大语言模型技术发展态势强劲&#xff0c;为数据科学的进步做出了巨大贡献。其中&#xf…