打印
[疑难问答]

【转】计算器原理分析

[复制链接]
589|12
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
shashaa|  楼主 | 2016-5-16 20:43 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
#include "STC89C5xRC.h"
#include<intrins.h>
#define uint8 unsigned char
#define uint unsigned int
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long

uchar code table[]={0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71,0};

ulong dat;       //数据
ulong datA;      //过度数据
uchar addflag;   //加法标志位
uchar subflag;   //减法标志位
uchar mulflag;   //乘法标志位
uchar divflag;   //除法标志位
uchar overflow;  //溢出标志位
uchar clrflag;   //数据处理标志位
uchar illegal;   //除法的非法标志位

uchar keynum;    //按键键值
uchar keycode;   //按键IO口状态值   

uchar scanok;    //IO口扫描结束
uchar checkok;   //键值获取结束


sbit DUAN       = P2^6;     //74HC573的LE端    LED的段选端
sbit WEI        = P2^7;     //74HC573的LE端    LED的位选端
sbit BUZZER     = P2^3;

void delay_ms(uint z)                      //1ms的延时函数   
{
        uchar x,y;
        for(x=z;x>0;x--)
        for(y=110;y>0;y--);
}


void wei_1(uchar wei)
{
        P0=wei;
        WEI=1;
        WEI=0;
}

void duan_1(uchar duan)
{
        uint i;
        P0=table[duan];
            DUAN=1;
        DUAN=0;
        for(i=25;i>0;i--);

        P0=0;
            DUAN=1;
        DUAN=0;
    for(i=50;i>0;i--);       //以上4行是消隐,如果不加其他数码
                                                        //        管会有暗亮非常难看
}

void leddisplay(uchar n,uchar value)
{
            wei_1(_crol_(0xfe,n));
        duan_1(value);
}

void  scankeyboard()                  //scankeyboard()函数(用于扫描键值)
{                                     //反转法测键值。。。
        uchar a,b;
//                        P3=0xfe;
//                        keycode=P3;
//                        keycode=keycode&0xf0;
//                        while(keycode!=0xf0)
//                        {
//                                        delay_ms(5);
//                                        keycode=P3;
////                                        a=keycode;
////                                        P3 = 0xF0;
////                                        b = P3;
//                                        keycode=keycode&0xf0;
//                                        while(keycode!=0xf0)
//                                        {
//                                                keycode=P3;
//                                                 BUZZER = 0;
//                                                 delay_ms(500);
//                                                
//                                        while(keycode!=0xf0)
//                                                {
//                                                        keycode=P3;
//                                                        keycode=keycode&0xf0;
//                                                        P0=keycode;
//                                                        scanok=1;
//                                                        BUZZER = 1;
//                                                }
//                                        }
//                                }
//                        P3=0xfd;
//                        keycode=P3;
//                        keycode=keycode&0xf0;
//                        while(keycode!=0xf0)
//                        {
//                                        delay_ms(5);
//                                        keycode=P3;
////                                        a=keycode;
////                                        P3 = 0xF0;
////                                        b = P3;
//                                        keycode=keycode&0xf0;
//                                        while(keycode!=0xf0)
//                                        {
//                                                keycode=P3;
//                                                 BUZZER = 0;
//                                                 delay_ms(500);
//                                                
//                                        while(keycode!=0xf0)
//                                                {
//                                                        keycode=P3;
//                                                        keycode=keycode&0xf0;
//                                                        P0=keycode;
//                                                        scanok=1;
//                                                        BUZZER = 1;
//                                                }
//                                        }
//                                }
//                        P3=0xfb;
//                        keycode=P3;
//                        keycode=keycode&0xf0;
//                        while(keycode!=0xf0)
//                        {
//                                        delay_ms(5);
//                                        keycode=P3;
////                                        a=keycode;
////                                        P3 = 0xF0;
////                                        b = P3;
//                                        keycode=keycode&0xf0;
//                                        while(keycode!=0xf0)
//                                        {
//                                                keycode=P3;
//                                                 BUZZER = 0;
//                                                 delay_ms(500);
//                                                
//                                        while(keycode!=0xf0)
//                                                {
//                                                        keycode=P3;
//                                                        keycode=keycode&0xf0;
//                                                        P0=keycode;
//                                                        scanok=1;
//                                                        BUZZER = 1;
//                                                }
//                                        }
//                                }
//                        P3=0xf7;
//                        keycode=P3;
//                        keycode=keycode&0xf0;
//                        while(keycode!=0xf0)
//                        {
//                                        delay_ms(5);
//                                        keycode=P3;
////                                        a=keycode;
////                                        P3 = 0xF0;
////                                        b = P3;
//                                        keycode=keycode&0xf0;
//                                        while(keycode!=0xf0)
//                                        {
//                                                P0=keycode;
//                                                scanok=1;
//                                                 BUZZER = 0;
//                                                 delay_ms(500);
//                                                
//                                        while(keycode!=0xf0)
//                                                {
//                                                        keycode=P3;
//                                                        keycode=keycode&0xf0;
//                                                        
//                                                        BUZZER = 1;
//                                                }
//                                        }
//                                }
        P3=0xfe;                     
        keycode=P3;
                keycode=keycode&0xf0;
        if(keycode!=0xf0)
        {
            delay_ms(10);                 //按键闭合消抖。。
                a=keycode;
                P3=0xf0;
                b=P3;
                keycode=a|b;
                                 BUZZER = 0;
                                delay_ms(500);
                while(P3!=0xf0);
                delay_ms(10);//按键释放消抖。。
                P0=keycode;
                scanok=1;//键值测完后。。scanok置1。。。
                                BUZZER = 1;
        }
}

void checkkeycode(void)      
{
        if(scanok)                                //如果键值测完后,则执行以下。。。
        {
                scanok=0;                             //scanok清零。。为下次使用准备
                switch(keycode)                       //用开关语句查找键值对应的逻辑功能...
                {
                        case 0xee: keynum=0  ;break;  //数字键
                        case 0xde: keynum=1  ;break;
                        case 0xbe: keynum=2  ;break;
                        case 0x7e: keynum=3  ;break;
                        case 0xeb: keynum=4  ;break;
                        case 0xdb: keynum=5  ;break;
                        case 0xbb: keynum=6  ;break;
                        case 0xe7: keynum=7  ;break;
                        case 0xd7: keynum=8  ;break;
                        case 0xb7: keynum=9  ;break;
                        case 0x77: keynum=10 ;break;   // +
                        case 0x7b: keynum=11 ;break;   // -
                        case 0x7d: keynum=12 ;break;   // *
                        case 0x7a: keynum=13 ;break;   // /
                        case 0xba: keynum=14 ;break;   // =
                        case 0xda: keynum=15 ;break;   //清零
                        
                        //0C=/
                        //123*
                        //456-
                        //789+
                }
                checkok=1;                         //查完后,checkok置1.
        }
}

void datpros(void)//数据处理函数。。
{
        if(keynum==15)//如果是15  则认为是清零的  进行清零
        {
                dat=0;
        }
        else        //否则则认为是数字键 进行显示 存贮 并运算
        {
                if(clrflag)//清除标志为1,则执行以下。
                {        
                        dat=0;
                        clrflag=0;//为下次使用准备。
                }
                dat=dat*10+(ulong)keynum;     //将每次按的数字合成一个整体。。比如按下"1","2","3"后就会把它合成"123"
                if(dat>1000000000) overflow=1; //如果输入值大于65535(所用的为int型数据,最大为65535)的话则溢出标志置1,可供显示程序查询并显示"EEEEEEE"
                if(divflag&&!dat) illegal=1;   //如果做除法时除了零,则非法标志置1,供显示程序查询
        }
}

void add(void)//加法计算
{
        addflag++;                          //加法标志置1。。。
        subflag=mulflag=divflag=0;          //将其它运算标志清零。。(一次只能作一种运算)
        clrflag=1;                          //清零标标置1,(当按下加号后,再按第二个加数时,这时应该显示第二加数。。所以要清掉第一个加数。)
        if(addflag>1)                       //此处用于边加。。
        {                                   //当连续加的时候。。加号应有等于的功能。。
                dat=dat+datA;                   //算出和
                datA=dat;                       //和保存,用于下一次连加。。
        }                                   //说明:比如进行"1+2+3"时,当按第二个加时,应该要显示1+2的和。。
        else datA=dat;                      //如果不是连加,将输入的第一个加数暂存。。(因为显示程序只显示dat变量的值。)

}

void sub(void) //减法计算
{
        subflag++;
        addflag=mulflag=divflag=0;
        clrflag=1;
        if(subflag>1)                //连减。。
        {
                dat=datA-dat;
                datA=dat;
        }
        else datA=dat;
}

void mul(void)//乘法计算
{
        mulflag++;
        addflag=subflag=divflag=0;
        clrflag=1;
        if(mulflag>1)                //连乘
        {
                dat=datA*dat;
                datA=dat;
        }
        else datA=dat;

}

void div(void)        //除法计算
{
        divflag++;
        addflag=subflag=mulflag=0;
        clrflag=1;
        if(divflag>1)
        {
                dat=datA/dat;
                datA=dat;
        }
        else datA=dat;
}

void equ(void)          //等于计算
{
        
        if(addflag)                           //如果些时做加法运算。。
        {
                dat=dat+datA;                     //计算各存入dat(显示程序会将dat显示的。。)
        }
                if(subflag)
        {
                dat=datA-dat;
        }
        if(mulflag)
        {
                dat=datA*dat;
        }
        if(divflag)
        {
                dat=datA/dat;
        }
        addflag=subflag=mulflag=divflag=0;    //运算一次完成后将所有运标志清零。为下次运算作准备。。
}

void display(void)
{
        uchar ge=0,shi=0,bai=0,qian=0,wan=0,shiwan=0,baiwan=0,qianwan=0;

        if(!overflow&&!illegal)
        {
                ge=dat%10;                     //将数据分开然后分别显示
                shi=dat%100/10;
                bai=dat%1000/100;
                qian=dat%10000/1000;
                wan=dat%100000/10000;
                shiwan=dat%1000000/100000;
                baiwan=dat%10000000/1000000;
                qianwan=dat%100000000/10000000;


                leddisplay(7,ge);
                if(shi|bai|qian|wan|shiwan|baiwan|qianwan)leddisplay(6,shi);
                if(bai|qian|wan|shiwan|baiwan|qianwan)leddisplay(5,bai);
                if(qian|wan|shiwan|baiwan|qianwan)leddisplay(4,qian);
                if(wan|shiwan|baiwan|qianwan)leddisplay(3,wan);
                if(shiwan|baiwan|qianwan)leddisplay(2,shiwan);
                if(baiwan|qianwan)leddisplay(1,baiwan);
                if(qianwan)leddisplay(0,qianwan);

                //P0=0xff;
        }
        //else P0=0x00;
}

void calculate_handle(void)//计算大函数。。
{
        if(checkok)//如果检测键值完万。。则执行以下。。
        {
                checkok=0;//检测完标志清零..
                switch (keynum)//如果是+,-,*,/,=则进入相应的函数。。
                {
                        case 10 : add(); break;    //如果是按了"+",则进入加法函数。
                        case 11 : sub(); break;    //如果是按了"-",则进入加法函数。
                        case 12 : mul(); break;    //如果是按了"*",则进入加法函数。
                        case 13 : div(); break;    //如果是按了"/",则进入加法函数。
                        case 14 : equ(); break;    //如果是按了"=",则进入加法函数。
                        default : datpros();       //如果不是,计算符(即为数字),则进入数据处理函数。
                }
        }
}

void main(void)
{

//                DUAN=1;
//                P0=0;
//                DUAN=0;
//                WEI=1;
//                P0=0xc0;
//                WEI=0;
        //P0=0xff;
        while(1)
        {
                scankeyboard();   
                checkkeycode();
                calculate_handle();
                display();

        }
}
沙发
wanglaojii| | 2016-5-16 20:52 | 只看该作者
查完后,checkok置1了吗??  

使用特权

评论回复
板凳
laozhongyi| | 2016-5-16 20:59 | 只看该作者
那计算器,数码管能正常显示吗?感觉不行吧

使用特权

评论回复
地板
Edisons| | 2016-5-16 21:05 | 只看该作者
没有电路图啊?怎么分析呢?

使用特权

评论回复
5
_gege| | 2016-5-16 21:11 | 只看该作者
电路图也没有,更不知道原理何在??

使用特权

评论回复
6
Mozarts| | 2016-5-16 21:28 | 只看该作者
如果不是连加,将输入的第一个加数暂存的。

使用特权

评论回复
7
shashaa|  楼主 | 2016-5-16 21:31 | 只看该作者
不好意思,原理图给大伙献上。

_DB-51 Ver2.1原理图.pdf

78.8 KB

使用特权

评论回复
8
shashaa|  楼主 | 2016-5-16 21:32 | 只看该作者
wanglaojii 发表于 2016-5-16 20:52
查完后,checkok置1了吗??

是的 ,checkok置1了。。。

使用特权

评论回复
9
shashaa|  楼主 | 2016-5-16 21:32 | 只看该作者
laozhongyi 发表于 2016-5-16 20:59
那计算器,数码管能正常显示吗?感觉不行吧

是啊,这就是我想要问的啊,请问知道是什么原因吗?

使用特权

评论回复
10
shashaa|  楼主 | 2016-5-16 21:33 | 只看该作者
Edisons 发表于 2016-5-16 21:05
没有电路图啊?怎么分析呢?

不好意思,刚刚电路图已经给出来了,可以看看。

使用特权

评论回复
11
shashaa|  楼主 | 2016-5-16 21:33 | 只看该作者
Mozarts 发表于 2016-5-16 21:28
如果不是连加,将输入的第一个加数暂存的。

这个是怎么说的呢?

使用特权

评论回复
12
Listate| | 2016-5-16 21:38 | 只看该作者
看看,这个还真不是很好明白呢?为什么会不正常显示!!!

使用特权

评论回复
13
laozhongyi| | 2016-5-23 20:14 | 只看该作者
shashaa 发表于 2016-5-16 21:33
不好意思,刚刚电路图已经给出来了,可以看看。

好的,多谢楼主分享了!!

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

142

主题

1494

帖子

6

粉丝