標(biāo)題: 關(guān)于用矩陣鍵盤和數(shù)碼管寫個(gè)計(jì)算器問題 [打印本頁]
作者: q391552859 時(shí)間: 2012-4-4 15:22
標(biāo)題: 關(guān)于用矩陣鍵盤和數(shù)碼管寫個(gè)計(jì)算器問題
我想用開發(fā)板做一個(gè)計(jì)算器,但是沒有思路,其實(shí)只要思路就好了,不過要是有程序我也不會拒絕的
。
如果能把簡單的計(jì)算器和復(fù)雜計(jì)算器都講了就更好了,如果有帶注釋的源程序的話那就太感謝了!!!!
謝謝各位大大了~~
作者: 青蘋果 時(shí)間: 2012-4-4 17:38
想法挺好的
作者: admin 時(shí)間: 2014-11-20 13:45
#include <reg51.h>
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
uchar code table8[]={0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89}; //最左邊顯示0-9
uchar code table7[]={0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99}; //左邊倒數(shù)第二
uchar code table6[]={0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9}; //左邊倒數(shù)第二
uchar code table5[]={0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9};
uchar code table4[]={0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9};
uchar code table3[]={0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9}; //左邊倒數(shù)第二
uchar code table2[]={0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9};
uchar code table1[]={0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9};
ulong dat; //數(shù)據(jù)
ulong datA; //過度數(shù)據(jù)
uchar addflag; //加法標(biāo)志位
uchar subflag; //減法標(biāo)志位
uchar mulflag; //乘法標(biāo)志位
uchar divflag; //除法標(biāo)志位
uchar overflow; //溢出標(biāo)志位
uchar clrflag; //數(shù)據(jù)處理標(biāo)志位
uchar illegal; //除法的非法標(biāo)志位
uchar keynum; //按鍵鍵值
uchar keycode; //按鍵IO口狀態(tài)值
uchar scanok; //IO口掃描結(jié)束
uchar checkok; //鍵值獲取結(jié)束
void delay_ms(uint z) //1ms的延時(shí)函數(shù)
{
uchar x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
void scankeyboard() //scankeyboard()函數(shù)(用于掃描鍵值)
{ //反轉(zhuǎn)法測鍵值。。。
uchar a,b;
P2=0x0f;
keycode=P2;
if(keycode!=0x0f)
{
delay_ms(10); //按鍵閉合消抖。。
a=keycode;
P2=0xf0;
b=P2;
keycode=a|b;
while(P2!=0xf0);
delay_ms(10);//按鍵釋放消抖。。
P1=keycode;
scanok=1;//鍵值測完后。。scanok置1。。。
}
}
void checkkeycode(void)
{
if(scanok) //如果鍵值測完后,則執(zhí)行以下。。。
{
scanok=0; //scanok清零。。為下次使用準(zhǔn)備
switch(keycode) //用開關(guān)語句查找鍵值對應(yīng)的邏輯功能...
{
case 0xee: keynum=0 ;break; //數(shù)字鍵
case 0xed: keynum=1 ;break;
case 0xdd: keynum=2 ;break;
case 0xbd: 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 0x7e: keynum=13 ;break; // /
case 0xbe: keynum=14 ;break; // =
case 0xde: keynum=15 ;break; //清零
}
checkok=1; //查完后,checkok置1.
}
}
void datpros(void) //數(shù)據(jù)處理函數(shù)。。
{
if(keynum==15) //如果是15 則認(rèn)為是清零的 進(jìn)行清零
{
dat=0;
}
else //否則則認(rèn)為是數(shù)字鍵 進(jìn)行顯示 存貯 并運(yùn)算
{
if(clrflag) //清除標(biāo)志為1,則執(zhí)行以下。
{
dat=0;
clrflag=0; //為下次使用準(zhǔn)備。
}
dat=dat*10+(ulong)keynum; //將每次按的數(shù)字合成一個(gè)整體。。比如按下"1","2","3"后就會把它合成"123"
if(dat>1000000000) overflow=1; //如果輸入值大于65535(所用的為int型數(shù)據(jù),最大為65535)的話則溢出標(biāo)志置1,可供顯示程序查詢并顯示"EEEEEEE"
if(divflag&&!dat) illegal=1; //如果做除法時(shí)除了零,則非法標(biāo)志置1,供顯示程序查詢
}
}
void add(void)
{
addflag++; //加法標(biāo)志置1。。。
subflag=mulflag=divflag=0; //將其它運(yùn)算標(biāo)志清零。。(一次只能作一種運(yùn)算)
clrflag=1; //清零標(biāo)標(biāo)置1,(當(dāng)按下加號后,再按第二個(gè)加數(shù)時(shí),這時(shí)應(yīng)該顯示第二加數(shù)。。所以要清掉第一個(gè)加數(shù)。)
if(addflag>1) //此處用于邊加。。
{ //當(dāng)連續(xù)加的時(shí)候。。加號應(yīng)有等于的功能。。
dat=dat+datA; //算出和
datA=dat; //和保存,用于下一次連加。。
} //說明:比如進(jìn)行"1+2+3"時(shí),當(dāng)按第二個(gè)加時(shí),應(yīng)該要顯示1+2的和。。
else datA=dat; //如果不是連加,將輸入的第一個(gè)加數(shù)暫存。。(因?yàn)轱@示程序只顯示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) //如果些時(shí)做加法運(yùn)算。。
{
dat=dat+datA; //計(jì)算各存入dat(顯示程序會將dat顯示的。。)
}
if(subflag)
{
dat=datA-dat;
}
if(mulflag)
{
dat=datA*dat;
}
if(divflag)
{
dat=datA/dat;
}
addflag=subflag=mulflag=divflag=0; //運(yùn)算一次完成后將所有運(yùn)標(biāo)志清零。為下次運(yùn)算作準(zhǔn)備。。
}
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; //將數(shù)據(jù)分開然后分別顯示
shi=dat0/10;
bai=dat00/100;
qian=dat000/1000;
wan=dat0000/10000;
shiwan=dat00000/100000;
baiwan=dat000000/1000000;
qianwan=dat0000000/10000000;
P0=table1[ge]; //個(gè)位顯示
delay_ms(2);
P0=table2[shi]; //十位顯示
delay_ms(2);
P0=table3[bai]; //百位顯示
delay_ms(2);
P0=table4[qian]; //千位位顯示
delay_ms(2);
P0=table5[wan]; //wan位顯示
delay_ms(2);
P0=table6[shiwan]; //個(gè)位顯示
delay_ms(2);
P0=table7[baiwan]; //個(gè)位顯示
delay_ms(2);
P0=table8[qianwan]; //個(gè)位顯示
delay_ms(2);
P0=0xff;
}
else
{
P0=table1[0];
}
}
void calculate_handle(void)//計(jì)算大函數(shù)。。
{
if(checkok)//如果檢測鍵值完萬。。則執(zhí)行以下。。
{
checkok=0;//檢測完標(biāo)志清零..
switch (keynum)//如果是+,-,*,/,=則進(jìn)入相應(yīng)的函數(shù)。。
{
case 10 : add(); break; //如果是按了"+",則進(jìn)入加法函數(shù)。
case 11 : sub(); break; //如果是按了"-",則進(jìn)入加法函數(shù)。
case 12 : mul(); break; //如果是按了"*",則進(jìn)入加法函數(shù)。
case 13 : div(); break; //如果是按了"/",則進(jìn)入加法函數(shù)。
case 14 : equ(); break; //如果是按了"=",則進(jìn)入加法函數(shù)。
default : datpros(); //如果不是,計(jì)算符(即為數(shù)字),則進(jìn)入數(shù)據(jù)處理函數(shù)。
}
}
}
void main(void)
{
P0=0xff;
while(1)
{
scankeyboard();
checkkeycode();
calculate_handle();
display();
}
}
作者: exv 時(shí)間: 2014-11-23 17:59
改了下您的代碼,table[1~8]有些占空間了。
scankeyboard()函數(shù)寫得很好,比光盤中“矩陣鍵盤_c_按鍵顯示1-16平方”精簡得多。
不知胡老師這有否Reverse Polish notation寫的計(jì)算器(使用PS2鍵盤接口,液晶顯示)。
RPN寫的計(jì)算器可計(jì)算復(fù)雜的函式,等整個(gè)式子寫完再給結(jié)果。
用一般思路實(shí)現(xiàn)的話,需預(yù)置較大的棧,用一般單片機(jī)且不借助外部存儲的話好像有些困難。
- #include <reg51.h>
- #include"intrins.h"
- #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};//共陰顯示字庫
- ulong dat; //數(shù)據(jù)
- ulong datA; //過度數(shù)據(jù)
- uchar addflag; //加法標(biāo)志位
- uchar subflag; //減法標(biāo)志位
- uchar mulflag; //乘法標(biāo)志位
- uchar divflag; //除法標(biāo)志位
- uchar overflow; //溢出標(biāo)志位
- uchar clrflag; //數(shù)據(jù)處理標(biāo)志位
- uchar illegal; //除法的非法標(biāo)志位
- uchar keynum; //按鍵鍵值
- uchar keycode; //按鍵IO口狀態(tài)值
- uchar scanok; //IO口掃描結(jié)束
- uchar checkok; //鍵值獲取結(jié)束
- sbit DUAN = P2^6; //74HC573的LE端 LED的段選端
- sbit WEI = P2^7; //74HC573的LE端 LED的位選端
- sbit BUZZER = P2^2;
- void delay_ms(uint z) //1ms的延時(shí)函數(shù)
- {
- 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行是消隱,如果不加其他數(shù)碼管會有暗亮非常難看
- }
- void leddisplay(uchar n,uchar value)
- {
- wei_1(_crol_(0xfe,n));
- duan_1(value);
- }
- void scankeyboard() //scankeyboard()函數(shù)(用于掃描鍵值)
- { //反轉(zhuǎn)法測鍵值。。。
- uchar a,b;
- P3=0x0f;
- keycode=P3;
- if(keycode!=0x0f)
- {
- delay_ms(10); //按鍵閉合消抖。。
- a=keycode;
- P3=0xf0;
- b=P3;
- keycode=a|b;
- while(P3!=0xf0);
- delay_ms(10);//按鍵釋放消抖。。
- P1=keycode;
- scanok=1;//鍵值測完后。。scanok置1。。。
- }
- }
- void checkkeycode(void)
- {
- if(scanok) //如果鍵值測完后,則執(zhí)行以下。。。
- {
- scanok=0; //scanok清零。。為下次使用準(zhǔn)備
- switch(keycode) //用開關(guān)語句查找鍵值對應(yīng)的邏輯功能...
- {
- case 0xee: keynum=0 ;break; //數(shù)字鍵
- case 0xed: keynum=1 ;break;
- case 0xdd: keynum=2 ;break;
- case 0xbd: 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 0x7e: keynum=13 ;break; // /
- case 0xbe: keynum=14 ;break; // =
- case 0xde: keynum=15 ;break; //清零
-
- //0C=/
- //123*
- //456-
- //789+
- }
- checkok=1; //查完后,checkok置1.
- }
- }
- void datpros(void) //數(shù)據(jù)處理函數(shù)。。
- {
- if(keynum==15) //如果是15 則認(rèn)為是清零的 進(jìn)行清零
- {
- dat=0;
- }
- else //否則則認(rèn)為是數(shù)字鍵 進(jìn)行顯示 存貯 并運(yùn)算
- {
- if(clrflag) //清除標(biāo)志為1,則執(zhí)行以下。
- {
- dat=0;
- clrflag=0; //為下次使用準(zhǔn)備。
- }
- dat=dat*10+(ulong)keynum; //將每次按的數(shù)字合成一個(gè)整體。。比如按下"1","2","3"后就會把它合成"123"
- if(dat>1000000000) overflow=1; //如果輸入值大于65535(所用的為int型數(shù)據(jù),最大為65535)的話則溢出標(biāo)志置1,可供顯示程序查詢并顯示"EEEEEEE"
- if(divflag&&!dat) illegal=1; //如果做除法時(shí)除了零,則非法標(biāo)志置1,供顯示程序查詢
- }
- }
- void add(void)
- {
- addflag++; //加法標(biāo)志置1。。。
- subflag=mulflag=divflag=0; //將其它運(yùn)算標(biāo)志清零。。(一次只能作一種運(yùn)算)
- clrflag=1; //清零標(biāo)標(biāo)置1,(當(dāng)按下加號后,再按第二個(gè)加數(shù)時(shí),這時(shí)應(yīng)該顯示第二加數(shù)。。所以要清掉第一個(gè)加數(shù)。)
- if(addflag>1) //此處用于邊加。。
- { //當(dāng)連續(xù)加的時(shí)候。。加號應(yīng)有等于的功能。。
- dat=dat+datA; //算出和
- datA=dat; //和保存,用于下一次連加。。
- } //說明:比如進(jìn)行"1+2+3"時(shí),當(dāng)按第二個(gè)加時(shí),應(yīng)該要顯示1+2的和。。
- else datA=dat; //如果不是連加,將輸入的第一個(gè)加數(shù)暫存。。(因?yàn)轱@示程序只顯示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) //如果些時(shí)做加法運(yùn)算。。
- {
- dat=dat+datA; //計(jì)算各存入dat(顯示程序會將dat顯示的。。)
- }
- if(subflag)
- {
- dat=datA-dat;
- }
- if(mulflag)
- {
- dat=datA*dat;
- }
- if(divflag)
- {
- dat=datA/dat;
- }
- addflag=subflag=mulflag=divflag=0; //運(yùn)算一次完成后將所有運(yùn)標(biāo)志清零。為下次運(yùn)算作準(zhǔn)備。。
- }
- 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; //將數(shù)據(jù)分開然后分別顯示
- 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=0;
- }
- void calculate_handle(void)//計(jì)算大函數(shù)。。
- {
- if(checkok)//如果檢測鍵值完萬。。則執(zhí)行以下。。
- {
- checkok=0;//檢測完標(biāo)志清零..
- switch (keynum)//如果是+,-,*,/,=則進(jìn)入相應(yīng)的函數(shù)。。
- {
- case 10 : add(); break; //如果是按了"+",則進(jìn)入加法函數(shù)。
- case 11 : sub(); break; //如果是按了"-",則進(jìn)入加法函數(shù)。
- case 12 : mul(); break; //如果是按了"*",則進(jìn)入加法函數(shù)。
- case 13 : div(); break; //如果是按了"/",則進(jìn)入加法函數(shù)。
- case 14 : equ(); break; //如果是按了"=",則進(jìn)入加法函數(shù)。
- default : datpros(); //如果不是,計(jì)算符(即為數(shù)字),則進(jìn)入數(shù)據(jù)處理函數(shù)。
- }
- }
- }
- void main(void)
- {
- P0=0xff;
- while(1)
- {
- scankeyboard();
- checkkeycode();
- calculate_handle();
- display();
-
- }
- }
復(fù)制代碼
作者: liang521 時(shí)間: 2015-4-4 14:12
評論里面的源代碼真的是太牛了
作者: 用戶 時(shí)間: 2015-4-11 22:22
做個(gè)記號少后看
作者: 用戶 時(shí)間: 2015-4-11 22:22
做個(gè)記號少后看
作者: 單片機(jī)初學(xué) 時(shí)間: 2015-5-21 20:46
這是C語言嗎,table[1-8】怎摸看不懂啊
作者: surongzhan 時(shí)間: 2015-5-21 23:30
認(rèn)認(rèn)真真去學(xué)習(xí)兩位老大的“C”程序,更加重要的是學(xué)習(xí)程序的編寫方法!
先謝謝兩位大大的程序啦!
作者: scx2006114 時(shí)間: 2015-7-28 19:51
本帖最后由 scx2006114 于 2015-7-29 09:50 編輯
我使用了這個(gè)程序后,出現(xiàn)了些問題,您能否幫我解決下,謝謝了
第一個(gè)問題,我要連按三下同一個(gè)九個(gè)數(shù)中的一個(gè)才能在數(shù)碼管顯示出相應(yīng)的數(shù)字
第二個(gè)問題,程序中加減可以正常運(yùn)行,而乘除則不能正常運(yùn)行
(我使用的51單片機(jī)板是六個(gè)數(shù)碼管)
作者: JKL 時(shí)間: 2019-8-20 21:41
admin 發(fā)表于 2014-11-20 13:45
#include
#define uchar unsigned char
#define uint unsigned int
學(xué)習(xí)了,感謝兩位源碼分享!
作者: zcg888 時(shí)間: 2020-6-23 08:42
認(rèn)真學(xué)習(xí),這里師傅真牛
歡迎光臨 (http://www.zg4o1577.cn/bbs/) |
Powered by Discuz! X3.1 |
主站蜘蛛池模板:
国产在线观看一区二区三区
|
成人免费看黄
|
国产在线一区二区三区
|
国产亚洲精品精品国产亚洲综合
|
久久久久国产精品一区
|
成人av电影网|
看av网|
日本高清视频在线播放
|
亚洲精品 在线播放
|
在线日韩不卡
|
狠狠亚洲|
国产精品小视频在线观看
|
中文字幕亚洲视频
|
色视频www在线播放国产人成
|
欧美日韩中文字幕在线
|
综合网中文字幕
|
亚洲一区二区免费
|
黑人巨大精品欧美一区二区免费
|
成人国产一区二区三区精品麻豆
|
国产三区精品
|
成人国产精品久久
|
精品成人一区
|
欧美日韩三级在线观看
|
国产美女精品
|
日韩精品一区二区三区高清免费
|
av在线免费播放
|
国产精品美女久久久久久免费
|
四虎影视免费观看
|
一区二区三区免费
|
久久久久成人精品
|
亚洲第一在线视频
|
久久综合av|
国产亚洲欧美日韩精品一区二区三区
|
五月综合激情婷婷
|
精品国模一区二区三区欧美
|
亚洲精品性视频
|
久久在线
|
久久精品一区二区视频
|
亚州av|
黄视频免费
|
午夜精品久久久久久久99黑人
|