標(biāo)題:
51單片機(jī)計(jì)算器的制作
[打印本頁]
作者:
a5d5d8e8e
時(shí)間:
2016-12-22 09:27
標(biāo)題:
51單片機(jī)計(jì)算器的制作
0.jpg
(65.61 KB, 下載次數(shù): 112)
下載附件
2016-12-23 04:04 上傳
#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);//寫命令或數(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);//寫入控制字
void LCD_inter_dat(unsigned char dat);//寫入要顯示的數(shù)據(jù)
void set_xy(unsigned char x,unsigned char y);//找地址
void write(unsigned char date);//寫入字符
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;//打開中斷
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);//從第二行開始顯示
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); //開顯示
ch451_write(0x580); //BCD譯碼方式
}
void ch451_write(uint command)//寫命令或數(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行開始顯示
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; //遇到“=”,開始運(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)//寫入控制字
{
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);//顯示打開,光標(biāo)開并閃爍
delay(5000);
}
void LCD_inter_dat(unsigned char dat)//寫入要顯示的數(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);//從第二行開始顯示
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;//開始進(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)*xiaosh
u; 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;
}
復(fù)制代碼
作者:
cjjcjj1
時(shí)間:
2017-3-17 14:50
提示:
作者被禁止或刪除 內(nèi)容自動(dòng)屏蔽
作者:
zqy181818
時(shí)間:
2017-3-17 15:02
不錯(cuò)哦
歡迎光臨 (http://www.torrancerestoration.com/bbs/)
Powered by Discuz! X3.1