搜索
bottom↓
回复: 9

关于4*4矩阵键盘与LCD1602显示问题

[复制链接]

出0入0汤圆

发表于 2012-6-27 11:33:39 | 显示全部楼层 |阅读模式
LCD显示正常,就是在键盘输入的时候出现问题,一个按键按下会在液晶上显示多个数字,按住按键不放,会一直显示那个按键值……但是我需要的是输入一个按键只显示一个按键值!求牛人帮忙,谢谢了……
   
  程序代码:
#include<reg52.h>
#include <intrins.h>
#include <stdlib.h>       
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
sbit BEEP = P3^7;
sbit RS = P2^0;         /*0:指令寄存器 1:数据寄存器*/
sbit RW = P2^1;         /*0:写选择 1:读选择*/
sbit EN = P2^2;         /*下降沿时LCD执行命令*/
uchar a[10] = {0,1,2,3,4,5,6,7,8,9};/*存随机数*/
uchar code dis1[] = {" Random Keyboard"};
uchar code dis2[] = {"    Design      "};
uchar code dis3[] = {"   Designed By  "};
uchar code dis4[] = {"     YYY        "};
uchar code dis5[] = {"  Please Enter  "};
uchar code dis6[] = {"  The Password  "};
uchar code dis7[] = {"0123456789"};                /*随机数显示*/
uchar code dis8[] = {"Enter:**********"};
/*******************************************************/
/**********************延时函数************************/
/*******************************************************/

void Delay(uint t)
{
        uint i,j;
        while(t--)
        for(i=0;i<75;i++);
                for(j=0;j<28;j++);       
}
/*******************************************************/
/*******************键盘扫描函数***********************/
/*******************************************************/
uchar Keys_Scan(void)
{
    uchar i, j, temp, Buffer[4] = {0xef, 0xdf, 0xbf, 0x7f};
    for(j = 0; j < 4; j++) { //循环四次
      P1 = Buffer[j];         //在P1高四位分别输出一个低电平
      temp = 0x01;            //计划先判断P1.0位
      for(i = 0; i < 4; i++) { //循环四次
        if(!(P1 & temp))      //从P1低四位,截取1位
          return (i + j * 4); //返回取得的按键值
        temp <<= 1;           //判断的位,左移一位
    } }
    return 16;                //判断结束,没有键按下,返回16
}


/*******************************************************/
/******************1602初始化函数*********************/
/*******************************************************/
/*************************************************************************
** 函数功能:LCD忙检查                                                                                                 **
** 入口参数:                                                                                                                         **
** 出口参数:LCD_Status                                                                                                     **
*************************************************************************/
uchar LCD_Busy()
{
        uchar LCD_Status;
        RS = 0;
        RW = 1;
        EN = 1;
        Delay(1);
           LCD_Status = P0;
        EN = 0;
        return LCD_Status;
}
/*************************************************************************
** 函数功能:向LCD写数据                                                                                                **
** 入口参数:dat                                                                                                                    **
** 出口参数:                                                                                                                        **
*************************************************************************/
void Write_Data(uchar dat)
{
        LCD_Busy();
        RS=1;
        RW=0;
        EN=0;
        P0=dat;
        EN=1;
        Delay(1);
        EN=0;       
}
/**************************************************************************
** 函数功能:向LCD写命令                                                                                                 **
** 入口参数:cmd                                                                                                                 **
** 出口参数:                                                                                                                         **
**************************************************************************/
void Write_LCD_Com(uchar cmd)
{
        LCD_Busy();
        RS=0;
        RW=0;
        EN=0;
        P0=cmd;
        EN=1;
        Delay(1);
        EN=0;       
}
/**************************************************************************
** 函数功能:设定LCD的显示位置                                                                                 **
** 入口参数:P                                                                                                                         **
** 出口参数:                                                                                                                         **
**************************************************************************/
void Set_LCD_POS(uchar p)
{
        Write_LCD_Com(0x80|p);       
}
/**************************************************************************
** 函数功能:按指定位置显示一个字符                                                                                 **
** 入口参数:X,Y,DData                                                                                                         **
** 出口参数:                                                                                                                         **
**************************************************************************/
void Display_LCD_OneChar(uchar X, uchar Y, uchar DData)
{
        Y &= 0x1;
        X &= 0xF;         /*限制X不能大于15,Y不能大于1*/
        if (Y) X |= 0x40; /*当要显示第二行时地址码+0x40;*/
        X |= 0x80;                   /*算出指令码*/
        Write_LCD_Com(X);   /*发命令字*/
        Write_Data(DData); /*发数据*/
}
/**************************************************************************
** 函数功能:在LCD上显示字符串                                                                                 **
** 入口参数:p,s                                                                                                                 **
** 出口参数:                                                                                                                         **
**************************************************************************/
void Display_LCD_String(uchar p,uchar *s)
{
        uchar i;
        Set_LCD_POS(p);
        for(i=0;i<16;i++)
        {
                Write_Data(s[i]);
                Delay(1);        
        }
}
/*************************************************************************
** 函数功能:LCD初始化                                                                                                        **
** 入口参数:                                                                                                                        **
** 出口参数:                                                                                                                        **
*************************************************************************/
void Init_LCD()
{       
        /* 开机画面初始化 */
        Write_LCD_Com(0x38);/*设置液晶工作模式,16*2行显示,5*7点阵,8位数据*/
        Delay(1);
        Write_LCD_Com(0x01);/*清屏*/
        Delay(1);
        Write_LCD_Com(0x06);/*整屏不移动,光标自动右移*/         
        Delay(1);
        Write_LCD_Com(0x0c);/*开显示不显示光标*/
        Delay(1);
        Display_LCD_String(0x00, dis1);       
        Display_LCD_String(0x40, dis2);
                  
        Delay(2000);
        Write_LCD_Com(0x38);
        Delay(1);
        Write_LCD_Com(0x01);
        Delay(1);
        Write_LCD_Com(0x06);         
        Delay(1);
        Write_LCD_Com(0x0c);
        Delay(1);
        Display_LCD_String(0x00, dis3);
        Display_LCD_String(0x40, dis4);

        Delay(2000);
        Write_LCD_Com(0x38);
        Delay(1);
        Write_LCD_Com(0x01);
        Delay(1);
        Write_LCD_Com(0x06);         
        Delay(1);
        Write_LCD_Com(0x0c);
        Delay(1);
        Display_LCD_String(0x00, dis5);
        Display_LCD_String(0x40, dis6);
        Delay(2000);
        Write_LCD_Com(0x38);
        Delay(1);
        Write_LCD_Com(0x01);
        Delay(1);
        Write_LCD_Com(0x06);         
        Delay(1);
        Write_LCD_Com(0x0c);
        Delay(1);
        }               

/*******************************************************/
/******************随机数产生函数*********************/
/*******************************************************/
void Random_Num()
{
        int i,j,k,m,b[10] = {0,1,2,3,4,5,6,7,8,9};
        for(i=0;i<10;i++)
        {
                k = TL0; /*取定时器的值*/
                m = k%(10-i);
/*在0~9的表中选一个数后,将后面的向前移,在9个数中随机选1个,依次循环*/
                a[i] = b[m];
                for(j=m;j<10;j++)
                        b[j] =b[j+1];
        }
}


void Osinit()
{
        uchar i;       
        Init_LCD();         /*调用液晶屏初始化子函数*/
    Delay(100);
        Write_LCD_Com(0x80+0x06);               
        for(i=0;i<10;i++)
          {
                Write_Data(dis7[a[i]]);        /*初次使用默认0123456789*/
        }
        Display_LCD_String(0x40, dis8);
}

void Beep()
{
        char i;
        for(i=0;i<100;i++)
        {
                BEEP = ~BEEP;
                Delay(1);
        }
        BEEP = 1;
}

void main(void)
{   int count=0;
    int Key_Num;                /*扫描得到的键号*/
    int Key_Temp;                /*键号暂存*/       
        Osinit();
        while(1)
        {Key_Temp=Keys_Scan();       
     Key_Num=Key_Temp;
         
         if(Key_Num==15)          
         {count=0;
          Display_LCD_String(0x40, dis8);}
         
     if((Key_Num>=0)&&(Key_Num<10))        /*数字键处理分支*/
                {
                       
                        if(count<10)                                        /*可以输入10位密码*/
                        {   
                            Write_LCD_Com(0xc0+0x06+count);
                                Write_Data(dis7[[Key_Num]]);
/*显示密码*/
                                count++;
                                if(count==10)
                        }               
                }

         }
}

阿莫论坛20周年了!感谢大家的支持与爱护!!

曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……

出0入0汤圆

发表于 2012-6-27 11:56:20 | 显示全部楼层
键盘扫描最基本是防抖,参考下坛中的程序

出0入0汤圆

发表于 2012-6-27 11:57:41 来自手机 | 显示全部楼层
键盘扫描函数里加入松手检测

出0入0汤圆

发表于 2012-6-27 15:08:41 | 显示全部楼层
2楼加三楼正解

出0入0汤圆

 楼主| 发表于 2012-6-27 19:38:31 | 显示全部楼层
信天游 发表于 2012-6-27 11:57
键盘扫描函数里加入松手检测

抖动问题已经解决……还有个问题希望可以帮我下,如何实现按键一次按下和弹起只显示一个数值呢? 谢谢

出0入0汤圆

发表于 2012-6-27 21:18:39 | 显示全部楼层
使用状态机

出0入0汤圆

 楼主| 发表于 2012-6-28 15:43:38 | 显示全部楼层
问题已经解决,谢谢各位

出0入0汤圆

发表于 2012-6-28 16:58:04 | 显示全部楼层
本帖最后由 liweiqiang668 于 2012-6-28 16:59 编辑

程序已邦你改好,按鍵部份已可以單次輸入,仿真文件和源程序已打包在一起了,LCD的讀忙指令為便於仿真已關閉,實物調試時打開即可,好象你的程序還沒有寫完。有些地方改了我常用的程序,希望不會影響你原來的思路。


你真快,我發之前沒有看到你,發完你就說已OK了。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

 楼主| 发表于 2012-6-29 23:54:29 | 显示全部楼层
liweiqiang668 发表于 2012-6-28 16:58
程序已邦你改好,按鍵部份已可以單次輸入,仿真文件和源程序已打包在一起了,LCD的讀忙指令為便於仿真已關 ...

还是要谢谢你……

出0入0汤圆

发表于 2012-7-5 17:25:39 | 显示全部楼层
yubobin5577 发表于 2012-6-27 19:38
抖动问题已经解决……还有个问题希望可以帮我下,如何实现按键一次按下和弹起只显示一个数值呢? 谢谢 ...

在按键还没松手时,让键盘扫描进入死循环,在循环里什么都不做,退出循环的条件是按键已经被松开了
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-8-27 00:13

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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