简易计算器系统设计.docx
- 文档编号:4772779
- 上传时间:2022-12-08
- 格式:DOCX
- 页数:18
- 大小:229.21KB
简易计算器系统设计.docx
《简易计算器系统设计.docx》由会员分享,可在线阅读,更多相关《简易计算器系统设计.docx(18页珍藏版)》请在冰豆网上搜索。
简易计算器系统设计
(此文档为word格式,下载后您可任意编辑修改!
)
湖南文理学院芙蓉学院
嵌入式系统课程设计报告
题目简易计算器系统设计
学生姓名刘胜凯
专业班级计算机科学与技术
指导老师娄小平
组员李阳、杨帆、曾家俊
目录
一、摘要3
二、原理与总体方案3
三、硬件设计6
四、调试10
五、测试与分析12
六、心得体会14
七、参考文献15
八、附录15
一、摘要
计算器一般是指“电子计算器”,是能进行数学运算的手持机器,拥有集成电路芯片。
对于嵌入式系统,以其占用资源少、专用性强,在汽车电子、航空和工控领域得到了广泛地应用。
本设计就是先通过C语言进行相应程序的编写然后在ADS中进行运行最后导入PROTUES进行仿真。
最后利用ARM中的LPC2106芯片来控制液晶显示器和4X4矩阵式键盘,从而实现简单的加、减、乘、除等四则运算功能。
二、原理与总体方案
主程序在初始化后调用键盘程序,再判断返回的值。
若为数字0—9,则根据按键的次数进行保存和显示处理。
若为功能键,则先判断上次的功能键,根据代号执行不同功能,并将按键次数清零。
程序中键盘部分使用行列式扫描原理,若无键按下则调用动态显示程序,并继续检测键盘;若有键按下则得其键值,并通过查表转换为数字0—9和功能键与清零键的代号。
最后将计算结果拆分成个、十、百位,再返回主程序继续检测键盘并显示;若为清零键,则返回主程序的最开始。
电路设计与原理:
通过LPC2106芯片进行相应的设置来控制LCD显示器。
而通过对键盘上的值进行扫描,把相应的键值通过MM74C922芯片进行运算从而让ARM芯片接收。
2.1系统整体流程图
2.2程序运行流程图
2.3仿真电路图设计
2.4仿真图形
2.4.1计算加法
2.4.2计算减法(结果为负数)
2.4.3计算减法(结果为正数)
2.4.4计算乘法
2.4.5计算除法
注:
本设计不能进行连续运算,只能进行当次运算,且只能进行单行显示。
进行除法时会自动取整,无小数。
显示器上不会显示加减乘除等运算符号,只有操作数和操作结果。
三、硬件设计
3.1元件清单
器件
件数
LPC2106
1个
LED
1个
KEYPAD
1个
电源
若干
电源地
若干
电线
若干
3.2键盘接口电路
计算器输入数字和其他功能按键要用到很多按键,如果采用独立按键的方式,在这种情况下,编程会很简单,但是会占用大量的I/O口资源,因此在很多情况下都不采用这种方式,而是采用矩阵键盘的方案。
矩阵键盘采用四条I/O线作为行线,四条I/O线作为列线组成键盘,在行线和列线的每个交叉点上设置一个按键。
这样键盘上按键的个数就为4×4个。
这种行列式键盘结构能有效地提高单片机系统中I/O口的利用率。
矩阵键盘的工作原理:
计算器的键盘布局如图3-1所示:
一般有16个键组成,在单片机中正好可以用一个P口实现16个按键功能,这种形式在单片机系统中也最常用。
图3-1矩阵键盘布局图
电路中采用4*4键盘作为输入电路模块的话,电路连线会比较简单,而且这种行列式键盘结构能有效地提高单片机系统中I/O口的利用率。
但是在硬件电路设计的过程中,实验室没有提供矩阵键盘,所以我们将4*4的矩阵键盘换成了16个独立按键。
采用独立按键的方式的话,会占用大量的I/O口资源,但是在这种情况下,编程会很简单。
矩阵键盘内部电路图如图3-2所示。
图3-2矩阵键盘内部电路图
3.3显示模块:
本设计采用LCD1液晶显示屏来显示输出数据。
通过D0-D7引脚向LCD1写指令字或写数据以使LCD1实现不同的功能或显示相应数据。
LCD1管脚图如图3-3所示。
图3-3LCD1管脚图
3.4各模块的特性与作用
3.4.1LPC2106的特性及引脚功能
LPC2106是基于一个支持实时仿真和跟踪的32位ARMCPU的微处理器,并带有256kB嵌入的高速Flash存储器。
128位宽度的存储器接口和独特的加速结构使32位代码能够最大时钟速率下运行,并具有广泛应用。
含向量中断控制器,多个串行接口,两个三十二位定时器,片内晶振的操作频率范围:
10MHZ-25MHZ,两个低功耗模式:
空闲和掉电.
CPU操作电压范围:
1.65V-1.95V
图3-4LPC2106管脚图
管脚说明:
V3、V18:
供电电压
Vss、DBGSEL:
接地
XTAL1:
反向振荡放大器的输入及内部时钟工作电路的输入。
XTAL2:
来自反向振荡器的输出。
P0.0-P0.14作为GPIO接口,P0.15作为EINT2接口。
3.4.2LCD的特性
LCD显示屏可以采用字符显示,当使用字符显示方式时,可以直接用外码作为输入数据,由显示屏自动给出显示字模数据,而无需由微处理器提供字模。
3.4.3数字式键盘的特性
数字式键盘的实质仍是行列式键盘,4根行线和4根列线通过下拉电阻接地,在其表面贴有标示对应按键的膜,使得易于观察和操作,更加贴近使用者的需求。
3.4.4MM74C922的特性及其引脚功能:
MM74C922具有功耗低,电压为3-5V,三态门输出,与LPTTL兼容,输出锁存按下最后的键,用一个电容器就可以消除键盘抖动,两键轮回,行具有上拉功能,具有芯片内或芯片外时钟,最大开关电阻为管脚说明:
A-D为行键扫描电平输出端,1-4为列键输入读取端;
OSC为振荡器的外接引线端,可用外部的输入脉冲或电容器;
OE为数据输出端,低电平有效;DAV为数据输出有效,高电平有效;VCC为电源端,接3-5V;GND为接地端。
本设计中选用LPC2106的P0.0~P0.10与LCD显示屏相连,它们所输出信号控制显示屏上的显示,其中P0.0~P0.7分别接显示屏的D0~D7,P0.8~P0.10分别接显示屏的RS、RW、E接口;选用LPC2106的P0.11~P0.14连续4个IO口与芯片MM74C922和计算器键盘相连,可通过反转法检测到按下按键的键码,再通过查键盘对应的字符编码使LCD显示,其中A~D依次接键盘的4根行线,1~4依次接键盘的4根列线。
管脚说明:
A-D为行键扫描电平输出端,1-4为列键输入读取端;
OSC为振荡器的外接引线端,可用外部的输入脉冲或电容器;
OE为数据输出端,低电平有效;DAV为数据输出有效,高电平有效;VCC为电源端,接3-5V;GND为接地端。
本设计中选用LPC2106的P0.0~P0.10与LCD显示屏相连,它们所输出信号控制显示屏上的显示,其中P0.0~P0.7分别接显示屏的D0~D7,P0.8~P0.10分别接显示屏的RS、RW、E接口;选用LPC2106的P0.11~P0.14连续4个IO口与芯片MM74C922和计算器键盘相连,可通过反转法检测到按下按键的键码,再通过查键盘对应的字符编码使LCD显示,其中A~D依次接键盘的4根行线,1~4依次接键盘的4根列线。
四、调试
4.1GPIO:
LPC2000系列ARM的GPIO具有如下特性:
1)可以独立控制每个GPIO口的方向(输入/输出模式);
2)可以独立设置每个GPIO的输出状态(高/低电平);
3)所有GPIO口在复位后默认为输入状态。
每个作为GPIO功能的引脚受到四个寄存器控制,分别为控制方向的IOxDIR、控制输出电平状态的IOxSET和IOxCLR、反映引脚电平状态的IOxPIN。
这四个寄存器构成一组,而一组寄存器控制着一个端口(P0、P1、P2或P3)。
注意事项:
引脚设置为输出方式时,输出状态由IOxSET和IOxCLR中最后操作的寄存器决定。
LPC2000系列ARM大部分的I/O引脚为推挽方式输出,但是具有总线功能的I/O引脚为开漏输出(P0.2/3和P0.11/14)。
使用这些开漏输出的引脚作为GPIO功能,并用于高电平输出或者引脚状态输入时,要接上拉电阻才能正常使用。
推挽输出的I/O引脚正常拉出/灌入电流均为4mA,短时间极限值为40mA。
复位后,大部分引脚默认作为GPIO功能,并且均为输入状态。
但是,有部分引脚在复位后默认作为第二功能(如:
P0.27~P0.30在复位后默认为A/D输入引脚)。
4.2硬件和程序原理
在键盘按键后,产生一个中断,mcu对键盘进行扫描,确定按下的键,如果不是等号,就把按下的字符依次存入数组,并在lcd显示表达式,如果是等号,就计算出数组中存入的表达式的值,并显示在lcd中。
计算表达式值的方法:
把表达式中的表示数值的字符转成数值存入一个数值数组,把表达式中的表示运算符的字符存入运算符数组;
关于四则运算优先级算法:
依次检索运算符数组,当遇到*号或者/号的时候,就先计算乘法或除法,算出结果后存入数值数组相应位置,然后删除此运算符和多余的数值,再重复检索,直到数值数组中只有一个数值为止,这个数值即是运算结果。
调用stdio.h库里的sprintf函数,把数值转化成字符数组,然后显示到lcd中。
五、测试与分析
5.1ADS1.2新建工程
5.2Proteus实时仿真
六、心得体会
本学期为期一周的嵌入式课程设计在不知不觉中结束了,虽说这次课程设计时间不是很长,但是感觉自己收获颇丰,不仅学习到了一些新知识,回顾了以前的一些快要遗忘的知识点,而且使自己的学习目标更加明确,学习方法更加完善,也体会到软件开发的趣味,更加清楚地认识到了自己在软件开发及学习上的一些不足之处。
一周的课程设计,一周的实训,让我明白计算机这个博大深奥的领域我感觉自己还有好多东西要学,还有好多的东西不懂,嵌入式软件开发应用广泛而且前景很好,目前正处于人才紧缺的关口,嵌入式技术在未来能够得到更加广泛的应用。
学好嵌入式,C语言很重要,所以感觉自己有必要在学习、积累一下这方面的知识。
要想学好还必须下大力气,还必须坚持。
这次的课程设计让我明确了一点:
嵌入式开发对于提升我们的系统知识有很大的帮助,尤其是操作系统的知识。
嵌入式系统开发对于我们的知识面要求非常的广,且要有一定的深度。
这次的课程设计因为是一个有针对性的训练,所以记的会非常牢固。
跟平时上课不太一样,平时上完理论课很少有时间上机进行时间或者隔几天才上机练习,等到上机时一些东西可能遗忘了,比较耗费时间。
在课上,有老师在前面演示我们感觉看得懂或感觉没问题,可轮到我们独立完成的时候,因为实际操作的少,跟中问题就来了!
我很感谢学校特别是学院老师有实训这样的安排,把我们这一学期学的东西系统的集中的进行训练,让我们深刻明确的体验了一下软件开发的流程!
经过这次的实训,我真真确确的感受到了计算机在我们生活中工作中的运用,这些软件、程序能让我们提高工作的效率,更直观更便捷的切入主题。
当然,在学习的过程中并不是一帆风顺的,在这之中,因为要操作的东西很多,有时错一步,后面的结果就无法显示,而自己的计算机水平还有待提高,根本检查不出来是哪里出了错!
在平时我们就需要好好的查阅书籍或者上网搜集相关资料去解决问题。
对我们而言,知识上的收获重要,精神上的丰收更加可喜。
挫折是一份财富,经历是一份拥有。
这次实习必将成为我人生旅途上一个非常美好的回忆!
此次实训最大的收获不是我学习到了多少知识而是这几天实训给我的感悟:
首先是心态。
一定要有一个积极的心态,独立解决问题的意识,培养扎实基础的认识。
不要什么东西都感觉跟简单,就不去做了或者不屑一做,以至于感觉网上搜搜就可以了,这样很不好。
有自己的东西有自己的付出才会有程序运行成功时的喜悦和小自豪,这样也有助于培养自己的兴趣。
要时刻牢记态度决定一切。
其次是兴趣,感觉学习工作中兴趣很关键,只是一个引发人积极性的问题,有了兴趣就自觉了,效率自然就高了。
再次要敢于尝试和挑战。
不要安于现成的程序,而且不要害怕失败,在程序调试的过程中这点尤为重要,“发现出问题然后解决问题”是一个积累经验的过程,而且很高效。
最后要不懈追求。
对于源代码进行不断的完善,要尽可能的实现课题所要求的功能。
对于初学者或者开发较少的人来说,大量大写程序还是有必要的,但同时要注意思考,理解其实现的内在意义。
还可以自己添加一些有意义的功能来实现。
当看到自己编写的程序正常运行时,兴趣也会随之而来,乐此不疲,形成一个良性循环。
七、参考文献
1、ARM嵌入式系统开发-软件设计与优化,AndrewN.Sloss,沈建华(译),北京航空航天大学出版社,2005;
2、ARM体系结构与编程,杜春雷,清华大学出版社,2007;
八、附录
#include"config.h"
#include"math.h"
//宏定义
#defineLCD_RS1<<0
#defineLCD_RW1<<1
#defineLCD_E1<<2
#defineD71<<10//判断LCD忙碌
//函数声明
voidsystem_init(void);
voidLCDInit(void);
void__irqIRQ_EINT2(void);
intucKeyScan(void);
chartranslate();
voidarithmetic(longx,longy);
chartxt1[]="error!
",
txt2[]="dataoverflow",
txt3[]="";
//全局变量定义
longadd1=0,add2=0;
intoperators=0,iny=0;
uint8num=0,x,y,sign=0,count=0,k=0,repeat=0,flag=0;
//列线扫描电压,分为第1,2,3,4根列线
unsignedintucRow,ucLine;//行号,列号。
/********************************************************************
*名称:
DelayNS()
*功能:
长软件延时
*入口参数:
dly延时参数,值越大,延时越久
*出口参数:
无
********************************************************************/
voidDelayNS(uint32dly)
{uint32i;
for(;dly>0;dly--)
{
for(i=0;i<500;i++);
}
}
/********************************************************************
*名称:
Busy()
*功能:
LCD是否忙碌
********************************************************************/
voidBusy()
{
while
(1)
{
IOCLR=LCD_RS;
IOSET=LCD_RW;
if(!
(IOPIN&D7))break;
}
}
/********************************************************************
*名称:
Command()
*功能:
LCD命令
********************************************************************/
voidCommand(charcom)
{
Busy();
IOCLR=0x0FFF;
IOCLR=LCD_RS;
IOCLR=LCD_RW;
IOSET=LCD_E;
IOSET=com<<3;
IOCLR=LCD_E;
}
/********************************************************************
*名称:
LCDInit()
*功能:
LCD初始化
*入口参数:
*出口参数:
无
********************************************************************/
voidLCDInit()
{
Command(0x0C);//显示开/关控制命令
Command(0x38);//功能设置命令:
数据线长度为8位
//Command(0x80);//地址命令
Command(0x06);//输入方式设置
}
/********************************************************************
*名称:
write()
*功能:
LCD写数据
********************************************************************/
voidwrite(chardata)
{
Busy();
IOCLR=0x0FFF;
IOSET=LCD_RS;
IOCLR=LCD_RW;
IOSET=LCD_E;
IOSET=data<<3;
DelayNS
(1);
IOCLR=LCD_E;
}
/*******************************************************************
*名称:
display()
*功能:
LCD显示
*******************************************************************/
voiddisplay(longa)
{
longtemp,b,c=-1;
uint8lenth=1,i,j;
//Command(0x01);
if(a<0)
{
a=a*c;
write('-');
}
temp=a;
while((temp=temp/10)!
=0)lenth++;
for(i=lenth;i>0;i--)
{
b=1;
for(j=0;j write(0x30+a/b); a=a%b; } }//为低电平,其他为高电平。 //主函数 intmain() { system_init(); LCDInit(); while (1) ucKeyScan(); return(0); } /******************************************************************** *名称: system_init() *功能: system初始化函数 ********************************************************************/ voidsystem_init() { //引脚功能选择 IODIR=0x0f007ff;//设置P0.0-P0.10,P0.20-P0.23为输出,其余为输入 //向量中断初始化 VICIntSelect=0x00;//设置P0.15为IRQ中断 VICVectAddr0=(uint32)IRQ_EINT2; VICVectCntl0=0x30; VICIntEnable=1<<16;//使能EINT2 //外部中断初始化 EXTMODE=1<<2;//设置为EINT2下降沿触发 EXTPOLAR=0; EXTINT=1<<2;//清除EINT2中断标志 } /******************************************************************** *名称: ucKeyScan() *功能: 键盘扫描函数当有外部中断2时调用此函数,使用列扫描的方式获取键码,键码 由2位数字组成。 高位为行号低位为列号。 ********************************************************************/ intucKeyScan() { unsignedintucTemp=0;//扫描状态暂存。 for(ucLine=0;ucLine<4;ucLine++)//行扫描 { IOSET=code[ucLine];//输出扫描电位。 IOCLR=(~code[ucLine])&0xF00000; //ucTemp=IOPIN>>24; if(ucTemp! =0x0F)//判断该列是否有按键按下。 continue; }//返回按键编码。 格式为2位数,高位为列号,低位为行号。 } /******************************************************************** *名称: IRQ_EINT2() *功能: EINT2中断服务程序 ********************************************************************/ void__irqIRQ_EINT2(void) { unsignedintucTemp2=0,a; ucTemp2=IOPIN>>24; switch(ucTemp2) { case0x0E: ucRow=00;break;//判断列号。 case0x0D: ucRow=10;break; case0x0B: ucRow=20;break; case0x07: ucRow=30;break; default: ucRow=40;break; } num=ucRow+ucLine; if(repeat==1&num! =23&x! =3)//计算结束后,若输入数字,在输入前清屏 { Command(0x01); add1=add2=sign=0; count=0; repeat=0; DelayNS(10);//延时让LCD反应 } switch(num) { case00: write('7');k=8;break; case01: write('4');k=5;break; case02: write('1');k=2;break; case03: Command(0x01);k=0;add1=add2=sign=0;break; case10: write('8');k=9;break; case11: write('5');k=6;break; case12: write('2');k=3;break; case13: write('0');k=1;break; case20: write('9');k=10;break; case21: write('6')
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 简易 计算器 系统 设计