标题:
计算器原理分析
[打印本页]
作者:
zzmm5520
时间:
2016-5-16 10:28
标题:
计算器原理分析
本帖最后由 zzmm5520 于 2016-5-16 10:32 编辑
胡老师,帮忙看看。那计算器,怎么数码管不显示。原理在附件
#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();
}
}
DB-51 Ver2.1原理图.pdf
2016-5-16 10:26 上传
点击文件名下载附件
78.8 KB, 下载次数: 10
作者:
zzmm5520
时间:
2016-5-16 10:32
#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(); } }
作者:
zzmm5520
时间:
2016-5-16 10:45
求老师 同学们帮忙看看,就是数码管没有显示。
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1