学习笔记|按键原理|消抖|按键点灯的4种模式|STC32G单片机视频开发教程(冲哥)|第七集:按键点灯

文章目录

  • 第六集(下)课后练习解答:SOS求救灯光编写
    • 求救信号原理
    • 冲哥代码及解析
      • 分模块设计:
        • math.h:
        • math.c:
        • while主程序部分
  • 按键点灯(下)
    • 1.按键的原理
      • Tips:按键消抖
    • 2.按键的代码实现过程
      • 示例代码1:
      • 示例代码2:
      • 工程示例
      • 串口打印输出
    • 3.按键的应用
    • 作业:实现P32(KEY1)按下一次以后,灯向右移动一个。
    • 总结
    • 课后练习:按下按键,切换LED输出不同的效果。

第六集(下)课后练习解答:SOS求救灯光编写

求救信号原理

来源:爱问知识人:sos用灯光怎么表示
三短三长三短
SOS作为世界上通用的求救信号,如果用灯光信号来表示,三短亮代表字母S,三长亮代表字母O,再接着的三短亮代表S。
灯的长亮时间是短亮时间的三倍,而短亮时间则与LED两次点亮的间隔时间相同,字母与下一个字母间也有三倍短亮时间的熄灭间隔。

冲哥代码及解析

分模块设计:

math.h:

#ifndef __MATH_H  //if no define
#define __MATH_H#include "stc.h"		//调用头文件,具体引用路径根据options选择的调用路径而定
#include "usb.h"#define MAIN_Fosc 24000000UL		//定义一个IRC系统时钟int  Add( int parm1,int parm2  );		//加法
int  Sub( int parm1,int parm2  );		//减法
int  Mul( int parm1,int parm2  );		//乘法void SOS_Led(void);
void delay_ms(u16 ms);	//unsigned int#endif

math.c:

增加函数定义:

#include "math.h"int  Add( int parm1,int parm2  )
{return parm1 + parm2;
}int  Sub( int parm1,int parm2  )
{return parm1 - parm2;
}int  Mul( int parm1,int parm2  )
{return parm1 * parm2;
}void SOS_Led(void)
{P60 = 0;			//点亮delay_ms(200);P60 = 1;			//熄灭delay_ms(200);P60 = 0;			//点亮delay_ms(200);P60 = 1;			//熄灭delay_ms(200);P60 = 0;			//点亮delay_ms(200);P60 = 1;			//熄灭delay_ms(200);P60 = 0;			//点亮delay_ms(500);P60 = 1;			//熄灭delay_ms(500);P60 = 0;			//点亮delay_ms(500);P60 = 1;			//熄灭delay_ms(500);P60 = 0;			//点亮delay_ms(500);P60 = 1;			//熄灭delay_ms(500);P60 = 0;			//点亮delay_ms(200);P60 = 1;			//熄灭delay_ms(200);P60 = 0;			//点亮delay_ms(200);P60 = 1;			//熄灭delay_ms(200);P60 = 0;			//点亮delay_ms(200);P60 = 1;			//熄灭delay_ms(200);delay_ms(3000);}void delay_ms(u16 ms)	//unsigned int
{u16 i;do{i = MAIN_Fosc/6000;while(--i);}while(--ms);
}

在主程序demo.c中:#include “math.h”,并在主函数体main()函数中直接调用: SOS_Led()实现SOS功能。
首先,将void SOS_Led(void)和void delay_ms(u16 ms)的函数声明放在头文件math.h中:

然后,将void SOS_Led(void)和void delay_ms(u16 ms)的函数定义移至math.c中:

delay函数中用到MAIN_Fosc,需增加。在main.c中:

#define MAIN_Fosc 24000000UL  //#define 名称 需要定义的内容

while主程序部分

while(1)		//死循环{if( DeviceState != DEVSTATE_CONFIGURED ) 	//continue;if( bUsbOutReady ){usb_OUT_done();printf("计算Add( 1,2 )结果为:%d\r\n",Add( 1,2 ));printf("计算Sub( 5,2 )结果为:%d\r\n",Sub( 5,2 ));printf("计算Mul( 5,3 )结果为:%d\r\n",Mul( 5,3 ));}P40 = 0;	//三极管引脚输出低电平SOS_Led();}

正常编译,开始闪灯。

按键点灯(下)

1.按键的原理

虽然按键长得千奇百怪,但是本质就是两个引脚之间的通断。
在这里插入图片描述
有的是按下之后两个引脚导通;
有的是按键之后两个引脚断开。
原理图:
在这里插入图片描述
有一个上拉电阻,如果说这个按键没有按下。这是一个完整的断开的信号。
单片机3.2引脚连接到了一个VCC。VCC通过R10,R82流进P3.2 INT0的IO口。按键按下后,电阻后段接GND,导线处
各个位置都是0V,R10是限流电阻,保护IO口。分析下来,没按下时是高电平,按下检测到低电平。
可以通过以上办法去判断按键有无按下。

Tips:按键消抖

假定:按键SW17松开,P3.2高电平,按键按下,P3.2是低电平。
按键属于机械,机械开关他按下弹起的时候,会有一个震动,震动时间的见下图:
在这里插入图片描述
低电平10ms以后,再检测,如果还是低电平,则判断为低电平,10ms就是需要处理的消抖时间。
按下和松开的过程中,电压都会有上下波动的过程。

2.按键的代码实现过程

示例代码1:

if( KEY == 0 )
{Delay_ms(10);if( KEY == 0 ){执行功能}
}

示例代码2:

if( KEY == 0 )
{Delay_ms(10);if( KEY == 0 ){while(KEY == 0);执行功能}
}

工程示例

复制模板工程文件夹1.C-Printf,并更名为:3.按键控制LED。
根据原理图,定义2个KEY:

#define KEY1 P32  //定义一个按键引脚KEY1
#define KEY2 P33  //定义一个按键引脚KEY2

复制Delay_ms函数,并声明。
增加控制代码:

		if( KEY1 == 0 ){Delay_ms(10);if( KEY1 == 0 ){printf("按键P32已经按下!\r\n");}}if( KEY2 == 0 ){Delay_ms(10);if( KEY2 == 0 ){printf("按键P33已经按下!\r\n");}}

串口打印输出

在这里插入图片描述

3.按键的应用

  • 3.1按键按下LED点亮,松开熄灭
    增加代码P22 = 0和P23 = 0可以实现点亮,但松开按钮后不熄灭。
    还需要增加判断,实现松开熄灭,板载的原有指示灯同状态亮灭:
    完整代码:
		if( KEY1 == 0 ){Delay_ms(10);if( KEY1 == 0 ){printf("按键P32已经按下!\r\n");P22 = 0;}}else //如果没有按下{P22 = 1;}if( KEY2 == 0 ){Delay_ms(10);if( KEY2 == 0 ){printf("按键P33已经按下!\r\n");P23 = 0;}}else //如果没有按下{P23 = 1;}
  • 3.2按键按下LED熄灭,松开点亮
    将P22,P23口的电平掉转(使用取反~操作即可),实现松开点亮,与板载的原有指示灯状态相反。
    实现代码:
		if( KEY1 == 0 ){Delay_ms(10);if( KEY1 == 0 ){printf("按键P32已经按下!\r\n");P22 =  0;  //实现按下点亮,抬起熄灭//P22 = !0;  //取反操作实现按下熄灭,抬起点亮}}else //如果没有按下{P22 =  1;//P22 = !1; //取反操作实现按下熄灭,抬起点亮}if( KEY2 == 0 ){Delay_ms(10);if( KEY2 == 0 ){printf("按键P33已经按下!\r\n");P23 =  0;  //实现按下点亮,抬起熄灭//P23 = !0;  //取反操作实现按下熄灭,抬起点亮}}else //如果没有按下{P22 =  1;//P23 = !1; //取反操作实现按下熄灭,抬起点亮}
  • 3.3按键按下一次,LED状态改变一次
    初步想法是按下则IO状态取反,P23 = !P23;
    按下后,等的状态不对。需要增加延时:Delay_ms(200); //防止检测太快
    但长按按钮(一直保持按下),发现LED闪烁。需要增加只执行1次的限制代码:
						printf("按键P33已经按下!\r\n");P23 =  !P23; //LED取反1次while( KEY2 == 0 ) //如果按键一直是按下,一直空循环,实现只执行1次{}

能不能修改为松开再执行?类似应用于手册侧边的长按,看代码:

						while( KEY2 == 0 ) //如果按键松开,则结束空循环,则执行以下程序{}printf("按键P33已经松开!\r\n");P23 =  !P23; //LED取反1次
  • 3.4按键按下一次,LED往左边走一个(流水灯效果)。
    操作一组灯,以P2为例:
    我们写成16进制的写法:P2 = 0xFE; //1111 1110 设定初始状态。
    在这里插入图片描述
    初始状态下,先是最右侧点亮,1111 1101
    左移1位,第二个灯点亮,右侧是末位,补0,则第1,2个都点亮,1111 1100,依次变化
    只想亮一个灯,则需要+1操作,变成:1111 1101 仅第2个灯点亮.
    这里采用单独变量进行计算,得到某次按键后的P2口状态,赋值:
u8 LED_Data = 0XFD; //8个2进制位的变量
P2 = LED_Data;  //1111 1110 设定初始状态

控制代码:

		if( KEY2 == 0  )	//判断按键有没有按下{Delay_ms(10);if( KEY2 == 0 )		//按键确实按下了{printf("按键P33已经按下,led左移一个\r\n");LED_Data = ( (LED_Data<<1) +1 );		//本来是直接输出P2,先计算,后输出if( LED_Data == 0xFF )LED_Data = 0xFD;P2 = LED_Data;while(KEY2 == 0);		//如果按键一直是按下的,一直执行while//while函数体如果无实际执行需要,即花括号内为空,可以直接跟;结束语句,
//				{
//
//				}}}

注意:while函数体如果仅用于判断,无实际代码执行需要,即花括号内为空,可以直接跟“;”结束语句。
STC-ISP串口工具设置
为了简化串口输出数据,可以进行串口工具的简化设置,至显示程序发送字符:
在这里插入图片描述

作业:实现P32(KEY1)按下一次以后,灯向右移动一个。

  • 4.数组的使用
    数组使用分为如下两步
    1.定义
    类型 名称[长度] = { 数值 };
    在这里插入图片描述

例如要实现流水灯,几个状态如下:
1111 1110 0XFE
1111 1101 0XFD
1111 1011 0XFB
1111 0111 0XF7
1110 1111 0XEF
1101 1111 0XDF
1011 1111 0XBF
0111 1111 0X7F
要实现流水灯,可以直接输出以上状态。
例如,在主while循环的最后一行加入测试代码:

		P2 = 	0XFB;	Delay_ms(500);P2 = 	0XF7;	Delay_ms(500);P2 = 	0XEF;	Delay_ms(500);P2 = 	0XDF;	Delay_ms(500);P2 = 	0XBF;	Delay_ms(500);P2 = 	0X7F;	Delay_ms(500);

效果:由右往左的流水灯,每次点亮500ms,依次点亮。
2.使用
赋值:名称[索引] = 数值
以实现上述的流水灯为例,数据为:0XFB,无符号8位,索引(总数据量)为8,定义数据为:

u8 LED_DataTab[8] = {0XFE,0XFD,0XFB,0XF7,0XEF,0XDF,0XBF,0X7F};

竖向列选择文本:光标选中待选字符的左侧,按住alt+shift,拖选中要求选择的行,列,反显后可以复制。
利用变量num实现流水灯:

		P2 = 	LED_DataTab[num+1]; Delay_ms(500);//1111 0111  0XF7num++;

以上代码实现了1次流水灯,然后就全亮了。
排查问题,为什么呢:num++是有范围的,需要限定:if(num > 7) num = 1; //num最大只能是7,到7后从1开始,回到最右边。
可以通过修改LED_DataTab数组值的方式,实现点灯控制,如赋值:LED_DataTab[3] = 0XFD;,则第3次还是点亮第1个灯。
可以随意改变数据实现花式点灯。

总结

1.学会按键的用法
2.掌握数组

课后练习:按下按键,切换LED输出不同的效果。

4个灯4个灯的亮,或者3个灯,3个灯的亮,2个2个的往左移等等。熟练实现按键功能的代码编写。

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

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

相关文章

python 基础篇 day 1 初识变量和数据类型

文章目录 变量变量作用——用于存储和表示数据。变量命名规则命名法大驼峰小驼峰下划体n j i a x 通常作为临时变量使用 建议 变量种类全局变量&#xff08;Global Variables&#xff09;局部变量&#xff08;Local Variables&#xff09;静态变量&#xff08;Static Variables…

万宾科技22款产品入选《城市生命线安全工程监测技术产品名录》

2023年8月17日-18日&#xff0c;由北京市地下管线协会主办的2023首届城市生命线安全与发展大会在北京召开&#xff0c;本次大会汇聚中央及地方政府主管领导、院士专家、行业领袖、龙头代表、产业精英等。 大会聚焦安全监管智慧平台和燃气爆炸、城市内涝、地下管线交互风险、第三…

解决Spring mvc + JDK17@Resource无法使用的情况

问题描述 我在使用jdk17进行Spring mvc开发时发现 Resource用不了了。 原因 因为JDK版本升级的改动&#xff0c;在Jdk9~17环境下&#xff0c;搭建Springboot项目&#xff0c;会出现原有Resource&#xff08;javax.annotation.Resource&#xff09;不存在的问题&#xff0c;导…

全流程R语言Meta分析核心技术

Meta分析是针对某一科研问题&#xff0c;根据明确的搜索策略、选择筛选文献标准、采用严格的评价方法&#xff0c;对来源不同的研究成果进行收集、合并及定量统计分析的方法&#xff0c;最早出现于“循证医学”&#xff0c;现已广泛应用于农林生态&#xff0c;资源环境等方面。…

政务、商务数据资源有效共享:让数据上“链”,记录每一个存储过程!

数据上链是目前“区块链”最常见的场景。因为链上所有参与方都分享了统一的事实来源&#xff0c;所有人都可以即时获得最新的信息&#xff0c;数据可用不可见。因此&#xff0c;不同参与方之间的协作效率得以大幅提高。同时&#xff0c;因为区块链上的数据难以篡改&#xff0c;…

香蕉派社区推出带10G SFP+ 端口的Banana Pi BPI-R4 Wifi7开源路由器

香蕉派BPI-R4 根据著名Banana Pi品牌背后的公司Sinovoip提供的初步信息&#xff0c;他们即将推出的Banana Pi BPI-R4路由器板目前正在开发中。与之前的 Banana Pi R3 板相比&#xff0c;这在规格上将有显着提升。这就是我们目前所知道的。 您可以选择 R4 板的两种不同配置。具…

Docker部署LNMP

Docker部署LNMP 一、安装docker1.安装docker2.镜像下载 二、部署MySQL1.获取镜像2.创建启动容器创建启动容器 huahua_mysql 三、部署PHP1.获取镜像2.创建容器3.查看信息 四、安装nginx1.获取镜像2.创建运行容器3.修改nginx配置文件 五、总结1. 安装Docker和Docker Compose&…

实战演练 | Navicat 导出向导

数据库工具中的导入导出功能是指将数据从一个数据库系统导出到另一个数据库系统&#xff0c;或者将数据从一个文件格式导出到另一个文件格式。导入导出功能可以通过各种方式实现&#xff0c;例如使用SQL语句、数据库管理工具或第三方库和工具。在进行数据迁移时&#xff0c;通常…

如何关闭“若要接收后续google chrome更新,您需使用windows10或更高版本”

Windows Registry Editor Version 5.00[HKEY_CURRENT_USER\Software\Policies\Google\Chrome] "SuppressUnsupportedOSWarning"dword:00000001 如何关闭“若要接收后续 google chrome 更新,您需使用 windows 10 或更高版本” - 知乎

【FAQ】安防监控视频云存储平台EasyNVR频繁离线的原因排查与解决

有用户反馈&#xff0c;在使用EasyNVR时会出现通道频繁离线的情况。针对该反馈我们立即进行了排查。 安防视频监控汇聚EasyNVR视频集中存储平台&#xff0c;是基于RTSP/Onvif协议的安防视频平台&#xff0c;可支持将接入的视频流进行全平台、全终端分发&#xff0c;分发的视频流…

区块链与算力网络:创造未来网络的安全与共享

在数字革命的浪潮下&#xff0c;网络技术正焕发着前所未有的活力&#xff0c;而算力网络以其独特的区块链技术应用&#xff0c;为网络的安全性和资源共享带来了新的可能性。本文将带您深入探索算力网络中区块链技术的神奇应用&#xff0c;为您呈现这个充满活力和创新的网络未来…

华为数通方向HCIP-DataCom H12-821题库(单选题:01-20)

第01题 下面关于OSPF邻居关系和邻接关系描述正确的是 A、邻接关系由 OSPF的 DD 报文维护 B、OSPF 路由器在交换 Hello 报文之前必须建立邻接关系 C、邻居关系是从邻接关系中选出的为了交换路由信息而形成的关系 D、并非所有的邻居关系都可以成为邻接关系 答案&#xff1a;D 解析…

smiley-http-proxy-servlet 实现springboot 接口反向代理,站点代理,项目鉴权,安全的引入第三方项目服务

背景&#xff1a; 项目初期 和硬件集成&#xff0c;实现了些功能服务&#xff0c;由于是局域网环境&#xff0c;安全问题当时都可以最小化无视。随着对接的服务越来越多&#xff0c;部分功能上云&#xff0c;此时就需要有一种手段可以控制到其他项目/接口的访问权限。 无疑 反向…

HTML a标签

<a>标签定义一个超链接。它有如下主要属性&#xff1a; href&#xff1a;指定链接的地址&#xff0c;可以是一个URL、文件路径或锚点。target&#xff1a;指定链接在何处打开。其值包括&#xff1a; _blank&#xff1a;在新窗口或新标签页打开链接。_self&#xff1a;在…

Spring统一功能处理

1. AOP存在的问题 获取参数复杂AOP的规则相对简单 2. 拦截器 2.1. 应用(以登录为例) 2.1.1. 自定义拦截器 新建interceptor文件夹 import org.springframework.web.servlet.HandlerInterceptor;import javax.servlet.http.HttpServletRequest; import javax.servlet.http…

go_并发编程

go并发编程 一、 并发介绍1&#xff0c;进程和线程2&#xff0c;并发和并行3&#xff0c;协程和线程4&#xff0c;goroutine 二、 Goroutine1&#xff0c;使用goroutine1&#xff09;启动单个goroutine2&#xff09;启动多个goroutine 2&#xff0c;goroutine与线程3&#xff0…

sdk manager (ubuntu20.4) 安装

1、首先下载sdk manager 1.9.3 下载链接 https://www.baidu.com/link?urlVXJhUqxxhS3eFK3bOPTzi5LFl6ybeW3JwDY1CwANaPf1gvO3IxQKzY547NIe53x1blJxnAXg7FTRTvs-cnfnVa&wd&eqida22baa7b0004ca980000000664e2d426 当然要登录自己的账号才能成功下载&#xff0c;下载对应…

用于智能图像处理的计算机视觉和 NLP

莫斯科&#xff0c;神秘之城...&#xff08;这张照片由伊戈尔沙巴林提供&#xff09; 一、说明 如今&#xff0c;每个拥有智能手机的人都可能成为摄影师。因此&#xff0c;每天都有大量新照片出现在社交媒体、网站、博客和个人照片库中。尽管拍照的过程可能非常令人兴奋&#x…

MyBaits注解开发

1、注解开发介绍 在过去使用框架开发项目&#xff0c;基本都采用xml作为框架的核心配置文件存在&#xff0c;但是这种方式开发效率还是比较地下、不灵活。 现在企业开发为了能够更快的提高开发效率&#xff0c;必然会使用企业级框架进行项目开发&#xff0c;而现在主流的框架…

docker 安装oracle19c linux命令执行sql

docker安装oracle # 下载镜像 19.3.0.0.0 docker pull registry.cn-hangzhou.aliyuncs.com/laowu/oracle:19c # 创建文件 mkdir -p /home/mymount/oracle19c/oradata # 授权&#xff0c;不授权会导致后面安装失败 chmod 777 /home/mymount/oracle19c/oradatadocker run -d \ …