当前位置: 首页 > news >正文

51单片机编程应用(C语言):独立按键

目录

1.独立按键介绍

2.独立按键控制LED亮灭

1.1按下时LED亮,松手LED灭(按一次执行亮灭)

    1.2首先按下时无操作,松手时LED亮(再按下无操作,所以LED亮),松手LED灭(松手时执行取反操作)(按两次执行亮灭)

        1.3.独立按键控制LED按二进制递增亮

        1.4.两个独立按键控制LED移位,左移,右移

1.5:一个独立按键控制流水灯方向

方法一:一个代码编程所有:

方法2:模块化编程,


1.独立按键介绍

独立按键的原理图:

 所有单片机I/O口上电时都是默认高电平,独立按键没有按下,就是高电平,按下时,外部接地时强下拉,与地相接,I/O就会变为低电平,这里讲一下什么是I/O口,I/O口也叫input/output口,输入输出口,cpu可以给寄存器写值,比如上一节LED灯,CPU写值给寄存器,,由于单片机内部是弱上拉,所以要加驱动器加强电流,最后连接到I/O口,寄存器通过数据总线把值给I/O口此时I/O口就是output,input刚好就是相反的操作,比如I/O口读取外部信息,把值给寄存器,CPU再识别寄存器的值,

讲一下编程的命名问题,前面我们讲了sbit,对单个I/O口命名,就像一个人一样,要有名字,不过称呼一个人是不是也可以取外号啊,C51编程就给了这样的命名规则,

#include <REGX52.H>这个函数就相当于父母一样,里面对I/O口八位或单个I/O都命名了,

 我们用单个I/O口就直接用P0_0,P0_0就像父母给的名字一样,但是也可以外号称呼,sbit LED=P2^0,此时LED就是外号,LED和P2_0都可以指向P2^0口(看成一个人)

记住:sbit LED=P2_0;是错的,把名字给外号显然不是喊你,P2^1=0;也是错的,赋值就像别人要称呼你,称呼你喊你的名字,肯定不是叫哎,这个人吧

 

延时消抖 

 

主要原因还是单片机运算速度太快了,us级别,这些抖动他是可以识别出来的, 比如上面这个图,你按一下,由于有抖动,出现高-低--高--低--高--低...这样的话单片机会误以为你按了5/6下,

 实际上你就按了一下,所以这样的操作就会与人们期望的不符,所以我们延时一段时间来消除抖动,按下与松手都加个延时,当然也可以加一个电路消抖动,(有点麻烦)

2.独立按键控制LED亮灭

1.1按下时LED亮,松手LED灭(按一次执行亮灭)

最终代码如下:

#include <REGX52.H>
sbit LED=P2^0;
void Delay1ms(unsigned int xms)		//@12.000MHz
{unsigned char i, j;while(xms){i = 2;j = 239;do{while (--j);} while (--i);xms--;}
}void main()
{while(1){if(P3_1==0)//按下{Delay1ms(20);//消抖,真正的按下P2_0=0;}else//松手{Delay1ms(20);LED=0;}}
}

    1.2首先按下时无操作,松手时LED亮(再按下无操作,所以LED亮),松手LED灭(松手时执行取反操作)(按两次执行亮灭)

   代码如下:

#include <REGX52.H>
sbit LED=P2^0;
void Delay1ms(unsigned int xms)		//@12.000MHz
{unsigned char i, j;while(xms){i = 2;j = 239;do{while (--j);} while (--i);xms--;}
}void main()
{while(1){if(P3_1==0){Delay1ms(20);//消抖,确定按下}else{Delay1ms(20);//消抖,确定松手LED=~LED;while(P3_1==1);}}
}

这段代码的现象是没有按之前,LED从1变为0;LED亮, 如果没有按独立按键,LED就一直亮,按下独立按键,没有任何反应,松手LED从0变为1,LED灭,一直是灭的状态,假如没有while(P3_1==1);这句,现象是LED一直在闪烁,无论按不按,都是闪烁,为什么呢,P3_1默认为高电平,一上电,我们没有按开关,执行else语句,LED=~LED,10101010.......延迟20ms的闪烁,按了就是多了延迟,只是增加了闪烁时间不同而已,有了这句话之后,松手的话,死循环,一直不执行,保持着了LED的状态,而不要让他一直变,

最后按一下松手执行下面操作,

亮----灭-----亮------灭.....

当然下面代码可以执行下面现象.

灭-----亮------灭.....亮........

void main()
{while(1){if(P3_1==0){Delay1ms(20);while(P3_1==0);Delay1ms(20);LED=~LED;}}
}

没有按下,不执行任何操作,保持原有状态 ,按下时,一直按着的话,就什么都不操作,执行while语句,一旦松手,跳出while语句,LED取反,再跳出if语句

        1.3.独立按键控制LED按二进制递增亮

 引入中间变量LEDNum,为什么呢,因为P2 ++,上电默认是不是1111 1111,加1变为0000 0000,全部亮,加一0000 0001,刚好与我们的预想的相反,而P2取反,就会1111 1111,变为0000 0000,取反you变为1111 1111,无法达到我们的效果,而引入中间变量LEDNum,LEDNum把值存起来,再给P2赋值就完美的解决了这一点,比如char类型刚好一个字节,存8位,

按下一次按键后LEDNum从0000 0000加加后变为0000 0001,取反1111 1110,给P2口,刚好第一个灯亮,而且LEDNum的值不会因为赋给P2而变成P2的值,还是 0000 0001,加一0000 0010 取反 1111 1101 给P2,刚好点亮第二个灯,依次循环,实现了用灯表示二进制,

#include <REGX52.H>void Delay(unsigned int xms)		
{unsigned char i, j;while(xms){i = 2;j = 239;do{while (--j);} while (--i);xms--;}
}void main()
{unsigned char LEDNum=0; while(1){if(P3_1==0){Delay(20);while(P3_1==0);Delay(20);LEDNum++;P2=~ LEDNum;}}
}

        1.4.两个独立按键控制LED移位,左移,右移

   方法一:

0000 0001    0x01<<0

0000 0010    0x01<<1

0000 0100    0x01<<2

0000 1000   0x01<<3

..............

0 1 2 3 4定义为LEDNum,每按一下加一,加到7,LEDNum回到0,加个if语句。if(LEDNum>=8),LEDNum=0,因为LEDNum=7时,继续执行i++,

P2口应该与上面写的是反的,再取反操作。

代码如下

#include <REGX52.H>unsigned char LEDNum;void Delay(unsigned int xms)		
{unsigned char i, j;while(xms){i = 2;j = 239;do{while (--j);} while (--i);xms--;}
}void main()
{while(1){if(P3_1==0){Delay(20);while(P3_1==0);Delay(20);if(LEDNum>=8) LEDNum=0;P2=~(0x01<<LEDNum);LEDNum++;}if(P3_0==0)//??????{Delay(20);while(P3_0==0);Delay(20);if(LEDNum==0)//???????LEDNum=7;elseLEDNum--;P2=~(0x01<<LEDNum);}}
}

注意:LEDNum是无符号型,最大值 255,LEDNum--的话,减到0,再减一的话,变成255,这就是越界。所以减到0我们重新让他变为7,

方法二:

 每按一次独立按键,P2的数值变化如下

P2:    1111 1111    上电时,           我们用左移操作时,最低位是不是补0,我们在或上0x01,补成1

          1111 1110     按一次按键    P2左移1位 ,此时P2=1111 1110

          1111 1101     按两次按键    P2左移1位后或上0000 0001,

          1111 1011     按三次按键    P2左移1位后或上0000 0001

          ...............

#include <REGX52.H>
void Delay(unsigned int xms)		
{unsigned char i, j;while(xms){i = 2;j = 239;do{while (--j);} while (--i);xms--;}
}void main()
{   P2=0xFE;while(1){if(P3_1==0){Delay(20);while(P3_1==0);Delay(20);P2=P2<<1|0x01;if(P2==0xFF){P2=0xFE;}}if(P3_0==0){Delay(20);while(P3_0==0);Delay(20);P2=P2>>1|0x80;if(P2==0xFF){P2=0x7F;}}}
}

1.5:一个独立按键控制流水灯方向

 代码如下:

方法一:一个代码编程所有:
#include <REGX52.H>
#include <INTRINS.H>  //导入头文件
unsigned char LEDNum;
unsigned int count;
void Delay1ms(unsigned int xms)		//@11.0592MHz   //延时函数
{unsigned char i, j;while (xms--){i = 2;j = 199;do{while (--j);} while (--i);}
}void main()
{while(1){if(P3_1==0){Delay1ms(20);while(P3_1==0);Delay1ms(20); //软件消抖P2=0xFE;Delay1ms(500);LEDNum = 0xFE;while(1){while(count == 0) //当count为0时进入此循环{LEDNum =_crol_(LEDNum,1);P2 = LEDNum;Delay1ms(500);//1if(P3_1==0){Delay1ms(20);while(P3_1==0);Delay1ms(20);count = 1; //再次按下K1改变count值使进入逻辑右移}}while(count == 1) //当count为1时进入此循环{LEDNum =_cror_(LEDNum,1);P2 = LEDNum;Delay1ms(500);if(P3_1==0){Delay1ms(20);while(P3_1==0);Delay1ms(20);count = 0; //再次按下K1改变count值使进入逻辑左移}}}			}}
}
方法2:模块化编程,

后面我们专门写一期怎么模块化编程,下面针对这个题进行一次模块化编程,涉及内容有中断,定时器,后面所以讲到了会一一再解释这里的所有代码的具体含义。

main.c

#include <REGX52.H>
#include "Timer0.h"
#include "Key.h"
#include <INTRINS.H>unsigned char KeyNum,LEDMode;void main()
{P2=0xFE;Timer0Init();while(1){KeyNum=Key();		//获取独立按键键码if(KeyNum!=0)			//如果按键按下{//if(KeyNum==1)	//如果K1按键按下//{LEDMode++;	//模式切换if(LEDMode>=2)LEDMode=0;//}}}
}void Timer0_Routine() interrupt 1
{static unsigned int T0Count;TL0 = 0x18;		//设置定时初值TH0 = 0xFC;		//设置定时初值T0Count++;		//T0Count计次,对中断频率进行分频if(T0Count>=500)//分频500次,500ms{T0Count=0;if(LEDMode==0)			//模式判断P2=_crol_(P2,1);	//LED输出    //_crol_循环左移if(LEDMode==1)P2=_cror_(P2,1);//_cror_循环右移}
}

Timer0.c :

#include <REGX52.H>/*** @brief  定时器0初始化,1毫秒@12.000MHz* @param  无* @retval 无*/
void Timer0Init(void)
{TMOD &= 0xF0;		//设置定时器模式TMOD |= 0x01;		//设置定时器模式TL0 = 0x18;		//设置定时初值TH0 = 0xFC;		//设置定时初值TF0 = 0;		//清除TF0标志TR0 = 1;		//定时器0开始计时ET0=1;EA=1;PT0=0;
}/*定时器中断函数模板
void Timer0_Routine() interrupt 1
{static unsigned int T0Count;TL0 = 0x18;		//设置定时初值TH0 = 0xFC;		//设置定时初值T0Count++;if(T0Count>=1000){T0Count=0;}
}
*/

Timer0.h :

#ifndef __TIMER0_H__
#define __TIMER0_H__void Timer0Init(void);#endif

Key.c :

#include <REGX52.H>
#include "Delay.h"/*** @brief  获取独立按键键码* @param  无* @retval 按下按键的键码,范围:0~4,无按键按下时返回值为0*/
unsigned char Key()
{unsigned char KeyNumber=0;if(P3_1==0){Delay(20);while(P3_1==0);Delay(20);KeyNumber=1;}if(P3_0==0){Delay(20);while(P3_0==0);Delay(20);KeyNumber=2;}if(P3_2==0){Delay(20);while(P3_2==0);Delay(20);KeyNumber=3;}if(P3_3==0){Delay(20);while(P3_3==0);Delay(20);KeyNumber=4;}return KeyNumber;
}

Key.h :

#ifndef __KEY_H__
#define __KEY_H__unsigned char Key();#endif

Delay.c :

void Delay(unsigned int xms)
{unsigned char i, j;while(xms--){i = 2;j = 239;do{while (--j);} while (--i);}
}

Delay.h :

#ifndef __DELAY_H__
#define __DELAY_H__void Delay(unsigned int xms);#endif

 

相关文章:

51单片机编程应用(C语言):独立按键

目录 1.独立按键介绍 2.独立按键控制LED亮灭 1.1按下时LED亮&#xff0c;松手LED灭&#xff08;按一次执行亮灭&#xff09; 1.2首先按下时无操作&#xff0c;松手时LED亮&#xff08;再按下无操作&#xff0c;所以LED亮&#xff09;&#xff0c;松手LED灭&#xff08;松手时…...

小程序定制开发前,应该考虑些什么?

引言 在移动互联网时代&#xff0c;小程序已经成为许多企业和个人推广业务、提供服务的理想平台。然而&#xff0c;在进行小程序定制开发之前&#xff0c;开发者和业务方需要细致入微地考虑一系列关键因素&#xff0c;以确保最终的小程序既能满足用户需求&#xff0c;又能够顺…...

2024/2/1学习记录

echarts 为柱条添加背景色&#xff1a; 若想设置折线图的点的样式&#xff0c;设置 series.itemStyle 指定填充颜色就好了&#xff0c;设置线的样式设置 lineStyle 就好了。 在折线图中倘若要设置空数据&#xff0c;用 - 表示即可&#xff0c;这对于其他系列的数据也是 适用的…...

10个React状态管理库推荐

本文将为您推荐十款实用的React状态管理库&#xff0c;帮助您打造出高效、可维护的前端应用。让我们一起看看这些库的魅力所在&#xff01; 在前端开发中&#xff0c;状态管理是至关重要的一环。React作为一款流行的前端框架&#xff0c;其强大的状态管理功能备受开发者青睐。…...

从0开始写android

系列文章目录 文章目录 一、 从0开始实现 onCreate 的setContentView二、 从0 开始实现 onMeasure三、 从0 开始实现 onLayout四、 从0 开始实现 onDraw总结 前言 接上文&#xff0c;测量完View树的每个节点View的宽和高后&#xff0c;开始布局。 一、ViewRootImpl 的调用栈…...

使用pygame建立一个简单的使用键盘方向键移动的方块小游戏

import pygame import sys# 初始化pygame pygame.init()# 设置窗口大小 screen_size (640, 480) # 创建窗口 screen pygame.display.set_mode(screen_size) # 设置窗口标题 pygame.display.set_caption("使用键盘方向键移动的方块的简单小游戏")# 设置颜色 bg_colo…...

从零开始:CentOS系统下搭建DNS服务器的详细教程

前言 如果你希望在CentOS系统上建立自己的DNS服务器,那么这篇文章绝对是你不容错过的宝藏指南。我们提供了详尽的步骤和实用技巧,让你能够轻松完成搭建过程。从安装必要的软件到配置区域文件,我们都将一一为你呈现。无论你的身份是运维人员,还是程序员,抑或是对网络基础设…...

2024美赛B题解析:寻找潜水器Searching for Submersibles

解析&#xff1a;传送门 Maritime Cruises Mini-Submarines &#xff08;MCMS&#xff09; 是一家总部位于希腊的公司&#xff0c;负责建造潜水器 能够将人类带到海洋的最深处。潜水器被移动到 位置和部署不受主机船的束缚。MCMS现在希望使用他们的潜水器 带领游客冒险探索爱奥…...

回归预测 | Matlab基于POA-LSSVM鹈鹕算法算法优化最小二乘支持向量机的数据多输入单输出回归预测

回归预测 | Matlab基于POA-LSSVM鹈鹕算法算法优化最小二乘支持向量机的数据多输入单输出回归预测 目录 回归预测 | Matlab基于POA-LSSVM鹈鹕算法算法优化最小二乘支持向量机的数据多输入单输出回归预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 Matlab基于POA-LSSVM…...

把 matlab 公式输出成 latex 公式形式

问题 latex 进行符号计算后&#xff0c;想直接把 matlab 中变量代表的公式结果输出成 latex 形式。 这样可以直接 复制到 latex 中&#xff0c;不需要手打公式了。 方法 matlab 函数 latex 可以实现上述功能&#xff0c;但最好是 使用 simpify(expand(~)) 进行化简 str_Jac…...

云上自动部署丨使用 Terraform 在 AWS 上搭建 DolphinDB

HashiCorp Terraform 是一款基础架构即代码工具&#xff0c;旨在实现 "Write, Plan, and Create Infrastructure as Code"。它通过配置文件来描述云资源的拓扑结构&#xff0c;包括虚拟机、存储账户和网络接口。Terraform 几乎支持市面上所有的云服务&#xff0c;能够…...

vscode的ssh忽然连不上服务器:远程主机可能不符合glibc和libstdc++ VS Code服务器的先决条件

vscode自动更新了一下就发现连不上服务器了&#xff0c;我寻思估计一大堆人都寄了&#xff0c;一搜&#xff0c;果然哈哈哈哈 然后我直接搜一天内新发布的博客&#xff0c;还真给我搜到了这个问题&#xff0c;按照这个问题里面的回答&#xff08;vscode1.86无法远程连接waitin…...

C++(17)——list的模拟实现

前面的文章中&#xff0c;介绍了&#xff0c;的模拟实现&#xff0c;本篇文章将介绍对于的模拟实现。 目录 1. list的基本结构&#xff1a; 2. list功能实现&#xff1a;尾部插入元素&#xff1a; 3. list迭代器的实现&#xff1a; 4. list功能实现&#xff1a;在任意位置前…...

花瓣网美女图片爬取

爬虫基础案例01 花瓣网美女图片 网站url&#xff1a;https://huaban.com 图片爬取 import requests import json import os res requests.get(url "https://api.huaban.com/search/file?text%E7%BE%8E%E5%A5%B3&sortall&limit40&page1&positionsear…...

Android native层c++调用java层API

在Android开发中&#xff0c;从本地&#xff08;native&#xff09;代码调用Java层的接口是一个常见的需求&#xff0c;尤其是在使用JNI&#xff08;Java Native Interface&#xff09;进行混合编程时。以下是一个基本的步骤指南&#xff0c;展示如何从C代码调用Java方法&#…...

Docker 集群配置

1、配置 MySQL MySQL 简单安装 docker安装完MySQL并run出容器后&#xff0c;建议请先修改完字符集编码后再新建mysql库-表-插数据 docker run -d -p 2222:3306 --privilegedtrue -e MYSQL_ROOT_PASSWORD123456 \ -v /opt/mysql/log:/var/log/mysql \ -v /opt/mysql/data:/va…...

VUE3+elementPlus 之 Form表单校验器 之 字符长度校验

需求&#xff1a;校验字符长度&#xff0c;超过后仍可输入&#xff0c;error提示录入字符数与限制字符数 校验字符长度&#xff1a; /*** 检验文字输入区的长度* param {*} rule 输入框的rule 对象&#xff0c;field&#xff1a;字段名称* param {*} value …...

【Mysql】数据库架构学习合集

目录 1. Mysql整体架构1-1. 连接层1-2. 服务层1-3. 存储引擎层1-4. 文件系统层 2. 一条sql语句的执行过程2-1. 数据库连接池的作用2-2. 查询sql的执行过程2-1. 写sql的执行过程 1. Mysql整体架构 客户端&#xff1a; 由各种语言编写的程序&#xff0c;负责与Mysql服务端进行网…...

轻型民用无人机驾驶航空器安全操控——理论考试多旋翼部分笔记

今天已经可以在线考取轻型民用无人机驾驶航空器执照了&#xff0c;所以我也在在线观看完视频之后整理了如下的知识点&#xff0c;所有知识点全部来自UOM平台。 目录 航空器知识 &#xff08;1&#xff09;多旋翼民用无人驾驶航空器螺旋桨的作用 &#xff08;2&#x…...

UE4学习笔记 FPS游戏制作3 添加武器

文章目录 章节目标为骨骼添加武器挂载点添加武器 章节目标 本章节为手部添加一个武器挂载点&#xff0c;并挂载一个武器 为骨骼添加武器挂载点 添加挂载点需要以一个动画片段为基础&#xff0c;为骨骼添加挂载点。 首先找到我们需要的动画片段&#xff0c;通常是idle 双击打…...

详解 Prim 算法的实现

一、算法思路 Prim 算法是用来求最小生成树的&#xff0c;它的思想也有点类似于贪心——逐个将离当前集合最近的点加入到集合中&#xff0c;直至发现图不连通或所有点都被加到集合中&#xff0c;算法即宣告终止。它的具体做法是&#xff1a; step 1&#xff1a;初始时&#xf…...

Android 使用高德地图

一、获取高德平台key 【1】基于application包名&sha1值在高德控制台获取key值&#xff0c;详情参考&#xff1a; 获取Key-创建工程-开发指南-Android 地图SDK | 高德地图API 【2】在manifest中声明权限 【3】将拿到的key值在manifest中进行声明 <!--允许程序打开网络…...

从redis setnx 来看看分布式锁

什么是分布式锁 分布式锁&#xff08;多服务共享锁&#xff09;在分布式的部署环境下&#xff0c;通过锁机制来让多客户端互斥的对共享资源进行访问/操作。 为什么需要分布式锁 在单体应用服务里&#xff0c;不同的客户端操作同一个资源&#xff0c;我们可以通过操作系统提供…...

校园网网络规划与设计——计算机网络实践报告

W...Y的主页 &#x1f60a; 代码仓库分享&#x1f495; 目录 一、设计目的 二、软硬件环境 三、理论基础 四、设计方案 五、网络配置步骤 六、设计过程中出现的问题及相应解决办法 八、参考资料 一、设计目的 深入理解网络工程的三层层次设计模型&#xff1b; 掌握网络…...

Qt QScrollArea 不显示滚动条 不滚动

使用QScrollArea时&#xff0c;发现添加的控件超出QScrollArea 并没有显示&#xff0c;且没有滚动条效果 原因是 scrollArea指的是scrollArea控件本身的大小&#xff0c;肉眼能看到的外形尺寸。 scrollAreaWidgetContents指的是scrollArea控件内部的显示区域&#xff0c;里面可…...

【SVN在Linux下的常用指令】

windows下的TortoiseSVN是资源管理器的一个插件&#xff0c;以覆盖图标表示文件状态&#xff0c;几乎所以命令都有图形界面支持&#xff0c;比较好用&#xff0c;这里就不多说。主要说说linux下svn的使用&#xff0c;因为linux下大部分的操作都是通过命令行来进行&#xff0c;所…...

2024 高级前端面试题之 Node 「精选篇」

该内容主要整理关于 Node 模块的相关面试题&#xff0c;其他内容面试题请移步至 「最新最全的前端面试题集锦」 查看。 Node模块精选篇 1. package.json版本号规则2. package.json 与 package-lock.json 的关3. npm 模块安装机制4. 模块化的差异 AMD CMD COMMONJS ESMODUL5. No…...

linux麒麟系统安装mongodb7.0

1.mogedb下载 下载的是他tar包 https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel80-7.0.5.tgz wget -o https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel80-7.0.5.tgz 也可以下载rpm包 2.将包上传至服务器并解压 #进入目录 并解压 cd /opt/ tar…...

Spring声明式事务

1.概念 事务就是用户定义的一系列执行SQL语句的操作, 这些操作要么完全地执行&#xff0c;要么完全地都不执行&#xff0c; 它是一个不可分割的工作执行单元 一个使用Mybatis-Spring的主要原因是它允许Mybatis参与到Spring的事务管理中&#xff0c;而不是给Mybatis创建一个新的…...

PyTorch深度学习实战(34)——Pix2Pix详解与实现

PyTorch深度学习实战&#xff08;34&#xff09;——Pix2Pix详解与实现 0. 前言1. 模型与数据集1.1 Pix2Pix 基本原理1.2 数据集分析1.3 模型构建策略 2. 实现 Pix2Pix 生成图像小结系列链接 0. 前言 Pix2Pix 是基于生成对抗网络 (Convolutional Generative Adversarial Netwo…...