找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2767|回复: 5
打印 上一主题 下一主题
收起左侧

C51模拟手机按键

[复制链接]
跳转到指定楼层
楼主
/*******************************************************************************************
课题:1602LCD显示仿手机键盘按键
LCD接口:P0.0-P0.7 TO D0-D7
                 P2.0 TO RS
                 P2.1 TO RW
                 P2.2 TO E
蜂鸣器: P2.7
键盘:         列(ltr) P1.0-P1.2
                 行(utd) P1.4-P1.7
*******************************************************************************************/
#include <reg52.h>
#include <string.h>
#define uint unsigned int
#define uchar unsigned char

sbit RS=P2^0;
sbit RW=P2^1;
sbit EN=P2^2;
sbit SPK=P2^7;

uchar code KeyPad_Chars[12][6]={"1 ","2ABC","3DEF","4GHI","5JKL","6MNO","7PQRS","8TUV","9WXYZ","*","0+","#"};//初始化键盘字库
uchar code Line1[]=" LJL'S Cellphone";//固定字符串
uchar code Line2[]="Your Key:       ";
uchar KeyNo=-1;                        //键位0~11
uchar Inner_Idx=0;                //同键位内部切换
uchar tSpan=0;                        //同键位连续按键时间间隔

/**********************毫秒延时************************************/
void DelayMS(uint ms)       
{
        uchar i;
        while(ms--)
        {
                for(i=0;i<110;i++);
        }
}

/************************忙检测***********************************/
uchar Busy_Waiting()
{
        uchar lcd_status;
        RS=0;
        RW=1;
        EN=1;
        DelayMS(1);
        lcd_status=P0;
        EN=0;
        return lcd_status;
}

/************************写数据***********************************/
void Write_LCD_DATA(uchar dat)
{
        while((Busy_Waiting()&&0x80)==0x80);
        RS=1;RW=0;EN=0;P0=dat;EN=1;DelayMS(1);EN=0;
}

/************************写指令********************************/
void Write_LCD_Command(uchar cmd)
{
        while((Busy_Waiting()&0x80)==0x80);
        RS=0;
        RW=0;
        EN=0;
        P0=cmd;EN=1;DelayMS(1);EN=0;
}

/*****************初始化***********************************/
void Init_LCD()
{
        Write_LCD_Command(0x38);
        DelayMS(1);
        Write_LCD_Command(0x01);
        DelayMS(1);
        Write_LCD_Command(0x06);
        DelayMS(1);
        Write_LCD_Command(0x0c);
        DelayMS(1);
}

/**********************键盘扫描************************************/
void Keys_Scan()
{
        P1=0x0f;                        //高四位置0
        DelayMS(1);
        switch(P1)                        //判断列
        {
                case 0x0e: KeyNo=0;break;
                case 0x0d: KeyNo=1;break;
                case 0x0b: KeyNo=2;
        }
        P1=0xf0;                        //第四位置0
        DelayMS(1);
        switch(P1)                         //根据行数加KN
        {
                case 0xe0: KeyNo+=0;break;
                case 0xd0: KeyNo+=3;break;
                case 0xb0: KeyNo+=6;break;
                case 0x70: KeyNo+=9;
        }
}

/**********************蜂鸣器**************************************/
void Beep()
{
        SPK=1;
        DelayMS(400);
        SPK=0;
}



/**********************主程序**************************************/
void main()
{
        uchar i,Pre_KeyNo=-1;
        IE=0x82;
        TMOD=0x01;
        TH0=-50000/256;
        TL0=-50000%256;
        P0=P2=0xff;
        SPK=0;
        DelayMS(10);
        Init_LCD();                        //初始化
        Set_LCD_POS(0);                //显示第一行
        for(i=0;i<16;i++)
                Write_LCD_DATA(Line1[i]);
        Set_LCD_POS(0x40);         //显示第二行
        for(i=0;i<16;i++)
                Write_LCD_DATA(Line2[i]);
        while(1)
        {
                P1=0xf0;
                if(P1!=0xf0)Keys_Scan();//按键检测
                else continue;
                if(Pre_KeyNo!=KeyNo)         //新按键判断
                {
                        Pre_KeyNo=KeyNo;
                        tSpan=0;                        //间隔请0
                        Inner_Idx=0;                   //按键内部切换清0
                        TR0=1;                                   //启动定时器
                }
                else                                          //如为同一按键
                {
                        if(tSpan<=40)
                                Inner_Idx=(Inner_Idx+1)%strlen(KeyPad_Chars[KeyNo]);        //显示下一个
                                else
                                        Inner_Idx=0;
                                tSpan=0;
                }
                Set_LCD_POS(0x4b);
                Write_LCD_DATA(KeyPad_Chars[KeyNo][Inner_Idx]);         //显示按键
                Beep();
                DelayMS(100);
        }
}

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的积分奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:97078 发表于 2015-11-25 13:27 | 只看该作者
学习了!受用
回复

使用道具 举报

板凳
ID:1 发表于 2015-11-25 16:40 | 只看该作者
楼主能分享一下电路图吗
回复

使用道具 举报

地板
ID:97070 发表于 2015-11-25 18:38 | 只看该作者
看看,希望能帮到我
回复

使用道具 举报

5#
ID:96742 发表于 2015-11-26 10:27 | 只看该作者
小心的提个醒,没有设定位置显示函数。 void Set_LCD_POS(uchar pos) {                             Write_LCD_Command(pos | 0x80);  //数据指针=80+地址变量 }
回复

使用道具 举报

6#
ID:82765 发表于 2017-9-24 20:21 | 只看该作者
提示: 作者被禁止或删除 内容自动屏蔽
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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