专注电子技术学习与研究
当前位置:单片机教程网 >> MCU设计实例 >> 浏览文章

基于HD7279和51单片机的计算器

作者:丁弘偎   来源:51hei   点击数:  更新时间:2010年08月18日   【字体:

   HD7279是一款用于扩展单片机I/O口的芯片,至少我是这么认为的,虽然它占用了单片机4个I/O但是真正作为传输的仅仅是一根总线,它可以同时驱动8位共阴数码管(或者8×8点阵),及8×8的矩阵键盘,而同时接在单片机上的话,至少需要3~4组I/O,当然单总线控制的芯片基本需要自己的指令和时序。

  接到这个课程设计之前我自己懒懒散散地看了一段时间的C51(用C语言编写单片机代码),之前老师教的是A51(用汇编编写单片机代码),我玩了很久,但是发现A51真的很局限,汇编这种语言是写给机器看的,真正地写0和写1,真正是一个寄存器一个寄存器的调用,对于8位的51单片机来说,要实现1000×1000或者小数是比较困难的。老师推荐用C,之前只是看书实现过一些小东西这回要做比较大的项目了,虽然还有其他课题比如温度计和数字钟,不过都做过,只是环境不一样,修改一下代码太没有挑战性了。

  确实开始轻敌了,真正做的时候发现不是那么简单,

   高中的时候学过一点VB做过计算器,如果让我现在做,也许给我几天我可以做出来,用C我也没什么问题,但是C51就有难度了,要考虑太多硬件的东西,特别是显示这个模块好不容易瘦下去的头又两个大了。等我真正意识到的时候,已经过去几个礼拜了,呵呵,要和朋友说抱歉了,虽然我答应“等我做完计算器之后再帮你改下程序”但是没一个实现。

    当然,此程序因为基本全是自己写的,被方晋甬老师称之为“程序设计不成熟、比较乱”的,额,本来准备用switch语句,但是吕昂老师说switch语句会产生过多闲置寄存器(可是他没有考虑到我仅仅是实现很少的功能),这段程序只实现+-×÷,符号闪烁,过八位报错等功能但是没有小数,只能计算一步(加少数程序即可计算多部)。其实程序挺早就写出来了,只是一直出不来效果,后来在仿真和VC++编译环境下修改了很多,理论上是可以实现了,可是还是没有显示,于是抓狂了“看来我已处在瓶颈...”,晃了最后一个礼拜,周日周一看了两天晚上,依然没有看出什么来,礼拜二去方晋甬老师办公室请教,查了近3个钟头【基本看过了我所有奇形怪状的子程序—。—||||】,在仿真多遍之后发现就少了一句“while(!key)【检测释放按键】”【程序中红字部分即主程序最后一句】囧啊~~~~以至于周四答辩的时候我演示之后,刚点看ppt他就说直接给A,不用答了。。。。
程序的完整版下载地址:http://www.51hei.com/ziliao/file/jsjq.rar 

/////////////////////////////****************程序*****************///////////////////////
 

#include<reg51.h>
#include<math.h>
sbit  cs=P2^6;
sbit clk=P1^0;
sbit dat=P1^1; 
sbit key=P3^3; 
bit  add,sub,mul,div,equ,clr;
unsigned char times,st,l,data_jp,flag,d;


unsigned int  tmr;
unsigned long    num[8],sn[8],disp[8],sh,result,hp=100000000;

void send(unsigned char);
unsigned char receive(void);
unsigned long real(unsigned long ,unsigned char);
unsigned long calcu(unsigned   long, unsigned long);
void display(unsigned long);
unsigned long write_key(unsigned   char);

void char_flk(void);
void test(void);
void error(void);
void long_delay(void);
void short_delay(void);
void delay10ms(unsigned char);  

/////////**************主函数****************//////////

void main ()
{
   times=0;
   l=times;
   st=0;
   flag=0;
   test();

   while(1)
   {
     unsigned char i;
     if(!key)
     {   
       send(0x15);
       data_jp=receive();
       cs=1;
       d=write_key(data_jp);
       if (data_jp<=9)
       {
         flag=0;
         num[times]=d;
       }
       else
       {
         flag=1;
         //times-=1;
       }
       if(flag!=1)
       { 

       
           if(num[0]==0)
           {
             times=0;
             continue;
           }
           if(7>times>=1)
           {
             send(0xa1);
         }

            send(0x80);
            send(num[times]);
            while(!key); 
             delay10ms(1);
            times=times+1;
            cs=1;

          if(times>7)
          {
            send(0xa4);
            error() ;
           times=0;
           send(0xa4); 
          }
       }
       else
       {
           send(0xa4);
           char_flk();
           
           
           times-=1;
           l=times;
           for(i=0;i<=times;i++)    
           {
           
             num[i]=real(num[i],l);
             sh=sh+num[i];
               l--;           
           }
          
           sn[st]=sh;
         
           if(st>=1)
           {
             result=calcu(sn[st],sn[st-1]);
             sn[st-1]=result;
             st--;           
           }
           st++;
           times=0;
           flag=0;
           sh=0;

          
         if(equ==1)
         {  
           st=0;           
           send(0xa4);
           display(result);
           equ=0;
         }
         if(clr==1)
         {
           st=0;
           times=0;
           flag=0;
           sh=0;
           add=0;
           sub=0;
           mul=0;
           div=0;
           equ=0;
           clr=0;
           send(0xa4);
         }
         while(!key);
        
         }
       }

     
    }
}
/////////*********************测试子函数****************////////
void test(void)
{   
    
    char i;
       delay10ms(2);
  
    send(0xbf);
    cs=1; 
    for (i=0;i<=3;i++)    
      {
      delay10ms(100);
    }
    send(0xa4);
    cs=1;
      delay10ms(20);

}
///////***********************读键盘程序**************///////
unsigned long write_key(unsigned char data_jp)
{
  unsigned char shuzi;

  if(data_jp<10)
  {
 
      shuzi=data_jp;
  }
  else
  {
     if(data_jp==10)
     {

        add=1;
     }
     else  if(data_jp==11)
     {
      sub=1;
     }
     else if(data_jp==12)
     {

      mul=1;
     }
     else if(data_jp==13)
     {

      div=1;
     }
     else if(data_jp==14)
     {

      equ=1;
     }
     else if(data_jp==15)
     {
      clr=1;
     }
     shuzi=0xff;
  }
    return(shuzi) ;
}

///////***********************发送子函数*************//////
void send(unsigned char data_out) 
{
   unsigned char i;
   cs=0;
   long_delay();
   for(i=0;i<=7;i++)
   {

    if(data_out&0x80)
    {
        dat=1;
    }
    else
    {
      dat=0;
    }
    clk=1;
    short_delay();
    clk=0;
    short_delay();
    data_out=data_out<<1;

   }
   
    dat=0;
}

/////************************接收键盘子函数************//////
unsigned char receive(void)
{
   unsigned char i,data_in;
   dat=1;
   long_delay();
   for(i=0;i<=7;i++)
   {
     clk=1;
   short_delay();
   data_in=data_in<<1;
   if(dat)
   {
    data_in=data_in|0x01;
   }
   else
   {
      data_in=data_in|0x00;
   }
   clk=0;
   short_delay();

   }
   dat=0;
   return(data_in);
}
/////////***************************显示数字处理子函数***********/////////
unsigned long real(unsigned long so, unsigned char s)
{
  unsigned char z;
     if(s!=0)
  {
    for(z=0;z<=(s-1);z++)
    {
         if(s!=0)
     {
       so=so*10;
     }
     else
     {
       so=so;
     }
     
    }
   }
   else
   {
      so=so;
   }
  return(so);
}

//////////*************************计算子函数*******************///////////
unsigned long calcu(unsigned   long    sn0,unsigned   long   sn1  ) 
{
  if(add==1)
  {
    sn0=sn0+sn1;
    add=0;
  }
  if(sub==1)
  {
    sn0=sn1-sn0;
    sub=0;
  }
  if(mul==1)
  {
     sn0=sn0*sn1;
    mul=0;
  }
  if(div==1)
  {
    if(sn0>0)
      sn0=sn1/sn0;
    else 
      error();
    div=0;
  }
  return(sn0);

}


////////****************************报错错误子函数***************/////////
void error(void)
{
 while(key)
 {
      send(0x96);
     send(0x4f);
     delay10ms(2);
     send(0x95);
     send(0x05);
     delay10ms(2);
     send(0x94);
     send(0x05);
     delay10ms(2);
     send(0x93);
     send(0x1d);
     delay10ms(2);
     send(0x92);
     send(0x05);
     delay10ms(2);    
 }
}
///////////********************显示子函数*********////////////
void display(unsigned long display)
{
 unsigned char i,asus=8;
 if(display>99999999)
  error();  
 else
 {  
   for(i=0;i<=7;i++)
   {
      if((display/hp)>=1)
         break;
      else
      {
         hp=hp/10;
         asus-=1;
      }
   }
   for(i=0;i<=asus;i++)
   {
         
         disp[i]=display/hp;
         if(hp>1)
         {
            display=display%hp;
            hp=hp/10;
           }
    }
    for(i=0;i<=asus;i++)
    {
       if(i>0)
      { send(0xa1); }
      send(0x80);
      send(disp[i]);
      
    }
 }
}

///////////********************符号判断闪烁显示*********////////////
void char_flk(void)
{
        if(add==1)
       {
         send(0x97);
         send(0x77);
       }
       else if(sub==1)
       {
         send(0x97);
         send(0x01);
       }
       else if(mul==1)
       {
         send(0x97);
         send(0x37);
       }
       else if(div==1)
       {
         send(0x97);
         send(0x49);
       }
       else if(clr)
       {
           ;
       }
       send(0x88);
       send(0x7f);
}
//////************************延时子函数*************///////

void long_delay(void)
{
 char i;
 for(i=0;i<=25;i++) ;
}

void short_delay(void)
{
 char j;
 for(j=0;j<=4;j++);

}


void delay10ms(unsigned char time)
{
 unsigned char i;
 unsigned int j;
 for (i=0;i<=time;i++)
 {
  for(j=0;j<=0x390;j++);

 }
}

///////////////////////////************效果图*************////////////////////

以上演示的为9876543÷234,其本来的结果是42207.4487179……无法显示小数位,所以结果为42207 。

关闭窗口

相关文章