找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3558|回复: 13
收起左侧

跪求大神讲解关于键盘输入显示的问题

[复制链接]
ID:278538 发表于 2018-4-13 16:25 | 显示全部楼层 |阅读模式
跪求大神讲解关于键盘输入显示的问题,我是一个新手,希望讲得简单易懂一些。
我用4*4矩阵键盘输入4位数,按下一个数时在12864液晶上显示一个数,就像我先按6就在液晶上显示6,再按下7液晶上显示67。想知道怎么弄,谢谢
回复

使用道具 举报

ID:213173 发表于 2018-4-13 21:23 | 显示全部楼层
像计算器那样显示键盘输入的数字,对于初学者来说有相当难度,还是循序渐进的学习好些,到时候自然就会了。
回复

使用道具 举报

ID:278538 发表于 2018-4-14 15:05 | 显示全部楼层
wulin 发表于 2018-4-13 21:23
像计算器那样显示键盘输入的数字,对于初学者来说有相当难度,还是循序渐进的学习好些,到时候自然就会了。

大神能不能说一下,我这确实比较需要,在网上搜不到,谢谢了
回复

使用道具 举报

ID:308255 发表于 2018-4-14 21:44 | 显示全部楼层
我感觉先建个数组,每按一个数都保存在数组里,每按一次刷新下屏幕显示出当前值
回复

使用道具 举报

ID:308255 发表于 2018-4-14 21:45 | 显示全部楼层
建数组,存数值,按键后刷新
回复

使用道具 举报

ID:213173 发表于 2018-4-15 06:25 | 显示全部楼层
78558mo 发表于 2018-4-14 15:05
大神能不能说一下,我这确实比较需要,在网上搜不到,谢谢了

给你一个6位数码管显示的密码锁程序参考,显示程序虽然不能直接套用,但可以提供思路和程序框架。单片机型号STC89C52RC,实验板TX-1C,键盘电路是4*4+4。有详细注释,希望对你有所帮助。
#include <AT89X52.H>                         //Keil库头文件
#include <intrins.h>                                //Keil库头文件
#define uint unsigned int                 //宏定义无符号整型数据
#define uchar unsigned char         //宏定义无符号字符型数据
#define ulong unsigned long         //宏定义无符号长整型数据
/****定义ISP的操作命令*****/
#define RdCommand 0x01                                //读命令
#define PrgCommand 0x02                                //写命令
#define EraseCommand 0x03                        //擦除命令
#define WaitTime 0x01                                 //定义CPU的等待时间,写入硬件延时
#define Error 0                                                //错误
#define OK 1                                                //正确
/*STC89系列EEPROM寄存器声明*/
sfr ISP_DATA=0xe2;                                        //0000,0000 EEPROM数据寄存器
sfr ISP_ADDRH=0xe3;                                        //0000,0000 EEPROM地址高字节
sfr ISP_ADDRL=0xe4;                                        //0000,0000 EEPROM地址第字节
sfr ISP_CMD=0xe5;                                        //xxxx,xx00 EEPROM命令寄存器
sfr ISP_TRIG=0xe6;                                        //0000,0000 EEPRPM命令触发寄存器
sfr ISP_CONTR=0xe7;                                        //0000,x000 EEPROM控制寄存器
/********端口定义**********/
sbit dula=P2^6;                                                //段选
sbit wela=P2^7;                                                //位选
sbit Q1=P1^5;                                                //门锁电磁开关端口定义
sbit Q2=P1^6;                                                //门锁电磁开关端口定义
sbit Buzzer=P2^3;                                        //蜂鸣器端口定义
sbit LED=P1^3;
sbit key_1=P3^4;                                        //清除键
sbit key_2=P3^5;                                        //上锁键
sbit key_3=P3^6;                                        //开锁键
sbit key_4=P3^7;                                        //万能密钥操作键
/****数组及变量声明*****/
uchar code table[]={                                //共阴数码管数组0~F
        0x3f,0x06,0x5b,0x4f,
        0x66,0x6d,0x7d,0x07,
        0x7f,0x6f,0x77,0x7c,
        0x39,0x5e,0x79,0x71};
uchar table1[6];                                        //输入密码缓存
uchar table2[6];                                        //读取EEPROM密码缓存
uchar key=0xff;                                        //定义键值变量
uchar P_bit=0;                                                //密码的位次变量
uchar Buzzer_sign=0;                                //响铃次数变量
uchar ERROR;                                                //密码错误
bit key_sign=0;                                        //操键标志
bit second=1;                                                //响铃允许位
bit Set_up=0;                                                //万能密钥设置标志
/***********子函数声明**************/
void ISP_IAP_enable();                                //打开 ISP,IAP 功能
void ISP_IAP_disable();                                //关闭 ISP,IAP 功能
void ISPgoon();                                                //公用的触发代码
uchar byte_read(uint byte_addr);        //字节读
void SectorErase(uint sector_addr);        //扇区擦除
void byte_write(uint byte_addr, uchar original_data);        //字节写
void Timer0Init();                                        //初始化定时器
void keyscan();                                                //按键扫描程序
void key_service();                                        //按键服务程序
void display();                                                //数码管动态显示程序
void Buzzer_second();                                //蜂鸣器响铃程序
void hdmm();
void Universal_key();                                //万能密钥
void delayms(uint k);                                //软件延时程序
void baojing();                                                //报警程序
/************主函数************/
void main()
{
        Timer0Init();                                //初始化定时器
        Q1=1;Q2=0;                                        //初始化门栓
        Buzzer=1;                                        //初始化蜂鸣器
        Universal_key();                        //万能密钥
        Buzzer_sign=1;                                //加电响提示声
        while(1)
        {
                keyscan();                                //矩阵按键扫描程序
                key_service();                        //按键服务程序
                Buzzer_second();                //蜂鸣器响铃
                display();                                //4位数码管显示程序
                baojing();                                //报警程序
        }
}
/*********初始化定时器***********/
void Timer0Init()        //50毫秒@11.0592MHz
{
        TMOD= 0x01;                //设置定时器模式
        TL0 = 0x00;                //设置定时初值
        TH0 = 0x4C;                //设置定时初值
        TF0 = 0;                //清除TF0标志
//        TR0 = 1;                //开定时器0
        EA = 1;                        //开总中断
        ET0 = 1;                //开T0中断
}
/************按键扫描程序**************/
void keyscan()                                       
{
        static bit sign=0,sign1=0,sign2=0,sign3=0;                        //按键有效标志
        static uint count=0,count1=0,count2=0,count3=0;                //消抖计数变量                       
        uchar num=0;                                //临时变量
/**************矩阵按键部分****************/
        P3=0x0f;                                        //赋值P3 1111 0000
        if(P3!=0x0f)                                //检测有按键按下
        {
                count++;                                //消抖计数
                if((count>=1000)&&(sign==0))        //100~1000,根据主循环周期调整约10~20ms
                {                       
                        sign=1;                                //按键有效标志置1
                        num=P3;                                //保存P3值xxxx 0000,x为0或1
                        num|=0xf0;                        //保存num按位或0x0f值xxxx 1111
                        P3=num;                                //赋值P3 xxxx 1111
                        num=P3;                                //保存P3值xxxx xxxx
                        switch(num)
                        {
                                case 0xee: key= 1; break;
                                case 0xde: key= 2; break;
                                case 0xbe: key= 3; break;
                                case 0x7e: key= 4; break;
                                case 0xed: key= 5; break;
                                case 0xdd: key= 6; break;
                                case 0xbd: key= 7; break;
                                case 0x7d: key= 8; break;
                                case 0xeb: key= 9; break;
                                case 0xdb: key= 0; break;
//                                case 0xbb: key=11; break;
//                                case 0x7b: key=12; break;
//                                case 0xe7: key=13; break;
//                                case 0xd7: key=14; break;
//                                case 0xb7: key=15; break;
//                                case 0x77: key=16; break;
                        }
                        key_sign=1;                //操键标志1
                        Buzzer_sign=1;//按键提示声
                }
        }
        else                                                //键抬起
        {
                sign=0;                                //按键有效标志清0
                count=0;                                //消抖计数清0
        }
/**************独立按键部分***************/
        P3=0xff;                                                //P3复位
        if(key_1==0)
        {
                count1++;                                //消抖计数
                if((count1>=1000)&&(sign1==0))        //100~1000,根据主循环周期调整约10~20ms
                {                       
                        sign1=1;                                //按键有效标志置1
                        key=13;
                        key_sign=1;                //操键标志1
                        Buzzer_sign=1;//按键提示声
                }
        }
        else                                                //键抬起
        {
                sign1=0;                                //按键有效标志清0
                count1=0;                                //消抖计数清0
        }
        if(key_2==0)
        {
                count2++;                                //消抖计数
                if((count2>=1000)&&(sign2==0))        //100~1000,根据主循环周期调整约10~20ms
                {                       
                        sign2=1;                                //按键有效标志置1
                        key=14;
                        key_sign=1;                //操键标志1
                        Buzzer_sign=1;//按键提示声
                }
        }       
        else                                                //键抬起
        {
                sign2=0;                                //按键有效标志清0
                count2=0;                                //消抖计数清0
        }
        if(key_3==0)
        {
                count3++;                                //消抖计数
                if((count3>=1000)&&(sign3==0))        //100~1000,根据主循环周期调整约10~20ms
                {                       
                        sign3=1;                                //按键有效标志置1
                        key=15;
                        key_sign=1;                //操键标志1
                        Buzzer_sign=1;//按键提示声
                }
        }       
        else                                                //键抬起
        {
                sign3=0;                                //按键有效标志清0
                count3=0;                                //消抖计数清0
        }
}
/***********按键服务程序***************/
void key_service()
{
        uchar i;                                                //临时变量
        if(key_sign==1)                        //操键标志如果1
        {
                key_sign=0;                                //操键标志清0
                if((P_bit<6)&&(key<11))
                {
                        P_bit++;
                        switch(P_bit)
                        {
                                case 1:table1[0]=key;break;
                                case 2:table1[1]=key;break;
                                case 3:table1[2]=key;break;
                                case 4:table1[3]=key;break;
                                case 5:table1[4]=key;break;
                                case 6:table1[5]=key;break;
                                default: break;
                        }
                }
                if((key>12)&&(key<16))
                {
                        switch(key)
                        {
                                case 13:
                                        if(P_bit>0)
                                                P_bit--;
                                        switch(P_bit)
                                        {
                                                case 5:table1[5]=0; break;
                                                case 4:table1[4]=0; break;
                                                case 3:table1[3]=0; break;
                                                case 2:table1[2]=0; break;
                                                case 1:table1[1]=0; break;
                                                case 0:table1[0]=0; break;
                                                default: break;
                                        }
                                break;

                                case 14:
                                        //保存密码、锁门
                                        if((Q1==1)&&(Q2==0)&&(P_bit==6))
                                        {
                                                EA = 0;                        //关总中断
                                                SectorErase(0x2000);//擦除EEPROM扇区中的数据
                                                for(i=0;i<6;i++)
                                                {
                                                        byte_write(0x2000+i,table1);//重新写入密码
                                                }
                                                EA = 1;                        //开总中断
                                                Q1=0;                                //门锁状态
                                                Q2=1;                                //门锁状态
                                                P_bit=0;                        //密码的位次变量清0
                                        }
                                        else Buzzer_sign=2;//警示错误
                                break;

                                case 15:
                                        //核对密码、开门
                                        if((Q1==0)&&(Q2==1)&&(P_bit==6)&&(Set_up==0))
                                        {
                                                EA = 0;                        //关总中断
                                                for(i=0;i<6;i++)
                                                {
                                                        table2=byte_read(0x2000+i);//读取EEPROM中数据保存在table2
                                                }
                                                EA = 1;                        //开总中断
                                                if((table1[0]==table2[0])&&(table1[1]==table2[1])&&(table1[2]==table2[2])
                                                &&(table1[3]==table2[3])&&(table1[4]==table2[4])&&(table1[5]==table2[5]))        //核对密码
                                                {
                                                        Q1=1;                                //门锁状态
                                                        Q2=0;                                //门锁状态
                                                        P_bit=0;                        //密码的位次变量清0
                                                }                                                                       
                                                else
                                                {
                                                        ERROR++;                        //密码错误计数
                                                        Buzzer_sign=2;//警示错误
                                                }
                                        }
                                        else Buzzer_sign=2;//警示错误
                                break;
                        }
                }
        }
}
/************数码管动态显示程序**************/
void display()
{        
        static uchar num=0;     //时分显示变量
        switch(num)
        {
                case 0:       
                        P0=0xff;                                //不选择位
                        wela=1;
                        wela=0;
                        if(P_bit==0)
                                P0=0x00;                        //消隐
                        num++;
                break;

                case 1:       
                        P0=0x00;                                //消隐
                        dula=1;
                        dula=0;
                        P0=0xdf;                                //第1位位码
                        wela=1;
                        wela=0;
                        if(P_bit<1)
                                P0=0x00;       
                        else
                        {
                                if(P_bit==1)P0=table[table1[0]];//第1位段码
                                if(P_bit==2)P0=table[table1[1]];
                                if(P_bit==3)P0=table[table1[2]];
                                if(P_bit==4)P0=table[table1[3]];
                                if(P_bit==5)P0=table[table1[4]];
                                if(P_bit==6)P0=table[table1[5]];
                        }
                        dula=1;
                        dula=0;       
                        num++;
                break;
               
                case 2:       
                        P0=0x00;                                //消隐
                        dula=1;
                        dula=0;
                        P0=0xef;                                //第2位位码
                        wela=1;
                        wela=0;
                        if(P_bit<2)
                                P0=0x00;       
                        else
                        {
                                if(P_bit==2)P0=table[table1[0]];//第2位段码
                                if(P_bit==3)P0=table[table1[1]];
                                if(P_bit==4)P0=table[table1[2]];       
                                if(P_bit==5)P0=table[table1[3]];
                                if(P_bit==6)P0=table[table1[4]];
                        }
                        dula=1;
                        dula=0;
                        num++;
                break;
                       
                case 3:                                       
                        P0=0x00;                                //消隐
                        dula=1;
                        dula=0;
                        P0=0x77;                                //第3位位码
                        wela=1;
                        wela=0;
                        if(P_bit<3)
                                P0=0x00;       
                        else
                        {
                                if(P_bit==3)P0=table[table1[0]];//第3位段码
                                if(P_bit==4)P0=table[table1[1]];
                                if(P_bit==5)P0=table[table1[2]];       
                                if(P_bit==6)P0=table[table1[3]];
                        }
                        dula=1;
                        dula=0;
                        num++;
                break;
                       
                case 4:                               
                        P0=0x00;                                //消隐
                        dula=1;
                        dula=0;
                        P0=0x7b;                                //第4位位码
                        wela=1;
                        wela=0;
                        if(P_bit<4)
                                P0=0x00;       
                        else
                        {
                                if(P_bit==4)P0=table[table1[0]];//第4位段码
                                if(P_bit==5)P0=table[table1[1]];
                                if(P_bit==6)P0=table[table1[2]];       
                        }
                        dula=1;
                        dula=0;
                        num++;
                break;
                       
                case 5:         
                        P0=0x00;                                //消隐
                        dula=1;
                        dula=0;
                        P0=0x7d;                                //第5位位码
                        wela=1;
                        wela=0;
                        if(P_bit<5)
                                P0=0x00;       
                        else
                        {
                                if(P_bit==5)P0=table[table1[0]];//第5位段码
                                if(P_bit==6)P0=table[table1[1]];       
                        }
                        dula=1;
                        dula=0;
                        num++;
                break;
                       
                case 6:   
                        P0=0x00;                                //消隐
                        dula=1;
                        dula=0;
                        P0=0x7e;                                //第6位位码
                        wela=1;
                        wela=0;
                        if(P_bit<6)
                                P0=0x00;       
                        else
                                P0=table[table1[0]];                //第6位段码
                        dula=1;
                        dula=0;
                        num=0;
                break;
        }
}
/*****************************
        蜂鸣器间歇响铃
*****************************/
void Buzzer_second()
{
        if((second==1)&&(Buzzer_sign>0))//响铃允许1与响铃次数
        {
                second=0;                                //响铃允许清0,等待下一秒
                Buzzer=0;                                //蜂鸣器响
                Buzzer_sign--;                        //响铃次数减1
                TR0=1;                                        //开定时器
        }
}
/*-----------------------------
  定时器0中断服务程序  50毫秒
------------------------------*/
void timer0() interrupt 1
{
        static uchar count=0;                                //中断计数变量
        count++;                                                        //中断计数变量count3自+1
        if(count==1)                                                //0.1秒时间到               
                Buzzer=1;                                                //蜂鸣器端口复位
        if(count>=2)                                                //1秒
        {
                count=0;                                                //中断计数变量清0
                second=1;                                                //响铃允许置1
                TR0 = 0;                                                //定时器0关闭
        }
}

/* ================ 打开 ISP,IAP 功能 ================= */
void ISP_IAP_enable()
{
        EA = 0;       /* 关中断   */
        ISP_CONTR = ISP_CONTR & 0x18;       /* 0001,1000 */
        ISP_CONTR = ISP_CONTR | WaitTime; /* 写入硬件延时 */
        ISP_CONTR = ISP_CONTR | 0x80;       /* ISPEN=1  */
}
/* =============== 关闭 ISP,IAP 功能 ================== */
void ISP_IAP_disable()
{
        ISP_CONTR = ISP_CONTR & 0x7f; /* ISPEN = 0 */
        ISP_TRIG = 0x00;
        EA   =   1;   /* 开中断 */
}
/* ================ 公用的触发代码 ==================== */
void ISPgoon()
{
        ISP_IAP_enable();   /* 打开 ISP,IAP 功能 */
        ISP_TRIG = 0x46;  /* 触发ISP_IAP命令字节1 */
        ISP_TRIG = 0xb9;  /* 触发ISP_IAP命令字节2 */
        _nop_();
}
/* ==================== 字节读 ======================== */
uchar byte_read(uint byte_addr)
{
        ISP_ADDRH = (uchar)(byte_addr >> 8);/* 地址赋值 */
        ISP_ADDRL = (uchar)(byte_addr & 0x00ff);
        ISP_CMD   = ISP_CMD & 0xf8;   /* 清除低3位  */
        ISP_CMD   = ISP_CMD | RdCommand; /* 写入读命令 */
        ISPgoon();       /* 触发执行  */
        ISP_IAP_disable();    /* 关闭ISP,IAP功能 */
        return (ISP_DATA);    /* 返回读到的数据 */
}
/* ================== 扇区擦除 ======================== */
void SectorErase(uint sector_addr)
{
        uint iSectorAddr;
        iSectorAddr = (sector_addr & 0xfe00); /* 取扇区地址 */
        ISP_ADDRH = (uchar)(iSectorAddr >> 8);
        ISP_ADDRL = 0x00;
        ISP_CMD = ISP_CMD & 0xf8;   /* 清空低3位  */
        ISP_CMD = ISP_CMD | EraseCommand; /* 擦除命令3  */
        ISPgoon();       /* 触发执行  */
        ISP_IAP_disable();    /* 关闭ISP,IAP功能 */
}
/* ==================== 字节写 ======================== */
void byte_write(uint byte_addr, uchar original_data)
{
        ISP_ADDRH = (uchar)(byte_addr >> 8);  /* 取地址  */
        ISP_ADDRL = (uchar)(byte_addr & 0x00ff);
        ISP_CMD  = ISP_CMD & 0xf8;    /* 清低3位 */
        ISP_CMD  = ISP_CMD | PrgCommand;  /* 写命令2 */
        ISP_DATA = original_data;   /* 写入数据准备 */
        ISPgoon();       /* 触发执行  */
        ISP_IAP_disable();     /* 关闭IAP功能 */
}
/**********万能密钥***********/
void Universal_key()
{
        while(!key_1&&!key_2&&!key_3)
        {
                delayms(5000);                                //延时5秒
                while(!key_1&&!key_2&&!key_3)
                {
                        Set_up=1;                                //万能密钥设置标志置1
                        LED=0;
                        while(!key_1&&!key_2&&!key_3);                        //等待键抬起
                        delayms(200);                        //延时
                }
        }
        while(Set_up)                                //万能密钥设置标志为1
        {
                if(key_4==0)
                {
                        Set_up=0;                        //万能密钥设置标志清0
                        LED=1;
                }
                keyscan();                                //矩阵按键扫描程序
                key_service();                        //按键服务程序
                Buzzer_second();                //蜂鸣器响铃
                display();                                //数码管显示程序
        }
}
/*-------------------------------
  1ms延时子程序(11.0592MHz 12T)
-------------------------------*/

void delayms(uint k)
{
        uint i,j;
        for(i=k;i>0;i--)
                for(j=114;j>0;j--);
}
/*-------------------------------
  报警程序
-------------------------------*/
void baojing()
{
        if(ERROR>=3)                                        //密码错误3次
        {
                Buzzer_sign=255;                        //响铃次数
                P0=0x00;
                dula=1;
                dula=0;
                while(Buzzer_sign)
                {
                        Buzzer_second();                //蜂鸣器响铃
//                        display();
                }
                ERROR=0;
        }
}
回复

使用道具 举报

ID:278538 发表于 2018-4-15 10:22 | 显示全部楼层
wulin 发表于 2018-4-15 06:25
给你一个6位数码管显示的密码锁程序参考,显示程序虽然不能直接套用,但可以提供思路和程序框架。单片机 ...

感谢大神
回复

使用道具 举报

ID:278538 发表于 2018-4-15 10:22 | 显示全部楼层
51heiwang 发表于 2018-4-14 21:45
建数组,存数值,按键后刷新

嗯,谢谢。我试一试
回复

使用道具 举报

ID:111634 发表于 2018-4-15 13:27 | 显示全部楼层

回帖奖励 +10

本帖最后由 zl2168 于 2018-4-15 13:40 编辑

这里有2个问题,一是输入识别键号,二是12864显示,宜分别弄懂弄通后合并。
介绍你几个实例,其中,下面第一个实例是识别键号,第二个实例是12864显示,第三个实例是保留前几个键号,显示新的键号。
自己去研读吧!
回复

使用道具 举报

ID:111634 发表于 2018-4-15 13:28 | 显示全部楼层
本帖最后由 zl2168 于 2018-4-15 13:29 编辑

矩阵式键盘
Proteus仿真一下,确认有效。
实例75 4×4矩阵式键盘.rar (44.8 KB, 下载次数: 6)
4×4矩阵式键盘.jpg
以上摘自张志良编著《80C51单片机仿真设计实例教程——基于Keil CProteus》清华大学出版社ISBN 978-7-302-41682-1.书中电路和程序设计有详细说明,程序语句条条有注解。
回复

使用道具 举报

ID:111634 发表于 2018-4-15 13:31 | 显示全部楼层
本帖最后由 zl2168 于 2018-4-15 13:32 编辑

LCD12864显示屏显示汉字
Proteus仿真一下,确认有效。
实验25 LCD12864显示屏显示.rar (60.48 KB, 下载次数: 4)
12864.jpg
以上摘自张志良编著《80C51单片机仿真设计实例教程——基于Keil CProteus》清华大学出版社ISBN 978-7-302-41682-1内有常用的单片机应用100案例,用于仿真实验操作,电路与程序真实可靠可信可行,可演示,可观测,程序语句条条有注解。
回复

使用道具 举报

ID:308515 发表于 2018-4-15 13:32 | 显示全部楼层
首先要定义引脚。然后令其低电平触发(也就是按下的状态为低电平)。中间定义一个变量,根据按下的按键不同,来判断按下的数值
回复

使用道具 举报

ID:111634 发表于 2018-4-15 13:33 | 显示全部楼层
本帖最后由 zl2168 于 2018-4-15 13:34 编辑

实例76  8279扩展8×8键盘
Proteus仿真一下,确认有效。
实例76 8279扩展键盘和显示.rar (125.29 KB, 下载次数: 3)
8279.jpg
以上摘自张志良编著《80C51单片机仿真设计实例教程——基于Keil CProteus》清华大学出版社ISBN 978-7-302-41682-1.书中电路和程序设计有详细说明,程序语句条条有注解。
回复

使用道具 举报

ID:308545 发表于 2018-4-15 14:19 | 显示全部楼层
建数组,存数值,按键后刷新
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表