大连理工软件学院嵌入式大作业51单片机计算器报告_第1页
大连理工软件学院嵌入式大作业51单片机计算器报告_第2页
大连理工软件学院嵌入式大作业51单片机计算器报告_第3页
大连理工软件学院嵌入式大作业51单片机计算器报告_第4页
大连理工软件学院嵌入式大作业51单片机计算器报告_第5页
已阅读5页,还剩31页未读 继续免费阅读

下载本文档

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

文档简介

1、大连理工大学本科实验报告课程名称: 学院(系): 专 业: 班 级: 学 号: 学生姓名: 年 月 日实验项目列表序号实验项目名称学时成 绩指导教师预习操作结果123456789101112131415161718总计学分:8位十进制整数计算器实验报告一、课题任务及要求11 矩阵键盘功能分配:S1S10:19、0S11:BackspaceS12:=2. 独立按键功能分配:3其他要求:1、两个操作数分别显示在两个行里;2、十进制数的最大为数为8位;3、运算符号显示在第二行最左边:开方、整除、倒数、正负用字母A、B、C、D显示;4、可以退格;5、连按两次=,清除显示;二、程序清单/* 描述: *

2、* 矩阵键盘1602液晶显示键值 * * 连接方法:JP8(P1) 与JP4(矩阵键盘接口) 连接 * * 矩阵键盘定义: * P1.1-P1.4为列线,P1.4-P1.7为行线 * * 喇叭接P1.5口 矩阵键盘P1口, * * 注意:请将JP165短路冒断开 * * 作者:aaron * 时间:2013/6/20至2013/6/23 */#include<reg52.h>#include<intrins.h>#include<math.h>/公共函数和宏#define uchar unsigned char #define luint unsigned

3、longvoid delay(uchar x);/延时函数,x是几则代表延时几毫秒uchar change(uchar key);/把数码转换成ascII码函数void hand(uchar tem);/独立按键松手判断uchar jump();/数字输入跳出函数,用在输入第一个数字之后,输入符号之前void result(uchar *innum,uchar inlength);/结果输出函数luint com(uchar *innum,uchar length);/组合函数,把最开始输入的数组值转换成一个long unsigned int储存起来uchar resolve(luint in

4、larnum,uchar *innum);/拆分函数,把一个long unsigned int转换成最开始输入的数组值储存起来/1602函数、宏和位#define delayNOP(); _nop_();_nop_();_nop_();_nop_();/用在以下1602函数中延时用void lcd_wcmd(uchar cmd);/写指令数据到LCD void lcd_wdat(uchar dat);/写显示数据到LCDvoid lcd_init();/LCD初始化设定bit lcd_busy();/检查LCD忙状态 void lcd_pos(uchar pos);/设定显示位置sbit LC

5、D_RW = P25;sbit LCD_RS = P26; sbit LCD_EN = P27;/矩阵键盘函数uchar keydown(void);/键判断uchar keyscan(void);/键扫描子程序/void delay0(uchar x); /x*0.14MS 不清楚用途!/矩阵与lcduchar S1_S12(uchar hang,uchar *num3,uchar *S12_flag);uchar S12clear(uchar *S12_flag);/清屏函数/独立键盘void sign_input(uchar sign);uchar sign_display(uchar

6、*innum,uchar inlength);/符号显示函数/显示函数uchar display();/液晶屏上显示函数void move(uchar *innum,uchar inlength);/数字位移函数/检测发光二级管位声明sbit LED=P20;/运算函数uchar plus(uchar *innum1,uchar *innum2,uchar inlength1,uchar inlength2);/加法函数,用大数加法实现uchar minus(uchar *innum1,uchar *innum2,uchar inlength1,uchar inlength2);/减法函数/*

7、最开始不知道long unsigned int可以储存八位,知道之后编写了com和resolve函数,这两个函数简化了后续的一切运算函数*/*还有解决ram不够的问题,让我一度绝望,但是最后用单片机以外的ram实现了,真是感觉大作业做的很有提高,遇到了几乎大部分问题,解决了之后真的好开心*/uchar multi(uchar *innum1,uchar *innum2,uchar inlength1,uchar inlength2);/*乘法函数,当时忘记把乘法函数加进来了,又调了20多分钟,真是什么错误都犯啊*/uchar division(uchar *innum1,uchar *innu

8、m2,uchar inlength1,uchar inlength2);/*除法函数uchar square(uchar *innum1,uchar inlength1);/开方函数*/uchar divided(uchar *innum1,uchar *innum2,uchar inlength1,uchar inlength2);/整除函数uchar bottom(uchar *innum1,uchar inlength1);/倒数函数uchar ne_po(uchar *innum1,uchar inlength1);/正负函数#include "head.h"/*/

9、* */* 主程序 */* */*/ main() P0=0xFF; /置P0口 P1=0xFF; /置P1口 delay(10); /延时 lcd_init(); /初始化LCD while(1) display(); /*/ #include"head.h"/显示数函数uchar display()/signflag是运算符的代表,length1,length2分别代表输入的第一个数和第二个数的位数uchar signflag,length1,length2,S12_flag1=0;/*最终结果是由num1或者num2储存,尽管数最多八位,但是结果可能出现16位,故申请

10、数组时空间为16*/uchar num116,num216;/第一步,显示并输入第一个数字(可以删可以改)length1=S1_S12(0x4f,num1,S12_flag);if(S12clear(S12_flag)=1)/判断S12是否按了两次,用于清屏lcd_wcmd(0x01);return 0;while(1)S12_flag0=0;/进去之后另算,所以清屏也另算/第二步,输入符号signflag=sign_display(num1,length1);/第三步,进行相应的运算/K1 2 3 4 6这五个独立按键都是两个数的运算,故而放在一块if(signflag=1|signflag

11、=2|signflag=3|signflag=4|signflag=6)/S12clear(S12_flag,1);/判断S12是否按了两次,用于清屏/输入第二个数字length2=S1_S12(0x4f,num2,S12_flag);/*在S1_S12函数中现阶段来讲按S12与按K1K8是有区别的区别在于按S12之后,S1_S12函数退出,在while(1)循环中一直到sign_display函数,无法前进而按K1K8在while(1)循环中一直到S1_S12函数时无法前进,经过sign_display之后 num2的值发生改变,导致第二行的数字被清空*/if(signflag=1)/此处为

12、加法运算函数该函数返回运算结果的长度length1=plus(num1,num2,length1,length2);if(signflag=2)/此处为减法运算函数该函数返回运算结果的长度length1=minus(num1,num2,length1,length2);if(signflag=3)length1=multi(num1,num2,length1,length2);if(signflag=4)length1=division(num1,num2,length1,length2);if(signflag=6)length1=divided(num1,num2,length1,leng

13、th2);else/都是只需要一位运算数的if(signflag=5)length1=square(num1,length1);if(signflag=7)length1=bottom(num1,length1);if(signflag=8)length1=ne_po(num1,length1);/此处为结果输出函数result(num1,length1);if(S12clear(S12_flag)=1)/判断S12是否按了两次,用于清屏lcd_wcmd(0x01);return 0;/数字位移函数,用于输入完符号后,最开始输入的数字移到第一行,并且把最后一行消去void move(uchar

14、 *innum,uchar inlength)uchar xdata count;for(count=0;count<inlength;count+)lcd_pos(0x0f-count);/显示位置设置 lcd_wdat(innuminlength-count-1); /数字显示 /此处inlength+1,多抹一位,为了让类似23/12之后能够把第二行消去for(count=0;count<inlength+1;count+)lcd_pos(0x4f-count);lcd_wdat(0x20);#include "head.h"/*/* */* 键扫描子程序

15、 (4*3 的矩阵) P1.4 P1.5 P1.6 P1.7为行 */* P1.1 P1.2 P1.3为列 */* */*/ uchar keyscan(void)/ uchar tem,key;/第一行矩阵键盘P1=0xfd;tem=P1;tem=tem&0xf0;if(tem!=0xf0)delay(10);tem=P1;tem=tem&0xf0;if(tem!=0xf0)tem=P1;switch(tem)case 0xed:key=0;break;case 0xdd:key=1;break;case 0xbd:key=2;break;case 0x7d:key=3;br

16、eak; /*观察按键是否释放循环,不能在函数最后用一个总的判断是否释放函数那样的话只有最后一行的数字可以在停止按键后显示数字,其他的按了就显示*/while(tem!=0xf0)tem=P1;tem=tem&0xf0;/第二行矩阵键盘P1=0xfb;tem=P1;tem=tem&0xf0;if(tem!=0xf0)delay(10);tem=P1;tem=tem&0xf0;if(tem!=0xf0)tem=P1;switch(tem)case 0xeb:key=4;break;case 0xdb:key=5;break;case 0xbb:key=6;break;ca

17、se 0x7b:key=7;break;while(tem!=0xf0)/观察按键是否释放循环tem=P1;tem=tem&0xf0;/第三行矩阵键盘P1=0xf7;tem=P1;tem=tem&0xf0;if(tem!=0xf0)delay(10);tem=P1;tem=tem&0xf0;if(tem!=0xf0)tem=P1;switch(tem)case 0xe7:key=8;break;case 0xd7:key=9;break;case 0xb7:key=10;break;case 0x77:key=11;break;while(tem!=0xf0)/观察按键

18、是否释放循环tem=P1;tem=tem&0xf0;if(key=10|key=11)/10和11键的功能特殊,不用转换成ASCII码return key;elsekey=change(key);/用来吧数码转换成ASCII码,该函数在公共函数中return key; /*/* */*判断键是否按下 */* */*/uchar keydown(void) uchar key3;if(key3=0)key3=0x30;/key3=0x30是为了让计算器初始化的时候显示0,0x30是0的ASCII码 P1=0xF0;delay(100);/*延时函数,确保数字显示在lcd上,不能过长也不能

19、过短,时间过短显示无法再lcd上固定,时间过长按键不流畅*/if(P1!=0xF0) /判断按键是否按下 如果按钮按下 会拉低P1其中的一个端口 key3=keyscan(); return key3; #include "head.h"/*/* */*检查LCD忙状态 */*lcd_busy为1时,忙,等待。lcd-busy为0时,闲,可写指令与数据 */* */*/ bit lcd_busy() bit result; LCD_RS = 0; LCD_RW = 1; LCD_EN = 1; delayNOP(); result = (bit)(P0&0x80);

20、 LCD_EN = 0; return(result); /*/* */*写指令数据到LCD */*RS=L,RW=L,E=高脉冲,D0-D7=指令码。 */* */*/void lcd_wcmd(uchar cmd) while(lcd_busy(); LCD_RS = 0; LCD_RW = 0; LCD_EN = 0; _nop_(); _nop_(); P0 = cmd; delayNOP(); LCD_EN = 1; delayNOP(); LCD_EN = 0; /*/* */*写显示数据到LCD */*RS=H,RW=L,E=高脉冲,D0-D7=数据。 */* */*/void

21、lcd_wdat(uchar dat) while(lcd_busy(); LCD_RS = 1; LCD_RW = 0; LCD_EN = 0; P0 = dat; delayNOP(); LCD_EN = 1; delayNOP(); LCD_EN = 0; /*/* */* LCD初始化设定 */* */*/void lcd_init() delay(15); lcd_wcmd(0x38); /16*2显示,5*7点阵,8位数据 delay(5); lcd_wcmd(0x38); delay(5); lcd_wcmd(0x38); delay(5); lcd_wcmd(0x0c); /显

22、示开,关光标 delay(5); lcd_wcmd(0x06); /移动光标 delay(5); lcd_wcmd(0x01); /清除LCD的显示内容 delay(5);/*/* */* 设定显示位置 */* */*/void lcd_pos(uchar pos) lcd_wcmd(pos|0x80); /数据指针=80+地址变量#include "head.h"/*/* */* 延时子程序 */* */*/void delay(uchar x) uchar j; while(x-)!=0) for(j=0;j<125;j+) ; /把数码转换成ascII码函数uc

23、har change(uchar key2) key2 = key2 & 0x0f; if(key2>9) /转换为ASCII码 key2 = key2+0x37; else key2 = key2+0x30; return (key2);/独立按键松手判断void hand(uchar tem)while(tem!=0xff)tem=P3;tem=tem&0xff;/数字输入跳出函数,用在输入第一个数字之后,输入符号之前uchar jump()uchar xdata tem,flag=0;tem=P3;tem=tem&0xff;if(tem!=0xff)dela

24、y(10);tem=P3;tem=tem&0xff;if(tem!=0xff)flag=1;return flag;/结果输出函数,innum为储存结果的数组,inlength为结果的位数void result(uchar *innum,uchar inlength)uchar xdata count;for(count=0;count<inlength;count+)lcd_pos(0x0f-count);/显示位置设置 lcd_wdat(innuminlength-count-1); /数字显示 /组合函数,把最开始输入的数组值转换成一个long unsigned int储存

25、起来luint com(uchar *innum,uchar length)luint xdata w1=1,w2=1,larnum=0,tem16;uchar i,j;for(i=0;i<length;i+)temi=innumi;/把ASCII吗都转换成具体数字,且不改变innumtemi=temi-0x30;/因为没把tem转换成具体数字,害的我又检查了两个小时for(i=0;i<length;i+)for(j=0;j<length-1-i;j+)w1*=10;w2=temi*w1;larnum+=w2;w1=1;/if(larnum=123)return larnum

26、;/拆分函数,把一个long unsigned int转换成最开始输入的数组值储存起来uchar resolve(luint inlarnum,uchar *innum)luint xdata w1=1,w2=1,mo9=1,10,100,1000,10000,100000,1000000,10000000,100000000;luint tem=inlarnum;uchar i,length=0;for(i=0;!length;i+)/求该数位数循环tem=inlarnum;tem/=moi+1;if(tem=0)length=i+1;tem=inlarnum;for(i=0;i<le

27、ngth;i+)/第几位innumi=tem/molength-i-1;tem=tem%molength-i-1;for(i=0;i<length;i+)/转码,转换成ASCII码innumi=change(innumi);return length;#include"head.h"/*数字输入函数hang 表示第一行还是第二行,只有两个值可赋,0x0f第一行与0x4f第二行num3表示储存输入数字的数组名*/uchar S1_S12(uchar hang,uchar *num3,uchar *S12_flag)/*key1用来储存数字的返回ASCII码用的,针对矩阵

28、键盘上的数字、退格、等于 count代表输入第几次,count1代表需要移动几个数字 用途:用来限制输入数字的位数 和 辅助前几个数字的移动 tem用于接收P1口 old用于储存以前的值*/uchar xdata count,tem,old;char xdata count1;/count1会出现负值,避免不了P1=0xf1;/P1如果不先给行赋一个低电位的话tem就无法接受到P1的值tem=P1;tem=tem&0xf0;while(tem=0xf0)/*该循环使得该函数只有在用独立键盘输入时才会退出,退出通道只有下面的两个while中的return 0语句*/用于判断S1-S10f

29、or(count=1;count<=8;)/位数不超过八位old=0; P1=0xf1;/不能少,因为在循环里要判断,不能依靠外面的那个tem=P1;tem=tem&0xf0;delay(10);/*只要不按键,就不退出该循环while循环必须在if的前面,否则会出现跳过count的现象*/while(tem=0xf0)P1=0xf1;tem=P1;tem=tem&0xf0;if(jump()=1)return count-1;if(tem!=0xf0)/S11用于退格键if(keydown()=10)for(count1=1;count1<count-1;coun

30、t1+)/*count1,count,与for里面的语句经过了痛苦的计算才得到的*/lcd_pos(hang+count1-count+2);/*显示位置设置! 0x4f为右下角的位置*/ lcd_wdat(num3old); /*数字显示 数据已经换完了,更新过的key1*/old+;lcd_pos(hang-count+2);/给最高位换成空白lcd_wdat(0x20); /给最高位换成空白count=count-2;/退格为了还是最多能输入八个数/S12用于输入=else if(keydown()=11) if(S12_flag0=0)S12_flag0+;return count-1

31、;if(S12_flag0=1)return 0;/S1-S10用于输入数字elsenum3count-1=keydown();for(count1=count;count1>0;count1-)/*count1是uchar类型的,不能小于零,一旦小于零,-1则等于511,这儿耗了我两个小时检查*/lcd_pos(hang-count1+1);/显示位置设置! 0x4f为右下角的位置 lcd_wdat(num3old); /数字显示 old+;/无奈之举,为了让输入数字达到8个以后还能继续操作S11和S12count+;if(count=9)old=0; P1=0xf1;/不能少,因为在

32、循环里要判断,不能依靠外面的那个tem=P1;tem=tem&0xf0;delay(10);/*只要不按键,就不退出该循环while循环必须在if的前面,否则会出现跳过count的现象*/while(tem=0xf0)P1=0xf1;tem=P1;tem=tem&0xf0;if(jump()=1)return count-1;if(tem!=0xf0)/S11用于退格键if(keydown()=10)for(count1=1;count1<count-1;count1+)/*count1,count,与for里面的语句经过了痛苦的计算才得到的*/lcd_pos(hang+

33、count1-count+2);/*显示位置设置! 0x4f为右下角的位置*/ lcd_wdat(num3old); /*数字显示 数据已经换完了,更新过的key1*/old+;lcd_pos(hang-count+2);/给最高位换成空白lcd_wdat(0x20); /给最高位换成空白count=count-1;/*退格为了还是最多能输入八个数,与上面的程序不一样的地方!*/S12用于输入=else if(keydown()=11)/*虽然在这里没实现11的功能,但是不能缺少,否则按S11就会输出乱码*/return count-1; /清屏函数uchar S12clear(uchar *

34、S12_flag)uchar xdata tem1,tem2,flag=0;/flag用于标记是不是按了S12P1=0xf1;tem1=P1;tem1=tem1&0xf0;delay(10);tem2=P3;tem2=tem2&0xff;delay(10);/*只要不按键,就不退出该循环矩阵键盘与独立按键要分别进行设置*/while(tem1=0xf0&&tem2=0xff)P1=0xf1;tem1=P1;tem1=tem1&0xf0;tem2=P3;tem2=tem2&0xff;P1=0xf7;tem1=P1;tem1=tem1&0x8

35、0;if(tem1!=0x80)delay(10);/防抖P1=0xf7;tem1=P1;tem1=tem1&0x80;if(tem1!=0x80)if(keydown()=11)/如果按了矩阵键盘的S12if(S12_flag0%2!=0)flag=1;return flag;#include "head.h"/符号输入函数void sign_input(uchar sign)lcd_pos(0x40);lcd_wdat(sign);/符号显示函数uchar sign_display(uchar *innum,uchar inlength)uchar xdata

36、tem,flag=0;/flag是用来标记最后的符号是哪个键按下的while(1)/第二步,显示并输入并列的运算中的一个(运算符不可删)tem=P3;tem=tem&0xff;if(tem!=0xff)delay(10);tem=P3;tem=tem&0xff;if(tem!=0xff) if(P3=0xfe)/加法flag=1;hand(tem);/独立键盘松手函数,在公共函数里sign_input(0x2b);/运算符输入move(innum,inlength);/此处为位移函数return flag;if(P3=0xfd)/减法flag=2;hand(tem);/独立键盘松手函数,在公共函数里sign_input(0x2d);/运算符输入move(innum,inlength);/此处为位移函数return flag;if(P3=0xfb)/乘法flag=3;hand(tem);/独立键盘松手函数,在公共函数里sign_input(0x2a);/运算符输入move(innum,inlength);/此处为位移函数return flag;if(P3=0xf7)/除法flag=4;ha

温馨提示

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

评论

0/150

提交评论