codeblocks 51单片机学习(四)简易计算器

基于51单片机的数码管和矩阵按键实现的简易计算器,其实可以加入的东西有很多,就像我这个负数运算还没有加进去,以及我的除法运算只能算655(65535/100)以内的数,不过就先做到这里,这个作品至少已经叫做计算器了。
首先我这个工程里加入了两个文件,数码管显示文件,查询式矩阵按键文件,直接调用这两块功能的函数,然后在主函数里解决相当于软件层的计算器功能。

简易计算器实现的功能(待完善)

  • 四则运算
  • 可以显示2位小数
  • 利用矩阵按键输入,用数码管显示
  • 连续运算
  • 负数运算

代码的解释和功能实现

其它函数说明:

/*定义局部函数*/
void deletenum(int s[]);//退位函数,用于退1位,等同'c'
void addnum(int s[]);//加位函数,在输入下一位数的时候将前面的数后移1位
void count(void);//计算函数等同'='
unsigned long pow10(u8 n);//计算10的n次方
void init(void);//计算完成后初始化第二个输入数
void division(void);//除法运算
void multiplication(void);//乘法运算
void subtraction(void);//减法运算
void addition(void);//加法运算

/*定义变量*/
int gDigValue[8];//gDigValue用于显示数码管作为全局变量
int val[8],a[8],b[8];//分别存放运算结果,第一个数,第二个数
unsigned long sum=0,um=0;//sum用于存储被除数
u8 num=0,ch=0;//ch存放运算符,num存放键值
u8 flag1=0,flag2=1,next_flag=1;//分别代表是否有小数点,是否显示运算结果,是否要输入下一个数

/*主函数
用于放置主要流程:1.获取键值,根据键值进行操作 2.分情况将数值显示在数码管
(输入数字时显示正在输入的数,运算后显示结果)
*/
void main(void)
{
    while(1)
    {
        num=key_val();//获取键值
        if(num!=17)
            flag2=1;//当有按键按下,不再显示运算结果,改为显示正在输入的数
        WaitForKeyUp();
        if(next_flag)
        {
            if(num>9)
            {
                switch(num)
                {
                    case 14:deletenum(a);break;//退位
                    case 15:break;//没有输入运算符的时候不能计算
                    case 17:break;//没有按键按下
                    default:ch=num;next_flag=0;break;//当按下的是运算符,用ch先保存,然后输入下一个数的标志next_flag等于0(逻辑否)
                }
            }
            else
            {
                addnum(a);
                a[7]=num;
            }
        }
        else
        {
            if(num>9)
            {
                switch(num)
                {
                    case 14:deletenum(b);break;
                    case 15:count();break;//在输入运算符后可以计算
                    case 17:break;//没有按键按下
                    default:ch=num;break;
                }
            }
            else//如果输入数字,所有数字左移一格,然后输入新的数字
            {
                addnum(b);//左移
                b[7]=num;
            }
        }
        if(flag2)//是否显示运算结果
        {
            if(next_flag)//显示正在输入的数
                for(u8 i=0;i<8;i++)
                {
                    gDigValue[i]=a[i];
                }
            else
                for(u8 i=0;i<8;i++)
                {
                    gDigValue[i]=b[i];
                }
        }
        else
        {
                if(flag1 && val[7]==0 && val[6]==0)//如果没有小数位(小数点后两位为0),则去掉小数点,所有数字右移两格
                {
                    flag1=0;//不再显示小数点
                    for(int j=7;j>=2;j--)//右移两格
                    {
                        val[j]=val[j-2];
                    }
                    val[0]=0;
                    val[1]=0;
                }
                for(u8 i=0;i<8;i++)
                {
                    a[i]=val[i];//让第一个数变为运算的结果,可以连续运算
                    gDigValue[i]=val[i];//显示运算结果
                }
        }
        DigDisplayVal();//数码管显示数值
    }

}

/*用于获取键值,方便键值的改变,包含在key.c文件中*/
u8 key_val(void)
{
    switch(KeyScan())//获得查询式获取键值的结果
    {
        case 1:return 7;break;//数字7
        case 2:return 8;break;//数字8
        case 3:return 9;break;//数字9
        case 4:return 11;break;// / 除号
        case 5:return 4;break;//数字4
        case 6:return 5;break;//数字5
        case 7:return 6;break;//数字6
        case 8:return 12;break;// * 乘号
        case 9:return 1;break;//数字1
        case 10:return 2;break;//数字2
        case 11:return 3;break;//数字3
        case 12:return 13;break;// - 减号
        case 13:return 14;break;// 退位
        case 14:return 0;break;//数字0
        case 15:return 15;break;// = 等于
        case 16:return 16;break;// + 加号
        default:return 17;//没有按下按键时返回17
    }
}

四则运算函数,除了除法
,其他的类比列式计算
是不是生动形象
codeblocks 51单片机学习(四)简易计算器_第1张图片

/*减法运算*/
void subtraction(void)
{
    for(int i=7;i>=0;i--)
    {
        val[i]=a[i]-b[i];
        if(val[i]<0)//小于0的要借位
        {
            val[i]+=10;
            a[i-1]-=1;
        }
    }
}

/*加法运算*/
void addition(void)
{
    for(int i=7;i>=0;i--)
    {
        val[i]=a[i]+b[i];
        if(val[i]>9)//大于10的要进位
        {
            val[i]-=10;
            val[i-1]+=1;
        }
    }
}
/*乘法运算*/
void multiplication(void)
{
    for(int i=7;i>=0;i--)//类比我们的列式乘法,将乘数的每一位分别和被乘数的每一位相乘。
    {
        for(int j=7;j>=0;j--)
        {
            if(i+j>=7)
                val[i-7+j]+=a[i]*b[j];
        }
    }
    for(int i=7;i>=0;i--)//将每一位大于10的进位
        while(val[i]>9)
        {
            val[i]-=10;
            val[i-1]+=1;
        }
}
/*除法运算,这个算法受51单
片机运算能力限制只能运算输
入数字在655以内的除法。顺
带一提,要显示小数点,我们
需要回到数码管显示的底层函
数里,将段码|(位与)一个0x80,
也就是DIG_PORT=gDuanMa[gDigVal[i]] | 0x80;
*/
void division(void)
{
    for(int i=7;i>=0;i--)
    {
        sum=sum+a[i]*pow10(7-i);//将输入的第一个数(被除数)获取
        um=um+b[i]*pow10(7-i);//将输入的第二个数(除数)获取
    }
    if(sum<1000000)//共两位小数点,所以整数部分最多6位,实际上到不了那么多位
    {
        sum=(sum*100)/um;
        for(int i=0;i<8;i++)
        {
            val[7-i]=(sum%pow10(i+1))/pow10(i);
        }
        flag1=1;
    }
}

你可能感兴趣的:(codeblocks 51单片机学习(四)简易计算器)