现在的位置: 首页 > 综合 > 正文

一个单片机的简易计算器

2013年10月09日 ⁄ 综合 ⁄ 共 7677字 ⁄ 字号 评论关闭

 //-----------------------------------------------------------------------------
// 
// 目标器件: C8051F320x
//
// 编译工具: Silicon Laboratories IDE
//
//-----------------------------------------------------------------------------
//程序描述:
//  16 Key + LCD Display
//  可以进行正整数的加、减、乘、整除运算,计算结果显示范围:-9999999~99999999
//-----------------------------------------------------------------------------
// 头文件包含
//-----------------------------------------------------------------------------
#include <c8051F320.h>                
//;************************************************************************
//;*  p1.0 : 1st column (k0,k4,k8,kc)
//;*  p1.1 : 2nd column (k1,k5,k9,kd)
//;*  p1.2 : 3rd column (k2,k6,ka,ke)
//;*  p1.3 : 4th column (k3,k7,kb,kf)
//;*  p1.4 : 1st row (k0,k1,k2,k3)  p1.7-p1.4 connect to 74LS21
//;*  p1.5 : 2nd row (k4,k5,k6,k7)
//;*  p1.6 : 3rd row (k8,k9,ka,kb)
//;*  p1.7 : 4th row (kc,kd,ke,kf)
//:*  p2.6 : =0 a key is pressed   
//;**********************************

//-----------------------------------------------------------------------------
//全局变量定义
//-----------------------------------------------------------------------------

                                 
unsigned char DispData0[8]={'0',' ',' ',' ',' ',' ',' ',' '};//                       
unsigned int x;
unsigned char *lcdpoint0;         //指向 lcddata数组的指针
unsigned char *lcdpoint1;         //指向 lcddata数组的指针
sbit rs = P2^3;
sbit e = P2^5;
sbit aKey = P2^6;
//-----------------------------------------------------------------------------
// 函数定义
//-----------------------------------------------------------------------------
void PORT_Init (void);           //通用I/O口及交叉开关初始化
void SYSCLK_Init (void);         //系统时钟初始化
void LCD_Init(void);             //液晶初始化
void LCD_Instruction(unsigned char comnd);
void LCD_Data(unsigned char data0);
void LCD_Display (void);
void Delay8_33us(unsigned int iM);

void ClearLCD(void);   //清除显示内容
void GetKey(unsigned char chkey);//获得显示字符
void GetResult(void);     // 计算结果
int ii,i=0;
unsigned char columNum;          //列号
unsigned char rowNum;            //行号
unsigned char tt;
unsigned char key;
 
//-----------------------------------------------------------------------------
// 主程序
//-----------------------------------------------------------------------------
void main (void)
 {

    PCA0MD &= ~0x40;                // no Watchdog
    SYSCLK_Init();                  // System Clock=12MHz/8
    PORT_Init();
    LCD_Display();
 while(1)
 {
       P1 = 0x0f;      //检测按键列号
     while(aKey)
    {    //waiting for a key
       }
        columNum = ~P1 & 0x0f;   //获得按键列号
  P1 = 0xf0;      //检测按键行号
  tt = P1;
  rowNum = ~P1>>4;    //获得按键行号
        if (columNum == 4) columNum = 3; //columNum为0100,列号为3
        if (columNum == 8) columNum = 4; //columNum为1000,列号为4
  if (rowNum == 4) rowNum = 3;  //rowNum为0100,行号为3
  if (rowNum == 8) rowNum = 4;  //rowNum为1000,行号为4

  /*根据行列号获得按键字符*/
  if(rowNum==1)
  {
   if(columNum==1)
    key='7';
   else if(columNum==2)
    key='8';
            else if(columNum==3)
    key='9';
   else if(columNum==4)
    key='/';
  }
  if(rowNum==2)
  {
   if(columNum==1)
    key='4';
   else if(columNum==2)
    key='5';
            else if(columNum==3)
    key='6';
   else if(columNum==4)
    key='x';
  }
  if(rowNum==3)
  {
   if(columNum==1)
    key='1';
   else if(columNum==2)
    key='2';
            else if(columNum==3)
    key='3';
   else if(columNum==4)
    key='-';
  }
  if(rowNum==4)
  {
   if(columNum==1)
    key='c';
   else if(columNum==2)
    key='0';
            else if(columNum==3)
    key='=';
   else if(columNum==4)
    key='+';
  }

     
  GetKey(key); //获得显示字符
  
      
        LCD_Display();
        P1 = 0x0f;
        Delay8_33us(5000);
   while(aKey == 0)
   {
  }
 }
}

//-----------------------------------------------------------------------------
//函数名称:      SYSCLK_Init ()
//函数功能:      系统时钟初始化
//入口参数:      无
//出口参数:      无
//全局变量引用:  无
//调用模块:      无
//-----------------------------------------------------------------------------
void SYSCLK_Init (void)
{
   OSCICL = 0x00;   // 基本频率12MHz,修正=0
   OSCICN = 0x80;   // 1:internal oscillator enabled,   2:  12MHz/8
   RSTSRC = 0x04;   // enable missing clock detector,时钟停止将复位
//隐含CLKSEL=0;USBCLK=000: 时钟4倍:6MHz(低速USB), CLKSL=00: 内部震荡器/8=1.5MHz
}//

//-----------------------------------------------------------------------------
//函数名称:      PORT_Init  ()
//函数功能:      通用I/O口及交叉开关初始化
//入口参数:      无
//出口参数:      无
//全局变量引用:  无
//调用模块:      无 
//-----------------------------------------------------------------------------

void PORT_Init (void)
{
    P0MDOUT   = 0xFF;     //P0 als Digital Output
 P1MDOUT   = 0x00;     //P1 als Digital Output
    P0MDIN    = 0xFF;     //P0 als Digital Input
    P1MDIN    = 0xFF;     //P1 als Digital Input
    P2MDIN    = 0xFF;     //P2 als Digital Input
    P2MDOUT   = 0x00;     //P2 as a push-pull mode
    XBR1      = 0x40;     //cross Bar funktioniert
    P1        = 0x0f;
}
//-----------------------------------------------------------------------------
//函数名称:      LCD_Init ()
//函数功能:      LCD初始化
//入口参数:      无
//出口参数:      无
//全局变量引用:  无
//调用模块:      无 
//-----------------------------------------------------------------------------
void LCD_Init(void)
{
   LCD_Instruction(0x38);    //lcd disabled
   LCD_Instruction(0x38);    //lcd disabled
   LCD_Instruction(0x01);    //clear screen
   LCD_Instruction(0x0C);    //open display
}
//-----------------------------------------------------------------------------
//函数名称:      LCD_Instruction ()
//函数功能:      LCD get Instruction
void LCD_Instruction(unsigned char Commnd)
{
    rs = 0;
 e = 1;
    P0 = Commnd;
    for(x=0;x<2000;x++);
 e = 0;
}
//-----------------------------------------------------------------------------
//函数名称:      LCD_Data ()
//函数功能:      LCD get Data
void LCD_Data(unsigned char data0)
{
    rs = 1;
 e = 1;
 P0 = data0;
    for(x=0;x<2000;x++);
    e = 0;
}
//
void Delay8_33us(unsigned int iM)  //8.33us
{
    while(iM>0)
 {
     iM--;
 }
}
//
void LCD_Display(void)
{
 lcdpoint0 = &DispData0[0]; 
    LCD_Init();                     //LCD初始化
    LCD_Instruction(0x80);          //address 0
 for(ii=0;ii<8;ii++)
 {
 
        LCD_Data(*lcdpoint0);
  lcdpoint0++;
 }
  
 
  
 
  
 } 

//---------------------------------------------------------------------------
//函数名称: GetKey(unsigned char)

void GetKey(unsigned char chkey)
{
 if(chkey!='c' )    //是否按下清零键
 {  
  if(chkey!='=')   //是否按下'='
  {
   DispData0[i] =chkey;  //显示按键数字和运算符
         i++;
  }
  else
  {
   
   GetResult();  //进行计算
  }
      
 }
 else
 {
  ClearLCD();    //清除显示
 }
}

//--------------------------------------------------------------------------
//函数名称: ClearLCD()
//函数功能: 清除显示

void ClearLCD(void)
{
  for(ii=0;ii<8;ii++)
  {
   DispData0[ii]=' ';   //清空显示数组
  }
  DispData0[0]='0';
  i=0;
}
//--------------------------------------------------------------------------
//函数名称: GetResult()
//函数功能: 计算
void GetResult(void)
{
   int  num1=0;   //第一个操作数
   int  num2=0;   //第二个操作数
   long  result;   //计算结果
   long  bufresult;  //计算结果缓存
   char oper;   //运算符
   char isOperator=0; //运算符按下标志,0表示没有按下运算符
   unsigned char count; //计算结果位数
   unsigned char buffer; //字符缓存

   for(ii=0;ii<8;ii++)
   {
  if(DispData0[ii]>='0'&&DispData0[ii]<='9')
  {
   if(isOperator==0)
   {
    num1=num1*10+(DispData0[ii]-0x30);  // 计算第一个操作数
   }
   else
   {
    num2=num2*10+(DispData0[ii]-0x30);  //计算第二个操作数
   }
  }
  else if(DispData0[ii]=='+'||DispData0[ii]=='-'||DispData0[ii]=='x'||DispData0[ii]=='/')  //取运算符
  {
   oper=DispData0[ii];       
   isOperator=1;
  }
   }
 
   ClearLCD();  //清除显示
  switch(oper)  //判断运算类型
  {
  case '+':
   {
     result=num1+num2;break;
   }
  case '-':
   {
     result=num1-num2;break;
   }
  case 'x':
   {
     result=num1*num2;break;
    
   }
  case '/':
   {
     result=num1/num2;break;
   }
 }
 
  bufresult=result;
  for(ii=0;ii<8;ii++) //计算结果的位数
  {
  bufresult=bufresult/10;
  if(bufresult==0)
  {
   count=ii+1;
   break;
  }
  }
 
  if(result<0)
    bufresult=-result;
   else
    bufresult=result;

   for(ii=0;ii<count;ii++)  //取结果的每一位放入显示数组
   {
  DispData0[ii]=bufresult%10+0x30;
  bufresult=bufresult/10;
  
   }
   if(result<0)
   {
    DispData0[ii]='-';  //如果是负数,添加'-'
    count+=1;
   }

   for(ii=0;ii<count/2;ii++)  //按显示顺序排列
   {
  buffer=DispData0[ii];
  DispData0[ii]=DispData0[count-ii-1];
  DispData0[count-ii-1]=buffer;
   }
}

 

主要缺点:

1、只能计算和显示整数

2、可以计算的数字位数和显示结果位数有限,最大8个字符,但可以通过修改DispData0[]长度调节,比较容易

抱歉!评论已关闭.