找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 5336|回复: 1
打印 上一主题 下一主题
收起左侧

一个简单的计算器 单片机程序(含原理图,代码注释)

[复制链接]
跳转到指定楼层
楼主

用的是普中的开发板,下面是程序:
#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_flag1,说明运算数1已输入
                                                        }
                                                }
                                                else                           // 如果cal的值不为0,说明现在在输入运算数2
                                                {
                                                        if(num2<1000)                // 限制运算数2的大小小于10000
                                                        {
                                                                LcdPrintNum(ret);                // 将按下的数字键显示
                                                                num2=num2*10+ret;        // 把运算数2放大10
                                                                num2_flag=1;                        // 将运算数2的标志变量num2_flag1,说明运算数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

89.25 KB, 下载次数: 25, 下载积分: 黑币 -5

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:509174 发表于 2019-10-15 11:04 来自手机 | 只看该作者
真全,,谢谢了
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表