您现在的位置是:首页 >学无止境 >基于pic16f877a的车辆里程记录与速度测量网站首页学无止境

基于pic16f877a的车辆里程记录与速度测量

793kelvins 2024-06-27 06:01:02
简介基于pic16f877a的车辆里程记录与速度测量

本文利用测速传感器模块对车轮的码盘进行计数,通过简单的数据处理可以转化成里程数与速度值。

首先是测速模块的硬件窄体的槽型光耦测速模块,在陶包x信可以买到

  

使用说明:

1、模块槽中无遮挡时,接收管导通,模块DO输出低电平,遮挡时,DO输出高电平;

2、DO输出接口可以与单片机IO口直接相连,检测传感器是否有遮档,如用电机码盘则可检测电机的转速。

3、模块DO可与继电器相连,组成限位开关等功能,也可以与有源蜂鸣器模块相连,组成报警器。

接线

1、VCC接电源正极3.3V-5V

2、GND接电源负极

3、D0(TTL开关信号输出)接单片机外部中断

4、A0无效

电机码盘的摆放位置 让码盘放在俩个柱子之间 通电后发现当光线被挡住时l开关指示的led灯将熄灭

代码部分

代码部分有俩个要处理的数据,一个时里程数,一个是速度值

1里程数(里程值被存放在eeprom中可以防止断电丢失)

我这款电机码盘上面有20个小孔,经过测量发现一个车轮的周长为20cm,测速模块每经过一个小孔输出一个跳变,也就是说一个跳变对应的里程为1cm,那么10个跳变则为1dm=10cm,

利用pic16f877a的RB0外部电平中断,每次收到一个跳变则进入中断并将计数值count_temp+1

我设置的分度值为1dm,进入10次中断后里程数就+1

2速度值

速度值的处理方式为一个俩个小孔之间是距离除以时间

简单来说就是在一个小孔到来时进入中断将定时器打开 下一个小孔到来进入中断将定时器关闭,为了防止定时器溢出,定时时器溢出时将n值+1,数据处理时(n*65535再加上定时器的数据)作为时间值

然后将俩个小孔之间对应车轮走过的距离1cm作为距离值

即 距离值/时间值 再进行简单的单位换算即可得出速度值

代码基本封装成函数了 可以直接看函数的注释

//from 793k
//基于pic16f877a编写代码
#include <pic.h>
__CONFIG(0xFF29);
__EEPROM_DATA(0,0,0,0,0,0,0,0);//eeprom寄存器一开始给一个0的值
static volatile char table[10]={0x30,0x31,0x32,0x33,
0x34,0x35,0x36,0x37,0x38,0x39} ;
#define rs RA5
#define rw RA2
#define e  RA3
//lcd对应的使能引脚,看自己的原理图,有些RA2改成RA4
unsigned int count_temp,n,speed;
unsigned char shuju[6];
unsigned char speed_data[4],m;
unsigned int t_speed; 
union
{	unsigned long count;
		char data[3]; 
					}li_cheng;
//共用体
//========================lcd相关函数===============================
void delay()//延时函数
{unsigned int i;for(i=999;i>0;i--);}
void lcdml()//写入命令
{rs=0;rw=0;e=0;delay();e=1;}
void lcdx()//写入字
{rs=1;rw=0;e=0;delay();e=1;}
void lcd_Init()//lcd初始化
{
	TRISD=0;TRISA=0;ADCON1=7;
	PORTD=0;
	delay();
	PORTD=1;lcdml();
	PORTD=0x38;lcdml();
	PORTD=0x0c;lcdml();
	PORTD=0x06;lcdml();	

}
//==========================数据处理部分========================================
void licheng_deal()//里程数的数据处理
{
	shuju[0]=li_cheng.count/100000;
	shuju[1]=li_cheng.count%100000/10000;
	shuju[2]=li_cheng.count%10000/1000;
	shuju[3]=li_cheng.count%1000/100;
	shuju[4]=li_cheng.count%100/10;
	shuju[5]=li_cheng.count%10;	
}
void speed_deal()//速度的数据处理
{
//speed为最后的速度,speed_data为lcd显示做的数据处理
	speed=1000000/t_speed;
	speed_data[0]=speed/1000;
	speed_data[1]=speed%1000/100;
	speed_data[2]=speed%100/10;
	speed_data[3]=speed%10;
}
//========================================================================================
void interrupt int_serve()//中断服务函数
{
	
	if(TMR1IF==1){n++;TMR1IF=0;}//防止速度部分TMR1模块溢出
	if(INTF==1)
	{	
		count_temp++;;
		if(count_temp==10){li_cheng.count++;count_temp=0;}//当收到100个高电平里程数+1,100个高电平相当于小车走了1m
		//====================================速度测量部分===============
		m++;
		if(m==0)//打开tmr1 清空定时器数据
		{n=0;TMR1IE=0;TMR1L=0;TMR1H=0;TMR1ON=1;TMR1IF=0;}
		
		if(m==1)
		{TMR1ON=0;TMR1IE=0;t_speed=(n*65535)+(TMR1H*256)+TMR1L;TMR1IF=0;}
		//===============================================================  
		INTF=0;//清电平中断标志位,不清的话会一直进中断出不去
	}
}
void init()
{
	t_speed=0;
	TRISD=0;TRISA=0;ADCON1=7;
	m=250;n=0;
	TRISB0=1;count_temp=0;
	GIE=1;PEIE=1;
	TMR1IE=1;
	TMR1IF=0;
	INTE=1;INTF=0;
	T1CON=0B00000001;	
}
void main()
{
	init();//中断&端口初始化函数调用
	lcd_Init();//lcd初始化函数调用	
	li_cheng.data[0]=eeprom_read(0x00);
	li_cheng.data[1]=eeprom_read(0x01);
	li_cheng.data[2]=eeprom_read(0x02);
	//从寄存器中调用上次存入的数据
	while(1)
	{	speed_deal();
		licheng_deal();
		eeprom_write(0x02,li_cheng.data[2]);
		eeprom_write(0x01,li_cheng.data[1]);
		eeprom_write(0x00,li_cheng.data[0]);
		//将里程放到寄存体中 掉电不会丢失
		PORTD=0x80;lcdml();
		PORTD=table[shuju[0]];lcdx();
		PORTD=table[shuju[1]];lcdx();
		PORTD=table[shuju[2]];lcdx();
		PORTD=table[shuju[3]];lcdx();
		PORTD=table[shuju[4]];lcdx();
		PORTD=table[shuju[5]];lcdx();
		PORTD='d';lcdx();
		PORTD='m';lcdx();
		PORTD=0xc0;lcdml();//========================第二行速度的显示
		PORTD=table[speed_data[0]];lcdx();
		PORTD=table[speed_data[1]];lcdx();
		PORTD='.';lcdx();
		PORTD=table[speed_data[2]];lcdx();
		PORTD=table[speed_data[3]];lcdx();
	//	PORTD='c';lcdx();
		PORTD='m';lcdx();
		PORTD='/';lcdx();
		PORTD='s';lcdx();	
	}
}

最后附上Proteus仿真(利用电源输入时钟信号代替测速模块的运行) 

输入100hz的时钟,对应1s100个跳变即100cm,所以对应的速度为1m/s,仿真结果正确。

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。