初学者写了一天都写不出来,12864lcd显示计算器,实现四则运算

2019-07-15 17:50发布

/*        12864液晶计算器

               只能实现一位的加减乘除运算,按键返回值,多位数的赋值方法,将多位数显示在液晶上
难疑点:   scanf输入,sprintf输出函数的格式和用途,ASCII码干什么用
                  将多位十进制数输入液晶,负数和分母为0的数的处理         

                                                                                                                                                                                                                                          

                                                                                                 */                                                                                                                                                       
#include<reg52.h>
#include<intrins.h>
#include<stdlib.h>
#define uchar unsigned char
#define uint unsigned int
#define KeyPort P3
#define LCD_data P0        //数据口
sbit LCD_RS=P1^2;              //寄存器选择输入
sbit LCD_RW=P1^1;             //液晶读写控制
sbit LCD_EN=P1^0;            //液晶使能控制
sbit LCD_PSB=P1^3;           //串并方式控制
sbit beep=P2^0;

void delayms(uint x);        //延时函数
uchar KeyPro(void);
uchar KeyScan(void);  //键盘扫描函数,使用行列反转扫描法
void lcd_pos(uchar X,uchar Y);  //*液晶地址设置函数         
void write_date(uchar date);           //向液晶写数据函数
void write_cmd(uchar cmd);         //向液晶写指令函数*  
void lcd_init();         // 液晶初始化函数   
void di()
{
  
  beep=1;
  delayms(20);
  beep=0;
}
/**************************/

void main()
{
lcd_init();         //液晶初始化
while(1)
{
   uint one,two,shu;
   uchar num,flag,fu;
//   uchar temp1[4];        
//   uchar temp2[4];
   num=KeyPro();  //扫描键盘
   if(num!=0xff) //如果扫描是按键有效值则进行处理
   {
     delayms(10);                 //延时10Us

  if(('+'==num)|| ('-'==num) || ('x'==num)|| ('/'==num) || ('='==num))//输入数字最大值8,输入符号表示输入结束
          {
          
       if(num!='=')           //判断当前符号位并做相应处理
             {      
                      flag=1;
                      fu=num;           //如果不是等号记下标志位
                          delayms(20);
                          //显示第2行内容
                  lcd_pos(1,7);             //位置函数
                  write_date(fu);
                 }  
                 
                  
           else
             {  
                  flag=2;   //检测到输入=号,判断上次读入的符合
         switch(fu)
               {
                    case '+':shu=one+two;
                        break;
                        case '-':shu=one-two;
                        break;
                        case 'x':shu=one*two;
                        break;
                        case '/':shu=one/two;
                        break;
                        default:break;
                   }
                  ////显示第4行内容
            lcd_pos(3,1);             //位置函数
            write_date(shu+48);  //
            }
          }


  else
          {       
          
            if(flag==0)  //如果是输入的第一个数据,赋值给a,并把标志位置1,到下一个数据输入时可以跳转赋值给b
             {                 //temp1[i]           i++;   //输入数值累加
                       
                       one=num;
                         lcd_pos(0,1);             //位置函数           s++;
                 write_date(one+48);
                       
//                          one=temp1[3]*1000+temp1[2]*100+temp1[1]*10+temp1[0];
//                  scanf(temp,"%d",&one);//从一个字符串输入到变量
//                          for(s=0;s<8;s++) //赋值完成后把缓冲区清零,防止下次输入影响结果
//                        temp1[s]=0xff;
                 }

                else
                  {
                    two=num;         //temp2[i] i++;
                        lcd_pos(2,1);             //位置函数        temp2[s] s++;
                write_date(two+48);
                         
//                        two=temp2[3]*1000+temp2[2]*100+temp2[1]*10+temp2[0];
//                        scanf(temp,"%d",&two);
//                         for(s=0;s<8;s++) //赋值完成后把缓冲区清零,防止下次输入影响结果
//                        temp2[s]=0xff;                  
              }
     }
}   
}  
}

void delayms(uint x)        //延时函数
    {
          uint i,j;
          for(i=x;i>0;i--)
          for(j=110;j>0;j--);
    }
   

/*------------------------------------------------
按键扫描函数,返回扫描键值
------------------------------------------------*/
unsigned char KeyScan(void)  //键盘扫描函数,使用行列反转扫描法
{
unsigned char cord_h,cord_l;//行列值中间变量
KeyPort=0x0f;            //行线输出全为0
cord_h=KeyPort&0x0f;     //读入列线值
if(cord_h!=0x0f)    //先检测有无按键按下
{
   delayms(20);       //去抖
  if((KeyPort&0x0f)!=0x0f)
  {
        di();
    cord_h=KeyPort&0x0f;  //读入列线值
    KeyPort=cord_h|0xf0;  //输出当前列线值
    cord_l=KeyPort&0xf0;  //读入行线值

    while((KeyPort&0xf0)!=0xf0);//等待松开并输出

    return(cord_h+cord_l);//键盘最后组合码值
   }
  }return(0xff);     //返回该值
}
/*------------------------------------------------
          按键值处理函数,返回扫键值
  P         可以根据需要改变返回值
       
                  7        -| 1 | 2 | 3 | + |  
                  6        -| 4 | 5 | 6 | -  |  
                  5        -| 7 | 8 | 9 | *  |  
                  4        -| 0 | . | = | /  |
                3   ----------------  -|
                2--------————|
                1-          -—|       
                0        -  |       

------------------------------------------------*/
unsigned char KeyPro(void)
{
switch(KeyScan())
{
  case 0x7e:return 1  ;break;//0 按下相应的键显示相对应的码值
  case 0x7d:return 2  ;break;//1
  case 0x7b:return 3  ;break;//2
  case 0x77:return '+';break;//3

  case 0xbe:return 4  ;break;//4
  case 0xbd:return 5  ;break;//5
  case 0xbb:return 6  ;break;//6
  case 0xb7:return '-';break;//7

  case 0xde:return 7  ;break;//8
  case 0xdd:return 8  ;break;//9
  case 0xdb:return 9  ;break;//a
  case 0xd7:return 'x';break;//b

  case 0xee:return 0  ;break;//c
  case 0xed:return '.';break;//d
  case 0xeb:return '=';break;//e
  case 0xe7:return '/';break;//f
  default:return 0xff;break;
}
}
/****************向液晶写指令函数*****************/  
void write_cmd(uchar cmd)          
  {
         //RS=L,  RW=L,  E=高脉冲,  D0~D7=指令码
     LCD_RS=0;                                  
     LCD_RW=0;
     LCD_EN=0;       
     P0=cmd;
     delayms(5);       
     LCD_EN=1;
     delayms(5);
     LCD_EN=0;
    }

/***********向液晶写数据函数*************/
  void write_date(uchar date)         
   {
    LCD_RS=1;
        LCD_RW=0;
        LCD_EN=0;
           P0=date;
        delayms(5);
        LCD_EN=1;  
        delayms(5);
        LCD_EN=0;
   
   }
/*****************液晶地址设置函数***************/
  void lcd_pos(uchar X,uchar Y)           
        {
        uchar pos;
        if(X==0)
        {X=0x80;}
        else if(X==1)
        {X=0x90;}
        else if(X==2)
        {X=0x88;}
        else if(X==3)
        {X=0x98;}
        pos=X+Y;        //0x80+1=0x81
        write_cmd(pos);
}
/***************液晶初始化函数******************/                          
void lcd_init()             
{       
        LCD_PSB=1;
        write_cmd(0x30);                  //基本指令
        delayms(5);
        write_cmd(0x0c);                //光标设置,不显示光标
        delayms(5);
        write_cmd(0x01);                 //液晶清屏
        delayms(5);

}


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