基于51单片机的出租车计价器

目录

一、项目功能

二、原理图

三、仿真

 四、程序

五、设计资料


资料下载地址:基于51单片机的出租车计价器

一、项目功能

1、1602显示时间、日期、行驶距离、当前金额、和总价等信息

2、按键设置时间、日期、起步金额、历史数据查看等功能

3、通过霍尔传感器计算电机转速

二、原理图

三、仿真

系统刚上电,显示时间

点击开始按钮系统显示行驶公里、时间、费用、司机等待时间

通过霍尔传感器计算电机转速,从而计算出行驶路程

 按下设置时间可以依次更改年月日、时分秒。

 按下设置金额,可以对价格进行设置

 

 四、程序

/*		
    1602液晶,是常用的显示器件,一共是16个管脚,其中有八个管脚是数据传输管脚,有三个管脚是数据命令使能端管脚,还有两组电源管脚,
其中一组电源管脚是给整个液晶进行供电的,还有一组电源是单纯的背景光电源,还剩下的最后一个管脚是对比度调节管脚,一般接上一个3K电
阻再接地即可。
 
*/ 

/*
数据显示的时候一般的处理:

    首先,无论是数码管显示还是液晶显示,进行显示的时候绝对都是一个一个进行显示的,那么,比如说一个数据123,一百二十三,
进行显示的时候,要先显示1,然后是2,然后是3,那么怎么把数据提取出来??   
提取百位    123/100=1
提取十位    123/10=12      12%10=2     “%”是取余的意思,像这个,就是12对10取余,换句话说,12除以10,然后取余数,就是2
提取个位    123%10=3       解释同上

取余的用法也有很多种,大家只要知道出现这个的时候,一般都是进行数据提取的就行


然后
如果您是数码管显示数据,将提取的数据放到段码数组里面送给IO即可,
如果是液晶显示,需要将数据转化成字符,因为液晶是字符屏,只能显示字符数据,数据0对应的字符是0x30,数据1对应的字符是0x31,
所以将提取出的数据直接加上0x30送给液晶即可,或者加上'0' 也是一样的 

*/

void Display()
 {
	   if(Page==0) 
	    {
				 LCD1602_write(0,0x80);                 
				 LCD1602_writebyte("20");           
		         if(state==1&&s0)  LCD1602_writebyte("  "); 
				 else 											 
				  {
				     LCD1602_write(1,0x30+time_data_1[5]/10);		   
				     LCD1602_write(1,0x30+time_data_1[5]%10);	 //显示年	   
				  }
		  		 LCD1602_writebyte("/"); 
		         if(state==2&&s0)  LCD1602_writebyte("  "); 	 //显示月
				 else 											 
				  {
				     LCD1602_write(1,0x30+time_data_1[4]/10);		   
				     LCD1602_write(1,0x30+time_data_1[4]%10);		   
				  }
		  		 LCD1602_writebyte("/"); 
		         if(state==3&&s0)  LCD1602_writebyte("  "); 	 //显示日
				 else 											 
				   {
				     LCD1602_write(1,0x30+time_data_1[3]/10);		   
				     LCD1602_write(1,0x30+time_data_1[3]%10);		   
				   }
		  		 LCD1602_writebyte(" "); 
		
		        switch(Conver_week(time_data_1[5],time_data_1[4],time_data_1[3]))
				 {
				  case 0: LCD1602_writebyte("  Sun");    break;
				  case 1: LCD1602_writebyte("  Mon");    break;
				  case 2: LCD1602_writebyte("  Tue");    break;
				  case 3: LCD1602_writebyte("  Wed");    break;
				  case 4: LCD1602_writebyte("  Thu");    break;
				  case 5: LCD1602_writebyte("  Fri");    break;
				  case 6: LCD1602_writebyte("  Sat");    break;	  //星期	 
				 }
		
				LCD1602_write(0,0xC0);    
				LCD1602_writebyte("    ");
		        if(state==4&&s0)    LCD1602_writebyte("  "); 	 //显示时
				else 											 
				 {
								    LCD1602_write(1,0x30+time_data_1[2]/10);		   
								    LCD1602_write(1,0x30+time_data_1[2]%10);		   
				 }
				LCD1602_writebyte(":"); 	 
		        if(state==5&&s0)  LCD1602_writebyte("  "); 	 //显示分
				else 											 
				  {
							      LCD1602_write(1,0x30+time_data_1[1]/10);		   
							      LCD1602_write(1,0x30+time_data_1[1]%10);		   
				  }
				LCD1602_writebyte(":");  
		        if(state==6&&s0)     LCD1602_writebyte("  "); 	 //显示分
				 else 											 
				  {
								  LCD1602_write(1,0x30+time_data_1[0]/10);		   
								  LCD1602_write(1,0x30+time_data_1[0]%10);		   
				  }		 
				LCD1602_writebyte("    "); 	
		}
	   else if(Page==1||Page==2)   //Page等于 1  2 代表的是,接客界面,1,开始计费,2,停止计费
	    {
				 LCD1602_write(0,0x80);                 
				 LCD1602_writebyte("S:");
 				 LCD1602_write(1,0x30+Mileage/100000%10);
 				 LCD1602_write(1,0x30+Mileage/10000%10);
 				 LCD1602_write(1,0x30+Mileage/1000%10);  //显示里程界面
//				 LCD1602_write(1,0x30+Mileage/100%10);
//				 LCD1602_write(1,0x30+Mileage/10%10);
//				 LCD1602_write(1,0x30+Mileage%10);	     //屏蔽这块是千米下数据,显示的时候直接显示千米数据了,千米下就不显示了

				 if(DJ_Star==0&&s0==0)	LCD1602_writebyte("Km   :"); 
				 else 		            LCD1602_writebyte("Km Wt:");   //在电机停止的时候,根据s0变量进行闪烁
				 if((Waiting_Time/60)>9)     LCD1602_write(1,0x30+(Waiting_Time/60)/10%10);
				 else 	                     LCD1602_writebyte(" ");
				 LCD1602_write(1,0x30+(Waiting_Time/60)%10);	 		   //显示等待时间
				 LCD1602_writebyte("Min");  
 
 
				 LCD1602_write(0,0xC0);                 		
				 LCD1602_write(1,0x30+(Driving_time/60)/10%10);
				 LCD1602_write(1,0x30+(Driving_time/60)%10);
				 LCD1602_writebyte(":"); 
				 LCD1602_write(1,0x30+(Driving_time%60)/10%10);
				 LCD1602_write(1,0x30+(Driving_time%60)%10);  			   //系统运行时间
				 LCD1602_writebyte(" ");

				 if(Page==2)	  LCD1602_writebyte("Off ");
				 else 			  LCD1602_writebyte("On  ");			   //Page等于 1 是 开始计费, 2 是不计费,这里显示On  Off

				 LCD1602_write(1,0x5c);

				 if(Unit_price>999)  LCD1602_write(1,0x30+Unit_price/1000%10);
				 else 	             LCD1602_writebyte(" ");
				 if(Unit_price>99)   LCD1602_write(1,0x30+Unit_price/100%10);
				 else 	             LCD1602_writebyte(" ");
				 LCD1602_write(1,0x30+Unit_price/10%10);
				 LCD1602_writebyte(".");
				 LCD1602_write(1,0x30+Unit_price%10);	 	//显示单价,该数据的个位数实际是小数位,这里注意一下
		}
	   else if(Page==3||Page==4||Page==5||Page==6) 	   //Page 等于 3  4  5  6 代表的是,设置,等待金额,白天价格,晚上价格还有起步价
	    {							     	 	
				 LCD1602_write(0,0x80);                 
				 LCD1602_writebyte("Wp:");			  //显示等待金额
				 if(Page==3&&s0)   LCD1602_writebyte("    ");
				 else 
				 {
					 if(Waiting_amount>99)   LCD1602_write(1,0x30+Waiting_amount/100%10);
					 else 	                 LCD1602_writebyte(" ");
					 LCD1602_write(1,0x30+Waiting_amount/10%10);
					 LCD1602_writebyte(".");
					 LCD1602_write(1,0x30+Waiting_amount%10);
				 }  
				 LCD1602_writebyte("  ");
				 LCD1602_writebyte("pD:");	  			//显示白天单价
				 if(Page==4&&s0)   LCD1602_writebyte("    ");
				 else 
				 {
					 if(Daytime_price>99)   LCD1602_write(1,0x30+Daytime_price/100%10);
					 else 	                 LCD1602_writebyte(" ");
					 LCD1602_write(1,0x30+Daytime_price/10%10);
					 LCD1602_writebyte(".");
					 LCD1602_write(1,0x30+Daytime_price%10);
 				 }
				 LCD1602_write(0,0xC0);                 
				 LCD1602_writebyte("Sp:");				//显示 起步价 
				 if(Page==5&&s0)   LCD1602_writebyte("    ");
				 else 
				 {
					 if(Starting_price>99)   LCD1602_write(1,0x30+Starting_price/100%10);
					 else 	                 LCD1602_writebyte(" ");
					 LCD1602_write(1,0x30+Starting_price/10%10);
					 LCD1602_writebyte(".");
					 LCD1602_write(1,0x30+Starting_price%10);
				 }
				 LCD1602_writebyte("  ");
				 LCD1602_writebyte("pN:");	 		   //显示夜晚单价
				 if(Page==6&&s0)   LCD1602_writebyte("    ");
				 else 
				 {
					 if(Night_price>99)   LCD1602_write(1,0x30+Night_price/100%10);
					 else 	              LCD1602_writebyte(" ");
					 LCD1602_write(1,0x30+Night_price/10%10);
					 LCD1602_writebyte(".");
					 LCD1602_write(1,0x30+Night_price%10);
				 }
 		}
	   else if(Page==7)  //Page等于7,代表的是
	    {
				 LCD1602_write(0,0x80);                 
				 LCD1602_writebyte("The total monney:");  //总金额	
				 LCD1602_write(0,0xC0); 
				 LCD1602_writebyte("     ");
				 LCD1602_write(1,0x5c);		 //显示人民币符号 

				 if(Total_amount>9999) LCD1602_write(1,0x30+Total_amount/10000%10);
				 else 	               LCD1602_writebyte(" ");
				 if(Total_amount>999)  LCD1602_write(1,0x30+Total_amount/1000%10);
				 else 	               LCD1602_writebyte(" ");
				 if(Total_amount>99)   LCD1602_write(1,0x30+Total_amount/100%10);
				 else 	               LCD1602_writebyte(" ");
				 LCD1602_write(1,0x30+Total_amount/10%10);
				 LCD1602_writebyte(".");
				 LCD1602_write(1,0x30+Total_amount%10);		//显示总金额数据
				 LCD1602_writebyte("      ");
		}
 
 }		 
void read_time1()     //实时读取DS1302中的时间数据
{
 uchar i;
	 if(state==0)  //等于 0 ,正常显示的时候,读取时间数据
	  {
			time_data[0]=ds1302read(0x81);
			time_data[1]=ds1302read(0x83);
			time_data[2]=ds1302read(0x85);
			time_data[3]=ds1302read(0x87);
			time_data[4]=ds1302read(0x89);
			time_data[5]=ds1302read(0x8D);  		
			time_data_1[0]=time_data[0]/16*10+time_data[0]%16;
			time_data_1[1]=time_data[1]/16*10+time_data[1]%16;
			time_data_1[2]=time_data[2]/16*10+time_data[2]%16;
			time_data_1[3]=time_data[3]/16*10+time_data[3]%16;
			time_data_1[4]=time_data[4]/16*10+time_data[4]%16;
			time_data_1[5]=time_data[5]/16*10+time_data[5]%16;
			if(time_data_1[0]>59||time_data_1[0]<0)
			   {
			 	ds1302write(0x8e,0x00); 
				ds1302write(0x80,0x80);
				ds1302write(0x80,0);
				ds1302write(0x8e,0x80);     
			   }				  
	  }	
	  else 	  //否则就是写时间,将时间数据实时写进DS1302,修改数据
	      {
			ds1302write(0x8e,0x00); 
			ds1302write(0x80,0x80);
			for(i=0;i<7;i++)
			{
				time_data_2[i]=time_data_1[i]/10;
				time_data_3[i]=time_data_1[i]%10;	  
			}
			for(i=0;i<7;i++){time_data_4[i]=time_data_2[i]*16+time_data_3[i];}
			ds1302write(0x80,time_data_4[0]);
			ds1302write(0x82,time_data_4[1]);
			ds1302write(0x84,time_data_4[2]);
			ds1302write(0x86,time_data_4[3]);
			ds1302write(0x88,time_data_4[4]);
			ds1302write(0x8C,time_data_4[5]);	
		  }
}




/*按键操作的方式多种多样,在学校里学到的普遍都是判断按键按下,延时等待一下再次判断按键按
下,进行消抖,然后确定按键按下之后执行所要执行的,再死循环等待按键释放。这样写按键自然也
行,但是有一个弊端,就是按键如果不松开,程序就会一直卡在那里,所以这里我换了一种书写方
式,标志位的方式--->  按键松开的时候,将标志位置一,按键按下之后,不进行延时消抖再次判断,
而是判断标志位是否为 1 ,如果是 1 ,就说明在你按下之前按键是松开的,将标志位清零,执行一下
所要执行的操作,下面就算你按键是一直按着不松开的,因为标志位是 0 ,他也不会再次执行所要执
行的操作了,只有当按键松开之后将标志位置一。*/ 
void Key_Dispose1()	  //按键处理函数
 {
   	if(!key1)  	 //按键 1 
	 {
	      if(key1_flag==1) 
		   {
		     key1_flag=0;
			 if(Page<3) 
			  {
			     Page=(Page+1)%3;        //界面累加,等于 1 开始计费,2,停止计费
				 if(Page==1) 	         //界面为 1 时,说明要开始计费了
				  {
				    DJ_Star=1;	         //开电机
					Mileage = 0;  		 
					Mileage_float = 0 ;  //清里程
				    Waiting_Time  = 0 ;
				    Driving_time  = 0 ;	 //清计时时间
				    Night_Temporary	 = 0 ;
					Day_Temporary	 = 0 ;
				  }
				 if(Page==2) 
				  {
				    Total_amount = Total_amount+Unit_price;	  //停止计费的时候,总金额累加一下
					Memory_flag=1;
				  }	
			  }
		   }
	 }
	 else key1_flag = 1;

   	if(!key2)  				     //按键 2 ,停止电机按钮
	 {
	      if(key2_flag==1) 
		   {
		     key2_flag=0;
			 DJ_Star=0;	
		   }
	 }
	 else key2_flag = 1;

   	if(!key3)  				     //按键 3 ,启动电机按钮 
	 {
	      if(key3_flag==1) 
		   {
		     key3_flag=0;
			    DJ_Star=1;
		   }
	 }
	 else key3_flag = 1;

 
   	if(!key4)  					 //按键 4 设定时间按钮
	 {
	      if(key4_flag==1) 
		   {
		     key4_flag=0;
			 if(Page==0)       //只有当主界面的时候,设置时间按钮才是可以按下的
			  {
			     state=(state+1)%7;	// 设置的有 年月日 时分秒 
			  }
		   }
	 }
	 else key4_flag = 1;

    if(!key5)  				   //按键五是切换到设置金额的界面
	 {
	      if(key5_flag==1) 
		   {
		     key5_flag=0;
			 if(Page<3) 	   
			 {
			    if(Page==0&&state==0) Page = 3;	 //只有在待机界面,并且没有设置时间数据的时候,进行切换到该界面
			 } 
			 else                                //页面不小于 3 ,那就是 3 4 5 6  
			  {
			     if(Page<6) Page++;				 //累加
				 else
				  {
				    if(Page!=7)  Page = 0;		 //当Page等于 6 的时候,该变量会被清零,返回主界面,这里加一个判断不等于 7 ,界面 7 是总金额显示 
				  }
			  }
		   }
	 }
	 else key5_flag = 1;

 
    if(!key6)  				  //修改数据的有,时间数据,计费数据
	 {	 
	      if(key6_flag==1) 
		   {
		     key6_flag=0;
			 if(Page==0)       //判断修改时间部分,另外该按钮还是切换显示总金额按钮
			  {
			  	 if(state==0)  //这里说明此时在主界面,并且没有进入设置时间状态,就切换显示总金额界面
				  {
				  	   Page=7;  //直接等于 7 ,切换到显示总金额界面
				  }
				  else 		   
				  {
				      switch(state)
					   {
					     case 0:break;
						 case 1:if(time_data_1[5]<99)  time_data_1[5]++;  break;
						 case 2:if(time_data_1[4]<12)  time_data_1[4]++; break;
						 case 3: 
							               if(time_data_1[4]==1||time_data_1[4]==3||time_data_1[4]==5||time_data_1[4]==7||time_data_1[4]==8||time_data_1[4]==10||time_data_1[4]==12) 
											{
											   if(time_data_1[3]<31)  time_data_1[3]++; 
											}
		                                    else if(time_data_1[4]==4||time_data_1[4]==6||time_data_1[4]==9||time_data_1[4]==11)	
											{
											   if(time_data_1[3]<30)  time_data_1[3]++; 
											}	
											else if((time_data_1[5]%4==0&&time_data_1[5]%100!=0)||(time_data_1[5]%400==0))
											{
											   if(time_data_1[3]<29)  time_data_1[3]++; 			
											}
											else 
											{
												if(time_data_1[3]<28)  time_data_1[3]++; 		
											}							 
							  
						 break;
		
						 case 4:if(time_data_1[2]<23)  time_data_1[2]++;    break;
						 case 5:if(time_data_1[1]<59)  time_data_1[1]++;   break;
						 case 6:if(time_data_1[0]<59)  time_data_1[0]++;   break;
					  }
				  }
			  }
			  else if(Page==3||Page==4||Page==5||Page==6) //这几个界面就是设置等待时间、白天价格、起步价、晚上价格
			  {
				      switch(Page)
					   {
					     case 0:break;	   	  	 	   
						 case 3:if(Waiting_amount<999)  Waiting_amount++;  break;
						 case 4:if(Daytime_price<999)   Daytime_price++;  break;
						 case 5:if(Starting_price<999)  Starting_price++;  break;
						 case 6:if(Night_price<999)     Night_price++;  break;
					   }
					   Memory_flag = 1;								   
			  }
			  else if(Page==7)	//当处于总金额界面的时候,就去跳转到主界面待机
			   {
			     Page=0;		//等于 0 
			   }
		   }
	 }
	 else key6_flag = 1;

  
    if(!key7)  					//设置 数据减 ,还有是在总金额界面的时候,清零数据按钮
	 {
	      if(key7_flag==1) 
		   {
		     key7_flag=0;
			 if(Page==0)     
			  {
			  	 if(state==0)  
				  {
			
				  }
				  else 
				  {
				   switch(state)
					 {
					     case 0:break;
						 case 1:if(time_data_1[5]>0)  time_data_1[5]--;    break;
						 case 2:if(time_data_1[4]>1)  time_data_1[4]--;    break;
						 case 3:if(time_data_1[3]>1)  time_data_1[3]--;    break;
						 case 4:if(time_data_1[2]>0)  time_data_1[2]--;    break;
						 case 5:if(time_data_1[1]>0)  time_data_1[1]--;    break;
						 case 6:if(time_data_1[0]>0)  time_data_1[0]--;    break;
		 
					 }
				  }
			  }
			  else if(Page==3||Page==4||Page==5||Page==6) //这几个界面就是设置等待时间、白天价格、起步价、晚上价格
			  {
				      switch(Page)
					   {
					     case 0:break;	   	  	 	   
						 case 3:if(Waiting_amount>0)  Waiting_amount--;  break;
						 case 4:if(Daytime_price>0)   Daytime_price--;   break;
						 case 5:if(Starting_price>0)  Starting_price--;  break;
						 case 6:if(Night_price>0)     Night_price--;     break;
					   }
					   Memory_flag = 1;								   
			  }
			  else if(Page==7) 
			   {
			     Memory_flag = 1;  
				 Total_amount = 0 ;  //在总金额界面,就清零该按钮
			   }
		   }
	 }
	 else key7_flag = 1;
 

 }

五、设计资料

猜你喜欢

转载自blog.csdn.net/qq_35654286/article/details/124232579