|
本帖最后由 1428327352 于 2019-4-19 19:29 編輯
由于新學(xué)習(xí)的單片機(jī)C語言,寫程序手法稚嫩,但適合新手做參考。算法比較繁瑣,但是經(jīng)過我一上午的修復(fù),現(xiàn)在已經(jīng)沒有任何漏洞了。。
四位數(shù)于四位數(shù)之間的加減乘除計算
已經(jīng)能夠顯示小數(shù)點后兩位,例:10/3=3.33;1/2=0.5;1/20=0.05
能夠計算負(fù)數(shù),例:1-20=-19;
基于1602液晶顯示屏
由于按鍵個數(shù)原因,目前只打了以下16個鍵
以后在擴(kuò)展的話會更新
1 | 2 | 3 | + | 4 | 5 | 6 | - | 7 | 8 | 9 | * | ce | 0 | = | / |
1602我的想法是送一行地址,再送一行數(shù)據(jù)
計算器主要分為顯示程序,計算程序,和按鍵掃描程序
將其結(jié)合
電路圖;
QQ圖片20190323202201.png (27.99 KB, 下載次數(shù): 97)
下載附件
2019-4-12 19:52 上傳
QQ圖片20190323202136.png (62.23 KB, 下載次數(shù): 85)
下載附件
2019-4-12 19:53 上傳
QQ圖片20190323202154.jpg (118 KB, 下載次數(shù): 94)
下載附件
2019-4-12 19:54 上傳
元器件:
QQ圖片20190323203108.png (16.92 KB, 下載次數(shù): 77)
下載附件
2019-4-12 19:54 上傳
QQ圖片20190323203100.png (16.6 KB, 下載次數(shù): 83)
下載附件
2019-4-12 19:55 上傳
源代碼:
#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
uchar z,x,num,key,m,n;
uint a; //a,b代表算子
ulong b, c; //這個c代表結(jié)果,原只想將c用ulong的,因為c是結(jié)果需要的數(shù)據(jù)范圍大,但是試了不行,只有將
ac或bc或abc設(shè)成大范圍才可以。在這里為節(jié)省存儲,設(shè)了bc?梢哉_\行到一個很大的數(shù)了。
uchar c1,c2,c3,c4,c5,c6,c7,c8;
void delay(uint xms)
{
uint i,j;
for(i=xms;i>0;i--)
for(j=110;j>0;j--);
}
sbit rs=P2^6;
sbit rw=P2^5;
sbit en=P2^7;
uchar code table[]="ERROR!"; // 在除數(shù)為0時直接報錯
void write_com(uchar com) //д???? //讀命令
{
rs=0;
rw=0;
delay(5);
P0=com;
delay(5);
en=1;
delay(5);
en=0;
delay(5);
}
void write_date(uchar date) //д???? //讀數(shù)據(jù)
{
rs=1;
rw=0;
delay(5);
P0=date;
delay(5);
en=1;
delay(5);
en=0;
delay(5);
}
void init() //????? 初始化函數(shù)
{
n=0;
m=5;
write_com(0x38);
write_com(0x0c);
write_com(0x06);
write_com(0x01);
write_com(0x80);
write_date('0');
}
short keycheckdown() /* ???????????? */鍵盤掃描函數(shù),帶回一個返回值,所以這里不用void
{
short temp1,temp2,temp,x=0xff;
P1=0xf0; /* ???????????????? */
delay(20); /* ??? */
temp1=P1; /* ?????????????? */
P1=0xff;
delay(20); /* ??? */
P1=0x0f; /* ???????????????? */
delay(20); /* ??? */
temp2=P1; /* ?????????????? */
P1=0xff;
temp=(temp1&0xf0)|(temp2&0xf); /* ?????ζ?????????? */
switch(temp) /* ???????????????ж????λ?? */
{
case 0x7e :x=0x0d;break;// ????/
case 0x7d :x=0x0e; break;// ????=
case 0x7b: x=0; break;// ????0
case 0x77 :x=0x0f; break;// ????CE
case 0xbe :x=0x0c;break;// ????*
case 0xbd :x=0x09;break; // ????9
case 0xbb :x=0x08;break; // ????8
case 0xb7 :x=0x07;break; // ????7
case 0xde :x=0x0b;break;// ????-
case 0xdd:x=0x06;break; // ????6
case 0xdb :x=0x05;break; // ????5
case 0xd7 :x=0x04;break; // ????4
case 0xee :x=0x0a; break;// ????+
case 0xed :x=0x03;break; // ????3
case 0xeb :x=0x02;break; // ????2
case 0xe7 :x=0x01;break; // ????1
default :x=0xff;
}
return x; /* ???????? */ 返回x
}
void axian() //算子a的顯示程序
{
uchar a1,a2,a3,a4;
write_com(0x01);
a1=a%10000/1000; //? 0
a2=a%1000/100; //?? 0
a3=a%100/10; //? 1
a4=a%10; //?? 2
if(999<a) {
write_com(0x80);
write_date('0'+a1);
delay(5);
}
if(99<a) {
write_com(0x81);
write_date('0'+a2);
delay(5);
}
if(9<a) {
write_com(0x82);
write_date('0'+a3);
delay(5);
}
if(0<a) {
write_com(0x83);
write_date('0'+a4);
delay(5);
}
}
void bxian() //算子b的4位,即上限為9999,a上限也是9999;
{
uchar b1,b2,b3,b4; // 1*10+2=12
b1=b%10000/1000; //? 0
b2=b%1000/100; //?? 0
b3=b%100/10; //? 1
b4=b%10; //?? 2
if(999<b)
{
write_com(0x88);
write_date('0'+b1);
delay(5);
}
if(99<b) {
write_com(0x89);
write_date('0'+b2);
delay(5);
}
if(9<b) {
write_com(0x8a);
write_date('0'+b3);
delay(5);
}
if(0<b) {
write_com(0x8b);
write_date('0'+b4);
delay(5);
}
if(b==0) { init(); //若除數(shù)為0,初始化并且報錯
write_com(0x80);
for(num=0;num<6;num++)
{
write_date(table[num]);
delay(5);
}
}
}
void gong() 這個是一些程序中重復(fù)使用的部分,將其提取成一個子函數(shù),會更簡潔
{
if(c>999)
{
write_com(0xc5);
write_date('0'+c5);
delay(5);
}
if(c>99)
{
write_com(0xc6);
write_date('0'+c6);
delay(5);
}
if(c>9)
{
write_com(0xc7);
write_date('0'+c7);
delay(5);
}
if(c>0)
{
write_com(0xc8);
write_date('0'+c8);
delay(5);
}
}
void jian() 減法會出現(xiàn)負(fù)號,需要特殊處理,顯示程序就和其他三個不一樣了
{
c5=c%10000/1000; //? 0
c6=c%1000/100; //?? 0
c7=c%100/10; //? 1
c8=c%10;
if(z==2) 當(dāng)減號鍵被按下時
{
if(b>a) 當(dāng)后一個數(shù)大于前一個數(shù)時
{
write_com(0xc4); 顯示負(fù)號
write_date('-');
delay(5);
if(b-a>999) 顯示負(fù)號后面的結(jié)果
{
write_com(0xc5);
write_date('0'+c5);
delay(5);
}
if(b-a>99)
{
write_com(0xc6);
write_date('0'+c6);
delay(5);
}
if(b-a>9)
{
write_com(0xc7);
write_date('0'+c7);
delay(5);
}
if(b-a>0)
{
write_com(0xc8);
write_date('0'+c8);
delay(5);
}
}
if(a>b) 如果前數(shù)大于后數(shù)的話
{
gong();
}
}
}
void chu() 除號會出現(xiàn)小數(shù)點,所以將其特殊處理,自成函數(shù)
{
if(z==4)
{
c=a*100/b;
c1=c/100000;
c2=c%100000/10000;
c3=c%10000/1000;
c4=c%1000/100;
c6=c%100/10;
c7=c%10;
if(a%b!=0) 如果不能整除
{
if(c>100)
{
if(c>99999)
{
write_com(0xc1);
write_date('0'+c1);
delay(5);
}
if(c>9999)
{
write_com(0xc2);
write_date('0'+c2);
delay(5);
}
if(c>999)
{
write_com(0xc3);
write_date('0'+c3);
delay(5);
}
if(c>99)
{
write_com(0xc4);
write_date('0'+c4);
delay(5);
}
write_com(0xc5);
write_date('.');
delay(5);
if(c>9)
{
write_com(0xc6);
write_date('0'+c6);
delay(5);
}
write_com(0xc7);
write_date('0'+c7);
delay(5);
}
}
if(9<c&&c<99) 在這里需注意不能寫成9<c<99!!
{
write_com(0xc4);
write_date('0');
delay(5);
write_com(0xc5);
write_date('.');
delay(5);
if(c>9)
{
write_com(0xc6);
write_date('0'+c6);
delay(5);
}
write_com(0xc7);
write_date('0'+c7);
delay(5);
}
if(c<9)
{
write_com(0xc4);
write_date('0');
delay(5);
write_com(0xc5);
write_date('.');
delay(5);
write_com(0xc6);
write_date('0');
write_com(0xc7);
write_date('0'+c7);
delay(5);
}
}
if(a%b==0) 如果能夠整除
{
c=a/b;
c1=c/1000;
c2=c%1000/100;
c3=c%100/10;
c4=c%10;
if(c>999)
{
write_com(0xc1);
write_date('0'+c1);
delay(5);
}
if(c>99)
{
write_com(0xc2);
write_date('0'+c2);
delay(5);
}
if(c>9)
{
write_com(0xc3);
write_date('0'+c3);
delay(5);
}
if(c>0)
{
write_com(0xc4);
write_date('0'+c4);
delay(5);
}
}
}
}
void cxian() c的顯示程序
{
if(z==1||z==3) 若按下的是加號或乘號,因為減法可能出現(xiàn)-,除法可能出現(xiàn)".",所以顯示要分開
{
c1=c%100000000/10000000;
c2=c%10000000/1000000;
c3=c%1000000/100000;
c4=c%100000/10000; // 1*10+2=12
c5=c%10000/1000; //? 0
c6=c%1000/100; //?? 0
c7=c%100/10; //? 1
c8=c%10; //?? 2
if(9999999<c)
{
write_com(0xc1);
write_date('0'+c1);
delay(5);
}
if(c>999999)
{
write_com(0xc2);
write_date('0'+c2);
delay(5);
}
if(c>99999)
{
write_com(0xc3);
write_date('0'+c3);
delay(5);
}
if(c>9999)
{
write_com(0xc4);
write_date('0'+c4);
delay(5);
}
gong();
}
}
void eql() 計算程序
{
switch(z)
{
case 0: break;
case 1: c=a+b; break;
case 2: c=a-b;
if(b>a)
{
c=b-a;
}
break;
case 3: c=a*b; break;
case 4: c=a/b; break;
}
}
void main() 主函數(shù)
{
uint key;
init();
while(1)
{
key=keycheckdown(); 將返回的值x賦給key
if(0xff!=key)
{
if(key<10)
{
if(n<4) n初始值為0, 每按下一次,n加一,當(dāng)按下第五次時就不執(zhí)行此if語句。用此方法將a的值固定
{
a=a*10+key;
m=5;
axian();
n++;
}
if(m<4) m的初始值為5,此時不會進(jìn)入這個程序,只有在運算符打出后,才將m的值命令得符合這個if語句
{
b=b*10+key;
n=5;
bxian();
m++;
}
}
else
{
switch(key) 判斷是那個運算符,并且將其顯示出來。
{
case 0x0a:
n=5;
m=0; 在運算符給出后,放開后一個數(shù),可以打后一個數(shù)了
z=1;
write_com(0x85);
write_date('+');
break;
case 0x0b:
n=5;
m=0;
z=2;
write_com(0x85);
write_date('-');
break;
case 0x0c:
n=5;
m=0;
z=3;
write_com(0x85);
write_date('*');
break;
case 0x0d:
n=5;
m=0;
z=4;
write_com(0x85);
write_date('/');
break;
case 0x0e: 當(dāng)是等號時,鎖定兩個算子a,b,此時已經(jīng)固定
m=5;
n=5;
eql(); 對a,b進(jìn)行計算
jian();
chu();
write_com(0xc0);
write_date('=');
cxian();
break;
case 0x0f: ce鍵,清零
n=0;
z=0;
m=5;
a=0;
b=0;
c=0;
init();
break;
}
do{P1=0xf0;}
while(P1!=0xf0);
}
}
}
}
|
評分
-
查看全部評分
|