学习笔记|按键原理|消抖|按键点灯的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  0XF7
		num++;

以上代码实现了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.mfbz.cn/a/80026.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2023年国赛数学建模思路 - 案例:异常检测

文章目录 赛题思路一、简介 -- 关于异常检测异常检测监督学习 二、异常检测算法2. 箱线图分析3. 基于距离/密度4. 基于划分思想 建模资料 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 一、简介 – 关于异常…

【学习日记】【FreeRTOS】延时列表的实现

前言 本文在前面文章的基础上实现了延时列表&#xff0c;取消了 TCB 中的延时参数。 本文是对野火 RTOS 教程的笔记&#xff0c;融入了笔者的理解&#xff0c;代码大部分来自野火。 一、如何更高效地查找延时到期的任务 1. 朴素方式 在本文之前&#xff0c;我们使用了一种朴…

esp32c3 micropython oled实时天气信息

目录 简介 效果展示 代码 main.py ssd1306.py font.py 实现思路 简介 合宙esp32c3 micropython框架&#xff0c;只支持128*64 I2C oled ssd1306驱动我优化过的&#xff0c;与其他的不一样&#xff0c;为避免出错&#xff0c;使用我的驱动 把下面两个py文件放入单片机内…

阿里云与中国中医科学院合作,推动中医药行业数字化和智能化发展

据相关媒体消息&#xff0c;阿里云与中国中医科学院的合作旨在推动中医药行业的数字化和智能化发展。随着互联网的进步和相关政策的支持&#xff0c;中医药产业受到了国家的高度关注。这次合作将以“互联网 中医药”为载体&#xff0c;致力于推进中医药文化的传承和创新发展。…

【Java并发编程面试题(60道)】

toc Java并发编程面试题(60道) 基础 1.并行跟并发有什么区别&#xff1f; 从操作系统的角度来看&#xff0c;线程是CPU分配的最小单位。 并行就是同一时刻&#xff0c;两个线程都在执行。这就要求有两个CPU去分别执行两个线程。并发就是同一时刻&#xff0c;只有一个执行&…

基于物理场的动态模式分解(piDMD)研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

自动驾驶港口车辆故障及事故处理机制

1、传感器故障&#xff1a; &#xff08;1&#xff09;单一传感器数据异常处理。自动驾驶电动平板传感方案为冗余设置&#xff0c;有其他传感器能够覆盖故障传感器观测区域&#xff0c;感知/定位模块将数据异常情况发给到规划决策模块&#xff0c;由“大脑”向中控平台上报故障…

ElasticSearch的客户端操作

ElasticSearch的客户端操作 1、客户端介绍 官方文档地址&#xff1a; https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html 实际开发中&#xff0c;有多种方式操作Elasticsearch&#xff1a; 客户端工具&#xff1a;发送http请求(RESTful风格)操作…

source insight 添加宏-文件头加注释

source insight 3.5 自带的一些宏&#xff0c;在安装目录下的 utils.em 文件中&#xff0c;用户也可以自己写文件&#xff0c;命令为xxx.em &#xff0c;然后把这个文件添加到项目中即可&#xff0c;添加后在菜单栏 Options -> Key Assignments 里输入macro 就能显示新添加的…

MongoDB升级经历(4.0.23至5.0.19)

MongoDB从4.0.23至5.0.19升级经历 引子&#xff1a;为了解决MongoDB的两个漏洞决定把MongoDB升级至最新版本&#xff0c;期间也踩了不少坑&#xff0c;在这里分享出来供大家学习与避坑~ 1、MongoDB的两个漏洞 漏洞1&#xff1a;MongoDB Server 安全漏洞(CVE-2021-20330) 漏洞2…

总结,由于顺丰的问题,产生了电脑近期一个月死机问题集锦

由于我搬家&#xff0c;我妈搞顺丰发回家&#xff0c;但是没有检查有没有坏&#xff0c;并且我自己由于不可抗力因素&#xff0c;超过了索赔时间&#xff0c;反馈给顺丰客服&#xff0c;说超过了造成了无法索赔的情况&#xff0c;现在总结发生了损坏配件有几件&#xff0c;显卡…

输入输出+暴力模拟入门:魔法之树、染色の树、矩阵、字母加密、玫瑰鸭

秋招实习刷题网站推荐&#xff1a;codefun2000.com&#xff0c;还有题解博客&#xff1a;blog.codefun2000.com/。以下内容都是来自塔子哥的~ 输入输出 2023.04.15-春招-第三题-魔法之树 //#include<bits/stdc.h> #include<vector> #include<iostream>usin…

AndroidStudio升级Gradle之坑

最近在做旧工程的升级&#xff0c;原来的Gradle版本是4.6的&#xff0c;需要升级到7.6&#xff0c;JDK从8升级到17&#xff0c;一路趟了很多坑&#xff0c;逐个记录下吧 1、Maven仓库需要升级到https 你会遇到这个报错 Using insecure protocols with repositories, without …

openLayers实战(八):坐标系及其转换

坐标系介绍 EPSG: 3857 --web地图&#xff0c;基于球体的、web墨卡托投影&#xff08;伪墨卡托投影Pseudo-Mercator&#xff09;的投影坐标系&#xff0c;范围为纬度85度以下&#xff0c;由于google地图最先使用而成为事实标准。至今&#xff0c;大多互联网地图都使用EPSG3857&…

Android 远程真机调研

背景 现有的安卓测试机器较少&#xff0c;很难满足 SDK 的兼容性测试及线上问题&#xff08;特殊机型&#xff09;验证&#xff0c;基于真机成本较高且数量较多的前提下&#xff0c;可以考虑使用云测平台上的机器进行验证&#xff0c;因此需要针对各云测平台进行调研、比较。 …

【环境配置】Windows10终端和VSCode下能够直接打开Anaconda-Prompt

很多小伙伴在 Windows 下做深度学习开发的时候&#xff0c;遇到终端没有在 Linux 那么方便&#xff0c;那么我们现在就可以来设置一下&#xff1b;这样我们也可以在文件夹内部右键打开终端&#xff0c;也可以在 VS Code 里面新建一个虚拟环境的控制台&#xff1b;这里主要是针对…

VS2015项目中,MFC内存中调用DLL函数(VC6生成的示例DLL)

本例主要讲一下&#xff0c;用VC6如何生成DLL&#xff0c;用工具WinHex取得DLL全部内容&#xff0c;VC2015项目加载内存中的DLL函数&#xff0c;并调用函数的示例。 本例中的示例代码下载&#xff0c;点击可以下载 一、VC6.0生成示例DLL项目 1.新建项目&#xff0c;…

爬虫逆向实战(十四)--某培训平台登录

一、数据接口分析 主页地址&#xff1a;某培训平台 1、抓包 通过抓包可以发现登录是表单提交到j_spring_security_check 2、判断是否有加密参数 请求参数是否加密&#xff1f; 通过查看“载荷”模块可以发现有一个j_password加密参数 请求头是否加密&#xff1f; 无响应是…

SAP MM学习笔记23-购买发注的账户分配类型(勘定Category)

SAP中控制财务凭证过账科目的是 账号分配类型&#xff08;勘定Category&#xff09;栏目。 ・账号分配类型&#xff08;勘定Category&#xff09;有&#xff1a; 1&#xff0c;K 原价Center&#xff08;成本中心。用于消耗物料采购 的过账&#xff09; 2&#xff0c;E 得意先…

TPAMI, 2023 | 用压缩隐逆向神经网络进行高精度稀疏雷达成像

CoIR: Compressive Implicit Radar | IEEE TPAMI, 2023 | 用压缩隐逆向神经网络进行高精度稀疏雷达成像 注1:本文系“无线感知论文速递”系列之一,致力于简洁清晰完整地介绍、解读无线感知领域最新的顶会/顶刊论文(包括但不限于Nature/Science及其子刊;MobiCom, Sigcom, MobiSy…
最新文章