简易出租车里程计费器
测控08级综合课程设计
题 目: 简易出租车里程计费器
摘要:本系统以STC89C52RC单片机为控制核心,辅以键盘调节、12864显示、
蜂鸣器报警、车速模拟、车速检测及信息存储电路,实现了出租车计价器的行车里程和车速的实时检测与显示、计价金额显示以及价格预置等功能,满足了题目中基本部分及发挥部分的要求。在此基础上,还增加了断电保护、蜂鸣器警示、行驶里程等功能。该系统功能齐全,实用性强。经测试,计价器的各项显示指标均满足题目要求。
关键词:出租车里程计费器;STC89C52RC+;MOC70T2;;掉电保护;
Abstract: This system uses STC89C52 microcontroller as control core. With the keyboard control circuit, digital display circuit, beep alarm circuit, speed
measureement circuit, speed detection circuit and information storage circuit,this system realizes function of the meter taxi driving mileage ,display and detection of real-time speed, valuation display and price set in advance, it meets all essential and additional requirement. Additional function such as power-off protection , beep alarm the print of mileage and consumption is added. This system is fully functioned and easy to implement. The measurement results show that all indicators of this taxi meter meet the requirement.
Key words: Taxi Meter; STC89C52; Price Set in Advance; Power-off Protection
目 录
第一章 出租车里程计费器的设计要求与设计方案 ...................... 1 1.1 出租车计价器系统组成......................................... 1 图1-1 系统功能图 .................................................. 1 1.2 系统主要功能................................................. 1 1.3 方案论证与比较............................................... 1 第二章 出租车里程计费器的硬件设计 ................................ 2 2.1 2.2 2.3 2.4 2.5 2.6
出租车的硬件框图............................................. 2 主控制器STC89C52RC+ ......................................... 2 按键扫描模块................................................. 2 显示模块..................................................... 3 掉电保护..................................................... 3 车速模拟和检测模块........................................... 4
第三章 出车里程计费器的软件设计 .................................. 5 3.1 系统主程序流程图............................................. 5 3.2 里程和费率计算程序流程图..................................... 5 第四章 设计体会与小结 ............................................ 6 参考文献 .......................................................... 6 附 录 ............................................................ 7 一.源程序 ........................................................ 7 二.12864驱动程序 ............................................... 12
第一章 出租车里程计费器的设计要求与设计方案
1.1 出租车计价器系统组成
此出租车计费系统以单片机为系统核心,利用STC89C52RC单片机配合12864液晶屏的显示模块及键盘模块等,实现基本的出租车计价器功能。本系统是由STC89C52RC+单片机、12864液晶显示模块、模拟出租车、复位电路及键盘等模块组成。系统框图如图1-1所示:
图1-1 系统功能图
1.2 系统主要功能
本课程设计所设计的出租车计价器的主要功能有:里程计量及费用计算功能、车速测量、按键功能。
1.3 方案论证与比较
1.3.1方案一:采用数字电路控制。
采用传感器件,输出脉冲信号过放大整形作为移位寄存器的脉冲,实现计价,但是考虑到这种电路过于简单,性能不稳定,而且不能调节单价,也不能根据需要调节计费标准,电路不够实用。 1.3.2 方案二:采用单片机控制。
利用单片机丰富的 I/O端口,及其控制的灵活性,实现基本的里程计价功能,车速测量和价格调节、液晶显示功能。
通过比较以上两种方案,单片机方案有较大的活动空间,不但能实现所要求的功能而且能在很大的程度上扩展功能, 而且还可以方便的对系统进行升级, 所以我们采用后一种方案。
1
第二章 出租车里程计费器的硬件设计
2.1 出租车的硬件框图
图2-2 单片机控制方案
2.2 主控制器STC89C52RC+
STC89C52RC是一种带8K FLASH程序存储器,512B SRAM,4K EEPROM,高性能CMOS 8位微处理器,俗称单片机。
主要特性:与MCS-51兼容、8K字节可编程闪烁存储器、512字节的SRAM最高工作频率:80MHz、4K字节EEPROM、32可编程I/O线、三个16位定时器/计数器、8个中断源、内置硬件看门狗、在线可编程和在系统可编程、可编程串行通道、低功耗的闲置和掉电模式、片内振荡器和时钟电路。
2.3 按键扫描模块
(1)按键扫描模块电路图及说明:
整个系统有四个按键,四个功能调整按键;本模块功能:扫描按键功能,返回扫描。
图2-3
2.4 显示模块
本设计是用12864液晶屏来实现计价的显示。原理图如图2-4所示。
图2-4 12864液晶屏显示模块
2.5 掉电保护
掉电保护功能采用了STC89C52RC+单片机内部EEPROM来实现。掉电存储单元的作用是在电源断开的时候,存储当前设定的单价信息。STC89C52内部自带了4K大小的EEPROM,地址是从2000H~2FFFH。写操作主要是编程和擦除。
2.6 车速模拟和检测模块
以电机为驱动,将电机的转子与码盘连接在一起,用码盘的转动模拟出租车车轮的转动,码盘的转速即为出租车的车速。
采用MOC70T2凹槽光电开关作为车速检测器。MOC70T2凹槽光电开关灵敏度高、实用性强、安装方便。MOC70T2凹槽光电开关检测码盘转动的圈数,将检测得到的信号送至单片机外部中断引脚,单片机运用算法处理接收到的信号,从而得到出租车的实时车速。MOC70T2凹槽光电开关的电路图如图2-6所示。
图2-6 车速模拟和检测模块
第三章 出车里程计费器的软件设计
3.1 系统主程序流程图
3.2 里程和费率计算程序流程图
第四章 设计体会与小结
经过这次出租车计价器的课程设计,我收益非浅,从中我学到了很多东西.课程设计不仅是对前面所学知识的一种检验,而且也是对自己能力的一种提高。通过这次设计使我明白了自己原来知识还比较欠缺。自己要学习的东西还太多,以前老是觉得自己什么东西都会,什么东西都懂,有点眼高手低。通过这次课程设计,我才明白学习是一个长期积累的过程,另外,还学会了在网络上查找有关本设计的各硬件的资源,其中包括:STC89C52单片机及其引脚说明,为本次课程设计提供了一定的资料。
在这次课程设计中也使我们的同学关系更进一步了,同学之间互相帮助,有什么不懂的大家在一起商量,听听不同的看法对我们更好的理解知识,所以在这里非常感谢帮助我的同学。
总之,不管学会的还是学不会的的确觉得困难比较多,真是万事开头难,不知道如何入手。最后终于做完了有种如释重负的感觉。此外,还得出一个结论:知识必须通过应用才能实现其价值!有些东西以为学会了,但真正到用的时候才发现是两回事,所以我认为只有到真正会用的时候才是真的学会了。
经过这次的课程设计,也为我们以后毕业设计的制作奠定了一定的基础。
参考文献
1. 2. 3. 4. 5. 6. 7.
丁跃军.单片机基础教程.北京:北航大学出版社,2004
张鑫、华臻、陈书谦.《单片机原理及应用》[M].电子工业出版社,2005 李群芳,肖看.单片机原理接口与应用.北京:清华大学出版社,2005 朱承高.电工及电子技术手册[M].北京:高等教育出版社,1990
高峰.单片微型应用系统设计及实用技术.北京:机械工业出版社,2004 廖常初.现场总线概述[J].电工技术,1999 丁元杰、吴大伟.《单片微机实题集与实验指导书》[M].机械工业出版社, 2004
附 录
一.源程
#include
#include"12864.h"
#include"eeprom.h"
sbit beep=P2^0;
uchar Trg,Cont;
uchar StartPrice,PerPrice;
uchar DisplayC;
uchar code num[]="0123456789";
uchar flag,f;
uint speed_count,speed_c;
uchar c;
uint speed;
uchar beep_count;
unsigned long Val;
void ScanKey(void);
void delay5s(void);
void main(void)
{
uint distance;
uint TotalPrice;
uchar price[]="元";
beep=1;
lcd_init();
display(0,0," Welcom to you !");
display(1,0,"出租车里程计费器");
display(2,0," Designed by");
display(3,0," 唐杰 王家佳");
delay5s();
lcd_init();
StartPrice=byte_read(0x2000);
PerPrice=byte_read(0x2200);
EX0=1;
EA=1;
IT0=1;
RCAP2L=TL2=0x3C;
RCAP2H=TH2=0xB0;
ET2=1;
TMOD = 0x01;
TH0 = 0x0B1;
TL0 = 0x0E0;
TR0 = 1;
TR2=1;
while(1)
{
ScanKey();
if(f==0)
{
display(0,0,"起步价:");
if(flag==0)
{
lcd_wdat(num[StartPrice/10]);
lcd_wdat('.');
lcd_wdat(num[StartPrice%10]);
}
if(flag==1)
{
if(DisplayC
{
lcd_wdat(num[StartPrice/10]);
lcd_wdat('.');
lcd_wdat(num[StartPrice%10]);
}
if((30
{
lcd_wdat(' ');
lcd_wdat(' ');
lcd_wdat(' ');
}
}
display(0,5,"元");
display(1,0,"每公里:");
if(flag==0)
{
lcd_wdat(num[PerPrice/10]);
lcd_wdat('.');
lcd_wdat(num[PerPrice%10]);
}
if(flag==2)
{
display(0,0,"起步价:");
lcd_wdat(num[StartPrice/10]);
lcd_wdat('.'); lcd_wdat(num[StartPrice%10]); display(1,0,"每公里:"); if(DisplayC40)DisplayC=0; display(1,5,"元"); } else if(f==1) { speed=speed_c*36; display(1,0,"速度:"); if(speed/1000!=0)lcd_wdat(num[speed/1000]); lcd_wdat(num[speed%1000/100]); lcd_wdat(num[speed%100/10]); lcd_wdat('k'); lcd_wdat('m'); lcd_wdat('/'); lcd_wdat('h'); } display(2,0,"行驶里程:"); lcd_wdat(num[distance/1000]); lcd_wdat(num[distance%1000/100]); lcd_wdat(num[distance%100/10]); lcd_wdat('.'); lcd_wdat(num[distance%10]); display(2,7,"km"); distance=Val/100; TotalPrice=distance*PerPrice/10+StartPrice; display(3,0,"总费用:"); if(TotalPrice/1000!=0)lcd_wdat(num[TotalPrice/1000]); else lcd_wdat(' '); if(TotalPrice%1000/100!=0)lcd_wdat(num[TotalPrice%1000/100]);
else lcd_wdat(' ');
lcd_wdat(num[TotalPrice%100/10]);
lcd_wdat('.');
lcd_wdat(num[TotalPrice%10]);
lcd_wdat(price[0]);
lcd_wdat(price[1]);
}
}
void ScanKey(void)
{
unsigned char ReadData;
static char Ctemp;
if(TF0==1)
{
TF0=0;
TH0 = 0x0B1;
TL0 = 0x0E0;
beep_count++;
if(beep_count>=5)
{
beep_count=0;
beep=1;
}
DisplayC++;
ReadData=P3^0xFF;
Trg=ReadData&(ReadData^Cont);
Cont=ReadData;
if(f==0)
{
if((Cont&(1
{
Ctemp++;
if(Ctemp>=50)
{
Ctemp=0;
flag=1;
beep=0;
}
}
if((Trg&(1
{
flag++;
beep=0;
}
if(flag>=3)
{
flag=0;
sector_erase(0x2000);
byte_program(0x2000,StartPrice);
sector_erase(0x2200);
byte_program(0x2200,PerPrice);
}
if((Trg&(1
{
StartPrice--;
beep=0;
}
if((Trg&(1
{
PerPrice--;
beep=0;
}
if((Trg&(1
{
StartPrice++;
beep=0;
}
if((Trg&(1
{
PerPrice++;
beep=0;
}
}
if((Trg&(1
{
lcd_init();
beep=0;
f=!f;
}
}
}
void Count() interrupt 0
{
Val+=2;
speed_count++;
}
void Timer2() interrupt 5
{
TF2=0;
c++;
if(c>=40)
{
c=0;
speed_c=speed_count;
speed_count=0;
}
}
void delay5s(void) //误差 0us
{
unsigned char a,b,c;
for(c=165;c>0;c--)
for(b=100;b>0;b--)
for(a=150;a>0;a--);
}
二.12864驱动程序
#ifndef _12864_H_
#define _12864_H_
#include
#include
#define uchar unsigned char
#define uint unsigned int
/*TS12864A-3 端口定义*/
#define LCD_data P0 //数据口
sbit LCD_RS = P1^0; //寄存器选择输入
sbit LCD_RW = P1^1; //液晶读/写控制
sbit LCD_E = P1^2; //液晶并行使能控制
sbit LCD_PSB = P2^7; //串/并方式控制
#define delayNOP(); {_nop_();_nop_();_nop_();};
void delay(int ms)
{
while(ms--)
{
uchar i;
for(i=0;i
{
_nop_();
_nop_();
// _nop_();
// _nop_();
}
}
}
/*写指令数据到LCD RS=L,RW=L,E=脉冲,D0-D7=指令码。只有LCD_RS的值不同
故这个函数可以和下面的写数据的函数写到一起,用两个参数,读者自己改写*/
void lcd_wcmd(uchar cmd)
{
LCD_RS = 0;//并行指令选择打开
LCD_RW = 0;//写
delayNOP();
delayNOP();
delayNOP();
// P0 = cmd;
LCD_E = 1;//打开并口
delayNOP();
_nop_();
P0 = cmd;
delayNOP();
delayNOP();
LCD_E = 0; //关闭并口 这个函数怎么写,完全参照时序图去写,
}
/*写显示数据到LCD RS=H,RW=L,E=脉冲,D0-D7=数据。*/
void lcd_wdat(uchar dat)
{
LCD_RS = 1;
LCD_RW = 0;
delayNOP();
delayNOP();
delayNOP();
//P0 = dat;
LCD_E = 1;
delayNOP();
_nop_();
P0 = dat;
delayNOP();
delayNOP();
LCD_E = 0;
}
/* LCD显示汉字初始化设定,只设必须的,若显示图片初始化设定得另外设定 */
void lcd_init()
{
unsigned int i;
LCD_PSB = 1; //并口方式
lcd_wcmd(0x34); //扩充指令操作 0011xRGL R=1扩充指令G=0关闭绘图显示L=0
for(i=400;i>0;i--);
lcd_wcmd(0x30); //基本指令操作
for(i=400;i>0;i--);
lcd_wcmd(0x08); //睡眠模式
for(i=400;i>0;i--);
lcd_wcmd(0x0C); //显示开,关光标00001DCB D=1整体显示,C=0关光标,B=0关游标位置
for(i=80;i>0;i--);
lcd_wcmd(0x01); //清除LCD的显示内容
delay(20); //改变启动时间长短
/* lcd_wcmd(0x02);
delay(5);
lcd_wcmd(0x80);
delay(5);*/
}
//设定显示位置
void lcd_pos(uchar X,uchar Y)
{
uchar pos;
if (X==0)
{X=0x80;} //参照12864PDF文档设定 else if (X==1)
{X=0x90;}
else if (X==2)
{X=0x88;}
else if (X==3)
{X=0x98;}
pos = X+Y ;
lcd_wcmd(pos);
}
void display(uchar y,uchar x,uchar *str) {
lcd_pos(y,x);
while(*str)
{
lcd_wdat(*str);
str++;
}
}
void display_char(uchar y,uchar x,uchar dat) {
lcd_pos(y,x);
lcd_wdat(dat);
}
#endif