基于单片机的计算器.doc_第1页
基于单片机的计算器.doc_第2页
基于单片机的计算器.doc_第3页
基于单片机的计算器.doc_第4页
基于单片机的计算器.doc_第5页
已阅读5页,还剩13页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

“简易计算器”设计、调试报告 2010年6月一、设计目标陈述计算器是人们在日常生活中很常见的电子产品。本次是基于Keil uVision调试编译软件和单片机AT89C51来设计简易计算器,实现正常的键盘扫描、LED显示、任意两个4位整数的连续加、减、乘、除运算以及计算器复位等基本功能。二、完成情况简述本次设计的简易计算器完成了进行正常的键盘扫描,任意两个4位整数的输入和LED循环显示,连续的加、减、乘、除四则运算,结果的正常显示,以及计算器的复位等预期目标。此外,在设计中还解决了键盘的抖动、长久按键时间所引起的键盘扫描问题、LED显示的亮度等细节问题。三、系统总体描述及系统框图该设计系统是基于单片机AT89C51,其中 P1口作为输入端,外接4X4的键盘,P0口为LED段选信号输出端,P2口为LED位选信号输出端,通过键盘扫描来读取运算数和运算符,再通过单片机进行相应的运算,将输出结果用LED显示。系统框图:键盘输入驱动电路数码显示AT89C51四、各模块说明1.键盘设计4X4的键盘(16个开关),与AT89C51芯片P1口相连,高四位作为输入,低四位作为输出。低四位逐位变低分别对各列进行扫描,一旦有键按下,则对应输入口为低电平,否则输入为高电平,通过这样可以判断按下什么键。在键按下后,要有一定的延时,防止由于键盘的抖动而引起误操作。2.控制中心用AT89C51来实现AT89C51单片机参数如下:Vcc正常的运行电压是5v的电源,Vss 为地端。I/O总线,P0口,P1口,P2口,P3口。AT89C51是MCS-51产品的兼容型,ROM、128字节ROM,32根I/O引线,每根都可以独立的使用。每个的端口包含一个8位的数据锁存和一个输入缓冲器。输出时,数据可以锁存;输入时,数据可以缓冲。作为一般的I/O口使用时,在指令的控制下,可以有三种基本的方式:输入输出和读修改写。在AT89C51用作输入端时,将首先向引脚写“1”而使内部MOS管截止以便引脚处于悬浮状态,从而可获得高阻抗输入。3. 驱动电路部分是用三极管和电阻来实现。AT89C51的P0口用于数码管的段选,由NPN管和限流电阻来驱动;P2口用于数码管的位选,由PNP管来驱动。所用数码管为4个共阳LED,段选端为低电平有效,位选端为高电平有效。4. 显示是用4个共阳的LED来完成。采用动态循环显示方式,全部数码管共用一套段选驱动电路,各位数码管的同段引脚短接后再接到对应段选的驱动线上。显示时通过位选信号采用扫描的方法逐位地循环点亮各位数码管。动态显示虽然在任一时刻只有一位数码管点亮,但是由于人眼具有的视觉残留效应,看起来与全部数码管持续点亮的效果完全一样。五、调试流程1.测试电源调节直流电压源输出+5V电压,并用万用表检测无误后接入电路板。2.LED测试编写LED调试程序如下:#include reg51.h#include intrins.hunsigned char code showcode=0xB7,/*0*/0xA0,/*1*/0xD3,/*2*/0xF1,/*3*/0xE4,/*4*/0x75,/*5*/0x77,/*6*/0xA1,/*7*/0xF7/*8*/,0xF5/*9*/; void main() / 单步调试 P0=0xB7;/显示0P2=0xfe;P2=0xfd;P2=0xfb;P2=0xf7;P0=0xf7;/显示8P2=0xfe;P2=0xfd;P2=0xfb;P2=0xf7; 进行单步运行,LED逐位显示,显示结果正常。3.整体调试 将主程序通过仿真器下载到电路板,检测键盘与LED的功能是否正常。4.功能优化 根据硬件显示的结果进行程序优化,调节LED的亮度与显示的稳定性,以及提高键盘读取数据的正确性和灵敏度。六、遇到的问题及解决方法1.问题:上电后四个LED中第四位无法显示 解决方法:先用万用表的二极管档进行LED电路测试,发现该为LED的位选信号线虚接。重新焊接后显示正常。2.问题:发现四位LED均显示8,改变输入码字后显示不变 解决方法:用万用表直接测试仿真器的P0口(码字输出端口),发现电平正常,但是接入电路后就显示错误。在老师的指导下,知道由于仿真器的内部结构与AT89C51的差异性和P0的特殊性,需要将外加电源接入仿真器的VCC端进行供电。进行修改后,LED能够根据输入码字的变化正常显示。3.问题:LED的显示亮度不稳定,位数较长时显示不清晰(比较闪) 解决方法:修改LED显示程序,将原先的8位LED显示程序改为4位,并适当缩短每位显示的延迟时间后,显示的亮度稳定。七、元器件清单元器件名称元器件型号元器件数量单片机AT89C51 1按键点触式 16LED共阳 4三极管NPN 8PNP 4电阻4.7k 12330 89.1k 12470 110k 12k 1电容33p 2晶振12M 1二极管发光二极管 1八、原理图及实物照片原理图:实物照片:九、软件层次结构框图和流程图 开始初始化显示器代码和键驱动码及其它参数分四组循环输出列扫描信号键盘译码存储按键数据并并显示数据运算存储结果并显示显示现有数据读入按键信息是否有键按下十、简易计算器软件包设计规格书1.修订记录时间作者描述2010-4-30马辰阳v0.12010-5-14俞淑婷v0.22010-6-4马辰阳、俞淑婷v0.32.文档说明本文档是基于AT89C51的简易计算器软件包的设计指导性文件,软件包的开发及维护均应在本文档的规定下进行。3.项目说明本项目基于AT89C51,软件包为源码的若干集合,并按照一定目录结构排列。4.开发环境Keil uVision5.目录结构- calculator |-.calculator.h |- function |- main.c |- delay.c |- key_show.c|- scan_show.c|- key_sweep.c |- store_as_single.c|- save_data.c |- calculate.c |- processing.c |- include |- reg51.h |- intrins.h |- calculator.h十一、源代码(附注释)/*function:简易计算器主函数*/#includeMcro.h /包含宏头文件#includecalculator.h /包含计算机头文件void main()uint j,k;while(1) processing(j,k); /循环执行处理子程序/* function end */* function: 宏定义头文件 */-数据类型定义-/#define uchar unsigned char#define uint unsigned int/-显示位数定义-/#define show_0 (position3=0)&(position2=0) &(position1=0)&(position0=0) /当个十百千位全为0时显示0#define show_1 (position3=0)&(position2=0)&(position1=0) /当十百千位全为0时显示*#define show_2 (position3=0)&(position2=0) /当百千位全为0时显示*#define show_3 (position3=0) /当千位全为0时显示*/=全局变量定义=/ /*显示器缓冲区段码 */uchar code showcode=0xB7,/*0*/0xA0,/ *1*/0xD3,/*2*/0xF1,/*3*/0xE4,/*4*/0x75,/*5*/0x77,/*6*/0xA1,/*7*/0xF7/*8*/,0xF5/*9*/; /*P10到P13的键驱动码*/uchar code sweep_code4=0xf7/*第一列*/,0xfb/*第二列*/,0xfd/*第三列*/,0xfe/*第四列*/; /* 运算符标志 负号标志 键盘译码数 第几操作数标志 */uint operator_signal,minus=0, key_decode,flag=0;/*操作数存储区 */ uint data mydata24=0,0,0,0, 0,0,0,0; /函数申明#includedelay.c /延时1ms子程序#include key_show.c /键码显示子程序#includekey_sweep.c /键盘扫描子程序#includestore_as_single.c /位数分离存储子程序#includesave_data.c /存储数据子程序#include calculate.c /执行计算功能的子程序#include processing.c /处理联合子程序/* function end */* function:数码管显示 子程序*/#includescan_show.cvoid key_show(uint position,uchar first)P2=first;if(minus=0) /minus=0表示显示的数据是正数if(show_0) /显示0P0=0xb7; /0xb7是0的段码else if(show_1) /显示*P0=showcodeposition0; else if(show_2) /显示* scan_show(position,2); /调用数码管显示数据子程序else if(show_3) /显示* scan_show(position,3); else /显示* scan_show(position,4);else /否则minus=1表示显示的数据是负数if(show_0) /显示0P0=0xb7;else if(show_1) /显示* P0=showcodeposition0; delay(3); P2=_crol_(P2,1); /P2口循环左移1位 P0=0x00; /段码消影 delay(3); P0=0x40; /0x40是-的段码 delay(3); P0=0x00; else if(show_2)/显示*scan_show(position,2);delay(3);P0=0x40;delay(3);P0=0x00;else if(show_3)/显示*scan_show(position,3); delay(3);P0=0x40;delay(3);P0=0x00; else /显示* scan_show(position,4); delay(3);P0=0x40;delay(3);P0=0x00; /*funcion end*/*scan_show.c*/void scan_show(uint position_x,uint scan_time_x) uint t; for(t=0;tscan_time_x;t+) /scan_time为数据的位数 P0=showcodeposition_xt; delay(3); P2=_crol_(P2,1); P0=0x00; /* function end */*function:键盘扫描子程序*/void key_sweep( ) uchar X,Y,Z,i2; P1=0xff; /P1口置高便于读取口数据 for(i2=0;i24;i2+) P1=sweep_codei2; /调用键驱动码进行扫描 X=P1; /读取P1口数据 X=X & 0xf0; /屏蔽低四位 if(X!=0xf0) /判断是否有键按下 delay(10); /去抖动 X=P1; X=X & 0xf0; if(X!=0xf0) /再次确认是否有键按下 Y=sweep_codei2; Y=Y & 0x0f; Z=X|Y; switch ( Z ) /确定按下的键码 case 0xe7: key_decode=0; break; case 0xeb: key_decode=1; break; case 0xed: key_decode=2; break; case 0xee: key_decode=3; break; case 0xd7: key_decode=4; break; case 0xdb: key_decode=5; break; case 0xdd: key_decode=6; break; case 0xde: key_decode=7; break; case 0xb7: key_decode=8; break; case 0xbb: key_decode=9; break; case 0xbd: key_decode=10;break; case 0xbe: key_decode=11;break; case 0x77: key_decode=12;break; case 0x7b: key_decode=13;break; case 0x7d: key_decode=14;break; case 0x7e: key_decode=15;break; while(X!=0xf0) /等待键抬起再退出程序 X=P1; X=X & 0xf0; key_show(mydataflag,0x01); /*funcion end*/*function:数据分位储存子程序*/void store_as_single(uint m) mydata03=m/1000; /存千位mydata02=m%1000/100; /存百位mydata01=m%100/10; /存十位mydata00=m%10; /存个位/*funcion end*/* function:存储按键数据子程序*/void save_data(uint m,uint n) /舍去最高位数据,将低位数据移向高位,再将读入的数据写入最低位 mydatan3=mydatan2; mydatan2=mydatan1; mydatan1=mydatan0; mydatan0=m;/*funcion end*/*function:基本四则运算子程序*/void calculate(uint m)/*分别定义计算结果,第一操作数和第二操作数*/uint result,operator_data_0,operator_data_1; operator_data_0=mydata00+mydata01*10+mydata02*100+mydata03*1000;/对第一操作数赋值operator_data_1=mydata10+mydata11*10+mydata12*100+mydata13*1000;/对第二操作数赋值switch(m) case 1: /加法 result=operator_data_0+operator_data_1; store_as_single(result); /将result各位数据分离存储break;case 2:/减法if(operator_data_0operator_data_1) /判断减法是否会产生负号result=operator_data_1-operator_data_0;minus=1;else result=operator_data_0-operator_data_1; store_as_single(result);break;case 3:/乘法result=operator_data_1*operator_data_0;store_as_single(result);break;case 4:/除法result=operator_data_0/operator_data_1;store_as_single(result);break;/*funcion end*/*function:执行扫描、显示、存储、计算子程序*/void processing(uint j ,uint k) key_show(mydataflag,0xfe); /数码管显示数据 key_sweep(); /键盘扫描 if(key_decode=15) /复位键按下,清除数据区,置负号位为0,进入计算器状态置操作码为0 for(j=0;j2;j+) for(k=0;k=0)&(key_decode=10)&(key_decode=13)/操作键 switch(key_decode) case 10: operator_signal=1;delay(100);break;/加 case 11: operator_signal=2;delay(100);break;/减 case 12: operator_signal=3;delay(100);break;/乘 case 13: operator_signal=4;delay(100);break;/除 flag+; /操作次数 if(flag=2) flag=0; key_decode=20; else if(key_decode=14)/读入的键是等于键 calculate(operator_signal);/计算 operator_signal=0; /操作位置0 mydata10=mydata11=mydata12=mydata13=0;/第二操作数置0 flag=0; /操作次数置0 key_decode=20; /*funcion end*/袁节膅薂羄肅蒃薁蚃芀荿薀螆肃芅蕿袈芈膁蚈羀肁蒀蚇蚀袄莆蚇螂肀莂蚆羅袂芈蚅蚄膈膄蚄螇羁蒂蚃衿膆莈蚂羁罿芄螁蚁膄膀螁螃羇葿螀袅膃蒅蝿肈羆莁螈螇芁芇莄袀肄膃莄羂艿蒂莃蚂肂莈蒂螄芈芄蒁袆肀膀蒀罿袃薈葿螈聿蒄葿袁羁莀蒈羃膇芆蒇蚃羀膂蒆螅膅蒁薅袇羈莇薄罿膄芃薃虿羆艿薃袁节膅薂羄肅蒃薁蚃芀荿薀螆肃芅蕿袈芈膁蚈羀肁蒀蚇蚀袄莆蚇螂肀莂蚆羅袂芈蚅蚄膈膄蚄螇羁蒂蚃衿膆莈蚂羁罿芄螁蚁膄膀螁螃羇葿螀袅膃蒅蝿肈羆莁螈螇芁芇莄袀肄膃莄羂艿蒂莃蚂肂莈蒂螄芈芄蒁袆肀膀蒀罿袃薈葿螈聿蒄葿袁羁莀蒈羃膇芆蒇蚃羀膂蒆螅膅蒁薅袇羈莇袄芈蒇袇螀芇蕿蚀聿芆艿蒃肅芅蒁螈羁芄薃薁袆芃芃螆螂芃莅蕿肁节蒈螅羇莁薀薈袃莀艿螃蝿荿莂薆膈莈薄袁肄莇蚆蚄羀莇莆袀袆羃蒈蚂螂羂薁袈肀肁芀蚁羆肁莃袆袂肀薅虿袈聿蚇蒂膇肈莇螇肃肇葿薀罿肆薂螆袅肅芁薈螁膅莃螄聿膄蒆薇羅膃蚈螂羁膂莈蚅袇膁蒀袀螃膀薂蚃肂腿节衿羈腿莄蚂袄芈蒇袇螀芇蕿蚀聿芆艿蒃肅芅蒁螈羁芄薃薁袆芃芃螆螂芃莅蕿肁节蒈螅羇莁薀薈袃莀艿螃蝿荿莂薆膈莈薄袁肄莇蚆蚄羀莇莆袀袆羃蒈蚂螂羂薁袈肀肁芀蚁羆肁莃袆袂肀薅虿袈聿蚇蒂膇肈莇螇肃肇葿薀罿肆薂螆袅肅芁薈螁膅莃螄聿膄蒆薇羅膃蚈螂羁膂莈蚅袇膁蒀袀螃膀薂蚃肂腿节衿羈腿莄蚂袄芈蒇袇螀芇蕿蚀聿芆艿蒃肅芅蒁螈羁芄薃薁袆芃芃螆螂芃莅蕿肁节蒈螅羇莁薀薈袃莀艿螃蝿荿莂薆膈莈薄袁肄莇蚆蚄羀莇莆袀袆羃蒈蚂螂羂薁袈肀肁芀蚁羆肁莃袆袂肀薅虿袈聿蚇蒂膇肈莇螇肃肇葿薀罿肆薂螆袅肅芁薈螁膅莃螄聿膄蒆薇羅膃蚈螂羁膂莈蚅袇膁蒀袀螃膀薂蚃肂腿节衿羈腿莄蚂袄芈蒇袇螀芇蕿蚀聿芆艿蒃肅芅蒁螈羁芄薃薁袆芃芃螆螂芃莅蕿肁节蒈螅羇莁薀薈袃莀艿螃蝿荿莂薆膈莈薄袁肄莇蚆蚄羀莇莆袀袆羃蒈蚂螂羂薁袈肀肁芀蚁羆肁莃袆袂肀薅虿袈聿蚇蒂膇肈莇螇肃肇葿薀罿肆薂螆袅肅芁薈螁膅莃螄聿膄蒆薇羅膃蚈螂羁膂莈蚅袇膁蒀袀螃膀薂蚃肂腿节衿羈腿莄蚂袄芈蒇袇螀芇蕿蚀聿芆艿蒃肅芅蒁螈羁芄薃薁袆芃芃螆螂芃莅蕿肁节蒈螅羇莁薀薈袃莀艿螃蝿荿莂薆膈莈薄袁肄莇蚆蚄羀莇莆袀袆羃蒈蚂螂羂薁袈肀肁芀蚁羆肁莃袆袂肀薅虿袈聿蚇蒂膇肈莇螇肃肇葿薀罿肆薂螆袅肅芁薈螁膅莃螄聿膄蒆薇羅膃蚈螂羁膂莈蚅袇膁蒀袀螃膀薂蚃肂腿节衿羈腿莄蚂袄芈蒇袇螀芇蕿蚀聿芆艿蒃肅芅蒁螈羁芄薃薁袆芃芃螆螂芃莅蕿肁节蒈螅羇莁薀薈袃莀艿螃蝿荿莂薆膈莈薄袁肄莇蚆蚄羀莇莆袀袆羃蒈蚂螂羂薁袈肀肁芀蚁羆肁莃袆袂肀薅虿袈聿蚇蒂膇肈莇螇肃肇葿薀罿肆薂螆袅肅芁薈螁膅莃螄聿膄蒆薇袁节膅薂羄肅蒃薁蚃芀荿薀螆肃芅蕿袈芈膁蚈羀肁蒀蚇蚀袄莆蚇螂肀莂蚆羅袂芈蚅蚄膈膄蚄螇羁蒂蚃衿膆莈蚂羁罿芄螁蚁膄膀螁螃羇葿螀袅膃蒅蝿肈羆莁螈螇芁芇莄袀肄膃莄羂艿蒂莃蚂肂莈蒂螄芈芄蒁袆肀膀蒀罿袃薈葿螈聿蒄葿袁羁莀蒈羃膇芆蒇蚃羀膂蒆螅膅蒁薅袇羈莇薄罿膄芃薃虿羆艿薃袁节膅薂羄肅蒃薁蚃芀荿薀螆肃芅蕿袈芈膁蚈羀肁蒀蚇蚀袄莆蚇螂肀莂蚆羅袂芈蚅蚄膈膄蚄螇羁蒂蚃衿膆莈蚂羁罿芄螁蚁膄膀螁螃羇葿螀袅膃蒅蝿肈羆莁螈螇芁芇莄袀肄膃莄羂艿蒂莃蚂肂莈蒂螄芈芄蒁袆肀膀蒀罿袃薈葿螈聿蒄葿袁羁莀蒈羃膇芆蒇蚃羀膂蒆螅膅蒁薅袇羈莇薄罿膄芃薃虿羆艿薃袁节膅薂羄肅蒃薁蚃芀荿薀螆肃芅蕿袈芈膁蚈羀肁蒀蚇蚀袄莆蚇螂肀莂蚆羅袂芈蚅蚄膈膄蚄螇羁蒂蚃衿膆莈蚂羁罿芄螁蚁膄膀螁螃羇葿螀袅膃蒅蝿肈羆莁螈螇芁芇莄袀肄膃莄羂艿蒂莃蚂肂莈蒂螄芈芄蒁袆肀膀蒀罿袃薈葿螈聿蒄葿袁羁莀蒈羃膇芆蒇蚃羀膂蒆螅膅蒁薅袇羈莇薄罿膄芃薃虿羆艿薃袁节膅薂羄肅蒃薁蚃芀荿薀螆肃芅蕿袈芈膁蚈羀肁蒀蚇蚀袄莆蚇螂肀莂蚆羅袂芈蚅蚄膈膄蚄螇羁蒂蚃衿膆莈蚂羁罿芄螁蚁膄膀螁螃羇葿螀袅膃蒅蝿肈羆莁螈螇芁芇莄袀肄膃莄羂艿蒂莃蚂肂莈蒂螄芈芄蒁袆肀膀蒀罿袃薈葿螈聿蒄葿袁羁莀蒈羃膇芆蒇蚃羀膂蒆螅膅蒁薅袇羈莇薄罿膄芃薃虿羆艿薃袁节膅薂羄肅蒃薁蚃芀荿薀螆肃芅蕿袈芈膁蚈羀肁蒀蚇蚀袄莆蚇螂肀莂蚆羅袂芈蚅蚄膈膄蚄螇羁蒂蚃衿膆莈蚂羁罿芄螁蚁膄膀螁螃羇葿螀袅膃蒅蝿肈羆莁螈螇芁芇莄袀肄膃莄羂艿蒂莃蚂肂莈蒂螄芈芄蒁袆肀膀蒀罿袃薈葿螈聿蒄葿袁羁莀蒈羃膇芆蒇蚃羀膂蒆螅膅蒁薅袇羈莇薄罿膄芃薃虿羆艿薃袁节膅薂羄肅蒃薁蚃芀荿薀螆肃芅蕿袈芈膁蚈羀肁蒀蚇蚀袄莆蚇螂肀莂蚆羅

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论