51单片机编写1602,有些问题。求C语言大神指点。

2019-07-15 17:12发布

#include<reg52.h>
#include<intrins.h>
#include<math.h>
#define uchar unsigned char
#define uint unsigned int
uchar key_No[]={'1','2','3','4','5','6','7','8','9','+','-','*','/'};
sbit RS=P2^4;    //寄存器选择位
sbit RW=P2^0;    //读写选择位
sbit E=P2^3;     //使能信号位
sbit busy=P0^7;
uchar tmp;     //暂存P2的值
uchar keynum;
void show(uint sum);
void clean();
void delay(uint z);
/*void check() // 判断忙或空闲
{
do{
    P0=0xFF;
    RS=0;     //指令
    RW=1;     //读
    E=0;     //禁止读写
    delay(1); //等待,液晶显示器处理数据
    E=1;     //允许读写
    }while(busy==1); //判断是否为空闲,1为忙,0为空闲
}*/

//毫秒级延时
void delay(uint z)
{
uint x, y;
for(x=z;x>0;x--)
  for(y=110;y>0;y--);
}
void keyscan()
{
while(1)
{
P3=0xfe;       //扫描第1行
if(P1!=0xff)   //有按键按下
{
  tmp = P3;
  delay(5);
  if(P1!=0xff) //延时后确定有按键按下
  {
   switch(tmp)
   {
    case 0xfe: keynum=1;break;   //第1行第1个按键按下         
    case 0xfd: keynum=2;break;   //第1行第2个按键按下     
    case 0xfb: keynum=3;break;   //第1行第3个按键按下
    case 0xf7: keynum=4;break;   //第1行第4个按键按下
    case 0xef: keynum=5;break;   //第1行第5个按键按下
   }
   while(tmp!=0xff)              //等待按键松手
   {
    tmp=P1;////?????????????????????????????
   }
  }
}
delay(5);
P3=0xfd;       //扫描第2行
if(P1!=0xff)   //有按键按下
{
  tmp = P1;
  delay(5);
  if(P1!=0xff) //延时后确定有按键按下
  {
   switch(tmp)
   {
    case 0xfe: keynum=9;show(6); break;   //第2行第1个按键按下         
    case 0xfd: keynum=10;show(7);break;   //第2行第2个按键按下     
    case 0xfb: keynum=11;show(8);break;   //第2行第3个按键按下
    case 0xf7: keynum=12;show(9);break;   //第2行第4个按键按下
    case 0xef: keynum=13;break;   //第2行第5个按键按下
   }
   while(tmp!=0xff)
   {
    tmp=P1;
   }
  }
}
delay(5);
P3=0xfb;       //扫描第3行
if(P1!=0xff)   //有按键按下
{
  tmp = P1;
  delay(5);
  if(P1!=0xff) //延时后确定有按键按下
  {
   switch(tmp)
   {
    case 0xfe: keynum=17;show(3);break;   //第3行第1个按键按下         
    case 0xfd: keynum=18;show(4);break;   //第3行第2个按键按下     
    case 0xfb: keynum=19;show(5);break;   //第3行第3个按键按下
    case 0xf7: keynum=20;show(10);break;   //第3行第4个按键按下
    case 0xef: keynum=21;break;   //第3行第5个按键按下

   }
   while(tmp!=0xff)
   {
    tmp=P1;
   }
  }
}
delay(5);

P3=0xf7;       //扫描第4行
if(P1!=0xff)   //有按键按下
{
  tmp = P1;
  delay(5);
  if(P1!=0xff) //延时后确定有按键按下
  {
   switch(tmp)
   {
    case 0xfe: keynum=25;show(0);break;   //第4行第1个按键按下         
    case 0xfd: keynum=26;show(1);break;   //第4行第2个按键按下     
    case 0xfb: keynum=27;show(2);break;   //第4行第3个按键按下
    case 0xf7: keynum=28;show(11);break;   //第4行第4个按键按下
    case 0xef: keynum=29;break;   //第4行第5个按键按下
    }
   while(tmp!=0xff)
   {
    tmp=P1;
   }
  }
}
delay(5);
P3=0xef;       //扫描第5行
if(P1!=0xff)   //有按键按下
{
  tmp = P1;
  delay(5);
  if(P1!=0xff) //延时后确定有按键按下
  {
   switch(tmp)
   {
    case 0xfe: keynum=33;break;   //第5行第1个按键按下         
    case 0xfd: keynum=34;break;   //第5行第2个按键按下     
    case 0xfb: keynum=35;break;   //第5行第3个按键按下
    case 0xf7: keynum=36;show(12);break;   //第5行第4个按键按下
    case 0xef: keynum=37;clean();break;   //第5行第5个按键按下

   }
   while(tmp!=0xff)
   {
    tmp=P2;
   }
  }
}
delay(5);
}
}
void Write_com(uchar com)
{  
// while(BusyTest()==1);
RS=0;                  //根据规定,RS和R/W同时为低电平时,可以写入指令
RW=0;  
E=0;                   //E置低电平(写指令时,E为高脉冲) 就是让E从0到1发生正跳变,所以应先置"0"
P0=com;            //将数据送入P0口,即写入指令或地址        
//check();
delay(1);
  E=1;                   //E置高电平
  _nop_();
  _nop_();
  _nop_();
  _nop_();               //空操作四个机器周期,给硬件反应时间
   E=0;                  //当E由高电平跳变成低电平时,液晶模块开始执行命令
}
//*********************写数据
void WriteData(uchar dat)
{
// while(BusyTest()==1);   
RS=1;   //RS为高电平,RW为低电平时,可以写入数据
RW=0;
E=0;            //(写指令时,E为高脉冲)
                   // 就是让E从0到1发生正跳变,所以应先置"0"
P0=dat;         //将数据送入P0口,即将数据写入液晶模块
//check();
delay(1);
  E=1;          //E置高电平
  _nop_();
  _nop_();
  _nop_();
  _nop_();      //空操作四个机器周期,给硬件反应时间
  E=0;          //当E由高电平跳变成低电平时,液晶模块开始执行命令
}
void Init(void)
{
Write_com(0x30);  //显示模式设置:16×1显示,5×7点阵,8位数据接口
Write_com(0x0f);  //显示模式设置:显示开,无光标
Write_com(0x06);  //显示模式设置:光标右移,
// Write_com(0x01);  //清屏幕指令,将以前的显示内容清除
}
void clean()//屏幕清零子函数。
{
  Write_com(0x01);  //清屏幕指令,将以前的显示内容清除
}
void show(uint sum)
{
   uint a;
   a=sum;
   Init();
   Write_com(0x80);
   WriteData( key_No[a]);
   delay(1);
}
void main()
{
  keyscan();

}
这个程序我用protues仿真了。遇到了两个问题:
1、按过的按键,再按就没有显示。
2、只能显示1个数字。
这个程序离我的要求还有点远啊!求大神指点!







友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。