分享

怎样用51单片机做计算器啊?

 lixinhecom 2017-08-03

原理图

51单片机简易计算器程序:

#include <reg51.h>

#include <math.h>

#define uchar() unsigned char()

#define uint unsigned int

//---------定义引脚--------------------

bit clr=0;

bit ok=0;

bit xiaoshu=0;

bit jiego=0;

bit first_1=1;

bit first_2=1;

sbit dout = P3^2;

sbit load = P2^0;

sbit din  = P2^1;

sbit dclk = P2^2;

sbit beer=P0^1;

sbit LCD1602_RS=P2^3;

sbit LCD1602_RW=P2^4;

sbit LCD1602_E=P2^5;

//---------定义变量--------------------

uchar() ch451_key=0xff;

uchar yun_sign;

uchar xiabiao=0;

uchar tab[32];

uchar tab1[]={"welcome to use!"};

uchar tab2[]={" make by JunRu!"};

uchar tab3[]={"ERR0R"};

float opr_1=0,opr_temp=0,end=0,a;

//---------声明函数--------------------

void ch451_init(void);     //CH451初始化

void ch451_write(uint  command);//写命令或数据到ch451

uchar ch451_read()(void);        //读按键值

uchar get_char(void);

void LCD_init(void);//初始化;

void delay(unsigned int k);//延时程序

void LCD_inter_command(unsigned char command);//写入控制字

void LCD_inter_dat(unsigned char dat);//写入要显示的数据

void set_xy(unsigned char x,unsigned char y);//找地址

void write(unsigned char date);//写入字符

void lcdbusy();//查忙时

void display()(void);

void spec(void);

void get_end(void);

void hun_he(uchar n);

//-------- 主函数----------------------

void main()

{

 uchar i;

 LCD_init();//LCD初始化;

 ch451_init();//CH451初始化

 EA = 1;//打开中断

 LCD_inter_command(0x01);//清屏

  for(i=0;i<=14;i++)

   {

    LCD_inter_dat(tab1[i]);

    beer=0;

    delay(4000);//延时

    beer=1;

 }

LCD_inter_command(0xc0);//从第二行开始显示

for(i=0;i<=14;i++)

    {

     LCD_inter_dat(tab2[i]);

     beer=0;

     delay(4000);//延时

     beer=1;

  }

 delay(0xffff);

 delay(0xffff);

LCD_inter_command(0x01);

 while(1)

  {

  if(ok)

  {

  display()();

  ok=0;clr=1;

  }

  }

}

//----------子函数--------------------

void hun_he(uchar n)

{int j;

      switch(n)

             {

     case '+':opr_temp=opr_temp+opr_1;break;

              case '-':opr_temp=opr_temp-opr_1;break;

              case '*':opr_temp=opr_temp*opr_1;break;

           case '/':

     {

             if(a==0)//减数为零显错

       { LCD_inter_command(0xc0);

               for(j=0;j<=4;j++)

                     { 

                      LCD_inter_dat(tab3[j]);

       beer=0;

                      delay(4000);//延时

                      beer=1;

      }

       }

       else

       {opr_temp=opr_temp/opr_1;}

       break;

        }

         default:break;}

}

void ch451_init(void)//CH451初始化

{

  EX0 = 1;

  din = 0;

  din = 1;

  ch451_write(0x403);   //开显示

  ch451_write(0x580);   //BCD译码方式

}

void ch451_write(uint  command)//写命令或数据到ch451

{  uchar i;

   EX0 = 0;

   load = 0;

   for(i=0;i<12;i++)

   {

    din = command&1;

    dclk = 0;

 command>>=1;

 dclk = 1;

   }

   load = 1;

   EX0 = 1;

}

uchar ch451_read()(void)//读按键值

{ uchar key=0x07;

  uchar i;

  EX0=0;

  load = 0;

  for(i=0;i<4;i++)        //将0111读入

  {

   din = key &1;

   dclk = 0;

   key>>=1;

   dclk =1;

  }

  load = 1;

  key = 0;

  for(i=0;i<7;i++)         //从CH451读出按键值

  {

    key<<=1;

 key|= dout;

 dclk =0;

 dclk =1;

  }

  EX0 =1;

  return key;

}

void EX0_ISR(void)interrupt 0 //中断程序

{

   uchar temp;

  ch451_key=ch451_read()(); //将读出的按键值赋给变量

  spec();

  if(clr) {LCD_inter_command(0x01);clr=0;}

  temp=get_char();    

  if(temp){tab[xiabiao++]=temp; LCD_inter_dat(temp);}

  if(xiabiao>=16)LCD_inter_command(0xc0);//若大于16,则从第2行开始显示          

  if(ok) get_end();

   beer=0;

   delay(3000);

   beer=1;

}

uchar get_char(void)

{

   uchar dis=0;

   uint temp=0,temp1=0;

  switch(ch451_key)

   {

    case 0x40:dis='1';break;

    case 0x41:dis='2';break;

    case 0x42:dis='3';break;

    case 0x48:dis='4';break;

    case 0x49:dis='5';break;

    case 0x4A:dis='6';break;

    case 0x50:dis='7';break;

    case 0x51:dis='8';break;

    case 0x52:dis='9';break;

    case 0x58:dis='0';break;

    case 0x43:dis='+';break;

    case 0x4B:dis='-';break;

    case 0x53:dis='x';break;

    case 0x5B:dis='/';break;

    case 0x44:dis='!';break;

    case 0x5A:dis='=';

       ok=1;                      //遇到“=”,开始运算

       break;

     case 0x59:dis='.';break;     //小数点

     case 0x5C:                    //删除键

      LCD_inter_command(0x01);

       xiabiao=0;

     break;

    default: break;

    }

    return dis;

}

void spec(void)                   //特殊功能键

{

  switch(ch451_key)

  {

  case 0x4C:LCD_inter_command(0x10);{if(xiabiao>0)xiabiao-=1;}break; //左移

  case 0x54:LCD_inter_command(0x14);{xiabiao+=1;}break;  //右移

  default:break;

  }

}

void delay(unsigned int k)//延时程序

{

while (k--);

}

void LCD_inter_command(unsigned char command)//写入控制字

{

delay(5000);

LCD1602_RS=0;

LCD1602_RW=0;

LCD1602_E=1;

P1=command;

LCD1602_E=0;

lcdbusy();

}

void LCD_init(void)//初始化;

{delay(5000);

LCD_inter_command(0x01);//清屏

delay(5000);

LCD_inter_command(0x38);//设置为8位的数据接口,两行显示,5、7点字符

delay(5000);

LCD_inter_command(0x0E);//显示打开,光标开并闪烁

delay(5000);

}

void LCD_inter_dat(unsigned char dat)//写入要显示的数据

{

delay(5000);

LCD1602_RS=1;

LCD1602_RW=0;

LCD1602_E=1;

P1=dat;

LCD1602_E=0;

lcdbusy();

}

void lcdbusy()//查忙

{

P1=0xFF;

LCD1602_RS=0;

LCD1602_RW=1;

LCD1602_E=1;

while((P1&0x80)==1);

}

void display()(void)            //转化在LCD上显示计算结果

{

  int temp=end;  //浮点数

  int i;

  uint xiao_temp;

  uint xx; //浮点数的整数部分

  if (end>-32769&&end<32768)

         {

  xx=fabs(end);

  xiao_temp=(fabs(end)-xx)*1000;//取出浮点数的小数部分

  LCD_inter_command(0xc0);

  if(end<0) LCD_inter_dat('-');beer=0;delay(4000); beer=1;//判断是否为负数,若是则显示负号

  if(xx>9999) LCD_inter_dat((xx/10000)%10+'0'); beer=0;delay(4000);beer=1;

  if(xx>999) LCD_inter_dat((xx/1000)%10+'0');beer=0;delay(4000);beer=1; //在LCD上显示千位的数

  if(xx>99)LCD_inter_dat((xx/100)%10+'0');  beer=0;delay(4000);beer=1;//百位

  if(xx>9)LCD_inter_dat((xx/10)%10+'0');beer=0;delay(4000); beer=1;//十位

  LCD_inter_dat(xx%10+'0');beer=0;delay(4000); beer=1;//个位

  if(xiao_temp!=0)  //显示小数部分

   {

  LCD_inter_dat('.');beer=0;delay(4000);beer=1;

  LCD_inter_dat((xiao_temp/100)%10+'0');beer=0;delay(4000);beer=1;

  LCD_inter_dat((xiao_temp/10)%10+'0');beer=0;delay(4000);beer=1;

  LCD_inter_dat(xiao_temp%10+'0');beer=0;delay(4000);beer=1;

   }

         }

    else {LCD_inter_command(0xc0);//从第二行开始显示

           for(i=0;i<=4;i++)

            {   LCD_inter_dat(tab3[i]);

                beer=0;

                delay(4000);//延时

                 beer=1;

         }

  }

}

void get_end(void)//计算子程序

{ float xiaoshu=1;

  uchar fu_flag=0;

  uchar xiao_flag=0;

  uchar lianji_sign;

 uchar i=0;

 uchar j;

 uchar n;//正负标记符

 while(i<=xiabiao)

 {

 while(tab[i]<=0x39&&tab[i]>=0x30)

  {  

   n=0;

    opr_1*=10;

    opr_1+=tab[i++]-0x30;

    n='+';

 }

  switch(tab[i])

  {

   case '.':  xiao_flag=1;break;//遇到小数点跳到“if(xiao_flag)”里

   case '!':  fu_flag=1;break;

   case '+':  xiaoshu=1;yun_sign='+';if(opr_temp==0){end=opr_temp=opr_1;}else hun_he(lianji_sign);opr_1=0;lianji_sign='+'; break;    

   case '-':  xiaoshu=1;yun_sign='-';if(opr_temp==0){end=opr_temp=opr_1;}else hun_he(lianji_sign);opr_1=0;lianji_sign='-'; break;

   case 'x':  xiaoshu=1;yun_sign='x';if(opr_temp==0){end=opr_temp=opr_1;}else hun_he(lianji_sign);opr_1=0;lianji_sign='*';break;      

   case '/':  xiaoshu=1;yun_sign='/';if(opr_temp==0){end=opr_temp=opr_1;}else hun_he(lianji_sign);a=opr_1;opr_1=0;lianji_sign='/';break;

   case '=':

   switch(yun_sign)//进行运算

       {

        case '+':end=opr_temp+opr_1;break;

        case '-':end=opr_temp-opr_1;break;

        case 'x':end=opr_temp*opr_1;break;

  case '/':{

             if(a==0)//减数为零显错

       { LCD_inter_command(0xc0);

               for(j=0;j<=4;j++)

                     { 

                      LCD_inter_dat(tab3[j]);

       beer=0;

                      delay(4000);//延时

                      beer=1;

      }

       }

       else

       {end=opr_temp/opr_1;}

       break;

       }

        default:break;

        }

        ok=1;//开始进行显示,标志位置1

        xiabiao=0;//小数的标志位清零

   break;

   default:break;

  }

  i++;

  if(xiao_flag)//表示小数

   {

    while(tab[i]<=0x39&&tab[i]>=0x30)

     {

        xiaoshu*=0.1;

  switch(n)

  {

          case '+': opr_1=opr_1+(tab[i++]-0x30)*xiaoshu;break;

          case '-':  opr_1=opr_1-(tab[i++]-0x30)*xiaoshu; break ;

     default:break; }

    xiao_flag=0;  

     }

   }

  

if(fu_flag)

{

while(tab[i]<=0x39&&tab[i]>=0x30)

     { 

    n=0;

     opr_1=-opr_1*10;

     opr_1=-(opr_1+(tab[i++]-0x30));

   n='-';

  fu_flag=0;

}

}

}

    opr_1=0;

    opr_temp=0;

    xiabiao=0;

    xiaoshu=1;

下方为原理图:

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约