找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 6095|回復: 1
打印 上一主題 下一主題
收起左側

一個簡單的計算器 單片機程序(含原理圖,代碼注釋)

[復制鏈接]
跳轉到指定樓層
樓主
ID:543026 發(fā)表于 2019-10-13 12:43 | 只看該作者 |只看大圖 回帖獎勵 |倒序瀏覽 |閱讀模式

用的是普中的開發(fā)板,下面是程序:
#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;                                        // 運算數(shù)1
ulong num2;                                          // 運算數(shù)2
ulong num3;                                           // 計算結果
uchar cal;                                                   // 運算符號,1加,2減,3乘,4
uchar num1_flag;                                // 運算數(shù)1的輸入標志
uchar num2_flag;                                // 運算數(shù)2的輸入標志


/*********************************************************/
// 毫秒級的延時函數(shù),time是要延時的毫秒數(shù)
/*********************************************************/
void DelayMs(uint time)
{
        uint i,j;
        for(i=0;i<time;i++)
                for(j=0;j<112;j++);
}

/*********************************************************/
// 1602液晶寫命令函數(shù),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液晶寫數(shù)據(jù)函數(shù),dat就是要寫入的數(shù)據(jù)
/*********************************************************/
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液晶初始化函數(shù)
/*********************************************************/
void LcdInit()
{
        LcdWriteCmd(0x38);        // 16*2顯示,5*7點陣,8位數(shù)據(jù)口
        LcdWriteCmd(0x0C);        // 開顯示,不顯示光標
        LcdWriteCmd(0x06);        // 地址加1,當寫入數(shù)據(jù)后光標右移
        LcdWriteCmd(0x01);        // 清屏
}

/*********************************************************/
// 液晶光標定位函數(shù)
/*********************************************************/
void LcdGotoXY(uchar line,uchar column)
{
        // 第一行
        if(line==0)        
                LcdWriteCmd(0x80+column);
        // 第二行
        if(line==1)        
                LcdWriteCmd(0x80+0x40+column);
}

/*********************************************************/
// 液晶輸出字符串函數(shù)
/*********************************************************/
void LcdPrintStr(uchar *str)
{
        while(*str!='\0')
                        LcdWriteData(*str++);
}

/*********************************************************/
// 液晶輸出數(shù)字
/*********************************************************/
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;
}

/*********************************************************/
// 主函數(shù)
/*********************************************************/
void main()
{
        uchar ret;
        uchar i;

         LcdInit();

        while(1)
        {
                LcdWriteCmd(0x01);                 // 清除屏幕顯示
                LcdWriteCmd(0x0f);                 // 開啟光標閃爍
                num1=0;                                          // 運算數(shù)1  清零
                num2=0;                                        // 運算數(shù)2  清零
                num3=0;                                          // 計算結果 清零
                cal=0;                                         // 運算符號 清零
                i=0;                                                  // 臨時變量 清零
                num1_flag=0;                                // 運算數(shù)1輸入標志 清零
                num2_flag=0;                                // 運算數(shù)2輸入標志 清零

                while(1)
                {
                        ret=KeyScanf();                        // 讀取矩陣鍵盤的掃描結果

                  if(ret!=99)                                        // 返回值不等于99,說明有按鍵按下了
                        {
                                DelayMs(20);
                                ret=KeyScanf();                // 讀取矩陣鍵盤的掃描結果

                                if(ret!=99)
                                {
                                        /*檢測到的是按下數(shù)字*/
                                        if(ret<10)
                                        {
                                                if(cal==0)                // 如果cal的值為0,說明現(xiàn)在在輸入運算數(shù)1
                                                {
                                                        if(num1<1000)         // 限制運算數(shù)1的大小小于10000
                                                        {        
                                                                LcdPrintNum(ret);                 //將按下的數(shù)字鍵刷新顯示
                                                                num1=num1*10+ret;        // 把運算數(shù)1放大10
                                                                num1_flag=1;                        // 將運算數(shù)1的標志變量num1_flag1,說明運算數(shù)1已輸入
                                                        }
                                                }
                                                else                           // 如果cal的值不為0,說明現(xiàn)在在輸入運算數(shù)2
                                                {
                                                        if(num2<1000)                // 限制運算數(shù)2的大小小于10000
                                                        {
                                                                LcdPrintNum(ret);                // 將按下的數(shù)字鍵顯示
                                                                num2=num2*10+ret;        // 把運算數(shù)2放大10
                                                                num2_flag=1;                        // 將運算數(shù)2的標志變量num2_flag1,說明運算數(shù)2已輸入
                                                        }
                                                }        
                                        }

                                        /*檢測到的是按下加號*/               
                                        if(ret==10)
                                        {
                                                if(cal==0)                                        // 判斷是否是第一次輸入計算符號
                                                {
                                                        if(num1_flag==0)                  // 判斷運算數(shù)1是否還未輸入
                                                        {
                                                                LcdPrintNum(0);          // 如果是的話,在液晶顯示數(shù)字0
                                                                num1=0;                          // 給運算數(shù)1一個計算初值0
                                                        }
                                                        cal=1;        // 將運算符變量改為1,代表即將進行加法運算
                                                        LcdWriteData('+');                  // 把加法運算符號顯示到屏幕上
                                                }
                                        }

                                        /*檢測到的是按下減號*/
                                        if(ret==11)                                                         
                                        {
                                                if(cal==0)                                // 判斷是否是第一次輸入計算符號
                                                {
                                                        if(num1_flag==0)                  // 判斷運算數(shù)1是否還未輸入
                                                        {
                                                                LcdPrintNum(0);          // 如果是的話,在液晶上面顯示0
                                                                num1=0;                             // 給運算數(shù)1一個計算初值0
                                                        }
                                                        cal=2;        // 將運算符變量改為2,代表即將進行減法運算
                                                        LcdWriteData('-');                // 把減法運算符號顯示到屏幕上
                                                }
                                        }

                                        /*檢測到的是按下乘號*/
                                        if(ret==12)
                                        {
                                                if(cal==0)                                           // 判斷是否是第一次輸入計算符號
                                                {
                                                        if(num1_flag==0)                  // 判斷運算數(shù)1是否還未輸入
                                                        {
                                                                LcdPrintNum(0);         // 如果是的話,在液晶上面顯示0
                                                                num1=0;                         // 給運算數(shù)1一個計算初值0
                                                        }
                                                        cal=3;          // 將運算符變量改為3,代表即將進行乘法運算
                                                        LcdWriteData('*');                // 把乘法運算符號顯示到屏幕上
                                                }
                                        }

                                        /*檢測到的是按下除號*/
                                        if(ret==15)
                                        {
                                                if(cal==0)                                          // 判斷是否是第一次輸入計算符號
                                                {
                                                        if(num1_flag==0)                  // 判斷運算數(shù)1是否還未輸入
                                                        {
                                                                LcdPrintNum(0);         // 如果是的話,在液晶上面顯示0
                                                                num1=0;                         // 給運算數(shù)1一個計算初值0
                                                        }
                                                        cal=4;        // 將運算符變量改為4,代表即將進行除法運算
                                                        LcdWriteData('/');                // 把除法運算符號顯示到屏幕上
                                                }
                                        }

                                        /*檢測到的是按下清除鍵*/
                                        if(ret==13)
                                        {
                                                break;                                           // 退出當前的while循環(huán)
                                        }

                                        /*檢測到的是按下等于號*/               
                                        if(ret==14)
                                        {        
                                                if(num2_flag==0)                          // 判斷運算數(shù)2是否還未輸入
                                                {
                                                        LcdPrintNum(0);                   // 如果是的話,在液晶上面顯示0
                                                        num2=0;                                // 給運算數(shù)2一個計算初值0
                                                }

                                                switch(cal) // 根據(jù)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);                        // 顯示數(shù)字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)                 // 如果是小數(shù)除以大數(shù)
                                                                        {
                                                                                num3=num3+1000;// 先給計算結果加1000
                                                                        }                                                               

                                                                        while(num3!=0)                // 顯示計算結果
                                                                        {
                                                                                LcdPrintNum(num3%10);
                                                                                num3=num3/10;
                                                                                i++;
                                                                                if(i==3)                        // 顯示小數(shù)點
                                                                                {
                                                                                        LcdWriteData('.');        
                                                                                }
                                                                        }

                                                                        if(num1<num2)                // 如果是小數(shù)除以大數(shù)
                                                                        {
                                                                                LcdGotoXY(1,11); // 把之前加的1000給清除
                                                                                LcdPrintNum(0);
                                                                        }

                                                                        LcdWriteData('=');                // 顯示等于號
                                                                        LcdWriteCmd(0x06);        // 光標右移
                                                                        break;
                                                                }
                                                                else                                // 如果除數(shù)位0,顯示“ERROR!
                                                                {                           
                                                                        LcdGotoXY(1,10);
                                                                        LcdPrintStr("ERROR!");        
                                                                }
                                                }
                                                LcdWriteCmd(0x0C);                // 光標不閃爍
                                                while(KeyScanf()!=13);                // 計算后,只能通過按下清除鍵,才能進入新一輪的計算               
                                                break;
                                        }

                                        DelayMs(10);                                  // 去除按鍵按下的抖動
                                        while(KeyScanf()!=99);                          // 等待按鍵釋放
                                        DelayMs(10);                                         // 去除按鍵松開的抖動
                                }
                        }
                }
        }
}

計算器程序 原理圖.rar

89.25 KB, 下載次數(shù): 25, 下載積分: 黑幣 -5

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復

使用道具 舉報

沙發(fā)
ID:509174 發(fā)表于 2019-10-15 11:04 來自手機 | 只看該作者
真全,,謝謝了
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網(wǎng)

快速回復 返回頂部 返回列表