51单片机教程:按键输入、矩阵按键(按键巧用)proteus仿真+keil

发布者:数字梦行最新更新时间:2022-01-12 来源: eefocus关键字:51单片机  按键输入  矩阵按键  keil 手机看文章 扫描二维码
随时随地手机看文章

IO口原理

(P1口最简单,所以这里只介绍P1,其他IO口原理类似)


P1口原理

可以看到的是P1口的工作原理比较简单,首先用P1口做输入输出较为好理解。

1、内部总线:就是内部P1.X位寄存器的值,比如说内部总线P1.0上电压为0V,那么对应P1.0=0;内部总线P1.0上电压为5V,那么对应P1.0=1;

2、P1.X引脚:对应单片机引脚接口

3、读锁存器:读锁存器为1,允许读锁存器。为0,不允许读锁存器。

4、读引脚:为0不允许读引脚,为1允许读引脚

5、写锁存器:提供一个上升沿锁存数据(写数据到单片机IO口上时自动提供一个脉冲)

在这里插入图片描述

几个核心问题:

1、读锁存器与读引脚区别是什么?

读锁存器:读锁存器Q的电平

读引脚:读P1.X引脚的电平


2、读锁存器与读引脚能不能同时读?

不能,两个输入缓冲器只能同时打开一个,所以只能同时读取一个电平。


3、什么时候读锁存器,什么时候读引脚?

凡属于读-修改-写方式的指令,从锁存器读入信号,其它指令则从端口引脚线上读入信号。也就是说遇到读指令时,相应的输入缓冲器才会打开,一般是出于关闭状态


4、如果P1.0口一开始置一,然后用按键拉低,松开按键后P1.0口会是低电平吗?

不会,锁存器锁1,没有写入0之前一直输出1,按下按键只不过P1.0引脚变低了,松开后依然是高电平


(有了以上知识,我们就可以轻松解决很多问题了)


按键输入

一、按键抖动

按键由于是机械结构,按下的时候难免产生抖动,一般抖动会在按下的时候与松开的时候产生,抖动时间大概是10ms

在这里插入图片描述

二、打开proteus仿真,绘制电路

功能:利用一个按键对一个发光二极管进行控制。

这个可以说是最简单的按键输入实验了!

由于是51单片机,内部有上拉电阻,我们就不要浪费材料在按键上接上拉了

在这里插入图片描述

三、打开keil,编写如下代码


#include


sbit key=P1^0;  //定义key为P1.0

sbit led=P2^0; //定义LED为P2.0


void delay10(void) //延时10ms

{

int n=1000;

while(n--);

}


void main(void)

{

while(1)

{

if(key==0)   //读P1.0引脚,如果引脚为低电平,则进入if

{

delay10(); //延时10ms消抖

if(key==0) //再次判断按键是否按下,防止干扰,增强稳定

{

led = !led;//led状态改变

while(key==0);//等待按键松开,防止往下执行

}

}

}

}


博主有个疑问也很不解,当"key"换成"P2^0"后程序就不能正常运行了,知道的小伙伴能不能给我解解惑。

烧录单片机后,我们会发现按下按键led会熄灭,再按一下,led又会亮起

在这里插入图片描述
在这里插入图片描述

四、程序的升级

!!!

不知道小伙伴们发现了这个代码的弊端了没有,一个好的代码是不能有延时的,对于51单片机来说10ms的延时影响不是很大,但是你来个 “while(key==0);//等待按键松开” ,我想说的是代码再多一点,你这个就是傻瓜程序,按键一按,其他子程序基本完蛋


接下来看看博主是怎么把“while(key==0);//等待按键松开”这句该死程序铲除的


方法二: (本次博客的灵魂)


#include

sbit key=P1^0;  //定义key为P1.0

sbit led1=P2^0; //定义LED为P2.0

sbit led2=P2^7; //定义LED为P2.0


void delay_ms(unsigned int t) //ms延时

{

unsigned int i,j;

for(i=0; i for(j=0; j<120; j++);

}

void keyscan()

{

static int key_up=1;  //按键松开标志位,

if(key==0 && key_up==1)//判断按键是否按下

{

delay_ms(10);//延时消抖

key_up=0;//按下状态,(防止循环执行按键控制程序)

if(key==0)    //再次判断,排除是松开状态或外界杂波干扰

{

led1=!led1;

}

}

else if(key==1) key_up=1;

}

void main(void)

{

int count=0; //计数

while(1)

{

keyscan();

count++;

if(count==10000)

{

count=0;

led2=!led2; //程序运行led2闪烁

}

}

}


为了验证按下按键其他程序还能运行,我又加了一个绿色led,闪烁代表程序正常运行,按下按键不会影响绿色led,也可以一样控制黄色led

在这里插入图片描述
在这里插入图片描述

4*4矩阵按键输入

代码稳定!


代码一:按下按键显示键值,松开不显示


#include

 

//分别显示0 1 2 3 4 5 6 7 8 9 A b c d E F -

char sg[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7c,0x39,0x5e,0x79,0x71,0x40};


void delayms(unsigned int t)

{

unsigned int i,j;

for(i=0; i for(j=0; j<120; j++);

}

int keyscan(void)//返回键值

{

int val=16;//无按键按下默认键值16吧

P1 = 0xf0;

if(P1!=0xf0)

{

delayms(10); //按键消抖

switch(P1)     //行扫描

{

case 0xe0:

val = 0; break;

case 0xd0:

val = 1; break;

case 0xb0:

val = 2; break;

case 0x70:

val = 3; break;

}

P1 = 0x0f;

switch(P1)       //列扫描

{

case 0x0e:

val += 0; break;

case 0x0d:

val += 4; break;

case 0x0b:

val += 8; break;

case 0x07:

val += 12; break;

}

}

return val;

}

void main(void)

{

/*在这里定义初始化防止循环执行时循环初始化*/

char keyval=0;

while(1)

{

keyval = keyscan();//按键扫描

P0 = sg[keyval];           //数码管输出

}


}


代码效果:

在这里插入图片描述
在这里插入图片描述

代码二:按下按键,松开按键后显示键值


#include

 

//分别显示0 1 2 3 4 5 6 7 8 9 A b c d E F -

char sg[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7c,0x39,0x5e,0x79,0x71,0x40};


void delayms(unsigned int t)

{

unsigned int i,j;

for(i=0; i for(j=0; j<120; j++);

}


int val=0;//使用全局变量定义键值

void keyscan(void)

{

P1 = 0xf0;

if(P1!=0xf0)

{

delayms(10); //按键消抖

switch(P1)     //行扫描

{

case 0xe0:

val = 0; break;

case 0xd0:

val = 1; break;

case 0xb0:

val = 2; break;

case 0x70:

val = 3; break;

}

P1 = 0x0f;

switch(P1)       //列扫描

{

case 0x0e:

val += 0; break;

case 0x0d:

val += 4; break;

case 0x0b:

val += 8; break;

case 0x07:

val += 12; break;

}while(P1!=0x0f);   //等待按键松开

}

}


void main(void)

{

//在这里定义初始化防止循环执行时循环初始化

while(1)

{

keyscan();//按键扫描

P0 = sg[val];           //数码管输出

}


}

在这里插入图片描述
在这里插入图片描述

关键字:51单片机  按键输入  矩阵按键  keil 引用地址:51单片机教程:按键输入、矩阵按键(按键巧用)proteus仿真+keil

上一篇:51单片机教程:按键的定时器消抖(有延时的程序不是好程序
下一篇:51单片机项目设计:定时宠物喂食系统

推荐阅读最新更新时间:2024-11-13 11:42

stc51单片机pwm程序stc12c5608ad
初始化pwm程序: void PWM_INIT() { TMOD=0X02; // 定时器0工作于8位自动重载模式 TH0=0xfc; TL0=0xfc; TR0=1; CMOD=0x04; // CPS1 = 0 CPS0 = 1,选择PCA的时钟源为定时器0的溢出 CL=0; // PCA计数器清零 CH=0; CCAP0H=0; // 初始化占空比为0% CCAPM0=0x42; // 把P3.7脚做为DAC1的输出引脚 CR=1; // PCA模块开始计时 } 初始化完成后,只需要修改CCAP0H寄存器的值,即可改变占空比值。
[单片机]
在Silicon IDE中集成Keil C51工具
注:编译或仿真工程必须安装Silicon IDE以及Keil软件,在本示例中,软件是安装在默认路径下 ·Silicon IDE的安装   请到 Silabs 官方网站: http://www.silabs.com/products/mcu/Pages/SoftwareDownloads.aspx?cm_sp= WebParts -_- MCUSupport -_- SWDownloads 下载安装。 ·Keil的安装   请到 Keil 官方网站: https://www.keil.com/c51/demo/eval/c51.htm 下载安装。 1、如下图所示,点击 Project - Tool Chain Integrati
[单片机]
在Silicon IDE中集成<font color='red'>Keil</font> C51工具
什么是51单片机最小系统
1.什么是51单片机 51 内核单片机是 指兼容Intel 的8051指令系统的单片机统称;从诞生到现在的几十年时间,已成为一款经过市场考验、成熟的芯片产品。目前国内也众多51单片机厂家,且还有众多带51内核,用于各种不同场景的专用类单片机。 51单片机内部框架: 以下以STC89C52单片机为例,其内部总体结构其基本特性如下: 8位CPU、4-8k 字节 ROM、128 字节 RAM、21 个特殊功能寄存器32根I/0线、可寻址的 64 字节外部数据、程序存贮空间、2个 16 位定时器计数器中断结构:具有二个优先级、五个中断源、一个全双工串行口、位寻址(即可对寄存器进行位操作)功能,能按位进行逻辑运算的位处理器。 除 1
[单片机]
什么是<font color='red'>51单片机</font>最小系统
c51单片机寻址结构
最近要一直uc/os,需要补习一下汇编
[单片机]
c<font color='red'>51单片机</font>寻址结构
51单片机LCD1602程序详解
LCD1602 工业字符型液晶。1602是指LCD显示的内容为16X2,即可以显示两行,每行16个字符. 特殊接口说明 RS:寄存器选择输入端 RS=1:指向数据寄存器 RS=0:指向指令寄存器 RW:读写控制输入端 RW=0:写操作 RW=1:读操作 E:使能信号输入端 读操作时,高电平有效; 写操作时,下降沿有效; 程序编写: #include reg51.h #include intrins.h //其中有nop函数的定义 /*对于延时很短的,要求在us级的,采用“_nop_”函数,这个函数相当汇编NOP指令,延时几微秒。NOP指令为单周期指令,可由晶振频率算出延时时间,对于12M晶振,延时1uS。*/
[单片机]
51单片机PWM细分控制步进电机的研究初稿
为什么要PWM细分呢?因为这样可以是步进电机运行平稳、减小噪音、增大转速(MAX的)、增加力矩 为什么要强调是51单片机呢?因为51单片机没有硬件PWM模块,所以只能软件模拟了 研究这玩意儿,我走了许多弯路,看了许多文献,最后发现,尽信书不如无书 就用28系列4相5线电机来说吧。 整步驱动(四相四拍)时序为: A相 B相 C相 D相 1拍 1 0 0 0 2拍 0 1 0 0 3拍 0 0 1 0 4拍 0 0 0 1 我想没人用这样的方式来驱动吧,这震动也太大了。 2细分驱动(四相八拍)时序为: A相 B相 C相 D相
[单片机]
<font color='red'>51单片机</font>PWM细分控制步进电机的研究初稿
基于51单片机+DS1302时钟模块+LCD1602显示
DS1302时钟模块相关介绍 基本介绍 概述 DS1302 可慢速充电实时时钟芯片包含实时时钟/日历和 31 字节的非易失性静态 RAM。它经过一个简 单的串行接口与微处理器通信。实时时钟/日历可对秒,分,时,日,周,月,和年进行计数,对于小于 31 天的月,月末的日期自动进行调整,还具有闰年校正的功能。时钟可以采用 24 小时格式或带 AM(上 午)/PM(下午)的 12 小时格式。31 字节的== RAM== 可以用来临时保存一些重要数据。使用同步串行通信, 简化了 DS1302 与微处理器的通信。与时钟/RAM 通信仅需3 根线:(1)RST(复位),(2)I/O(数据线) 和(3)SCLK(串行时钟)。数据可以以每次一个字
[单片机]
基于<font color='red'>51单片机</font>+DS1302时钟模块+LCD1602显示
keil中GD32 MCU IAP中APP的存储地址如何设置?
前面和大家聊过什么是IAP(有不懂的小伙伴请看下前面的视频哦),那么IAP中APP的存储地址该如何设置呢 以keil为例,打开工程的option选项卡: 将IROM1中的地址改为你想要保存的位置,比如0x08008000开始的位置: 这样通过keil烧录,程序就自动下载到从0x08008000起始的flash区域哦。 如果你想要通过IAP烧录APP,也一定要烧录到0x08008000起始的flash区域哦,否则跳转到APP中执行程序就会出错的。
[单片机]
<font color='red'>keil</font>中GD32 MCU IAP中APP的存储地址如何设置?
热门资源推荐
热门放大器推荐
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
  • 学习ARM开发(16)
    ARM有很多东西要学习,那么中断,就肯定是需要学习的东西。自从CPU引入中断以来,才真正地进入多任务系统工作,并且大大提高了工作效率。采 ...
  • 学习ARM开发(17)
    因为嵌入式系统里全部要使用中断的,那么我的S3C44B0怎么样中断流程呢?那我就需要了解整个流程了。要深入了解,最好的方法,就是去写程序 ...
  • 学习ARM开发(18)
    上一次已经了解ARM的中断处理过程,并且可以设置中断函数,那么它这样就可以工作了吗?答案是否定的。因为S3C44B0还有好几个寄存器是控制中 ...
  • 嵌入式系统调试仿真工具
    嵌入式硬件系统设计出来后就要进行调试,不管是硬件调试还是软件调试或者程序固化,都需要用到调试仿真工具。 随着处理器新品种、新 ...
  • 最近困扰在心中的一个小疑问终于解惑了~~
    最近在驱动方面一直在概念上不能很好的理解 有时候结合别人写的一点usb的例子能有点感觉,但是因为arm体系里面没有像单片机那样直接讲解引脚 ...
  • 学习ARM开发(1)
  • 学习ARM开发(2)
  • 学习ARM开发(4)
  • 学习ARM开发(6)
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved