📄 计数器.txt
字号:
// 1 2 3 + =
// 4 5 6 - ce
// 7 8 9 * on/off
// +/- 0 . /
//按键: 0 1 2 3 4 5 6 7 8 9
//对应值: 0 1 2 3 4 5 6 7 8 9
//按键: + - * / = . +/-
//对应值: 10 11 12 13 15 16 17
#include "reg51.h"
#include "math.h"
#define key_null 255
#define uchar unsigned char
#define uint unsigned int
sbit P0_0=P0^0 ;
sbit P0_1=P0^1 ;
sbit P0_2=P0^2 ;
sbit P0_3=P0^3 ;
sbit P0_4=P0^4 ;
sbit P0_5=P0^5 ;
sbit P0_6=P0^6 ;
sbit P0_7=P0^7 ;
sbit P1_0=P1^0 ;
sbit P1_1=P1^1 ;
sbit P1_2=P1^2 ;
sbit P1_3=P1^3 ;
sbit P1_4=P1^4 ;
sbit P1_5=P1^5 ;
sbit P1_6=P1^6 ;
sbit P1_7=P1^7 ;
sbit P2_0=P2^7 ;
sbit P3_0=P3^0 ;
sbit P3_1=P3^1 ;
sbit P3_2=P3^2 ;
sbit P3_3=P3^3 ;
sbit P3_4=P3^4 ;
sbit P3_5=P3^5 ;
sbit P3_6=P3^6 ;
sbit P3_7=P3^7 ;
uchar idata p_led,buff[9],keynum[8],opcode[4],op,operate,key,knum,num,dot ;
// buff[9]的前8个元素为显示屏上8片led对应的数字,buff[8]为显示屏中应显示的数字的个数
// 数组keynum(8)存放从键盘获得的计算数,operate 存放从键盘获的计算符
// key 存放获得的键盘值,区分计算数和计算符后分别存入keynum(8)和operate中
// opcode[4]为为实现优先运算而设立存放计算符
// knum 为 keynum[8]的指针
// num 为 opnum[3]的指针
// dot为keynum[8]中小数点的位置
float opnum[3] ;
// opnum[3]为为实现优先运算而设立存放计算数
bit flag=1;
// 标志是否可将计算符operate存入opcode[]中,以防出现多次按下计算符
bit flag3=1;
// 标志是否有计算符按键按下
bit flag4=0;
// 进行count()中第一种运算的标志
bit flag5=0;
// 进行count()中第二种运算的标志
bit dotflag,revflag;
// dotflag为小数点标志,revflag 为正负数标志
uchar keyscan(void) // 键盘扫描程序
{
uchar temp=key_null;
// 对p0赋初值1111 1111 ,p2_0赋初值0
P0=0xfe;
// 对p0赋值 1111 1110,对第一行进行扫描
if (P0_4==0) temp=1; // 扫描第一列
else if (P0_7==0) temp=10;
P0=0xfe;
if (P2_0==0) temp=15;
P0=0xfe;
if (P0_5==0) temp=2; // 扫描第二列
P0=0xfe;
if (P0_6==0) temp=3; // 扫描第三列
// 扫描第四列
// 扫描第五列
P0= 0xfd; // 对第二行进行扫描
if (P0_4==0) temp=4;
else if (P0_5==0) temp=5;
P0= 0xfd;
if (P0_6==0) temp=6;
else if (P0_7==0) temp=11;
P0=0xfb; // 对第三行进行扫描
if (P0_4==0) temp=7;
else if (P0_5==0) temp=8;
P0=0xfb;
if (P0_6==0) temp=9;
else if (P0_7==0) temp=12;
P0=0xf7; // 对第四行进行扫描
if (P0_4==0) temp=17;
else if (P0_5==0) temp=0;
P0=0xf7;
if (P0_6==0) temp=16;
else if (P0_7==0) temp=13;
//send(temp);
return temp;
}
uchar read_key(void) // 把键盘值取入程序中
{
uchar i;
uint j;
for(;keyscan()!=key_null;); // 等待按键放开
loop: for(;keyscan()==key_null;); // 等待按键按下
i=keyscan();
for(j=0;j<2000;j++) // 延时2ms
if(i==keyscan()) return i; // 两次获取按键,若一致,输出该值
else goto loop ;
}
void ledscan(void) interrupt 1 // 显示屏扫描程序
{
uchar led_code[21]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90, 0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,0xbf};
// led_code[0~9] : 0~9 led_code[10~19]:0.~9. led[20]:-
TH0=-(1000/256);
TL0=-(1000%256); // 计数器复位
if(p_led<buff[8]){
// 对显示屏的led进行动态赋值
if(p_led<4) P3=~(0x10<<p_led); //注意电路中得接法
else P3=~(0x01<<(p_led-4));
P1=led_code[buff[p_led]]; //注意取数时应倒取
p_led++;
}
else p_led=0;
if(p_led==8)p_led=0;
if(buff[7]==20)
{
P3=0xf7;
P1=led_code[20];
}
}
void getopnum(void) // 获取计算数
{
uchar i,n;
float a,b;
if(keynum[0]<20) //如果没有新数进knum[0]=20
{
if(dotflag==1) n=dot; // n为keynum[8]中整数部分的长度
else n=knum;
a=0;
b=0;
for(i=0;i<n;i++) a+=keynum[i]*pow(10,n-i-1); //取出整数部分
if(dotflag==1)
for(i=n+1;i<knum;i++) b+=keynum[i]*pow(0.1,i-n); //取出小数部分
keynum[0]=20;
opnum[num]=a+b;
if(revflag==1)opnum[num]=-opnum[num]; //若有按下+/-键,对opnum[num]取反
if(num==0) opnum[1]=opnum[0];
num++;
}
}
uchar judge(uchar opno1,uchar opno2) //对计算符进行优先级别判断,先乘除后加减
{
char a,b;
switch(opno1)
{
case 10:
a=2;
break;
case 11:
a=2;
break;
case 12:
a=3 ;
break;
case 13:
a=3;
break;
case 14: // 14为自己添加的最低等级的符号,且一直存放在opcode[0]中
a=0;
break;
case 15:
a=1;
break;
}
switch(opno2)
{
case 10:
b=2;
break;
case 11:
b=2;
break;
case 12:
b=3;
break;
case 13:
b=3;
break;
case 14:
b=0;
break;
case 15:
b=1;
break;
}
if((a-b)>=0) return 1; //优先级别高的,所赋的值较大
else return 0;
}
void count(void)
{
while(judge(opcode[op],operate)==1)
{
if(operate==15 && op<=2) //第一种运算,使opcode中至少存放一个计算符,可进行累运算,如2+3===11
{
if(opcode[op]==10) opnum[num-2] += opnum[num-1];
else if(opcode[op]==11) opnum[num-2] -= opnum[num-1];
else if(opcode[op]==12) opnum[num-2] *= opnum[num-1];
else if(opcode[op]==13) opnum[num-2] /= opnum[num-1];
flag4=1;
break;
}
else //在为按下等号时将式中可运算的部分运算完,但要保留最后一个运算符
{
if(opcode[op]==10) opnum[num-2] += opnum[num-1];
else if(opcode[op]==11) opnum[num-2] -= opnum[num-1];
else if(opcode[op]==12) opnum[num-2] *= opnum[num-1];
else if(opcode[op]==13) opnum[num-2] /= opnum[num-1];
op--;
num--;
flag5=1;
}
}
}
void send(uchar lednum ) // 送出按键按下时代表的值
{
uchar i;
if(flag3==1)
{
buff[8]=0;
flag3=0;
}
if(lednum>=0 && lednum<=9)
{
for(i=buff[8];i>0;i--) buff[i]=buff[i-1];
buff[0]=lednum;
buff[8]++;
}
if(lednum==16) buff[0]+=10;
if(revflag==1) buff[7]=20;
else buff[7]=0;
}
void send2(float f) // 送出每次可计算的计算结果的值
{
int intnum,temp,i,k,n,j,dectemp[6];
float dec;
bit flag;
buff[7]=0;
flag=0;
i=0;
temp=0;
buff[8]=0;
if(f<0) // #####
{
flag=1;
f=fabs(f);
buff[7]=20;
}
intnum=f;
dec=f-intnum;
if(intnum>0)
{
while(intnum>0)
{
buff[i]=intnum%10;
intnum=intnum/10;
i++;
buff[8]++;
}
n=i;
}
else buff[0]=0;
if(dec>0.000009 && dotflag==1)
{
buff[0]+=10;
for(j=0;j<6;j++)
{
dec*=10;
temp=dec;
dec-=temp;
dectemp[j]=temp;
}
dectemp[5]+=5 ; //########################
for(i=4;i>=0;i--)
{
dectemp[i]+= dectemp[i+1]/10; //#########################
dectemp[i+1]=dectemp[i+1]%10;
} //######################
dectemp[0]=dectemp[0]%10;
for(j=4;j>=0;j--)
{
if(dectemp[j]!=0)
{
temp=j;
break;
}
temp=j;
}
if(flag==1) k=7;
else k=8;
for(j=0;j<=temp && n+j<k;j++)
{
for(i=buff[8];i>0;i--) buff[i]=buff[i-1];
buff[0]=dectemp[j];
buff[8]++; //##### 此算法为将所得结果浮点型的数拆分为单个整数,存放在数组buff中
}
}
}
void getnum()
{
uchar k;
key=read_key();
if(key==16 && dotflag==0)
{
dotflag=1;
if(knum==0)
{
keynum[0]=0;
knum++;
buff[8]=1;
}
dot=knum;
knum++;
send(16);
}
if(key==17)
{
revflag=!revflag;
send(17);
} //main(): flag2=revflag
if(key>=0 && key<=9)
{
if(revflag==1) k=7;
else k=8;
if(knum<=k)
{
keynum[knum]=key;
knum++;
if(operate==15)
{
opcode[0]=14;
op=0;
num=0;
revflag=0;
}
if(flag==1 && (opcode[op]!=15 || operate!=15))
{
op++;
opcode[op]=operate;
flag=0;
}
send(key);
}
}
else if(key>=10 && key<16)
{
flag3=1;
if(key!=15 && flag==1 && operate==15)
{
op=0;
opcode[0]=14;
num--;
}
if(flag==0)
{
getopnum();
}
operate=key;
flag=1;
if(num>=2 && op>=1) count();
if(flag4==1)
{
send2(opnum[num-2]);
flag4=0;
}
else if(flag5==1)
{
send2(opnum[num-1]);
flag5=0;
}
knum=0;
dotflag=0;
revflag=0;
}
}
main()
{
p_led=0;
P1=0xc0;
P3=0xef;
buff[8]=0;
buff[7]=0;
knum=0;
op=0;
num=0;
operate=14;
opnum[0]=0;
buff[0]=0;
revflag=0;
dotflag=0;
TH0=-(1000/256);
TL0=-(1000%256);
TMOD=0x01;
EA=1;
ET0=1;
TR0=1;
while(1) getnum();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -