51基于OLED的高精度计算器设计

您所在的位置:网站首页 精度计算器 51基于OLED的高精度计算器设计

51基于OLED的高精度计算器设计

#51基于OLED的高精度计算器设计| 来源: 网络整理| 查看: 265

首先,第一次发帖,请多多包含,有不妥的地方请指正。

51基于OLED显示的高精度计算  器设计

这个是我一个实训课作业,我选的是矩阵键盘的应用最后选了计算器。然后有要求精度至少达到小数点后6位(因为int型最多可以到小数点后5位,老师为了给我们增加难度!),且不使用浮点型(我用的long int 占4个Byte范围0~+4 294 967 295),要求计算器有删除,撤销删除和清除等功能按键。并且要通过OLED显示实时操作。

首先要用OLED,IIC协议必不可少,我也是边学边做,这里推荐看其他大佬的讲解(很详细的,侵删)IIC原理超详细讲解---值得一看_Z小旋-CSDN博客_iic原理

OLED驱动程序商家一般都给了,但是老师还是建议我们写一写,因为我们专业就是电子专业,本来就是做电路设计,看时序。这里也不详讲,放一张ssd1306的命令图自己去参透吧!

 矩阵键盘:

这个应该不陌生吧,采用的4x4矩阵的按键,按键对应值如图

#include //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义 #include"keyboard.h" #include"delay.h" #define KeyPort P2 /*------------------------------------------------ 按键扫描函数,返回扫描键值 ------------------------------------------------*/ unsigned char KeyScan(void) //键盘扫描函数,使用行列反转扫描法 { unsigned char cord_h,cord_l;//行列值中间变量 KeyPort=0x0f; //行线输出全为0 cord_h=KeyPort&0x0f; //读入列线值 if(cord_h!=0x0f) //先检测有无按键按下 { DelayMs(10); //去抖 if((KeyPort&0x0f)!=0x0f) { cord_h=KeyPort&0x0f; //读入列线值 KeyPort=cord_h|0xf0; //输出当前列线值 cord_l=KeyPort&0xf0; //读入行线值 while((KeyPort&0xf0)!=0xf0);//等待松开并输出 return(cord_h+cord_l);//键盘最后组合码值 } }return(0xff); //返回该值 } /*------------------------------------------------ 按键值处理函数,返回扫键值 可以根据需要改变返回值 | 1 | 2 | 3 | + | | 4 | 5 | 6 | - | | 7 | 8 | 9 | * | | 0 | . | = | / | ------------------------------------------------*/ unsigned char KeyPro(void) { switch(KeyScan()) { case 0x7e:return '1';break;//0 按下相应的键显示相对应的码值 case 0x7d:return '2';break;//1 case 0x7b:return '3';break;//2 case 0x77:return '+';break;//3 case 0xbe:return '4';break;//4 case 0xbd:return '5';break;//5 case 0xbb:return '6';break;//6 case 0xb7:return '-';break;//7 case 0xde:return '7';break;//8 case 0xdd:return '8';break;//9 case 0xdb:return '9';break;//a case 0xd7:return 'x';break;//b case 0xee:return '0';break;//c case 0xed:return '.';break;//d case 0xeb:return '=';break;//e case 0xe7:return '/';break;//f default:return 0xff;break; } } 重点来了,本次主讲计算器常见加减乘除的思想 加法:

主要就是考虑小数部分,主要是将小数位数对齐。例如 a=4.52  b=8.9  我们在输入的时候只会记录小数点位置,并不会在存在临时数组内 。所以取的时候直接取的 452  和  89 ,但是会记录扩大的倍数,比如a扩大了100倍,b扩大了10倍。这是我们要将两个数的小数位对其只需做

 a*(100/100)+b*(100/10)   即  452+890=1342  ,之所以用100来除以100和10是因为100是这两个数扩大倍数的最小公倍数。目的就是为了对齐小数位置。

//先将a,b乘以最小取整公倍数,即a,b对其,Rsulat_z存整数部分,Rsulat_fp存小数部分 case '+': Resulat_z=(a*(sign_fp/fp_a) + b*(sign_fp/fp_b))/sign_fp; Resulat_fp=(a*(sign_fp/fp_a) + b*(sign_fp/fp_b))%sign_fp; break; //fp_a和fp_b分别存放a,b扩大了多少倍 减法:

常见得需要考虑负数情况,负数我们就用b-a(原则就是大减小),不过这样还得考虑小数部分问题。比如当减数的整数部分小于被减数,而小数部分却大于被减数。直接用b-a的话小数部分就会出问题,因此在小数部分还得做一次大小的判断。

case '-': //sign_fp存放的是小数位多的 那个数扩大的倍数 fp_a、fp_b分别存放a、b扩大的倍数 if(a*(sign_fp/fp_a) < b*(sign_fp/fp_b)) //判断a,b大小 { // Resulat_z取结果的整数部分,_fp取小数部分 Resulat_z=(b*(sign_fp/fp_b)-a*(sign_fp/fp_a))/sign_fp; if(((a*(sign_fp/fp_a))%sign_fp) > (b*(sign_fp/fp_b)))//判断a , b的小数大小 { Resulat_fp=(((a*(sign_fp/fp_a))%sign_fp) - (b*(sign_fp/fp_b))%sign_fp)%sign_fp; } else{ Resulat_fp=((b*(sign_fp/fp_b))%sign_fp - (a*(sign_fp/fp_a))%sign_fp); OLED_ShowChar((lessk_Resulat+1)*8,OLED_Show_H+2,'-',16);//显示一个负号 lessk_Resulat++;//光标+ } } else{ Resulat_z=(a*(sign_fp/fp_a) - b*(sign_fp/fp_b))/sign_fp; Resulat_fp=(a*(sign_fp/fp_a) - b*(sign_fp/fp_b))%sign_fp; } break; 乘法:

乘法最简单,直接相乘,然后对这  两个数扩大倍数之积  取整取余即可

//a,b取的时候已经取整了,直接运算后对公倍数取整取余即可 case 'x': Resulat_z=(a * b)/(fp_a*fp_b); Resulat_fp=(a * b)%(fp_a*fp_b); break; 除法:

首先整数相除,考虑除不尽得情况,整数可直接取 a/b,小数先取a%b,之后扩大10的6次方倍再除b  即:((a%b)*1000000)/b(精确到小数点后6位)。

这里要做一个判断,若除数小于被除数,结果直接就取小数部分即可。

带小数的除法:思路也是一样的,先扩大,把两个数的小数位对齐。例 :98.25   /   65.234  

先乘以最小公倍数1000(不知道这样说有没有问题),处理成 98250  /  65234剩余步骤和上面一样

//除法考虑除不尽情况,小数部分算法即将a%b后扩大百万倍在除b,精度即可达到小数点后6位 case '/': if(a*(sign_fp/fp_a) > b*(sign_fp/fp_b)){ Resulat_z=(a*(sign_fp/fp_a)) / (b*(sign_fp/fp_b)) ; Resulat_fp=((a*(sign_fp/fp_a) % b*(sign_fp/fp_b))*1000000)/b; } else { div_x=(a*(sign_fp/fp_a))*1000000/(b*(sign_fp/fp_b)); } break;

结果

 总结:

        第一次写,瞎写,主要是分享一下心得,也不知有没有人愿意看两眼。计算器的话,主要就是精度,然后小数运算。涉及到小数就一个原则,小数对齐后再运算。其实也大可直接用double来做,可能就没有太多数据处理的步骤。但是  老师规定了用整型!

吐槽一下,其实本来是想做《简易计算器》,结果老师说不行,还夸我真会给自己省事^_^......!

工程源码即仿真:链接:https://pan.baidu.com/s/1aybJBOirx-WRb1bFwLkMsw                               提取码:brdn



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3