標題: 一個簡單的計算器 單片機程序(含原理圖,代碼注釋) [打印本頁]
作者: 張大仙123 時間: 2019-10-13 12:43
標題: 一個簡單的計算器 單片機程序(含原理圖,代碼注釋)
0.png (24.28 KB, 下載次數: 33)
下載附件
2019-10-13 18:37 上傳
用的是普中的開發板,下面是程序:#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
sbit LcdEn_P = P2^5; // 1602液晶的EN管腳
sbit LcdRw_P = P2^6; // 1602液晶的RW管腳
sbit LcdRs_P = P2^7; // 1602液晶的RS管腳
ulong num1; // 運算數1
ulong num2; // 運算數2
ulong num3; // 計算結果
uchar cal; // 運算符號,1加,2減,3乘,4除
uchar num1_flag; // 運算數1的輸入標志
uchar num2_flag; // 運算數2的輸入標志
/*********************************************************/
// 毫秒級的延時函數,time是要延時的毫秒數
/*********************************************************/
void DelayMs(uint time)
{
uint i,j;
for(i=0;i<time;i++)
for(j=0;j<112;j++);
}
/*********************************************************/
// 1602液晶寫命令函數,cmd就是要寫入的命令
/*********************************************************/
void LcdWriteCmd(uchar cmd)
{
LcdRs_P = 0;
LcdRw_P = 0;
LcdEn_P = 0;
P0=cmd;
DelayMs(2);
LcdEn_P = 1;
DelayMs(2);
LcdEn_P = 0;
}
/*********************************************************/
// 1602液晶寫數據函數,dat就是要寫入的數據
/*********************************************************/
void LcdWriteData(uchar dat)
{
LcdRs_P = 1;
LcdRw_P = 0;
LcdEn_P = 0;
P0=dat;
DelayMs(2);
LcdEn_P = 1;
DelayMs(2);
LcdEn_P = 0;
}
/*********************************************************/
// 1602液晶初始化函數
/*********************************************************/
void LcdInit()
{
LcdWriteCmd(0x38); // 16*2顯示,5*7點陣,8位數據口
LcdWriteCmd(0x0C); // 開顯示,不顯示光標
LcdWriteCmd(0x06); // 地址加1,當寫入數據后光標右移
LcdWriteCmd(0x01); // 清屏
}
/*********************************************************/
// 液晶光標定位函數
/*********************************************************/
void LcdGotoXY(uchar line,uchar column)
{
// 第一行
if(line==0)
LcdWriteCmd(0x80+column);
// 第二行
if(line==1)
LcdWriteCmd(0x80+0x40+column);
}
/*********************************************************/
// 液晶輸出字符串函數
/*********************************************************/
void LcdPrintStr(uchar *str)
{
while(*str!='\0')
LcdWriteData(*str++);
}
/*********************************************************/
// 液晶輸出數字
/*********************************************************/
void LcdPrintNum(uchar num)
{
LcdWriteData(num+0x30);
}
/**********************************************************
矩陣鍵盤掃描程序.
如果掃描到有按鍵按下,則返回按鍵值,返回值情況如下所示:
-------------------------------------------------------------
| 第1列 第2列 第3列 第4列 |
|第1行 1 2 3 10 |
|第2行 4 5 6 11 |
|第3行 7 8 9 12 |
|第4行 13 0 14 15 |
------------------------------------------------------------
如果掃描不到有按鍵按下,則返回99
**********************************************************/
uchar KeyScanf()
{
uchar ret,temp1,temp2;
P1=0x0f;
if(P1!=0x0f)
{
DelayMs(15);
if(P1!=0x0f)
{
temp1=P1; // 判斷出是哪一行按鍵按下
P1=0xf0;
DelayMs(5);
temp2=P1; // 判斷出是哪一列按鍵被按下
ret=temp1|temp2; // 通過行和列的值,確定是哪個按鍵被按下
switch(ret)
{
case 0xe7: return 1;
case 0xd7: return 2;
case 0xb7: return 3;
case 0x77: return 10;
case 0xeb: return 4;
case 0xdb: return 5;
case 0xbb: return 6;
case 0x7b: return 11;
case 0xed: return 7;
case 0xdd: return 8;
case 0xbd: return 9;
case 0x7d: return 12;
case 0xee: return 13;
case 0xde: return 0;
case 0xbe: return 14;
case 0x7e: return 15;
}
return ret;
}
}
return 99;
}
/*********************************************************/
// 主函數
/*********************************************************/
void main()
{
uchar ret;
uchar i;
LcdInit();
while(1)
{
LcdWriteCmd(0x01); // 清除屏幕顯示
LcdWriteCmd(0x0f); // 開啟光標閃爍
num1=0; // 運算數1 清零
num2=0; // 運算數2 清零
num3=0; // 計算結果 清零
cal=0; // 運算符號 清零
i=0; // 臨時變量 清零
num1_flag=0; // 運算數1輸入標志 清零
num2_flag=0; // 運算數2輸入標志 清零
while(1)
{
ret=KeyScanf(); // 讀取矩陣鍵盤的掃描結果
if(ret!=99) // 返回值不等于99,說明有按鍵按下了
{
DelayMs(20);
ret=KeyScanf(); // 讀取矩陣鍵盤的掃描結果
if(ret!=99)
{
/*檢測到的是按下數字*/
if(ret<10)
{
if(cal==0) // 如果cal的值為0,說明現在在輸入運算數1
{
if(num1<1000) // 限制運算數1的大小小于10000
{
LcdPrintNum(ret); //將按下的數字鍵刷新顯示
num1=num1*10+ret; // 把運算數1放大10倍
num1_flag=1; // 將運算數1的標志變量num1_flag置1,說明運算數1已輸入
}
}
else // 如果cal的值不為0,說明現在在輸入運算數2
{
if(num2<1000) // 限制運算數2的大小小于10000
{
LcdPrintNum(ret); // 將按下的數字鍵顯示
num2=num2*10+ret; // 把運算數2放大10倍
num2_flag=1; // 將運算數2的標志變量num2_flag置1,說明運算數2已輸入
}
}
}
/*檢測到的是按下加號*/
if(ret==10)
{
if(cal==0) // 判斷是否是第一次輸入計算符號
{
if(num1_flag==0) // 判斷運算數1是否還未輸入
{
LcdPrintNum(0); // 如果是的話,在液晶顯示數字0
num1=0; // 給運算數1一個計算初值0
}
cal=1; // 將運算符變量改為1,代表即將進行加法運算
LcdWriteData('+'); // 把加法運算符號顯示到屏幕上
}
}
/*檢測到的是按下減號*/
if(ret==11)
{
if(cal==0) // 判斷是否是第一次輸入計算符號
{
if(num1_flag==0) // 判斷運算數1是否還未輸入
{
LcdPrintNum(0); // 如果是的話,在液晶上面顯示0
num1=0; // 給運算數1一個計算初值0
}
cal=2; // 將運算符變量改為2,代表即將進行減法運算
LcdWriteData('-'); // 把減法運算符號顯示到屏幕上
}
}
/*檢測到的是按下乘號*/
if(ret==12)
{
if(cal==0) // 判斷是否是第一次輸入計算符號
{
if(num1_flag==0) // 判斷運算數1是否還未輸入
{
LcdPrintNum(0); // 如果是的話,在液晶上面顯示0
num1=0; // 給運算數1一個計算初值0
}
cal=3; // 將運算符變量改為3,代表即將進行乘法運算
LcdWriteData('*'); // 把乘法運算符號顯示到屏幕上
}
}
/*檢測到的是按下除號*/
if(ret==15)
{
if(cal==0) // 判斷是否是第一次輸入計算符號
{
if(num1_flag==0) // 判斷運算數1是否還未輸入
{
LcdPrintNum(0); // 如果是的話,在液晶上面顯示0
num1=0; // 給運算數1一個計算初值0
}
cal=4; // 將運算符變量改為4,代表即將進行除法運算
LcdWriteData('/'); // 把除法運算符號顯示到屏幕上
}
}
/*檢測到的是按下清除鍵*/
if(ret==13)
{
break; // 退出當前的while循環
}
/*檢測到的是按下等于號*/
if(ret==14)
{
if(num2_flag==0) // 判斷運算數2是否還未輸入
{
LcdPrintNum(0); // 如果是的話,在液晶上面顯示0
num2=0; // 給運算數2一個計算初值0
}
switch(cal) // 根據cal這個變量的不同值,采取不同的四則運算
{
/*加法運算*/
case 1:
LcdGotoXY(1,15); // 定位到液晶的第2行最后一列
LcdWriteCmd(0x04); // 光標左移
num3=num1+num2; // 計算結果
if(num3==0) // 如果計算結果為0
{
LcdPrintNum(0); // 在屏幕上顯示0
}
while(num3!=0) // 顯示計算結果
{
LcdPrintNum(num3%10);
num3=num3/10;
}
LcdWriteData('='); // 顯示等于號
LcdWriteCmd(0x06); // 光標右移
break;
/*減法運算*/
case 2:
LcdGotoXY(1,15); // 定位到液晶的第2行最后一列
LcdWriteCmd(0x04); // 光標左移
if(num1>num2)
{
num3=num1-num2; // 計算結果
while(num3!=0) // 顯示計算結果
{
LcdPrintNum(num3%10);
num3=num3/10;
}
}
else if(num1<num2)
{
num3=num2-num1; // 計算結果
while(num3!=0) // 顯示計算結果
{
LcdPrintNum(num3%10);
num3=num3/10;
}
LcdWriteData('-'); // 顯示負號
}
else
{
LcdPrintNum(0); // 顯示數字0
}
LcdWriteData('='); // 顯示等于號
LcdWriteCmd(0x06); // 光標右移
break;
/*乘法運算*/
case 3:
LcdGotoXY(1,15); // 定位到液晶的第2行最后一列
LcdWriteCmd(0x04); // 光標左移
num3=num1*num2; // 計算結果
if(num3==0) // 如果計算結果為0
{
LcdPrintNum(0); // 在屏幕上顯示0
}
while(num3!=0) // 顯示計算結果
{
LcdPrintNum(num3%10);
num3=num3/10;
}
LcdWriteData('='); // 顯示等于號
LcdWriteCmd(0x06); // 光標右移
break;
/*除法運算*/
case 4:
if(num2!=0)
{
LcdGotoXY(1,15); // 定位到液晶的第2行最后一列
LcdWriteCmd(0x04); // 光標左移
num3=(ulong)(((float)num1/num2)*1000); // 計算結果(放大了1000倍)
if(num1<num2) // 如果是小數除以大數
{
num3=num3+1000;// 先給計算結果加1000
}
while(num3!=0) // 顯示計算結果
{
LcdPrintNum(num3%10);
num3=num3/10;
i++;
if(i==3) // 顯示小數點
{
LcdWriteData('.');
}
}
if(num1<num2) // 如果是小數除以大數
{
LcdGotoXY(1,11); // 把之前加的1000給清除
LcdPrintNum(0);
}
LcdWriteData('='); // 顯示等于號
LcdWriteCmd(0x06); // 光標右移
break;
}
else // 如果除數位0,顯示“ERROR!”
{
LcdGotoXY(1,10);
LcdPrintStr("ERROR!");
}
}
LcdWriteCmd(0x0C); // 光標不閃爍
while(KeyScanf()!=13); // 計算后,只能通過按下清除鍵,才能進入新一輪的計算
break;
}
DelayMs(10); // 去除按鍵按下的抖動
while(KeyScanf()!=99); // 等待按鍵釋放
DelayMs(10); // 去除按鍵松開的抖動
}
}
}
}
}
-
-
計算器程序 原理圖.rar
2019-10-13 12:38 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
89.25 KB, 下載次數: 25, 下載積分: 黑幣 -5
作者: zzzzz.c 時間: 2019-10-15 11:04
真全,,謝謝了
| 歡迎光臨 (http://m.raoushi.com/bbs/) |
Powered by Discuz! X3.1 |