51单片机——按键操作

发布者:runaway2000最新更新时间:2022-12-14 来源: zhihu关键字:51单片机  按键操作  按键设置 手机看文章 扫描二维码
随时随地手机看文章

在51单片机开发板上,对按键设置进行操作,其中包括按键的按下,显示对应位置,以及按键密码锁


1.按下按键显示对应位置

main.c

#include

#include "Delay.h"

#include "LCD1602.h"

#include "MatrixKey.h"

unsigned char KeyNum;


void main()

{

LCD_Init();

LCD_ShowString(1,1,"helloworld");

while(1)

{

KeyNum=MatrixKey();

if(KeyNum)

{

LCD_ShowNum(2,1,KeyNum,2);

}

}

}

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

LCD1640.c

#include


//引脚配置:

sbit LCD_RS=P2^6;

sbit LCD_RW=P2^5;

sbit LCD_EN=P2^7;

#define LCD_DataPort P0


//函数定义:

/**

  * @brief  LCD1602延时函数,12MHz调用可延时1ms

  * @param  无

  * @retval 无

  */

void LCD_Delay()

{

unsigned char i, j;


i = 2;

j = 239;

do

{

while (--j);

} while (--i);

}


/**

  * @brief  LCD1602写命令

  * @param  Command 要写入的命令

  * @retval 无

  */

void LCD_WriteCommand(unsigned char Command)

{

LCD_RS=0;

LCD_RW=0;

LCD_DataPort=Command;

LCD_EN=1;

LCD_Delay();

LCD_EN=0;

LCD_Delay();

}


/**

  * @brief  LCD1602写数据

  * @param  Data 要写入的数据

  * @retval 无

  */

void LCD_WriteData(unsigned char Data)

{

LCD_RS=1;

LCD_RW=0;

LCD_DataPort=Data;

LCD_EN=1;

LCD_Delay();

LCD_EN=0;

LCD_Delay();

}


/**

  * @brief  LCD1602设置光标位置

  * @param  Line 行位置,范围:1~2

  * @param  Column 列位置,范围:1~16

  * @retval 无

  */

void LCD_SetCursor(unsigned char Line,unsigned char Column)

{

if(Line==1)

{

LCD_WriteCommand(0x80|(Column-1));

}

else if(Line==2)

{

LCD_WriteCommand(0x80|(Column-1+0x40));

}

}


/**

  * @brief  LCD1602初始化函数

  * @param  无

  * @retval 无

  */

void LCD_Init()

{

LCD_WriteCommand(0x38);//八位数据接口,两行显示,5*7点阵

LCD_WriteCommand(0x0c);//显示开,光标关,闪烁关

LCD_WriteCommand(0x06);//数据读写操作后,光标自动加一,画面不动

LCD_WriteCommand(0x01);//光标复位,清屏

}


/**

  * @brief  在LCD1602指定位置上显示一个字符

  * @param  Line 行位置,范围:1~2

  * @param  Column 列位置,范围:1~16

  * @param  Char 要显示的字符

  * @retval 无

  */

void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char)

{

LCD_SetCursor(Line,Column);

LCD_WriteData(Char);

}


/**

  * @brief  在LCD1602指定位置开始显示所给字符串

  * @param  Line 起始行位置,范围:1~2

  * @param  Column 起始列位置,范围:1~16

  * @param  String 要显示的字符串

  * @retval 无

  */

void LCD_ShowString(unsigned char Line,unsigned char Column,char *String)

{

unsigned char i;

LCD_SetCursor(Line,Column);

for(i=0;String[i]!='';i++)

{

LCD_WriteData(String[i]);

}

}


/**

  * @brief  返回值=X的Y次方

  */

int LCD_Pow(int X,int Y)

{

unsigned char i;

int Result=1;

for(i=0;i {

Result*=X;

}

return Result;

}


/**

  * @brief  在LCD1602指定位置开始显示所给数字

  * @param  Line 起始行位置,范围:1~2

  * @param  Column 起始列位置,范围:1~16

  * @param  Number 要显示的数字,范围:0~65535

  * @param  Length 要显示数字的长度,范围:1~5

  * @retval 无

  */

void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)

{

unsigned char i;

LCD_SetCursor(Line,Column);

for(i=Length;i>0;i--)

{

LCD_WriteData(Number/LCD_Pow(10,i-1)%10+'0');

}

}


/**

  * @brief  在LCD1602指定位置开始以有符号十进制显示所给数字

  * @param  Line 起始行位置,范围:1~2

  * @param  Column 起始列位置,范围:1~16

  * @param  Number 要显示的数字,范围:-32768~32767

  * @param  Length 要显示数字的长度,范围:1~5

  * @retval 无

  */

void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length)

{

unsigned char i;

unsigned int Number1;

LCD_SetCursor(Line,Column);

if(Number>=0)

{

LCD_WriteData('+');

Number1=Number;

}

else

{

LCD_WriteData('-');

Number1=-Number;

}

for(i=Length;i>0;i--)

{

LCD_WriteData(Number1/LCD_Pow(10,i-1)%10+'0');

}

}


/**

  * @brief  在LCD1602指定位置开始以十六进制显示所给数字

  * @param  Line 起始行位置,范围:1~2

  * @param  Column 起始列位置,范围:1~16

  * @param  Number 要显示的数字,范围:0~0xFFFF

  * @param  Length 要显示数字的长度,范围:1~4

  * @retval 无

  */

void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)

{

unsigned char i,SingleNumber;

LCD_SetCursor(Line,Column);

for(i=Length;i>0;i--)

{

SingleNumber=Number/LCD_Pow(16,i-1)%16;

if(SingleNumber<10)

{

LCD_WriteData(SingleNumber+'0');

}

else

{

LCD_WriteData(SingleNumber-10+'A');

}

}

}


/**

  * @brief  在LCD1602指定位置开始以二进制显示所给数字

  * @param  Line 起始行位置,范围:1~2

  * @param  Column 起始列位置,范围:1~16

  * @param  Number 要显示的数字,范围:0~1111 1111 1111 1111

  * @param  Length 要显示数字的长度,范围:1~16

  * @retval 无

  */

void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)

{

unsigned char i;

LCD_SetCursor(Line,Column);

for(i=Length;i>0;i--)

{

LCD_WriteData(Number/LCD_Pow(2,i-1)%2+'0');

}

}

LCD1640.h

#ifndef __LCD1602_H__

#define __LCD1602_H__


//用户调用函数:

void LCD_Init();

void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char);

void LCD_ShowString(unsigned char Line,unsigned char Column,char *String);

void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);

void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length);

void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);

void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);


#endif

MatrixKey.c

#include 

#include "Delay.h"

unsigned char MatrixKey()

{

unsigned char KeyNumber = 0;

P1=0xFF;

P1_3=0;

if(P1_7==0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=1;}

if(P1_6==0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=5;}

if(P1_5==0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=9;}

if(P1_4==0){Delay(20);while(P1_4==0);Delay(20);KeyNumber=13;}

P1=0xFF;

P1_2=0;

if(P1_7==0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=2;}

if(P1_6==0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=6;}

if(P1_5==0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=10;}

if(P1_4==0){Delay(20);while(P1_4==0);Delay(20);KeyNumber=14;}

P1=0xFF;

P1_1=0;

if(P1_7==0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=3;}

if(P1_6==0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=7;}

if(P1_5==0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=11;}

if(P1_4==0){Delay(20);while(P1_4==0);Delay(20);KeyNumber=15;}

P1=0xFF;

P1_0=0;

if(P1_7==0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=4;}

if(P1_6==0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=8;}

if(P1_5==0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=12;}

if(P1_4==0){Delay(20);while(P1_4==0);Delay(20);KeyNumber=16;}

return KeyNumber;

}

MatrixKey.h

#ifndef __MATRIXKEY_H__

#define __MATRIXKEY_H__


unsigned char MatrixKey();

#endif

2.按键密码锁

密码锁中函数除了main函数不同,其他的库函数都相同,这就是模块化编程的好处,用户只需要对逻辑部分进行编辑,对其余规则类的编程可以调用函数。


main.c

#include

#include "Delay.h"

#include "LCD1602.h"

#include "MatrixKey.h"

unsigned char KeyNum;

unsigned int Password;

unsigned int Count;

void main()

{

LCD_Init();

LCD_ShowString(1,1,"password:");

while(1)

{

KeyNum=MatrixKey();

if(KeyNum)

{

if(KeyNum<=10)

{

if(Count<4)

{

Password*=10;       //ÃÜÂë×óÒÆһλ

Password+=KeyNum%10;//»ñȡһλÃÜÂë

Count++;

}

LCD_ShowNum(2,1,Password,4);

}

if(KeyNum==11)

{

if(Password==2345)

{

LCD_ShowString(1,15,"OK");

Password=0;

Count=0;

LCD_ShowNum(2,1,Password,4);

}

else

{

LCD_ShowString(1,14,"ERR");

Password=0;

Count=0;

LCD_ShowNum(2,1,Password,4);

}

}

if(KeyNum==12)

{

Password=0;

Count=0;

LCD_ShowNum(2,1,Password,4);

}

}

}

}

关键字:51单片机  按键操作  按键设置 引用地址:51单片机——按键操作

上一篇:7种常见的51单片机时钟电路图
下一篇:51单片机—数码管显示

推荐阅读最新更新时间:2024-11-08 10:23

如何利用51单片机同时扩展RAM和ROM
下面这个系统中,8051同时扩展片外程序存储器和数据存储器,两片存储器的片选信号都接地, 即同时有效,也就是说,这两片存储器无需选择。 51同时扩展RAM和ROM 下面来分析这个问题,该系统中虽然有两片存储器,但由于两片存储器的输入,输入允许信号不同,程序存储器没有输入允许,其输出允许由8051的引脚PSEN控制,只有当程序存储器的片选信号和输出允许信号同时有效时,程序存储器的总线才挂接到CPU总线上 。否则,程序存储器的所有总线引脚都为高阻态,即相当于存储器与CPU总线断开。 数据存储器的输入允许端为WR,受控于8051的P3.6, 输出允许信号为RD,受控于8051的P3.7,数据存储器要与8051挂接的条件是片选信号
[单片机]
51-基于51单片机射频RFID卡考勤上课上班统计设计
具体实现功能 系统由STC89C52单片机电路+RFID模块电路+1602液晶显示电路+电源电路组成。 具体功能: (1)系统有3张卡,分别代表依次是张三、李四、王二; (2)任何一个人刷卡成功能,1602液晶响应显示,未刷卡显示“N”,刷卡成功后显示“Y”; (3)液晶第二行显示刷卡人数,即出勤总人数。 设计背景 随着信息化建设的不断发展,磁卡得到普遍的推广,大部分采用RFID射频技术,通过射频信号自动识别目标对象获取数据,识别工作不受环境的影响,操作方便快捷,具有防污、防水、加密存储等优点,较传统的接触式IC卡,具有明显的优势,被广泛应用在身份识别、消费等各项服务上,为企业或单位的管理以及人们的生活提供极大
[单片机]
51-基于<font color='red'>51单片机</font>射频RFID卡考勤上课上班统计设计
51单片机STC15W408AS驱动无感无刷电机BLDC
看到很多人在用C8051做无感无刷电机的驱动,今天瑞生给大家来个国产51单片机STC15W408AS驱动无刷电机的驱动资料吧! 1.硬件设计 主控单片机使用STC15W408AS,单片机自带硬件PWM模块、ADC模块和比较器模块,所以非常适合做无刷电机的驱动,主频35M,无需外部晶振和复位电路,接好VCC和GND就可以工作。半桥电路使用PMOS+NMOS的组合,PMOS为IRF9540,NMOS为IRF540.驱动芯片用TC4427A。 先在洞洞板上做实验吧。原理图如下所示,懒得用软件画了,还是手画来得快些。下面的图中,只画出了A相的桥,B相和C相的桥与A相一样。 依照原理图,焊接好的板子如下图所示: 2.软件设计 2
[单片机]
<font color='red'>51单片机</font>STC15W408AS驱动无感无刷电机BLDC
51单片机 定时器3计时示例
_ :16位定时器自动重装,60ms定时周期,LED闪烁 _ :连接方式:将任意一个LED的引脚和P1.2相连 _ :实验现象:LED以60ms为周期闪烁。 1 /*-- 2 名称:定时器2 3 论坛:www.doflye.net 4 编写:shifang 5 内容:通过定时让LED灯闪烁 6 */ 7 #include reg52.h //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义 8 9 sbit LED=P1^2; //定义LED端口 10 11 /* 12 定时器初始化子程序 13 */ 14 void TIM2Inital(void) 15 { 16 RCAP2H = (6553
[单片机]
57-基于51单片机的光照温度蓝牙上传设计
具体实现功能 系统由STC89C52单片机电路+光照检测电路+DS18B20温度检测电路+蓝牙模块电路+LCD1602液晶显示电路+电源电路组成。 具体功能: (1)LCD1602液晶实时显示光照值(0-100)和温度。 (2)将光照值和温度通过蓝牙模块实时上传到手机APP。 设计背景 现在国家大力提倡智能化农业,传统的生产方式很难在科技发达的今天立足,所以实现智能化农业生产是大势所趋。蔬菜大棚智能控制系统指的是自动判断大棚内的温度、湿度、光照、二氧化碳浓度等指标是否合乎农作物的生活环境,若与设定的理想值有偏差就自动传递出信息或警报,然后自动或者手动调节这些指标使之适应生长。实现自动化的生产方式,紧跟时代和科技的发
[单片机]
57-基于<font color='red'>51单片机</font>的光照温度蓝牙上传设计
利用51单片机实现对激光器电流的精度控制
引 言   近年来,随着光电技术的迅猛发展,激光器已广泛应用于医疗、国防、测量等各个领域。而环境温度变化会直接影响激光器的波长。把关键元件(如高性能晶振、SAW 滤波器、光放大器、激光二极管) 的本机温度限制在窄范围内,可以提高电子系统的精度。一般需要将温度控制在0. 1 ℃内,激光器的工作精度才能很好地保持在0. 1nm 内 。文中的设计方案能为大功率半导体激光器提供有效支持,最大电流可达2. 5A。    1  半导体激光控制器的设计   激光控制器由受控恒流源,温度监视及控制电路,主控制器及显示器构成。整体结构原理见图1。      1. 1  受控恒流源:   为了使激光器输出稳定的激光,对流过激光
[单片机]
51单片机的时钟及总线时序和总线扩展
说到51单片机的时钟首先想到51时怎么工作的呢?微型控制器要想工作必须要有一个“动力”,对于51单片机来说,这个“动力”就是时钟源。一般应用上会外接一个12MHz的晶振作为时钟源。 一般第一种接法用的比较多。选择内部震荡方式时晶振旁边有两个小电容。这两个电容叫晶振的负载电容,分别接在晶振的两个脚上和对地的电容,一般在几十皮发。它会影响到晶振的谐振频率和输出幅度。晶振的负载电容= +Cic+△C式中Cd,Cg为分别接在晶振的两个脚上和对地的电容,Cic(集成电路内部电容)+△C(PCB上电容)经验值为3至5pf。 各种逻辑芯片的晶振引脚可以等效为电容三点式振荡器。晶振引脚的内部通常是一个反相器, 或者是奇数个反相器串
[单片机]
<font color='red'>51单片机</font>的时钟及总线时序和总线扩展
51单片机知识大汇总
1.取指译码执行模型:首先我们来看看单片机是如何工作的,我们拿电脑的主板来作为对比,我们买电脑时,总是追求处理器的主频。处理器的工作原理是从存储器上取出一条指令,然后对指令译码,译码完后执行。然后取下一条指令,译码,执行。它为什么能这么有序的工作?是因为它有一个工作时钟,在这个工作时钟的统一管理下,处理器有序的工作,这里的主频就是工作时钟的速度,当然,现在你可能也知道主频越高,取指译码速度越快,性能越好。那么你可能会问,这跟51单片机有什么关系,OK,切入正题,单片机的工作也是这个原理,从存储器上取指,译码,执行。但是单片机的存储器在哪?在单片机的内部,对于电脑来说,是把处理器,内存集中在一块主板上。而现在你应该很明确,对于单
[单片机]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

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

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

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