原理图 51单片机简易计算器程序: #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; //---------声明函数-------------------- void ch451_init(void); //CH451初始化 void ch451_write(uint command);//写命令或数据到ch451 uchar ch451_read()(void); //读按键值 uchar get_char(void); void LCD_init(void);//初始化; void delay(unsigned int k);//延时程序 void LCD_inter_command(unsigned char command);//写入控制字 void LCD_inter_dat(unsigned char dat);//写入要显示的数据 void set_xy(unsigned char x,unsigned char y);//找地址 void write(unsigned char date);//写入字符 void lcdbusy();//查忙时 void display()(void); void spec(void); void get_end(void); void hun_he(uchar n); //-------- 主函数---------------------- void main() { uchar i; LCD_init();//LCD初始化; ch451_init();//CH451初始化 EA = 1;//打开中断 LCD_inter_command(0x01);//清屏 for(i=0;i<=14;i++) { LCD_inter_dat(tab1[i]); beer=0; delay(4000);//延时 beer=1; } LCD_inter_command(0xc0);//从第二行开始显示 for(i=0;i<=14;i++) { LCD_inter_dat(tab2[i]); beer=0; delay(4000);//延时 beer=1; } delay(0xffff); delay(0xffff); LCD_inter_command(0x01); while(1) { if(ok) { display()(); ok=0;clr=1; } } } //----------子函数-------------------- 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)//减数为零显错 { LCD_inter_command(0xc0); for(j=0;j<=4;j++) { LCD_inter_dat(tab3[j]); beer=0; delay(4000);//延时 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); //开显示 ch451_write(0x580); //BCD译码方式 } void ch451_write(uint command)//写命令或数据到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行开始显示 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; //遇到“=”,开始运算 break; case 0x59:dis='.';break; //小数点 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)//延时程序 { while (k--); } void LCD_inter_command(unsigned char command)//写入控制字 { 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);//设置为8位的数据接口,两行显示,5、7点字符 delay(5000); LCD_inter_command(0x0E);//显示打开,光标开并闪烁 delay(5000); } void LCD_inter_dat(unsigned char dat)//写入要显示的数据 { 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) //转化在LCD上显示计算结果 { int temp=end; //浮点数 int i; uint xiao_temp; uint xx; //浮点数的整数部分 if (end>-32769&&end<32768) { xx=fabs(end); xiao_temp=(fabs(end)-xx)*1000;//取出浮点数的小数部分 LCD_inter_command(0xc0); if(end<0) LCD_inter_dat('-');beer=0;delay(4000); beer=1;//判断是否为负数,若是则显示负号 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上显示千位的数 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;//个位 if(xiao_temp!=0) //显示小数部分 { 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);//从第二行开始显示 for(i=0;i<=4;i++) { LCD_inter_dat(tab3[i]); beer=0; delay(4000);//延时 beer=1; } } } void get_end(void)//计算子程序 { float xiaoshu=1; uchar fu_flag=0; uchar xiao_flag=0; uchar lianji_sign; uchar i=0; uchar j; uchar n;//正负标记符 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;//遇到小数点跳到“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)//进行运算 { 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)//减数为零显错 { LCD_inter_command(0xc0); for(j=0;j<=4;j++) { LCD_inter_dat(tab3[j]); beer=0; delay(4000);//延时 beer=1; } } else {end=opr_temp/opr_1;} break; } default:break; } ok=1;//开始进行显示,标志位置1 xiabiao=0;//小数的标志位清零 break; default:break; } i++; if(xiao_flag)//表示小数 { 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; 下方为原理图: |
|
来自: lixinhecom > 《计算器》