四位加法计数器设计

一、设计任务:

1、系统通过 4×4 的矩阵键盘输入数字及运算符;

2、可以进行 4 位十进制数以内的加法运算,如果计算结果超过 4 位十进制数,则屏幕显示;

3、可以进行加法以外的计算(乘、除、减);

4、其他功能。

二、硬件系统设计

 

 

 三、系统设计流程

 四、源代码

#include<reg51.h>
#define uint unsigned int
#define uchar unsigned char
//--------LCD1602-------------------
//P00-07==== D0-7
sbit rs=P2^5;        //指令or数据
sbit wela=P2^6;      //读or写
sbit lcden=P2^7;	 //使能信号
//--------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;                     //写入指令com
	LCD_Delay_ms(1);            //延时1ms
	lcden=1;                    //使能1602
	LCD_Delay_ms(2);            //延时2ms  
	lcden=0;	                //使能1602
}
//************************************************************************/
// 描述:1602液晶写数据 
//************************************************************************/
void write_date(uchar date) //1602液晶写数据
{
	rs=1;                        //写数据
	lcden=0;                     //使能1602 
	P0=date;                     //写入数据date
	LCD_Delay_ms(1);             //延时1ms
	lcden=1;                     //使能1602
	LCD_Delay_ms(2);             //延时2ms
	lcden=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;                     //使能1602
	write_com(0x38);             //8 位总线,双行显示,5X7 的点阵字符
	LCD_Delay_us(100);           //延时100us
	write_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=0x0d;break;//  按键/   
		case 0x7b :a=0x0e; break;// 按键=	
		case 0x7d :a=0;	   break;// 按键0
		case 0x7e :a=0x0f; break;// 按键CE

		case 0xb7 :a=0x0c;break;// 	按键*
		case 0xbb :a=0x9;break; //  按键9
		case 0xbd :a=0x8;break; //  按键8 
		case 0xbe :a=0x7;break; // 	按键7

		case 0xd7 :a=0x0b;break;//  按键-
		case 0xdb :a=0x6;break; // 	按键6
		case 0xdd :a=0x5;break; // 	按键5
		case 0xde :a=0x4;break; // 	按键4

		case 0xe7 :a=0x0a; break;// 按键+
		case 0xeb :a=3;break;	//  按键3
		case 0xed :a=2;break;	//  按键2
		case 0xee :a=1;break;	//  按键1

		default :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);               //显示数据a
	if(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]);}    //十万
								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(n<4){data_a=data_a*10+key;m=5;display_a();}n++;  //首先输入第一个数
		    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

五、清单

六、PCB图

 七、实物图

 

 

 

 

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值