HD7279是一款用于擴展單片機I/O口的芯片,至少我是這么認為的,雖然它占用了單片機4個I/O但是真正作為傳輸的僅僅是一根總線,它可以同時驅動8位共陰數碼管(或者8×8點陣),及8×8的矩陣鍵盤,而同時接在單片機上的話,至少需要3~4組I/O,當然單總線控制的芯片基本需要自己的指令和時序。
接到這個課程設計之前我自己懶懶散散地看了一段時間的C51(用C語言編寫單片機代碼),之前老師教的是A51(用匯編編寫單片機代碼),我玩了很久,但是發現A51真的很局限,匯編這種語言是寫給機器看的,真正地寫0和寫1,真正是一個寄存器一個寄存器的調用,對于8位的51單片機來說,要實現1000×1000或者小數是比較困難的。老師推薦用C,之前只是看書實現過一些小東西這回要做比較大的項目了,雖然還有其他課題比如溫度計和數字鐘,不過都做過,只是環境不一樣,修改一下代碼太沒有挑戰性了。
確實開始輕敵了,真正做的時候發現不是那么簡單,
高中的時候學過一點VB做過計算器,如果讓我現在做,也許給我幾天我可以做出來,用C我也沒什么問題,但是C51就有難度了,要考慮太多硬件的東西,特別是顯示這個模塊好不容易瘦下去的頭又兩個大了。等我真正意識到的時候,已經過去幾個禮拜了,呵呵,要和朋友說抱歉了,雖然我答應“等我做完計算器之后再幫你改下程序”但是沒一個實現。
當然,此程序因為基本全是自己寫的,被方晉甬老師稱之為“程序設計不成熟、比較亂”的,額,本來準備用switch語句,但是呂昂老師說switch語句會產生過多閑置寄存器(可是他沒有考慮到我僅僅是實現很少的功能),這段程序只實現+-×÷,符號閃爍,過八位報錯等功能但是沒有小數,只能計算一步(加少數程序即可計算多部)。其實程序挺早就寫出來了,只是一直出不來效果,后來在仿真和VC++編譯環境下修改了很多,理論上是可以實現了,可是還是沒有顯示,于是抓狂了“看來我已處在瓶頸...”,晃了最后一個禮拜,周日周一看了兩天晚上,依然沒有看出什么來,禮拜二去方晉甬老師辦公室請教,查了近3個鐘頭【基本看過了我所有奇形怪狀的子程序—。—||||】,在仿真多遍之后發現就少了一句“while(!key)【檢測釋放按鍵】”【程序中紅字部分即主程序最后一句】囧啊~~~~以至于周四答辯的時候我演示之后,剛點看ppt他就說直接給A,不用答了。。。。
程序的完整版下載地址:http://www.zg4o1577.cn/ziliao/file/jsjq.rar
/////////////////////////////****************程序*****************///////////////////////
#include<reg51.h> #include<math.h> sbit cs=P2^6; sbit clk=P1^0; sbit dat=P1^1; sbit key=P3^3; bit add,sub,mul,div,equ,clr; unsigned char times,st,l,data_jp,flag,d; unsigned int tmr; unsigned long num[8],sn[8],disp[8],sh,result,hp=100000000; void send(unsigned char); unsigned char receive(void); unsigned long real(unsigned long ,unsigned char); unsigned long calcu(unsigned long, unsigned long); void display(unsigned long); unsigned long write_key(unsigned char); void char_flk(void); void test(void); void error(void); void long_delay(void); void short_delay(void); void delay10ms(unsigned char); /////////**************主函數****************////////// void main () { times=0; l=times; st=0; flag=0; test(); while(1) { unsigned char i; if(!key) { send(0x15); data_jp=receive(); cs=1; d=write_key(data_jp); if (data_jp<=9) { flag=0; num[times]=d; } else { flag=1; //times-=1; } if(flag!=1) { if(num[0]==0) { times=0; continue; } if(7>times>=1) { send(0xa1); } send(0x80); send(num[times]); while(!key); delay10ms(1); times=times+1; cs=1; if(times>7) { send(0xa4); error() ; times=0; send(0xa4); } } else { send(0xa4); char_flk(); times-=1; l=times; for(i=0;i<=times;i++) { num[i]=real(num[i],l); sh=sh+num[i]; l--; } sn[st]=sh; if(st>=1) { result=calcu(sn[st],sn[st-1]); sn[st-1]=result; st--; } st++; times=0; flag=0; sh=0; if(equ==1) { st=0; send(0xa4); display(result); equ=0; } if(clr==1) { st=0; times=0; flag=0; sh=0; add=0; sub=0; mul=0; div=0; equ=0; clr=0; send(0xa4); } while(!key); } } } } /////////*********************測試子函數****************//////// void test(void) { char i; delay10ms(2); send(0xbf); cs=1; for (i=0;i<=3;i++) { delay10ms(100); } send(0xa4); cs=1; delay10ms(20); } ///////***********************讀鍵盤程序**************/////// unsigned long write_key(unsigned char data_jp) { unsigned char shuzi; if(data_jp<10) { shuzi=data_jp; } else { if(data_jp==10) { add=1; } else if(data_jp==11) { sub=1; } else if(data_jp==12) { mul=1; } else if(data_jp==13) { div=1; } else if(data_jp==14) { equ=1; } else if(data_jp==15) { clr=1; } shuzi=0xff; } return(shuzi) ; } ///////***********************發送子函數*************////// void send(unsigned char data_out) { unsigned char i; cs=0; long_delay(); for(i=0;i<=7;i++) { if(data_out&0x80) { dat=1; } else { dat=0; } clk=1; short_delay(); clk=0; short_delay(); data_out=data_out<<1; } dat=0; } /////************************接收鍵盤子函數************////// unsigned char receive(void) { unsigned char i,data_in; dat=1; long_delay(); for(i=0;i<=7;i++) { clk=1; short_delay(); data_in=data_in<<1; if(dat) { data_in=data_in|0x01; } else { data_in=data_in|0x00; } clk=0; short_delay(); } dat=0; return(data_in); } /////////***************************顯示數字處理子函數***********///////// unsigned long real(unsigned long so, unsigned char s) { unsigned char z; if(s!=0) { for(z=0;z<=(s-1);z++) { if(s!=0) { so=so*10; } else { so=so; } } } else { so=so; } return(so); } //////////*************************計算子函數*******************/////////// unsigned long calcu(unsigned long sn0,unsigned long sn1 ) { if(add==1) { sn0=sn0+sn1; add=0; } if(sub==1) { sn0=sn1-sn0; sub=0; } if(mul==1) { sn0=sn0*sn1; mul=0; } if(div==1) { if(sn0>0) sn0=sn1/sn0; else error(); div=0; } return(sn0); } ////////****************************報錯錯誤子函數***************///////// void error(void) { while(key) { send(0x96); send(0x4f); delay10ms(2); send(0x95); send(0x05); delay10ms(2); send(0x94); send(0x05); delay10ms(2); send(0x93); send(0x1d); delay10ms(2); send(0x92); send(0x05); delay10ms(2); } } ///////////********************顯示子函數*********//////////// void display(unsigned long display) { unsigned char i,asus=8; if(display>99999999) error(); else { for(i=0;i<=7;i++) { if((display/hp)>=1) break; else { hp=hp/10; asus-=1; } } for(i=0;i<=asus;i++) { disp[i]=display/hp; if(hp>1) { display=display%hp; hp=hp/10; } } for(i=0;i<=asus;i++) { if(i>0) { send(0xa1); } send(0x80); send(disp[i]); } } } ///////////********************符號判斷閃爍顯示*********//////////// void char_flk(void) { if(add==1) { send(0x97); send(0x77); } else if(sub==1) { send(0x97); send(0x01); } else if(mul==1) { send(0x97); send(0x37); } else if(div==1) { send(0x97); send(0x49); } else if(clr) { ; } send(0x88); send(0x7f); } //////************************延時子函數*************/////// void long_delay(void) { char i; for(i=0;i<=25;i++) ; } void short_delay(void) { char j; for(j=0;j<=4;j++); } void delay10ms(unsigned char time) { unsigned char i; unsigned int j; for (i=0;i<=time;i++) { for(j=0;j<=0x390;j++); } }
///////////////////////////************效果圖*************////////////////////
以上演示的為9876543÷234,其本來的結果是42207.4487179……無法顯示小數位,所以結果為42207 。