【51单片机】汽车里程表之测速功能

在这里插入图片描述

设计说明

以通用MCS-51单片机为处理核心,用传感器将车轮的转数转换为电脉冲,进行处理后送入单片机。里程及速度的测量,是经过MCS-51的定时/计数器测出总的脉冲数和每转一圈的时间,再经过单片机的计算得出,其结果通过LED显示器显示出来。

里程表可以在淘宝上买到成品,我的思路是在成品的基础上,把电机的电流引到里程表上;除了测速功能外,还可以再加上控速功能,在速度超过某一个固定值后,蜂鸣器响,提示需要减速,同时通过串口发送标志位给汽车模块,汽车模块根据标志位,控制汽车的PWM占空比,进行减速。

流程图

计算速度和里程模块:
在这里插入图片描述
报警和测速模块:
在这里插入图片描述

主要代码

/***********计算速度函数**************/
void menu_dis()	  //计算速度函数
{
    
    
	static uchar value;
	if(menu_1 == 0)
	{
    
    	
		if(flag_1s == 1)   
		{
    
    	
			flag_1s = 0; 		
			if(flag_en == 0)
			{
    
    
				value ++;
				if(value >= 3)	//2秒
				{
    
    	
					speed_km = 0;  //速度为0
					shudu = (uint)speed_km;	
					value = 0;				
				}
			}
			if((flag_en == 1))
			{
    
    	
				value = 0;		
				flag_en = 0;	 
				 //1s = 1 / 1000000us;	  // 1m/s=0.001km除以1/3600h=3.6km/h			
				f_hz = 1/(t2_num * 65536.0 + TH11 * 256 + TL11) / 1000000 ;  //算出来就是秒
				t2_num = 0;	//把变量清零
				TH11 = 0;
				TL11 = 0;					   
				speed_m = f_hz * zhijing * 3.14  ;	//算出来的是m/s
				juli_z = (juli_z + (uint)speed_m) ;        //总路程m	
				speed_km = speed_m * 3.6 ;	//(带个小数点) km/s		
			    shudu = (uint)speed_km;
				zong_lc += speed_m;
			}		
			write_sfm2(1,3,shudu);		
			write_sfm4(2,3,juli_z);	

		}
	}
}

/********************独立按键程序*****************/
uchar key_can;	 //按键值

void key()	 //独立按键程序
{
    
    
	static uchar key_new;
	key_can = 20;                   //按键值还原
	P3 |= 0x78;                     //对应的按键IO口输出为1
	if((P3 & 0x78) != 0x78)		//按键按下
	{
    
    
		delay_1ms(1);	     	//按键消抖动
		if(((P3 & 0x78) != 0x78) && (key_new == 1))
		{
    
    						//确认是按键按下
			key_new = 0;
			switch(P3 & 0x78)
			{
    
    
				case 0x70:  key_can = 4;  break;	 //得到按键值
				case 0x68:  key_can = 3;  break;	 //得到按键值
				case 0x58:  key_can = 2;  break;	 //得到按键值
				case 0x38:  key_can = 1;  break;	 //得到按键值
			}
		}			
	}
	else 
		key_new = 1;	
}


/**********************设置函数************************/
void key_with()
{
    
    
	if(key_can == 1)	//设置键
	{
    
    
		menu_1++;
		if(menu_1 == 1)	  //设置时间
		{
    
    
			menu_2 = 1;
			write_string(1,0,"    :  :    W:  ");			
			write_string(2,0," 20  -  -       ");	
		}
		if(menu_1 == 2)	  //设置报警速度
		{
    
    
			menu_2 = 1;
			write_string(1,0,"set-sd:00km/h   ");			
			write_string(2,0,"zlc:             ");	
		}
		if(menu_1 == 3)	  //设置直径
		{
    
    
			menu_2 = 1;
			write_string(1,0,"  Set Zhijing  ");			
			write_string(2,0,"               ");	
		}
		menu_2 = 1;

		if(menu_1 > 3)    //回到正常显示
		{
    
    
			menu_1 = 0;
			write_guanbiao(1,2,0);	  //关闭光标
			init_1602();      //1602初始化     //初始化液晶显示		
		}
	}
	if(key_can == 2)	//选择键
	{
    
    
		if(menu_1 == 1)		  //设置时间
		{
    
    
			menu_2 ++;
			if(menu_2 > 7)
				menu_2 = 1;
		}
		if(menu_1 == 2)		 //设置
		{
    
    
			menu_2 ++;
			if(menu_2 > 2)
				menu_2 = 1;				
		}

	}
	if(menu_1 == 1)
	{
    
    
		if(menu_2 == 1)		  //设置时
		{
    
    
			if(key_can == 3)	//加
			{
    
    
				shi+=0x01;
				if((shi & 0x0f) >= 0x0a)
					shi = (shi & 0xf0) + 0x10;
				if(shi >= 0x24)
					shi = 0;
			}		
			if(key_can == 4)	//减
			{
    
    
				if(shi == 0x00)
					shi = 0x24;
				if((shi & 0x0f) == 0x00)
					shi = (shi | 0x0a) - 0x10;
				shi -- ; 
			}	  				
		}
		if(menu_2 == 2)		  //设置分
		{
    
    
			if(key_can == 3)	//加
			{
    
    
				fen+=0x01;
				if((fen & 0x0f) >= 0x0a)
					fen = (fen & 0xf0) + 0x10;
				if(fen >= 0x60)
					fen = 0;
			}		
			if(key_can == 4)	//减	  
			{
    
    
				if(fen == 0x00)
					fen = 0x5a;
				if((fen & 0x0f) == 0x00)
					fen = (fen | 0x0a) - 0x10;
				fen -- ;
			}	
		}
		if(menu_2 == 3)		  //设置秒
		{
    
    
			if(key_can == 3)	//加
			{
    
    
				miao+=0x01;
				if((miao & 0x0f) >= 0x0a)
					miao = (miao & 0xf0) + 0x10;
				if(miao >= 0x60)
					miao = 0;
			}	
			if(key_can == 4)	//减	  
			{
    
    
				if(miao == 0x00)
					miao = 0x5a;
				if((miao & 0x0f) == 0x00)
					miao = (miao | 0x0a) - 0x10;
				miao -- ;			
			}
		}
		if(menu_2 == 4)		  //设置星期
		{
    
    
			if(key_can == 3)	//加
			{
    
    
	    		week+=0x01;
				if((week & 0x0f) >= 0x0a)
					week = (week & 0xf0) + 0x10;
				if(week >= 0x08)
					week = 1;
			}		
			if(key_can == 4)	//减	  
			{
    
    
				if(week == 0x01)
					week = 0x08;
				if((week & 0x0f) == 0x00)
					week = (week | 0x0a) - 0x10;
				week -- ;
			}	
		}
		if(menu_2 == 5)		  //设置年
		{
    
    
			if(key_can == 3)	//加
			{
    
    
		    	nian+=0x01;
				if((nian & 0x0f) >= 0x0a)
					nian = (nian & 0xf0) + 0x10;
				if(nian >= 0x9a)
					nian = 1;
			}		
			if(key_can == 4)	//减	  
			{
    
    
				if(nian == 0x01)
					nian = 0x9a;
				if((nian & 0x0f) == 0x00)
					nian = (nian | 0x0a) - 0x10;
				nian -- ;		
			}	
		}
		if(menu_2 == 6)		  //设置月
		{
    
    
			if(key_can == 3)	//加
			{
    
    
		    	yue+=0x01;
				if((yue & 0x0f) >= 0x0a)
					yue = (yue & 0xf0) + 0x10;
				if(yue >= 0x13)
					yue = 1;
			}		
			if(key_can == 4)	//减	  
			{
    
    
				if(yue == 0x01)
					yue = 0x13;
				if((yue & 0x0f) == 0x00)
					yue = (yue | 0x0a) - 0x10;
				yue -- ;					
			}	
		}
		if(menu_2 == 7)		  //设置日
		{
    
    
			if(key_can == 3)	//加
			{
    
    
	    	ri+=0x01;
			if((ri & 0x0f) >= 0x0a)
				ri = (ri & 0xf0) + 0x10;
			if(ri >= 0x32)
				ri = 0;			
			}		
			if(key_can == 4)	//减	  
			{
    
    
				if(ri == 0x01)
					ri = 0x32;
				if((ri & 0x0f) == 0x00)
					ri = (ri | 0x0a) - 0x10;
				ri -- ;			
			}	
		}
		write_sfm2_ds1302(1,2,shi);	   //显示时
		write_sfm2_ds1302(1,5,fen);	   //显示分
		write_sfm2_ds1302(1,8,miao);	   //显示秒
		write_sfm1(1,14,week);	   //显示星期					
		write_sfm2_ds1302(2,3,nian);	   //显示年
		write_sfm2_ds1302(2,6,yue);	   //显示月
		write_sfm2_ds1302(2,9,ri);	   //显示日
		switch(menu_2)	   // 光标显示
		{
    
    
			case 1:  write_guanbiao(1,2,1);  break;
			case 2:  write_guanbiao(1,5,1);  break;
			case 3:  write_guanbiao(1,8,1);  break;
			case 4:  write_guanbiao(1,14,1); break;
			case 5:  write_guanbiao(2,3,1);  break;
			case 6:  write_guanbiao(2,6,1);  break;
			case 7:  write_guanbiao(2,9,1);  break;
		}
		write_time();	   //把时间写进去
	}	

	if(menu_1 == 2)
	{
    
    		
		if(menu_2 == 1)		  //设置速度
		{
    
    
			if(key_can == 3)	//加
			{
    
    
				bj_shudu++;
				if(bj_shudu >= 99)
					bj_shudu = 99;
			}	
			if(key_can == 4)	//减	  
			{
    
    
				if(bj_shudu != 0)
					bj_shudu -- ;			
			}
		}	
		if(menu_2 == 2)		  //把总量程清零
		{
    
    
			if(key_can == 3)	
			{
    
    
				zong_lc= 0;
			}	
			if(key_can == 4)		  
			{
    
    
				zong_lc= 0;			
			}
		}	


		write_sfm2(1,7,bj_shudu);   //显示报警速度
		write_sfm7(2,4,zong_lc);   //显示
		
		switch(menu_2)	   // 光标显示
		{
    
    
			case 1:  write_guanbiao(1,6,1);  break;
			case 2:  write_guanbiao(2,3,1);  break;
		}
	}
	if(menu_1 == 3)
	{
    
    		
		if(key_can == 3)	//加
		{
    
    
			s_zhijing++;
			if(s_zhijing >= 999)
				s_zhijing = 999;
		}	
		if(key_can == 4)	//减	  
		{
    
    
			if(s_zhijing != 0)
				s_zhijing -- ;			
		}
		zhijing = s_zhijing ;
		write_sfm2(2,5,s_zhijing);		//显示
	}
}

/****************报警函数***************/
void clock_h_l()
{
    
    
	static uchar value;	   
	if((shudu >= bj_shudu))
	{
    
    
		value ++;  //消除实际距离在设定距离左右变化时的干扰
		{
    
    
			beep = ~beep; 	  //蜂鸣器报警			
		}	
	}
	else
	{
    
    
		beep = 1;	
	}			
}


/******************主程序**********************/	   
void main()
{
    
    
	init_1602();      //1602初始化
	init_int0();
	time_init();	  //定时器0初始化程序 
	while(1)
	{
    
    	 //  shudu = 11;
		key();			 //按键程序
		if(key_can < 10)
		{
    
    
			key_with();	

		}
		if(flag_200ms == 1)
		{
    
    
			flag_200ms = 0;
			read_time();		  //读时间
			init_1602_ds1302();   //显示时钟
			menu_dis();	  //计算速度函数
			clock_h_l();        //报警函数
		}
	}
}


/*********************外部中断0中断服务程序************************/
void int0() interrupt 0
{
    
    
	static uchar value=1;
	switch(value)
	{
    
    
		case 0: 
			t1_num = 0;		 //第一次就把变量清零
			TH1 = 0;
			TL1 = 0;
			break;
		case 1: 
				t2_num = t1_num;  //保存
				TH11 = TH1;
				TL11 = TL1;
				flag_en = 1;
			break;
	}		
}

/*************定时器0中断服务程序***************/
void time0_int() interrupt 1
{
    
    	
	static uchar value=1;
	TH0 = 0x3c;
	TL0 = 0xb0;     // 50ms
	value++;
	if(value % 4 == 0)
		flag_200ms = 1;

	if(value >= 20)  //1秒   才是一秒钟的速度
	{
    
    
		value = 0;
		flag_1s = 1;
	}
}

/*************定时器1中断服务程序***************/
void time1_int() interrupt 3
{
    
    
	t1_num++;
}

猜你喜欢

转载自blog.csdn.net/wangshuqian1314/article/details/113800918