资源描述
一、任务规定
1.性能规定:
测量范畴:5~5000rpm;
2.功能规定:
采用MCS51系列单片机完毕测量,并将测量值显示于数码管上。分别采用测频法和测周法进行设计,并比较不同速度段测量精度。
二、方案论证
系统构成:
图1-1 系统构成框图
如图1-1所示,本次设计系统重要由如下几种某些构成,即:传感器、单片机以及显示某些构成。各个某些方案论证如下:
2.1传感器选取
当前,可用于测速传感器有诸多,例如:光电传感器,开关型霍尔传感器,电涡流传感器以及光电编码器等。
方案一:采用光电传感器
光电传感器是通过光电二极管和光敏三极管把光输入信号转化为磁输入信号器件。光电传感器长处是响应速度快、测量精度高,可以直接输出高低电平,缺陷是容易受外来光线、灰尘等影响,即对周边环境规定比较高。
方案二:采用开关型霍尔传感器
开关型霍尔传感器是运用霍尔效应把磁输入信号转换成电信号器件。开关型霍尔长处是可以直接输出高低电平,属于大信号传感器,对外部信号调理电路规定不高,缺陷是响应速度不如光电传感器。
方案三:采用电涡流传感器
电涡流传感器是运用电涡流效应来工作传感器,具备长期工作稳定性好,抗干扰能力强,但是输出信号比较弱,后续解决电路比较复杂,且普通价格比较高。
在灰尘和粉尘较少而规定频率响应范畴比较宽状况下,可以采用光电传感器。而在灰尘和粉尘比较多状况下,则选用开关型霍尔传感器。由于本次设计重要针对自行车和汽车测速,故选用开关型霍尔传感器。
2.2显示模块选取
方案一:采用LED数码管
LED数码管只可以显示数字和简朴字母,其长处是价格便宜,程序编写比较简朴,功耗低,缺陷是亮度不高,在要显示数字多场合下,体积较大,比较占空间。
方案二:采用LCD1602液晶显示
LCD1602液晶显示模块具备体积小、功耗低,对比度可调且可以显示ASCII码和简朴中文等长处,其缺陷是成本比数码管高,并且程序编写相对复杂。
方案三:采用LCD12864液晶显示
LCD12864液晶显示屏长处是可以显示中文,且功耗比较低,其拟定是软件编程比较复杂。
2.3测速原理论证
2.3.1测频法原理:
测频法原理图如图1-2所示,即测量一段时间t内,所计脉冲数为N,则所测得频率为f=t/N,其“1误差”为。由此可见,在t一定期,所测频率f越高,则“1误差”越小。因而测频法合用于测低频。
图1-2 测频法原理图
测周法原理:
测周法原理图如图1-3所示,即对信号周期T进行测量,然后依照f=1/T就可以得到频率。在本设计中就是通过对单片机内部时钟脉冲计数得到两个脉冲之间时间间隔T。假设单片机内部时钟为,所计得脉冲数为N,则时间间隔T =N/,即频率f =/N。其“1误差”为。由此可知,在时钟脉冲一定期,所测时间间隔T越大,即所测频率越低,则“1误差”越小,精度越高。
图1-3 测周法原理图
综上所述,为了提高所设计测速仪精度,因而本次设计采用测频法和测周法相结合办法,即低频时采用测周法,高频时采用测频法。
三、硬件设计
总原理框图:
图1-4 总硬件原理框图
如图1-4所示,即为整个系统原理框图,该智能测速仪是运用霍尔传感器来采集信号,当磁粒接近霍尔传感器时,霍尔传感器向单片机输出一种脉冲,通过单片机解决,将频率和转速送到LCD1602中显示。
3.1单片机最小系统
图1-5 单片机最小系统原理图
单片机最小系统电路如上图1-5所示,重要由单片机、晶振电路、复位电路三某些构成。其中晶振电路由一种12MHz晶体振荡器和两个瓷片电容构成,为单片机提供时钟频率,本次设计采用12M晶振是为了使定期可以更精准,计算更以便。复位电路由上图中S1,R3,R4和C1所构成,具备上电复位和按键复位两种复位方式。由于要使用P0口作为数据传送端,因此需要在P0加上拉电阻。本次设计选用单片机是STC89C54RD+。
3.2霍尔传感器电路
图1-6 霍尔传感器电路原理图
霍尔传感器电路如上图1-6所示,本次设计选用霍尔型号为44E开关型霍尔传感器,当小磁粒接近时,霍尔输出低电平。图中D2为电源批示灯,D1为小磁粒接近霍尔批示灯。LM393为电压比较器,2脚输入电压为2.5V,此处加个电压比较器使输出信号更稳定,可以输出比较稳定脉冲信号。
3.3液晶显示模块电路
图1-7 液晶显示电路原理图
液晶显示电路如右图所示,其中1脚VSS和2脚VDD为电源地和电源正极,3脚VO是用来调节液晶屏幕显示对比度,4脚RS为数据/命令选取端,5脚R/W为读写端,6脚E为使能端,7~14脚DB0~DB7为数据端,15脚BLA和16脚BLK为背光电源端。
四、软件设计
4.1软件实现功能
软件重要实现功能是完毕测频法和测周法算法实现,并且可以进行自动依照频率范畴进行两种办法之间转换。
4.2主程序框图
图1-8主程序框图
主程序框图如图
4.3定期器中断程序框图
4.4外部中断程序框图
三、 模仿调试某些
5.1模仿装置简介
本次设计所使用
5,2模仿调试办法
5.3成果
四、 小结
6.1实验中所遇到问题
①、在编程时,采用测周法时始终无法得到对的频率,所显示频率值始终在4000到5000左右变化,而定期器计数值(用来计算两个脉冲之间时间量)始终只有几百,即时间为几百微秒。
②、在实际测量时,发现测得频率值与实际频率值相差很大,且相对误差在10%左右,例如实际值为325r/min,而测得值为354r/min,即相对误差为(354-325)/325*100%=8.9%,误差比较大。
③、采用测周法时,当频率为0时,其实际显示值不为零,始终停留在之前值,保持不变。
6.2分析、解决
6.3设计成果评价
附录1
#include<reg52.h>
#define uint unsigned int
#define uchar unsigned char
sbit LCD_RS = P2^6;//液晶控制端
sbit LCD_RW = P2^5;
sbit LCD_EP = P2^7;
uchar code tab1[] = {"freq 0000 Hz"}; //液晶第一行默认显示数据
uchar code tab2[] = {"n 0000 r/min"}; //液晶第二行默认显示数据
long speed_count=0; //计数值
uint freq=0; //频率值
uint speed=0; //转速值
uint timer_count=0; //定期器计数值
uint int_t0_count=0; //M法时外部中断计数值
uchar intt0_count=0; //T法中用来平均
bit m_flag=1; //M法标志位
bit t_flag=0; //T法标志位
bit first_flag=0;//第一种测频值显示标志
void delay(uchar ms); //延时子程序
void init_interuppt(); //定期器0初始化
void lcd_init(); //液晶初始化
void write_1602_wcmd(uchar com); //液晶写入指令函数
void write_1602_wdat(uchar dat); //液晶写入数据函数
void write_speed(uchar address,uint dat);//1602写速度值
void main()
{
lcd_init(); //液晶初始化
init_interuppt(); //中断初始化
while(1)
{
if(first_flag==1)
{
if(freq>1000) //频率不不大于1000则采用测频法
{
m_flag=1;
t_flag=0;
}
else
{
m_flag=0;
t_flag=1;
}
}
write_speed(0x45,freq); //显示频率值
write_speed(5,speed);//显示转速值
}
}
/******************************************************************/
/* 延时函数 */
/******************************************************************/
void delay(uchar ms)
{
uint i,j;
for(i=ms;i>0;i--)
for(j=150;j>0;j--);
}
/******************************************************************/
/* 定期器 计数器初始化 */
/******************************************************************/
void init_interuppt()
{
TMOD=0x01; //设立为工作方式1,16位计数方式
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
ET0=1; //使能定期器0中断
EX0=1; //使能外部中断
IT0=1; //下降沿触发
EA=1; //使能总中断
TR0=1; //开定期器0中断
}
/******************************************************************/
/* 定期器中断函数 */
/******************************************************************/
void timer0() interrupt 1
{
TH0=(65536-50000)/256; //每50毫秒进一次中断
TL0=(65536-50000)%256;
if(m_flag==1)
{
timer_count++;
if(timer_count==20) //每1秒钟更新一次速度
{
freq=int_t0_count;
speed=freq*10; //频率转换为转速
int_t0_count=0;
timer_count=0;
if(first_flag==0)
first_flag=1;
}
}
if(t_flag==1)
{
timer_count++;
if(timer_count==10)
{
speed=0;
freq=0;
}
}
}
/******************************************************************/
/* 外部中断函数 */
/******************************************************************/
void int_t0() interrupt 0
{
if(m_flag==1)
{
int_t0_count++;
}
if(t_flag==1)
{
intt0_count++;
speed_count += TH0*256 + TL0 + timer_count*65536;
if(intt0_count==2)
{
freq = (unsigned int)(000.0/(speed_count));
speed = (unsigned int)(000.0/(speed_count)*10);
speed_count=0;
intt0_count=0;
}
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
timer_count = 0;
}
}
/******************************************************************/
/* LCD初始化设定 */
/******************************************************************/
void lcd_init()
{
uchar i;
write_1602_wcmd(0x38); //16*2显示,5*7点阵,8位数据
write_1602_wcmd(0x0c); //显示开,关光标
write_1602_wcmd(0x06); //移动光标
write_1602_wcmd(0x01); //清除LCD显示内容
write_1602_wcmd(0x82); //第一行字符写入位置
for(i=0;i<13;i++)
write_1602_wdat(tab2[i]);
write_1602_wcmd(0xc0);
for(i=0;i<12;i++)
write_1602_wdat(tab1[i]);
}
/******************************************************************/
/* 写指令到LCD */
/******************************************************************/
void write_1602_wcmd(uchar com)
{
LCD_RS = 0; //置为写入命令,低为写指令
LCD_RW = 0;
P0 = com; //送入数据
delay(1);
LCD_EP = 1; //拉高使能端
delay(1);
LCD_EP = 0; //完毕高脉冲,传入数据到LCD
}
/******************************************************************/
/* 写数据到LCD */
/******************************************************************/
void write_1602_wdat(uchar dat)
{
LCD_RS = 1; //置为写入数据,高为写数据
LCD_RW = 0;
P0 = dat; //送入数据
delay(1);
LCD_EP = 1; //拉高使能端
delay(1);
LCD_EP = 0; //完毕高脉冲,传入数据到LCD
}
/******************************************************************/
/* 写速度值到LCD */
/******************************************************************/
void write_speed(uchar address,uint dat)
{
uchar gw,sw,bw,qw;
qw = dat/1000;
bw = dat%1000/100;
sw = dat%1000%100/10; //分出十位数据
gw = dat%1000%100%10; //分出个位数据
write_1602_wcmd(0x80+address); //在第二行相应位置显示
write_1602_wdat(0x30+qw);
write_1602_wdat(0x30+bw);
write_1602_wdat(0x30+sw);
write_1602_wdat(0x30+gw);
}
展开阅读全文