}
/****端口初始化****/
voidport_init()
{
DI=0xff;
DDRA|=BIT(0);
DDRA|=BIT
(1);//输出状态
lone_key_ddr&=~BIT(0);
lone_key_port|=BIT(0);//独立键盘接口设置为输入,并打开上拉电阻
DDRD=0;//全部设为输入,有个上拉电阻,可以输入高电平
DDRB=0xff;
}
/*******夜晶初始化********/
voiddevice_init()
{
en_0;//使能端拉低
wright_com(0x38);//初始化格式
wright_com(0x0c);//0x0e打开光标0x0c不显示光标0x0e光标不闪,0x0f光标闪
wright_com(0x01);//清显示
wright_com(0x80);
for(i=0;i<17;i++)
{
wright_data(table1[i]);
_delay_ms(20);
}
}
/******夜晶写入指令的函数***********/
voidwright_com(ucharcom)
{
rs_0;//低电平时写指令
DI=com;
_delay_ms
(1);
en_1;
_delay_ms
(1);
en_0;
}
/******夜晶写入数据的函数**********/
voidwright_data(uchardata)
{
rs_1;//高电平时写数据
DI=data;
_delay_ms
(1);
en_1;
_delay_ms
(1);
en_0;
}
/**********4x4矩阵键盘及一个独立键盘的扫描函数*********/
ucharkeyscan(void)
{
unsignedchartemp,temp1,key,row,column;
key_ddr=0x0f;//高四位输入列线/低四位输出到行线
key_port=0xf0;//高四位打开上拉电阻/低四位输出低电平上拉电阻会把电平拉高
if(lone_key_pin==0)
{
_delay_ms(5);//延时消抖
if(lone_key_pin==0)
{
_delay_ms(90);//等待松手
return(31);
}
}
if((key_pin&0xF0)!
=0xF0)//作初检查有否键按下,没有,就返回如果列线不全为1,可能有键按下
{
_delay_ms(5);//延时去抖动
if((key_pin&0xF0)!
=0xF0)//确认有按键按下
{
_delay_ms(1000);//延时等待松手
for(row=0,key_port=0b11111110;row<4;row++)
{
for(column=0,temp=0b11101111;column<4;column++)//设置列线初始值1110
{
if((key_pin&0xF0)==(temp&0xF0))//输入列线,查看这列有否键按下
{
key=4*row+column;//键编码=4*行输入值+列扫描值
key=key_table[key];//键盘编码转换键值
return(key);
}
temp<<=1;//列线左移1位
}
key_port=((key_port<<1)|0x01);//行线扫描值左移1位,扫描下一行
}
}
}
return(No_key);
}
/****对键盘扫描返回值进行判断是不是为符号*******/
voidjudgechar(uchart)//用带参数的函数可以减少键盘扫描次数
{
if(t>9&&t<14&&allowflag)//符号范围
{
fuhao=1;//标志为符号,为后面的程序作决断算完后再将其清零
allowflag=0;//禁止下一个符号的输入,只能输入一个符号
if(t==10)//输入的是减号
{
wright_data('/');
}
if(t==11)//输入的是减号
{
wright_data('*');
}
if(t==12)//输入的是减号
{
wright_data('-');
}
if(t==13)//输入的是减号
{
wright_data('+');
}
sym=t;//把符号的编号保存下来,方便以后调用
}
}
/*****夜晶显示处理,该显示什么,不该显示什么*****/
voidlcd_handle(uchartemp)//用带参数的函数可以减少键盘扫描次数
{
if(temp>=0&&temp<10)//以下处理仅对数字有效
{
if(fuhao)//表示已经写了符号了,提示是输入第二个数了
{
if(deflag2)//判断为小数部分
{
if(dd<=3)
{
wright_data('0'+temp);//输入一个数就显示一个数
b1[++dd]=temp;//保存小数点后面的数字
}
else
overflag=1;
}
else//整数部分
if(bb<=5)//条件为位数还不足六位
{
wright_data('0'+temp);//输入一个数就显示一个数
b[++bb]=temp;//输入的是第二个数保存的是整数部分
}
else
overflag=1;//数值溢出
}
else//输入的是第一个数
{
if(deflag1)//判断为小数部分
{
if(cc<=3)
{
wright_data('0'+temp);//输入一个数就显示一个数
a1[++cc]=temp;//保存小数点后面的数字
}
else
overflag=1;
}
else//整数部分
if(aa<=5)//条件为位数还不足六位
{
if(aa==0)
{
wright_com(0x80);//从每个位置起写
}
wright_data('0'+temp);//输入一个数就显示一个数
a[++aa]=temp;//保存的是整数部分
}
else
overflag=1;//数值溢出
}
}
}
/*********重新初始化的函数*********/
voidreset()//按下复位键后变量要全部变到初始状态
{
uchark;
for(k=1;k<7;k++)
{
a[k]=0;
b[k]=0;
}
overflag=0;//溢出标志复位
flag=0;//启动标志复位
allowflag=1;//符号允许标志置位
fuhao=0;//符号已使用标志复位
aa=0;
bb=0;//元素个数清零
sym=0;//符号的编码置0;
}
/***********对数值进行计算,a[],b[]存储的是数,sym操作符编号***********/
voidcalculate(void)
{
switch(aa)//根据位数代入对应的公式
{
case1:
temp1=a[aa];
break;
case2:
temp1=a[2]+a[1]*10;
break;
case3:
temp1=a[3]+a[2]*10+a[1]*100;
break;
case4:
temp1=a[4]+a[3]*10+a[2]*100+a[1]*1000;
break;
case5:
temp1=a[5]+a[4]*10+a[3]*100+a[2]*1000+a[1]*10000;
break;
case6:
temp1=a[6]+a[5]*10+a[4]*100+a[3]*1000+a[2]*10000+a[1]*100000;
}
switch(bb)//根据位数代入对应的公式
{
case1:
temp2=b[bb];
break;
case2:
temp2=b[2]+b[1]*10;
break;
case3:
temp2=b[3]+b[2]*10+b[1]*100;
break;
case4:
temp2=b[4]+b[3]*10+b[2]*100+b[1]*1000;
break;
case5:
temp2=b[5]+b[4]*10+b[3]*100+b[2]*1000+b[1]*10000;
break;
case6:
temp2=b[6]+b[5]*10+b[4]*100+b[3]*1000+b[2]*10000+b[1]*100000;
}
temp3=a1[1]*1000+a1[2]*100+a1[3]*10+a1[4];
temp4=b1[1]*1000+b1[2]*100+b1[3]*10+b1[4];//小数部分放大10000倍
temp1=temp1+temp3/10000.0;
temp2=temp2+temp4/10000.0;//整数与小数的结合
switch(sym)//判断输入的是哪个操作符并作相应的计算
{
case10:
temp1=temp1/temp2;
break;
case11:
temp1=temp1*temp2;
break;
case12:
temp1=temp1-temp2;
break;
case13:
temp1=temp1+temp2;
break;
}
if(temp1>999999.9999)//数据溢出要作处理
overflag=1;
temp1*=10000;//变成整数处理,方便
if(temp1<0)
{
temp1=-temp1;//变负为正
negative=1;//负数标志
}
}
/*****把结果数值拆分显示*********/
voidresult(longvalue)
{
ucharwe[10];
uchark;
ucharj;
we[10]=value/1000000000;
we[9]=value/100000000%10;
we[8]=value/10000000%10;
we[7]=value/1000000%10;
we[6]=value/100000%10;
we[5]=value/10000%10;
we[4]=value/1000%10;
we[3]=value/100%10;
we[2]=value/10%10;
we[1]=value%10;
if(negative)
{
wright_data('-');//要是得到的结果是个负数得先输入个负号
}
for(k=10;k>5;k--)//只能十位以上的数字进行检测,个位的不管是不是零都要显示
{
if(we[k]!
=0)
{
break;//确定第一个非零数字,只显示有效数字
}
}
for(j=k;j>0;j--)//从第一个非零数字开始显示
{
if(j==4)
wright_data('.');//小数部分前面要加个小数点
wright_data('0'+we[j]);
_delay_ms
(2);
}
}
/**********溢出提示函数*******************/
voidflow_clew()
{
ucharnum;
if(overflag)
{
wright_com(0x80+0x40+5);
for(num=0;num<6;num++)
{
wright_data(table2[num]);
_delay_ms
(2);
}
}
}
/***********判断是不是小数点**************/
voiddecimal(ucharde)
{
if(de==31)
{
if(fuhao==0&&deflag1==0)//条件为正在输入的是第一个数且此数之前还没有小数点出现
{
wright_data('.');//显示小数点
deflag1=1;//不能再有下一个小数点了,置位可以防止有第二个小数点
}
if(fuhao&&deflag2==0)//条件为正在输入的是第一个数且此数之前还没有小数点出现
{
wright_data('.');//显示小数点
deflag2=1;//不能再有下一个小数点了,置位可以防止有第二个小数点
}
}
}