Taxi Meter Based on 51 MCU

content

1. Project function

2. Schematic diagram

3. Simulation

 4. Procedure

5. Design information


Data download address: Taxi meter based on 51 microcontroller

1. Project function

1. 1602 displays information such as time, date, driving distance, current amount, and total price

2. Press the button to set time, date, starting amount, historical data viewing and other functions

3. Calculate the motor speed through the Hall sensor

2. Schematic diagram

3. Simulation

The system is just powered on and the time is displayed

Click the start button and the system will display the distance traveled, time, cost, driver waiting time

The motor speed is calculated by the Hall sensor to calculate the driving distance

 Press to set the time to change the year, month, day, hour, minute, and second in sequence.

 Press Set Amount to set the price

 

 4. Procedure

/*		
    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;
 

 }

5. Design information

 

Guess you like

Origin blog.csdn.net/qq_35654286/article/details/124232579