專注電子技術(shù)學(xué)習(xí)與研究
當(dāng)前位置:單片機(jī)教程網(wǎng) >> MCU設(shè)計(jì)實(shí)例 >> 瀏覽文章

基于51單片機(jī)的簡易計(jì)算器1602顯示

作者:我行天下   來源:本站原創(chuàng)   點(diǎn)擊數(shù):  更新時(shí)間:2014年03月30日   【字體:

/*注:4 X4 矩陣接P3口*/
#include<reg52.h>
#include<stdio.h>
#include<intrins.h>
#define uchar  unsigned char 
#define uint  unsigned int
#define CHECK_BUSY
sbit RS = P2^4;
sbit RW = P2^5;
sbit EN = P2^6;
void DelayMs(int z)
{
 int x,y;
 for (x=z;x>0;x--)
   for(y=110;y>0;y--);
}
/***********判忙函數(shù)***********/
 bit LCD_Check_Busy()
 {
#ifdef CHECK_BUSY
 P0= 0xFF;
 RS=0;
 RW=1;
 EN=0;
 _nop_();
 EN=1;
 return (bit)(P0 & 0x80);
#else
 return 0;
#endif
 }
/***********寫入命令函數(shù)***********/
 void write_com(uchar com)
 {
while(LCD_Check_Busy()); //忙則等待
 RS=0;
 RW=0;
 EN=1;
 P0= com;
 _nop_();
 EN=0;
 }
/**********寫入數(shù)據(jù)函數(shù)**********/
 void write_dat(uchar dat)
 {
 while(LCD_Check_Busy()); //忙則等待
 RS=1;
 RW=0;
 EN=1;
 P0= dat;
 _nop_();
 EN=0;
 }
/*******寫入字符函數(shù)***********/
void LCD_Write_Char(uchar x,uchar y,uchar dat)
 {   
 if (y == 0)
  {   
  write_com(0x80 + x);   
  }  
 else
  {   
  write_com(0xC0 + x);   
  }      
 write_dat( dat);
 }
/******寫入字符串函數(shù)***********/
 void Write_String(uchar x,uchar y,uchar *s)
 {   
     
 while (*s)
  {   
  LCD_Write_Char(x,y,*s);   
  s++;
  x++;   
  }
 }
/*****初始化函數(shù)******/
 void LCD_Init()
 {
   write_com(0x38); /*顯示模式設(shè)置*/
   DelayMs(5);
   write_com(0x06);/*顯示光標(biāo)移動(dòng)設(shè)置*/
   DelayMs(5);
   write_com(0x0C); /*顯示開及光標(biāo)設(shè)置*/
   write_com(0x01);  /*顯示清屏*/
   }
 
/*按鍵掃描函數(shù),返回掃描鍵值*/
uchar KeyScan()  //鍵盤掃描函數(shù),使用行列反轉(zhuǎn)掃描法
{
 unsigned char cord_h,cord_l;//行列值中間變量
 P3=0x0f;            //行線輸出全為0
 cord_h=P3&0x0f;     //讀入列線值
 if(cord_h!=0x0f)    //先檢測有無按鍵按下
 {
  DelayMs(10);        //去抖
  if((P3&0x0f)!=0x0f)
  {
    cord_h=P3&0x0f;  //讀入列線值
    P3=cord_h|0xf0;  //輸出當(dāng)前列線值
    cord_l=P3&0xf0;  //讀入行線值
    while((P3&0xf0)!=0xf0);//等待松開并輸出
    return(cord_h+cord_l);//鍵盤最后組合碼值
   }
  }
  return(0xff);  //返回該值
}

unsigned char KeyPro()
{
 switch(KeyScan())
 {
  case 0x7e:return '1';break;//0 按下相應(yīng)的鍵顯示相對應(yīng)的碼值
  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;
 }
}
main()
{
 unsigned char num,i,sign;                
 unsigned char temp[16];   //最大輸入16個(gè)
 bit firstflag;
 float a=0,b=0;
 unsigned char s;
 LCD_Init(); //初始化液晶屏
 DelayMs(10);//延時(shí)用于穩(wěn)定,可以去掉
 write_com(0x01); //清屏
 Write_String(0,0,"I LIKE MCU");    //寫入第一行信息,主循環(huán)中不再更改此信息,所以在while之前寫入
 Write_String(0,1,"HBKJXY");    //寫入第二行信息,提示輸入密碼
 for(s=0;s<25;s++)//延時(shí)5s
    DelayMs(200);
 write_com(0x01);
while (1)         //主循環(huán)
  {

 num=KeyPro();  //掃描鍵盤
 if(num!=0xff)  //如果掃描是按鍵有效值則進(jìn)行處理
   {
    if(i==0)    //輸入是第一個(gè)字符的時(shí)候需要把改行清空,方便觀看
   write_com(0x01);
 if(('+'==num)|| (i==16) || ('-'==num) || ('x'==num)|| ('/'==num) || ('='==num))//輸入數(shù)字最大值16,輸入符號表示輸入結(jié)束
   {
   i=0;  //計(jì)數(shù)器復(fù)位
  if(firstflag==0)  //如果是輸入的第一個(gè)數(shù)據(jù),賦值給a,并把標(biāo)志位置1,到下一個(gè)數(shù)據(jù)輸入時(shí)可以跳轉(zhuǎn)賦值給b
      {
      sscanf(temp,"%f",&a);
         firstflag=1;
   }
   else
      sscanf(temp,"%f",&b);
   for(s=0;s<16;s++) //賦值完成后把緩沖區(qū)清零,防止下次輸入影響結(jié)果
      temp[s]=0;
      LCD_Write_Char(0,1,num);
   ///////////////////////
   if(num!='=')      //判斷當(dāng)前符號位并做相應(yīng)處理
      sign=num;      //如果不是等號記下標(biāo)志位
   else
      {
   firstflag=0;   //檢測到輸入=號,判斷上次讀入的符合
         switch(sign)
        {
      case '+':a=a+b;
   break;
   case '-':a=a-b;
   break;
   case 'x':a=a*b;
   break;
   case '/':a=a/b;
   break;
   default:break;
     }
   sprintf(temp,"%g",a);    //輸出浮點(diǎn)型,無用的0不輸出
         Write_String(1,1,temp);//顯示到液晶屏
   sign=0;a=b=0;            //用完后所有數(shù)據(jù)清零
   for(s=0;s<16;s++)
      temp[s]=0;
   }
   }
  else if(i<16)
   {
    if((1==i)&& (temp[0]=='0') )//如果第一個(gè)字符是0,判讀第二個(gè)字符
      {
    if(num=='.')  //如果是小數(shù)點(diǎn)則正常輸入,光標(biāo)位置加1
      {
      temp[1]='.';
   LCD_Write_Char(1,0,num);//輸出數(shù)據(jù)
   i++;
            } //這里沒有判斷連續(xù)按小數(shù)點(diǎn),如0.0.0
   else
    {
     temp[0]=num; //如果是1-9數(shù)字,說明0沒有用,則直接替換第一位0
     LCD_Write_Char(0,0,num);//輸出數(shù)據(jù)
     }
   }
    else
      {
         temp[i]=num;
         LCD_Write_Char(i,0,num);//輸出數(shù)據(jù)
      i++;   //輸入數(shù)值累加
   }
    }
 
    }
  }
}

關(guān)閉窗口

相關(guān)文章