基于STC89C52单片机实现简易计算器

今天,我在Keil uVision4中制作了一个小项目,利用STC29C52单片机实现了简易计算器的功能。
此计算器利用矩阵键盘(线扫描法)输入数据,利用八位数码管显示数据。能实现四位整数(及四位以下)与四位整数(及四位以下)的加减乘除运算。
优势是:操作及界面 与日常计算器相同;
具备按键消抖功能;
缺陷是:计算位数有限;
仅支持整数运算;
运算结果最大为65535(受限于int数据类型);

以下为具体程序:
工程组织 及 主程序:
工程组织 及 主程序

矩阵键盘扫描程序:

#include "bsp.h"
#define KEYPORT P1
unsigned char val = 0;
unsigned char mkeyvalue = 99;

void mkey_scan(void)
{
    KEYPORT = 0xf0;
    if(KEYPORT != 0xf0)
    {
        KEYPORT = 0xfe;
        if(KEYPORT != 0xfe)
        {
            val = KEYPORT;
            while(KEYPORT != 0xfe)  seg7_show_CC(); //死等
            //或者delay;
        }

        KEYPORT = 0xfd;
        if(KEYPORT != 0xfd)
        {
            val = KEYPORT;
            while(KEYPORT != 0xfd) seg7_show_CC();
        }

        KEYPORT = 0xfb;
        if(KEYPORT != 0xfb)
        {
            val = KEYPORT;
            while(KEYPORT != 0xfb) seg7_show_CC();
        }

        KEYPORT = 0xf7;
        if(KEYPORT != 0xf7)
        {
            val = KEYPORT;
            while(KEYPORT != 0xf7) seg7_show_CC();
        }
    }
    else
    {
        val = 0xff; //没按键按下时,不进入switch语句;
    }
}

void mkey_pro(void)
{
    if(val != 0xff)
    {

        switch(val)
        {
            case(0x7e): mkeyvalue = 1; break;
            case(0xbe): mkeyvalue = 2; break;
            case(0xde): mkeyvalue = 3; break;
            case(0xee): mkeyvalue = 11; break;

            case(0x7d): mkeyvalue = 4; break;
            case(0xbd): mkeyvalue = 5; break;
            case(0xdd): mkeyvalue = 6; break;
            case(0xed): mkeyvalue = 12; break;

            case(0x7b): mkeyvalue = 7; break;
            case(0xbb): mkeyvalue = 8;  break;
            case(0xdb): mkeyvalue = 9;  break;
            case(0xeb): mkeyvalue = 13; break;

            case(0x77): mkeyvalue = 0; break;
            case(0xb7): mkeyvalue = 16; break;
            case(0xd7): mkeyvalue = 15; break;
            case(0xe7): mkeyvalue = 14; break;

            default: mkeyvalue = 99; break;
        }
    }
}

按键功能程序:

#include "bsp.h"
unsigned char type = 1;
unsigned char distype = 0;
unsigned char num1[4]={0,0,0,0};
unsigned char num2[4]={0};
unsigned char symbol;
unsigned char i = 0;
unsigned char digit1=0, digit2=0;

void key_record(void)
{
    if((mkeyvalue==1||mkeyvalue==2||mkeyvalue==3||
        mkeyvalue==4||mkeyvalue==5||mkeyvalue==6||
        mkeyvalue==7||mkeyvalue==8||mkeyvalue==9||mkeyvalue==0))
    {

        if(type == 1)
        {   
            distype = 1;
            num1[i++] = mkeyvalue;
            digit1++;
        }
        else if(type == 3)
        {
            distype = 3;
            num2[i++] = mkeyvalue;
            digit2++;
        }
        if(i >= 4)
        {
            if(type == 1)
            {
                type = 2;
            }
            else if(type == 3)
            {
                type = 4;
            }       
            i = 0;
        }
        mkeyvalue = 99;
    }

    if((type==1||type==2)&&(mkeyvalue==11||mkeyvalue==12||mkeyvalue==13||mkeyvalue==14))
    {
        symbol = mkeyvalue;
        distype = 2;
        i = 0;
        type = 3;
        mkeyvalue = 99;
    }

    if((type==3||type==4)&&mkeyvalue==15)       //=
    {
        type = 5;
        distype = 5;                  
        result();

        mkeyvalue = 99;     
    //  type = 6;
    }

//  if(type == 6)
//  {
//      while(mkeyvalue == 99);
//      mkeyvalue = 16;
//  }

    if(mkeyvalue == 16)    //清屏
    {
        num1[0] = 0;
        num1[1] = 0;
        num1[2] = 0;
        num1[3] = 0;
        symbol = 0;
        num2[0] = 0;
        num2[1] = 0;
        num2[2] = 0;
        num2[3] = 0;
        showvalue[0] = 0;
        showvalue[1] = 0;
        showvalue[2] = 0;
        showvalue[3] = 0;
        showvalue[4] = 0;
        showvalue[5] = 0;
        showvalue[6] = 0;
        showvalue[7] = 0;
        i = 0;

        distype = 0;

        digit1 = 0;
        digit2 = 0;
        type = 1; 
        mkeyvalue = 99;
    }
}

运算程序:

#include "bsp.h"

unsigned int cal_result = 0;
unsigned int cal_num1 = 0;
unsigned int cal_num2 = 0;

void result(void)
{
    switch(symbol)
    {
        case(11): cal_result = cal_num1 + cal_num2; result_digit_compute();break;   //在此处计算出结果的位数,
        case(12): cal_result = cal_num1 - cal_num2; result_digit_compute();break;   //避免写在reg显示程序中,
        case(13): cal_result = cal_num1 * cal_num2; result_digit_compute();break;   //否则扫描的时候重复计算,
        case(14): cal_result = cal_num1 / cal_num2; result_digit_compute();break;   //占用时间片,造成显示负担
        default: break; 
    }
}

unsigned int adjust(unsigned char *num, unsigned char digit)
{
    unsigned char temp_digit = digit;
    unsigned int true_num = 0;
    true_num = num[0]*1000+num[1]*100+num[2]*10+num[3];
    while((4-temp_digit) > 0)
    {
        true_num = true_num/10;
        temp_digit++;
    }

    return true_num;           
}

数码管显示程序:

#include "bsp.h"
//unsigned char distype = 4;
//unsigned char digit1 = 3;
//unsigned char digit2 = 0;
//unsigned int cal_num1 = 0;
//unsigned int cal_num2 = 0;
//unsigned int cal_result = 0;

#define SEGPORT P0
unsigned char code distab_CC[16]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07, 0x7f,0x6f,
                                  0x77,0x7c,0x39,0x5e,0x79,0x71};
//unsigned char TABLESEL[8] = {0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f}; //位选码
unsigned char TABLESEL[8] = {0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe};
unsigned char showvalue[8] = {0};
unsigned char dis_digit = 0;
unsigned char result_digit = 0;

sbit LATCH_DUAN = P2^2;
sbit LATCH_WEI = P2^3;

//8位动态扫描
void seg7_show_CC(void)
{
    static unsigned char j = 0;
    if(distype == 0)
    {
        dis_digit = 1;
    }
    if(distype == 1)
    {
        dis_digit = digit1;
    }
    if(distype == 2)
    {
        dis_digit = 1;
    }
    if(distype == 3)
    {
        dis_digit = digit2;
    } 
    if(distype == 5)
    {
//      if(cal_result <= 65535)
//      {
            dis_digit = result_digit;
//      }
//      else if(cal_result > 65535)
//      {
//          dis_digit = 4;
//      }

    }  

    SEGPORT = 0x00;//消除残影
    LATCH_DUAN = 1;
    LATCH_DUAN = 0;  

    SEGPORT = TABLESEL[j];
    LATCH_WEI = 1;//位锁存
    LATCH_WEI = 0;                   

    SEGPORT = showvalue[j];
    LATCH_DUAN = 1;//段锁存
    LATCH_DUAN = 0;   

    j++;
    if(distype == 5)
    {
        if((j==dis_digit+1))
        {
            j = 0;
        }
    }
    else
    {
        if(j == dis_digit)
        {
            j = 0;
        }
    }
}

void showvalue_set(void)
{
    if(distype == 0)
    {
        showvalue[0] = distab_CC[0];
    }
    if(distype == 1)
    {
        dis_num_compute(cal_num1, digit1);
    }
    if(distype == 2)
    {
        showvalue[0] = distab_CC[0];        
    }
    if(distype == 3)
    {
        dis_num_compute(cal_num2, digit2);
    }
    if(distype == 5)
    {
//      if(cal_result <= 65535)
//      {
        //  result_digit_compute(); //此句会造成,重复计算结果的位数,导致显示负担
            dis_num_compute(cal_result, result_digit);
            showvalue[result_digit] = 0x48; //显示‘=’号
//      }
//      else if(cal_result > 65535)
//      {
//          showvalue[4] = 0x75;        //显示Error
//          showvalue[3] = 0x50;
//          showvalue[2] = 0x50;
//          showvalue[1] = 0x5c;
//          showvalue[0] = 0x50;
//      }
    }   
}

void result_digit_compute(void)
{
    unsigned int result_temp = 0;
    result_digit = 0;
    if(cal_result==0)
    {
        result_digit = 1;
    }
    else
    {
        result_temp = cal_result;
        while(result_temp != 0)
        {
            result_temp /= 10;
            result_digit++;
        }
    }
}

void dis_num_compute(unsigned int cal, unsigned char digit)
{
     unsigned char temp = digit;
     unsigned char temp2 = 0;
     unsigned int temp3 = 0;
     unsigned char temp4 = 0;
     while(temp != 0)
     {  
        for(temp3 = cal,temp2 = temp-1; temp2 > 0; temp2--)
        {
            temp3 /= 10;
        }   
        showvalue[temp-1] = distab_CC[temp3];

        temp4 = temp-1;
        while(temp4 != 0)
        {
            temp3 *= 10;
            temp4--;
        }
        cal = cal-temp3; 
        temp--;
     }
}

头文件:
这里写图片描述

#ifndef _BSP_H_
#define _BSP_H_

//系统自带的头文件
#include "reg52.h"
#include "stdio.h"
#include "string.h"
#include "stdlib.h"

//外设的头文件
//#include "bsp_xx.h"
#include "bsp_seg7.h"
#include "bsp_delay.h"
//#include "bsp_key.h"
//#include "bsp_int.h"
//#include "bsp_timer.h"
#include "bsp_mkey.h"
#include "bsp_mkeyfunc.h"
//#include "bsp_alarm.h"
#include "process.h"

//初始化外设的函数声明
void bsp_init(void);

#endif

每个外设的头文件就不一一上传了。

  • 11
    点赞
  • 106
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值