枣庄手机网站建设公司百度号码查询平台
目录
一、设计背景
二、实现功能
三、硬件设计
3.1 总体硬件设计
3.2 键盘电路的设计
3.3 显示电路的设计
四、仿真演示
五、源程序
一、设计背景
随着社会的发展,科学的进步,人们的生活水平在逐步的提高,尤其是微电子技术的发展,犹如雨后春笋般的变化。电子产品的更新速度快就不足惊奇了。计算器在人们的日常中是比较的常见的电子产品之一。如何使计算器技术更加的成熟,充分利用已有的软件和硬件条件,设计出更出色的计算器,使其更好的为各个行业服务,成了如今电子领域重要的研究课题。
二、实现功能
本设计是以AT89C51单片机为核心的计算器模拟系统设计,输入采用4×4矩阵键盘,可以进行加、减、乘、除4位带符号数字运算,最大运算是可达9999*9999,可以运算负数,并在LCD1602上显示操作过程。
三、硬件设计
3.1 总体硬件设计
为了更好的实现系统得功能,硬件电路的设计应该遵循以下原则:
1、优化硬件电路
采用软件设计与硬件设计相结合的方法;尽管采用软件来实现硬件系统的功能时,也许响应时间会比单纯使用硬件时长,而且还要占用微处理器(MCU)的时间;但是,用软件实现硬件的功能可以简化硬件结构,提高电路的可靠性。所以,在设计本系统得时候,在满足可靠性和实时性的前提下,尽可能的通过软件来实现硬件功能。
2、可靠性及抗干扰设计
根据可靠性设计理论,系统所用芯片数量越少,系统的平均无故障时间越长。而且,所用芯片数量越少,地址和数据总线在电路板上受干扰的可能性也就越小。因此,系统的设计思想是在满足功能的情况下力争使用较少数量的芯片。
3、灵活的功能扩展
功能扩展是否灵活是衡量一个系统优劣的重要指标。一次设计往往不能完全考虑到系统的各个方面,系统需要不断完善以及进行功能升级。进行功能扩展时,应该在原有设计的基础上,通过修改软件程序和少量硬件完成。对于本系统而言,就是要求在系统硬件不变的情况下,能够通过修改软件程序,完成功能的升级和扩展。
根据第提出的系统设计方案,结合以上三条原则,确定了系统硬件的设计。计算器主要由以下一些功能模块构成:非编码键盘模块、LCD液晶显示屏模块等。
下图为总体硬件结构。
3.2 键盘电路的设计
键盘可分为两类:编码键盘和非编码键盘。编码键盘是较多按键(20个以上)和专用驱动芯片的组合,当按下某个按键时,它能够处理按键抖动、连击等问题,直接输出按键的编码,无需系统软件干预。通用计算机使用的标准键盘就是编码键盘。在智能仪器中,使用并行接口芯片8279或串行接口芯片HD7279均可以组成编码键盘,同时还可以兼顾数码管的显示驱动,其相关的接口电路和接口软件均可在芯片资料中得到。当系统功能比较复杂,按键数量很多时,采用编码键盘可以简化软件设计。从成本角度出发,本设计选用的是非编码键盘。如下图所示:
3.3 显示电路的设计
当系统需要显示少量数据时,采用LCD液晶显示屏进行显示是一种经济实用的方法。P0口作为液晶显示的数据端口,P3.5-P3.7口作为其控制端口,控制LCD液晶显示屏显示输出数据。如下图所示:
四、仿真演示
初始界面
加运算
减运算
乘运算
除运算
五、源程序
#include<reg51.h>
#define uint unsigned int
#define uchar unsigned char
//--------LCD1602-------------------
//P00-07==== D0-7
sbit rs=P2^7; //指令or数据
sbit wela=P2^6; //读or写
sbit lcden=P2^5; //使能信号
//--------LCD1602-------------------
//--------KEY-----------------------
//P1口
//--------KEY-----------------------
uchar code table[]= " ";long int data_a,data_b; //第一个数和第二个数
long int data_c; //计算结果uchar dispaly[10]; //显示缓冲//************************************************************************/
// 描述: 延时t us函数
//************************************************************************/
void LCD_Delay_us(unsigned int t)
{while(t--); //t=0,退出
}
//************************************************************************/
// 描述: 延时t ms函数
//************************************************************************/
void LCD_Delay_ms(unsigned int t)
{unsigned int i,j;for(i=0;i<t;i++) //执行t次循环for(j=0;j<113;j++) //执行113次循环;
}
//************************************************************************/
// 描述: 1602液晶写指令
//************************************************************************/
void write_com(uchar com) //1602液晶写指令
{rs=0; //写指令lcden=0; //使能1602 P0=com; //写入指令comLCD_Delay_ms(1); //延时1mslcden=1; //使能1602LCD_Delay_ms(2); //延时2ms lcden=0; //使能1602
}
//************************************************************************/
// 描述:1602液晶写数据
//************************************************************************/
void write_date(uchar date) //1602液晶写数据
{rs=1; //写数据lcden=0; //使能1602 P0=date; //写入数据dateLCD_Delay_ms(1); //延时1mslcden=1; //使能1602LCD_Delay_ms(2); //延时2mslcden=0; //使能1602
}
//************************************************************************/
// 描述:指定x,y写入字符函数
//************************************************************************/void W_lcd(unsigned char x,unsigned char y,unsigned char Data) { if (y == 0){write_com(0x80 + x);} //第一行 else{write_com(0xc0 + x);} //第二行write_date( Data); //写入数据}//指定x,y写入字符串函数void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s) { if (y == 0){write_com(0x80 + x);} //第一行else{write_com(0xC0 + x);} //第二行while (*s) //{write_date( *s); s++;} //写入数据}
//************************************************************************/
// 描述:初始化液晶,及画面初始化
//************************************************************************/
void init_lcd(void) //初始化液晶,及画面初始化
{wela=0; //写液晶lcden=0; //使能1602write_com(0x38); //8 位总线,双行显示,5X7 的点阵字符LCD_Delay_us(100); //延时100uswrite_com(0x0c); //开显示,无光标,光标不闪烁write_com(0x06); //光标右移动write_com(0x01); //清屏write_com(0x80); //DDRAM 地址归0
}
//************************************************************************/
// 描述: 反转法键盘扫描
//************************************************************************/
short keycheckdown() /* 反转法键盘扫描 */
{short temp1,temp2,temp,a=0xff;P1=0xf0; /* 输入行值(或列值) */LCD_Delay_ms(20); /* 延时 */temp1=P1; /* 读列值(或行值) */P1=0xff;LCD_Delay_ms(20); /* 延时 */P1=0x0f; /* 输入列值(或行值) */LCD_Delay_ms(20); /* 延时 */ temp2=P1; /* 读行值(或列值) */P1=0xff;temp=(temp1&0xf0)|(temp2&0xf); /* 将两次读入数据组合 */switch(temp) /* 通过读入数据组合判断按键位置 */{case 0x77 :a=0x0a;break;// 按键+ case 0x7b :a=0x0e; break;// 按键= case 0x7d :a=0; break;// 按键0case 0x7e :a=0x0f; break;// 按键CEcase 0xe7 :a=0x0d;break;// 按键/case 0xeb :a=0x9;break; // 按键9case 0xed :a=0x8;break; // 按键8 case 0xee :a=0x7;break; // 按键7case 0xd7 :a=0x0c;break;// 按键*case 0xdb :a=0x6;break; // 按键6case 0xdd :a=0x5;break; // 按键5case 0xde :a=0x4;break; // 按键4case 0xb7 :a=0x0b; break;// 按键-case 0xbb :a=3;break; // 按键3case 0xbd :a=2;break; // 按键2case 0xbe :a=1;break; // 按键1default :a=0xff;}return a; /* 返回按键值 */
}
void display_a() //显示数据a
{dispaly[3]=data_a%10000/1000; //千dispaly[2]=data_a%1000/100; //百dispaly[1]=data_a%100/10; //十dispaly[0]=data_a%10; //个 write_com(0x80+0); //显示数据aif(data_a>999){ write_date('0'+dispaly[3]);} //显示千位if(data_a>99){ write_date('0'+dispaly[2]);} //显示百位if(data_a>9){ write_date('0'+dispaly[1]);} //显示十位write_date('0'+dispaly[0]); //显示个位
}void display_b() //显示数据b
{write_com(0x80+7); //第一行dispaly[3]=data_b%10000/1000; //千dispaly[2]=data_b%1000/100; //百dispaly[1]=data_b%100/10; //十dispaly[0]=data_b%10; //个 if(data_b>999){ write_date('0'+dispaly[3]); } //显示千位
if(data_b>99) { write_date('0'+dispaly[2]); } //显示百位
if(data_b>9) { write_date('0'+dispaly[1]); } //显示十位write_date('0'+dispaly[0]); //显示个位
}//计算结果
void display_c(x)
{if(data_c<100000000&&data_c>-1)//溢出时显示错误{ dispaly[8]=data_c%1000000000/100000000; //万万dispaly[7]=data_c%100000000/10000000; //千万dispaly[6]=data_c%10000000/1000000; //百万dispaly[5]=data_c%1000000/100000; //十万dispaly[4]=data_c%100000/10000; //万dispaly[3]=data_c%10000/1000; //千dispaly[2]=data_c%1000/100; //百dispaly[1]=data_c%100/10; //十dispaly[0]=data_c%10; //个 write_com(0x80+6+0x40); //第一行if(x==4){ if(data_c>99999999) { write_date('0'+dispaly[8]);} //显示万万if(data_c>9999999) { write_date('0'+dispaly[7]);} //千万if(data_c>999999) { write_date('0'+dispaly[6]);} //百万if(data_c>99999) { write_date('0'+dispaly[5]);} //十万if(data_b!=0) {write_date('0'+dispaly[4]); //万write_date('.');write_date('0'+dispaly[3]); //千write_date('0'+dispaly[2]); //百write_date('0'+dispaly[1]); //十write_date('0'+dispaly[0]); //个 }}else{if(data_c>99999999) { write_date('0'+dispaly[8]);} //显示万万if(data_c>9999999) { write_date('0'+dispaly[7]);} //千万if(data_c>999999) { write_date('0'+dispaly[6]);} //百万if(data_c>99999) { write_date('0'+dispaly[5]);} //十万if(data_c>9999) { write_date('0'+dispaly[4]);} //万if(data_c>999) { write_date('0'+dispaly[3]);} //千if(data_c>99) { write_date('0'+dispaly[2]);} //百if(data_c>9) { write_date('0'+dispaly[1]);} //十write_date('0'+dispaly[0]); //个 }}
// else //溢出时显示错误
// {
// write_com(0x80+11+0x40); //第一行
// write_date('E'); //显示 E
// write_date('r'); //显示R
// write_date('r'); //显示R
// write_date('o'); //显示O
// write_date('r'); //显示E
// }
}void eql(uchar x)//加减乘除运算
{switch(x) /*功能键选择*/{ case 1:data_c=data_a+data_b;break; //加 /* + S=1 */ /* 数值转换函数 */ case 2:if(data_a>=data_b){data_c=data_a-data_b;} /* - S=2 *///减else{data_c=data_b-data_a;W_lcd(5,1,'-');} //负数符号break; case 3:data_c=(data_a*data_b);break; /* * S=3 *///乘case 4:if(data_b==0){LCD_Write_String(0,1,"Error ! ");}else{data_c=(data_a*10000)/data_b;}break; /* / S=4 *///除//溢出时显示错误case 0:break;} }void main()
{uchar key=0xff; //键值初始化uchar n=0; //第1个数可以按1-4次uchar m=5; //第2个数可以按1-4次uchar x=0; data_a=0; //前一个数data_b=0; //后一个数data_c=0; //结果 init_lcd(); //1602液晶初始化display_a();while(1){key=keycheckdown(); /*动态扫描键盘,返回按键对应值,赋给j key=0到f */if(0xff!=key) /*若返回值有效,进入内部处理程序*/{ if(key<10){if(key==0&&n==0) ;else{if(n<4){data_a=data_a*10+key;m=5;display_a();}n++; //首先输入第一个数 }if(key==0&&m==0) ;else{if(m<4){data_b=data_b*10+key;n=5;display_b();}m++; //必须按了+-*/才能输入第二个数 }}else{ switch(key) /*功能键选择*/{case 0xa:n=5;m=0;x=1;W_lcd(5,0,'+');break; //加 /* + S=1 */ /* 数值转换函数 */ case 0xb:n=5;m=0;x=2;W_lcd(5,0,'-');break; /* - S=2 *///减case 0xc:n=5;m=0;x=3;W_lcd(5,0,'*');break; /* * S=3 *///乘case 0xd:n=5;m=0;x=4;W_lcd(5,0,'/');break; /* / S=4 *///除case 0xe:n=5;m=5;eql(x);W_lcd(12,0,'=');display_c(x);break; /* = */case 0xf:n=0;x=0;m=5; data_a=0;data_b=0;data_c=0;LCD_Write_String(0,0,table);LCD_Write_String(0,1,table);W_lcd(0,0,'0');break; /* C*/} }do{P1=0xf0;}while(P1!=0xf0); /*等待按键松开*/}//(0xff!=key) }//while
}//main