基于51单片机的计算器DIY大概设计过程
写在前面:关于这个计算器的制作完全是出于对DIY的爱好,因为闲的无聊总要做些东西玩玩,于是想到做一个计算器。这个计算器的功能跟平常大家网上见到的计算器的差别大概也就是在功能上支持浮点数的运算吧。不过目前因为使用单精度浮点数所以只能精确到小数点后面的第六位,其实第六位在很多时候已经不准确了。以目前我的编程思路我只能做到这里了。如果哪位有兴趣的朋友能做到更精确的话请跟我联系,洗耳恭听~!
在此写一下大概的思路,希望对于喜欢自己DIY的朋友有所帮助或者能让你看到有可以借鉴的地方。
整个框架在硬件部分很简单,只有三部分,从这个角度来讲很容易实现DIY(便宜并且器件都是常用的,容易凑齐)
1.单片机及最小系统部分:我使用的是CEPARK的实验板,所以这部分我不用做,用现
成的实验板即可,当然你要是有别的实验板也可以用,大同小异。
2.显示部分:至少是LCD1602的显示了,数码管肯定是满足不了要求的,而且我用的这
个板子上数码管是四位的,所以用常用的LCD1602吧。
3.键盘部分:这部分就自己DIY一个吧,要不整个过程也就算不上是DIY了,没有一个
模块是自己做的,我当时设计的时候大概想了一下是有22个键需要使用,故采用了4*6的矩阵键盘。当然实际上在我实际编程的时候很多按键没有用上,因为实在是RAM空间不够用了。
基本上这就是一个计算器完整的三个模块了,但是实际上我在这个基础上加了一个红外的模块,也就是说这个计算器得到的结果我是可以控制的,呵呵,是不是很邪恶~~,使用定时器对红外遥控器解码准确的很,没有任何出现按键显示不准的情况。有兴趣的可以跟我交流。前面就先说到这里,下面开始分模块介绍一下。
第一部分:最小系统部分
这部分其实没有什么好说,这里对CEPARK的实验板发表一点小意见。我要扩展的时候4根矩阵键盘的行线是要接到P1口的低四位的,这样比较有利于写矩阵键盘的检测程序,但是后来发现在我安装上LCD1602的时候,液晶盖住了P1.0口没有办法连线,后来我想用高四位也行啊~于是,很开心的接上高四位~~第一次测试程序的时候差点没把我吓晕~,对CEPARK的板子比较了解的朋友可能会记得P1.7口是接在蜂鸣器上的,呵呵,所以最后只好用了P1.3,P1.4,P1.5,P1.6来接矩阵键盘的行线,至于程序,慢慢写了~~,呵呵。其实也是可以的,只是比较费劲而已,但是程序行差不多,注意端口电平。
单片机printf函数第二部分:显示部分
显示部分的函数我在原始的帖子里已经贴出来了,有兴趣的可以看一下,原帖的地址是:park/viewthread.php?tid=2717&extra=page%3D1,至于LCD1602的操作不是本文讨论的内容,如果还不清楚液晶的操作请参见sunhm版主的单片机教程,在单片机综合板块,有很详细的介绍。这里只是想提一下两个函数。
void lcd_printf(uchar *str)//显示字符串
{
while(*str!='\0')
{
write1602(*str,1); //写入数据
str++;
}
}
void lcd_moveto(uchar x,uchar y)//指定显示的行列坐标
{
if(x==0)
write1602(0x80|y,0);
if(x==1)
write1602(0xc0|y,0);
}
第一个函数void lcd_printf(uchar *str)是用来显示字符串的,学过C语言的朋友对指针肯定都很熟悉,对于一个字符型的数组,起数组名跟指向数组第一个元素的地址其实是一样的,所以在需要输出一个字符串的时候我们就可以一次性输出,而不用用for循环来实现,这样最少看起来比较简洁而且实用。在后面的浮点数的输出中,这个是很有用的,现在你就可以想一下如果是你来做的话你怎么将任一个浮点数在液晶上显示出来了。
第二个函数lcd_moveto(uchar x,uchar y),很显然这个函数是用来定位显示的数据在1602上的位置的,x,y分别表示是在哪一行和第几个位置,在第一行时x=0,第二行x=1,也就是说坐标都是从0开始的,同理列也是。这个函数很方便的可以让我们快速的定义显示位置,比如我想在初始化的时候在第二行的最后两个位置显示’0.’(这是一般计算器的初始化显示吧~~!)那么我们可以用下面两个语句来实现:
Lcd_moveto(1,14);// 定位在第2行的第15个位置, x=1,y=14
Lcd_printf(“0.”);//显示字符串0.
看到了吗?很方便的吧?对于指针不是很熟悉的朋友可以去翻一下C语言的课本,这个概念不是太难理解。简单的说Lcd_printf(“0.”);会把要显示的字符串的首地址传递到指针变量中去,直到遇到’\0’为止。(’\0’是字符串结束的标志,后面的字符不会被显示),下面的图片是用来测试1602的时候用手机拍下的。
第三部分:矩阵键盘模块
这部分的按键我设置了24个,数字键11个(包括小数点),运算符6个(包括等号和正负号),清零键一个,按键音选择一个。其他的按键属于无效按键,无任何功能(因为RAM 实在放不下去了)。实际
使用的键一共是19个,功能的扩充以后再做。
实物图片如下:
按键部分的程序思路:先设置两个数组用来存放按键获取的键盘码,(如何获取就不用说了吧?矩阵键盘的扫描,任何方式都可以,扫描法和计算法等,只要获取正确即可),然后每次获取按键之后进行重新显示,数组长度加一,比如说我现在输入了5个字符,那么我就要定义到第二行的第11个位置处,不是12哦,因为最后一位是小数点固定的,大家可以回去看一下自己的计算器都是这样的撒。然后按下运算符
的时候将第一个操作数的内容放到第一行顶格显示,输入的第二个操作数继续在第二行开始显示,按下等号结果在第一行显示并且初始化第二行。
按键的获取是通过外部中断来获取的。
这里有些小细节需要注意下,比如说我输入的时候第一个按下的是0,那么很显然是不可以有显示的,连续按下几次0的话显示一定是0.而不是0000.这样,这个需要简单的处理一下,可以设置一个标志位来判断,用bit不要用uchar,节省ram。
我用到的函数有:
V oid key_scan();//矩阵键盘的扫描
void key_press();//按键的获取
void operation(uchar num1[16],uchar num2[16],uchar option_sel);//运算过程获取结果
void int1() interrupt 2;//响应按键
程序思路大概就是这样的,源程序我不提供了,如果有兴趣的可以动手自己做一下试试,如果你手头有
一个实验板的话那么你需要再投入的费用大概在2到3元左右,所以大可以自己做了硬件亲自调试一下。这样才有乐趣。如果在调试的时候需要帮助请跟我联系。
注意写程序的时候节省RAM空间哟~!下面是我的程序的空间占用情况:
不小了吧?DATA区用到了94.7个字节,有兴趣的朋友可以试一下,这个DATA区在我这里实测使用到104字节左右的时候会溢出,所以在我添加红外功能的时候需要定义个33个元素的一维数组是完全不现实的。想扩展其他7个按键的功能也要十分的谨慎。
好了,如果你有足够的耐心看到这里,相信你对这个DIY的过程已经大致的了解了,相信自己可以尝试一下了。
下面是我的键盘的按键说明:(不是太清楚,仔细看)
一个乘法的计算过程如下:
1.输入第一个数
2.输入运算符