原理圖 51單片機(jī)簡(jiǎn)易計(jì)算器程序: #include <reg51.h> #include <math.h> #define uchar() unsigned char() #define uint unsigned int //---------定義引腳-------------------- bit clr=0; bit ok=0; bit xiaoshu=0; bit jiego=0; bit first_1=1; bit first_2=1; sbit dout = P3^2; sbit load = P2^0; sbit din = P2^1; sbit dclk = P2^2; sbit beer=P0^1; sbit LCD1602_RS=P2^3; sbit LCD1602_RW=P2^4; sbit LCD1602_E=P2^5; //---------定義變量-------------------- uchar() ch451_key=0xff; uchar yun_sign; uchar xiabiao=0; uchar tab[32]; uchar tab1[]={"welcome to use!"}; uchar tab2[]={" make by JunRu!"}; uchar tab3[]={"ERR0R"}; float opr_1=0,opr_temp=0,end=0,a; //---------聲明函數(shù)-------------------- void ch451_init(void); //CH451初始化 void ch451_write(uint command);//寫(xiě)命令或數(shù)據(jù)到ch451 uchar ch451_read()(void); //讀按鍵值 uchar get_char(void); void LCD_init(void);//初始化; void delay(unsigned int k);//延時(shí)程序 void LCD_inter_command(unsigned char command);//寫(xiě)入控制字 void LCD_inter_dat(unsigned char dat);//寫(xiě)入要顯示的數(shù)據(jù) void set_xy(unsigned char x,unsigned char y);//找地址 void write(unsigned char date);//寫(xiě)入字符 void lcdbusy();//查忙時(shí) void display()(void); void spec(void); void get_end(void); void hun_he(uchar n); //-------- 主函數(shù)---------------------- void main() { uchar i; LCD_init();//LCD初始化; ch451_init();//CH451初始化 EA = 1;//打開(kāi)中斷 LCD_inter_command(0x01);//清屏 for(i=0;i<=14;i++) { LCD_inter_dat(tab1[i]); beer=0; delay(4000);//延時(shí) beer=1; } LCD_inter_command(0xc0);//從第二行開(kāi)始顯示 for(i=0;i<=14;i++) { LCD_inter_dat(tab2[i]); beer=0; delay(4000);//延時(shí) beer=1; } delay(0xffff); delay(0xffff); LCD_inter_command(0x01); while(1) { if(ok) { display()(); ok=0;clr=1; } } } //----------子函數(shù)-------------------- void hun_he(uchar n) {int j; switch(n) { case '+':opr_temp=opr_temp+opr_1;break; case '-':opr_temp=opr_temp-opr_1;break; case '*':opr_temp=opr_temp*opr_1;break; case '/': { if(a==0)//減數(shù)為零顯錯(cuò) { LCD_inter_command(0xc0); for(j=0;j<=4;j++) { LCD_inter_dat(tab3[j]); beer=0; delay(4000);//延時(shí) beer=1; } } else {opr_temp=opr_temp/opr_1;} break; } default:break;} } void ch451_init(void)//CH451初始化 { EX0 = 1; din = 0; din = 1; ch451_write(0x403); //開(kāi)顯示 ch451_write(0x580); //BCD譯碼方式 } void ch451_write(uint command)//寫(xiě)命令或數(shù)據(jù)到ch451 { uchar i; EX0 = 0; load = 0; for(i=0;i<12;i++) { din = command&1; dclk = 0; command>>=1; dclk = 1; } load = 1; EX0 = 1; } uchar ch451_read()(void)//讀按鍵值 { uchar key=0x07; uchar i; EX0=0; load = 0; for(i=0;i<4;i++) //將0111讀入 { din = key &1; dclk = 0; key>>=1; dclk =1; } load = 1; key = 0; for(i=0;i<7;i++) //從CH451讀出按鍵值 { key<<=1; key|= dout; dclk =0; dclk =1; } EX0 =1; return key; } void EX0_ISR(void)interrupt 0 //中斷程序 { uchar temp; ch451_key=ch451_read()(); //將讀出的按鍵值賦給變量 spec(); if(clr) {LCD_inter_command(0x01);clr=0;} temp=get_char(); if(temp){tab[xiabiao++]=temp; LCD_inter_dat(temp);} if(xiabiao>=16)LCD_inter_command(0xc0);//若大于16,則從第2行開(kāi)始顯示 if(ok) get_end(); beer=0; delay(3000); beer=1; } uchar get_char(void) { uchar dis=0; uint temp=0,temp1=0; switch(ch451_key) { case 0x40:dis='1';break; case 0x41:dis='2';break; case 0x42:dis='3';break; case 0x48:dis='4';break; case 0x49:dis='5';break; case 0x4A:dis='6';break; case 0x50:dis='7';break; case 0x51:dis='8';break; case 0x52:dis='9';break; case 0x58:dis='0';break; case 0x43:dis='+';break; case 0x4B:dis='-';break; case 0x53:dis='x';break; case 0x5B:dis='/';break; case 0x44:dis='!';break; case 0x5A:dis='='; ok=1; //遇到“=”,開(kāi)始運(yùn)算 break; case 0x59:dis='.';break; //小數(shù)點(diǎn) case 0x5C: //刪除鍵 LCD_inter_command(0x01); xiabiao=0; break; default: break; } return dis; } void spec(void) //特殊功能鍵 { switch(ch451_key) { case 0x4C:LCD_inter_command(0x10);{if(xiabiao>0)xiabiao-=1;}break; //左移 case 0x54:LCD_inter_command(0x14);{xiabiao+=1;}break; //右移 default:break; } } void delay(unsigned int k)//延時(shí)程序 { while (k--); } void LCD_inter_command(unsigned char command)//寫(xiě)入控制字 { delay(5000); LCD1602_RS=0; LCD1602_RW=0; LCD1602_E=1; P1=command; LCD1602_E=0; lcdbusy(); } void LCD_init(void)//初始化; {delay(5000); LCD_inter_command(0x01);//清屏 delay(5000); LCD_inter_command(0x38);//設(shè)置為8位的數(shù)據(jù)接口,兩行顯示,5、7點(diǎn)字符 delay(5000); LCD_inter_command(0x0E);//顯示打開(kāi),光標(biāo)開(kāi)并閃爍 delay(5000); } void LCD_inter_dat(unsigned char dat)//寫(xiě)入要顯示的數(shù)據(jù) { delay(5000); LCD1602_RS=1; LCD1602_RW=0; LCD1602_E=1; P1=dat; LCD1602_E=0; lcdbusy(); } void lcdbusy()//查忙 { P1=0xFF; LCD1602_RS=0; LCD1602_RW=1; LCD1602_E=1; while((P1&0x80)==1); } void display()(void) //轉(zhuǎn)化在LCD上顯示計(jì)算結(jié)果 { int temp=end; //浮點(diǎn)數(shù) int i; uint xiao_temp; uint xx; //浮點(diǎn)數(shù)的整數(shù)部分 if (end>-32769&&end<32768) { xx=fabs(end); xiao_temp=(fabs(end)-xx)*1000;//取出浮點(diǎn)數(shù)的小數(shù)部分 LCD_inter_command(0xc0); if(end<0) LCD_inter_dat('-');beer=0;delay(4000); beer=1;//判斷是否為負(fù)數(shù),若是則顯示負(fù)號(hào) if(xx>9999) LCD_inter_dat((xx/10000)%10+'0'); beer=0;delay(4000);beer=1; if(xx>999) LCD_inter_dat((xx/1000)%10+'0');beer=0;delay(4000);beer=1; //在LCD上顯示千位的數(shù) if(xx>99)LCD_inter_dat((xx/100)%10+'0'); beer=0;delay(4000);beer=1;//百位 if(xx>9)LCD_inter_dat((xx/10)%10+'0');beer=0;delay(4000); beer=1;//十位 LCD_inter_dat(xx%10+'0');beer=0;delay(4000); beer=1;//個(gè)位 if(xiao_temp!=0) //顯示小數(shù)部分 { LCD_inter_dat('.');beer=0;delay(4000);beer=1; LCD_inter_dat((xiao_temp/100)%10+'0');beer=0;delay(4000);beer=1; LCD_inter_dat((xiao_temp/10)%10+'0');beer=0;delay(4000);beer=1; LCD_inter_dat(xiao_temp%10+'0');beer=0;delay(4000);beer=1; } } else {LCD_inter_command(0xc0);//從第二行開(kāi)始顯示 for(i=0;i<=4;i++) { LCD_inter_dat(tab3[i]); beer=0; delay(4000);//延時(shí) beer=1; } } } void get_end(void)//計(jì)算子程序 { float xiaoshu=1; uchar fu_flag=0; uchar xiao_flag=0; uchar lianji_sign; uchar i=0; uchar j; uchar n;//正負(fù)標(biāo)記符 while(i<=xiabiao) { while(tab[i]<=0x39&&tab[i]>=0x30) { n=0; opr_1*=10; opr_1+=tab[i++]-0x30; n='+'; } switch(tab[i]) { case '.': xiao_flag=1;break;//遇到小數(shù)點(diǎn)跳到“if(xiao_flag)”里 case '!': fu_flag=1;break; case '+': xiaoshu=1;yun_sign='+';if(opr_temp==0){end=opr_temp=opr_1;}else hun_he(lianji_sign);opr_1=0;lianji_sign='+'; break; case '-': xiaoshu=1;yun_sign='-';if(opr_temp==0){end=opr_temp=opr_1;}else hun_he(lianji_sign);opr_1=0;lianji_sign='-'; break; case 'x': xiaoshu=1;yun_sign='x';if(opr_temp==0){end=opr_temp=opr_1;}else hun_he(lianji_sign);opr_1=0;lianji_sign='*';break; case '/': xiaoshu=1;yun_sign='/';if(opr_temp==0){end=opr_temp=opr_1;}else hun_he(lianji_sign);a=opr_1;opr_1=0;lianji_sign='/';break; case '=': switch(yun_sign)//進(jìn)行運(yùn)算 { case '+':end=opr_temp+opr_1;break; case '-':end=opr_temp-opr_1;break; case 'x':end=opr_temp*opr_1;break; case '/':{ if(a==0)//減數(shù)為零顯錯(cuò) { LCD_inter_command(0xc0); for(j=0;j<=4;j++) { LCD_inter_dat(tab3[j]); beer=0; delay(4000);//延時(shí) beer=1; } } else {end=opr_temp/opr_1;} break; } default:break; } ok=1;//開(kāi)始進(jìn)行顯示,標(biāo)志位置1 xiabiao=0;//小數(shù)的標(biāo)志位清零 break; default:break; } i++; if(xiao_flag)//表示小數(shù) { while(tab[i]<=0x39&&tab[i]>=0x30) { xiaoshu*=0.1; switch(n) { case '+': opr_1=opr_1+(tab[i++]-0x30)*xiaoshu;break; case '-': opr_1=opr_1-(tab[i++]-0x30)*xiaoshu; break ; default:break; } xiao_flag=0; } }
if(fu_flag) { while(tab[i]<=0x39&&tab[i]>=0x30) { n=0; opr_1=-opr_1*10; opr_1=-(opr_1+(tab[i++]-0x30)); n='-'; fu_flag=0; } } } opr_1=0; opr_temp=0; xiabiao=0; xiaoshu=1; 下方為原理圖: |
|
來(lái)自: lixinhecom > 《計(jì)算器》