出租车计价器
南京工业大学
创新实践报告
(2011 — 2012 学年 第1 学期)
课程名称: 出租车计价器设计 班 级: 电子0805 学 号: 11 姓 名: 吾晓于 指导教师: 包亚萍
2011年 11月
一.出租车计价器概述 1.设计要求:
设计一个出租车计价器,该计价器的计费系统:行程3公里内,起步费为6元; 3公里外以 每公里1.4元计费.
并能显示日期和当前时间,行驶公里数,总费用和暂停计价功能. 设计的主要技术指标 :
①计价范围:0~999.9元 计价分辨率: 0.1元 ②计程范围:0~99公里 计程分辨率: 1.0公里
本电路以SST89E58单片机为中心、附加555定时器构成多谐振荡器,组成信号产生电路来实现里程计数,DS1302构成时钟电路,实现对出租车计价统计,输出采用LCD液晶显示器。本电路设计的计价器不但能实现基本的计价,同时还能作为时钟为司机提供方便。
二.计价器硬件设计
本系统的硬件设计主要包括单片机SST89E58、LCD数据显示部件、555定时器电路、DS1302时钟电路的设计。在硬件设计过程中,充分利用各部件的功能,实现出租车计价器设计。 1. 系统的硬件构成及功能
它由以下几个部件组成:SST89E58单片机、总金额及里程显示、键盘控制,里程计算单元、时钟电路等。
利用单片机丰富的IO端口,及其控制的灵活性,实现基本的里程计价功能和时钟显示功能。
2. 单片机及其引脚说明
SST89E58与ATMEL、PHILIPS、WINBOND等公司的8位标准8051系列单片机完全兼容,工作频率为0~40MHZ,2.7V~5.5V,1K字节内部SRAM,三个高电流驱动端口(每端口16mA),三个16位定时器/计数器,全双工、增强型串口,掉电检测,低功耗。
SST89E58是一个有40
个引脚的芯片,引脚配置和仿真图如下图所示:
其各自引脚功能如下:
Vcc:电源电压。 GND:地。
P0口:P0口是一组8位漏极开路型双向I/O接口,也即地址/数据总线复用口。当访问外部数据存储器或程序存储器时,这组口线分时转换地址和数据总线复用,在访问期间激活内部上拉电阻。在FLASH编程时,P0口接受指令字节,而在程序校验时 ,输出指令字节。
P1口:P1口是一个带内部上拉电阻的8位双向I/O接口,P1的输出缓冲级
可驱动4个TTL逻辑门电路。FLASH编程和程序校验时,P1接收低8位地址。
P2口:P2口是一个带有内部上拉电阻的8位双向I/O口,P2的输出缓冲级可驱动4个TTL逻辑门电路。在访问外部程序存储器或16位地址的外部数据存储器时P2口送高8位地址数据。FLASH编程或校验时,P2亦接收高位地址和其他控制信号。
P3口:P3口是一组带有内部上拉电阻的8位双向I/O接口。P3口输出缓冲级可驱动4个TTL逻辑门电路。
RST:复位输入。
ALE/ PROG:当访问外部数据时,ALE(地址锁存允许)输出脉冲用于锁存地址的低8位字节。
EA/VPP:外部访问允许。
PSEN:程序储存允许。PSEN输出是外部程序存储器的度选通信号。
XTAL1:振荡器反相放大及内部是钟发生器的输入端。 XTAL2:振荡器反相放大器的输出端。
3. 按键单元的.设计
电路共采用了六个按键和一个开关,S1、S2、S3、S4、S5、S6,其功能分别是:S1光标左移,S2光标右移,S3『+』,S4『-』,S5设定时间,S6暂停。开关为控制计价器工作和停止。
4. 555定时器构成多谐振荡器
555 定时器是一种模拟和数字功能相结合的中规模集成器件。一般用双极性工艺制作的称为 555,用 CMOS 工艺制作的称为 7555,除单定时器外,还有对应的双定时器 556/7556。555 定时器的电源电压范围宽,可在 4.5V~16V 工作,7555 可在 3~18V 工作,输出驱动电流约为 200mA,因而其输出可与 TTL、CMOS 或者模拟电路电平兼容。
555构成多谐振荡器,组成信号产生电路
振荡周期: T=0.7(R1+2R2)C
输出高电平时间 T=(R1+R2)Cln2 输出低电平时间T=R2Cln2
输出方波的占空比为D=tPH/T=(R1+R2)/(R1+2R2) R1=R2=47KΩ
f=1/T=1.43/( R1+R2)C=150Hz
5.DS1302时钟电路
DS1302 是美国DALLAS公司推出的一种高性能、低功耗、带RAM的实时时钟电路,它可以对年、月、日、周日、时、分、秒进行计时,具有闰年补偿功能,工作电压为2.5V~5.5V。采用三线接口与CPU进行同步通信,并可采用突发方式一次传送多个字节的时钟信号或RAM数据。
DS1302的引脚排列,其中Vcc1为后备电源,VCC2为主电源。在主电源关闭的情况下,也能保持时钟的连续运行。DS1302由Vcc1或Vcc2两者中的较大者供电。当Vcc2大于
Vcc1+0.2V时,Vcc2给DS1302供电。当Vcc2小于Vcc1时,DS1302由Vcc1供电。X1和X2是振荡源,外接32.768kHz晶振。RST是复位/片选线,通过把RST输入驱动置高电平来启动所有的数据传送。RST输入有两种功能:首先,RST接通控制逻辑,允许地址/命令序列送入移位寄存器;其次,RST提供终止单字节或多字节数据的传送手段。当RST为高电平时,所有的数据传送被初始化,允许对DS1302进行操作。如果在传送过程中RST置为低电平,则会终止此次数据传送,I/O引脚变为高阻态。上电运行时,在Vcc>2.0V之前,RST必须保持低电平。只有在SCLK为低电平时,才能将RST置为高电平。I/O为串行数据输入输出端(双向),后面有详细说明。SCLK为时钟输入端。 下图为DS1302的引脚功能和仿真图:
6.LCD显示器
LM016L 的结构及功能
LM016L 液晶模块采用 HD44780 控制器,hd44780 具有简单而功能较强的指令集,可以实 现字符移动,闪烁等功能。 液晶模块的引脚功能如下: VSS 一般接地 VDD 接电源(+5V)
V0 液晶显示器对比度调整端,接正电源时对比度最弱,接地电源时对比度最高(对比 度过高时会产生"鬼影",使用时可以通过一个 10K 的电位器调整对比度).
RS 为寄存器选择,高电平 1 时选择数据寄存器,低电平 0 时选择指令寄存器.
R/W 为读写信号线,高电平(1)时进行读操作,低电平(0)时进行写操作. E E(或 EN)端为使能(enable)端,下降沿使能. D0—D3 底4位三态, 双向数据总线0-3位 D4—D7 高4位三态, 双向数据总线4-7位
计价器流程图
总原理图
计价器程序
//出租车车计价器 设计
//该模拟程序折合规则:1km-1m,等待30s-1km-1m,1m-1.4元 //底层规则:若脉冲个数/秒 #include #include #include #include
uchar code univalent[2] = {1,40}; 价整数位,[1]-里程单价小数位
//保存单价的数组,[0]-里程单
uchar code time_pos[7] = {4,-1,7,10,4,7,10}; //各时间在液晶上的显示位置
uchar code money_pos[4] = {4,7,4,7}; //计价器价格各位在液晶上的显示位置
bit config_ok = 0; bit state = 0;
(计里程),1-低速(计时间) bit pause = 0; 价,1-暂停计价
uint pulse_count = 0;
//0-未配置完成,1-配置完成 //当前仪表的运行状态,0-全速//计价停止状态位,0-正常计//脉冲计数器
//保存等待计时的变量,单位为
uint pulse_count_tmp = 0;
uint time_count = 0; 秒,10s-1km-1.4元
uint mileage_count_new = 0,mileage_count_old = 0; //保存里程的变量,通过差值计
算里程变化,单位为km,1km-1.4元,
uchar idata time[7] = {0x09,0x1,0x1,0x1,0x0,0x0,0x0}; //保存时间的数组 uint money[2]={6,0}; //保存车费的数组,[0]-整数位,[1]-小数位
uchar first_3_km = 0;
void INT0_init(void); void INT1_init(void); void Delay(uint); void System_init(void);
void Time_Show(uchar time_data[7]);
void Run_Show_Time(uchar time_data[7]); void Money_Show(uint money[2]); void Show_Wait_Time(uint); void Show_Mileage(void);
void Run_BackGround(void);
出现的
void Run_BackGround(void) { WriteChar('/', 3,0); WriteChar(':',10,0); WriteChar(':',13,0); WriteChar('.',3,1);
WriteChar('Y',6,1);
}
void Show_Mileage(void) { WriteDecimal(pulse_count / 200,0,12,1); WriteInt(pulse_count % 200 / 10,0,0,13,1); WriteChar('.',12,1); WriteString("km",14,1);
}
void Show_Wait_Time(uint time_count) { WriteChar('s',15,1); WriteChar(' ', 10,1);
WriteInt(time_count,1,4,11,1);
//运行起来后,将在LCD上一直
void Money_Show(uint money[2]) { WriteDecimal(money[0],0,3,1); WriteDecimal(money[1],1,3,1);
}
void Run_Show_Time(uchar time_data[7]) { WriteInt(BcdToInt(time_data[2]),1,2, 1,0); WriteInt(BcdToInt(time_data[3]),1,2, 4,0); WriteInt(BcdToInt(time_data[4]),1,2, 8,0); WriteInt(BcdToInt(time_data[5]),1,2,11,0); WriteInt(BcdToInt(time_data[6]),1,2,14,0);
}
void Time_Show(uchar time_data[7]) { WriteChar('/',6,0); WriteChar('/',9,0);
WriteChar(':',6,1); WriteChar(':',9,1);
WriteInt(BcdToInt(time_data[0]),1,2, 4,0); WriteInt(BcdToInt(time_data[2]),1,2, 7,0); WriteInt(BcdToInt(time_data[3]),1,2,10,0); WriteInt(BcdToInt(time_data[4]),1,2, 4,1); WriteInt(BcdToInt(time_data[5]),1,2, 7,1); WriteInt(BcdToInt(time_data[6]),1,2,10,1);
}
void System_init(void) { RstLcd(); ClrLcd(); P1 = 0x00; config_ok = 0; Time_Show(time); LcdPos(5,0);
SetCur(3); INT1_init();
while(config_ok == 0); //等待配置时间结束标志
}
SetCur(1);
WriteString("set time over...",0,0); Delay(60000); ClrLcd();
Run_BackGround(); P1= 0xff;
void Delay(uint dtime) { }
uint temp;
for(temp=0;temp
void INT0_init(void) {
EA = 0; IT0 = 1; EX0 = 1; EA = 1;
}
void INT1_init(void) { EA = 0; }
IT1 = 1; EX1 = 1; EA = 1;
void main() {
uchar time_tmp[7],i; System_init();
DS1302_GetData(time);
pulse_count_tmp = pulse_count;
mileage_count_new = mileage_count_old = 0; Money_Show(money); Run_Show_Time(time); Show_Mileage(); while(1)
{
if(config_ok == 0) System_init();
DS1302_GetData(time_tmp);
if(!(P1 & 0x04)) {
P1 &= 0xfe; P1 |= 0x02; pause = 0;
if(time[6] != time_tmp[6]) { }
Run_Show_Time(time_tmp); for(i = 0;i
time[i] = time_tmp[i];
//若设置时间未完成
first_3_km = 0; money[0] = 6; money[1] = 0;
mileage_count_new = mileage_count_old = 0; WriteString(" ",0,1); WriteString(" ",9,1); Money_Show(money); pulse_count = 0; Show_Mileage(); time_count = 0;
}
else if(pause == 0) {
INT0_init();
if(time[6] != time_tmp[6]) {
Run_Show_Time(time_tmp); for(i = 0;i
if(pulse_count - pulse_count_tmp
行驶(计时),即一秒内,脉冲数目的个数变化值若小于10,则判为低速
{
state = 1; P1 &= 0xfe; P1 |= 0x02;
time_count ++;
//等待计时加1
if(time_count % 10 == 0 && first_3_km > 2)//由等待时间换算公
里数,10s折合为1km(1m) {
}
}
money[1] += 40; if(money[1] > 99) { }
money[0] += 1; money[1] %= 100;
money[0] += 1; Money_Show(money);
else if(time_count % 10 == 0 && first_3_km
mileage_count_old = mileage_count_new; Show_Wait_Time(time_count);
//否则则判为全速状
态(计里程)
}
else {
state = 0; P1 &= 0xfd; P1 |= 0x01; time_count = 0;
//全速状态下,把等
待时间清0
}
pulse_count_tmp = pulse_count;
if(state == 0) {
mileage_count_new = pulse_count / 200;
if(mileage_count_new != mileage_count_old && first_3_km > 2) {
Show_Mileage();
for(i = mileage_count_old;i
money[1] += 40; if(money[1] > 99) { }
money[0] += 1; money[1] %= 100;
}
}
}
}
money[0] += 1;
Money_Show(money); }
mileage_count_old = mileage_count_new;
} else if(mileage_count_new != mileage_count_old && first_3_km
first_3_km ++;
mileage_count_old = mileage_count_new; Show_Mileage();
else { }
if(time[6] != time_tmp[6]) { Run_Show_Time(time_tmp); }
for(i = 0;i
static void INT0_ser(void) interrupt 0 { }
pulse_count ++;
static void INT1_ser(void) interrupt 2 {
uchar month_day[12]={31,0,31,30,31,30,31,31,30,31,30,31}; char result; uchar i;
static uchar pos;
//配置时间
if(!(P2 & 0x20) && config_ok == 0) {
for(i = 0;i
if(!(P2 & 0x20) && config_ok == 0) {
//++
//配置到哪一项
result = BcdToInt(time[pos]) + 1;
if((pos == 0 && result == 50) || (pos == 4 && result == 24) || (pos == 5 && result == 60) || (pos == 6 && result == 60)) result = 0; else if(pos == 2 && result == 13)
result = 1; else if(pos == 3) {
month_day[1] = (time[0] % 4 == 0 && time[0] % 100 != 0) || time[0] % if(result == month_day[time[2] - 1] + 1)
result = 1;
400 == 0 ? 29:28;//判断润平年
}
time[pos] = IntToBcd(result);
//--
}
else;
}
else if(!(P2 & 0x40) && config_ok == 0) {
for(i = 0;i
if(!(P2 & 0x40) && config_ok == 0) {
result = BcdToInt(time[pos]) - 1; if((pos == 0 && result == -1)) result = 49; else if(pos == 2 && result == 0) result = 12;
else if(pos == 3) { month_day[1]=(time[0] % 4 == 0 && time[0] % 100 != 0) || time[0] %
400 == 0 ? 29:28;//判断润平年
if(result == 0)
}
result = month_day[time[2] - 1];
else if(pos == 4 && result == -1) result = 23;
else if((pos == 5 || pos == 6) && result == -1) result = 59; else
;
time[pos] = IntToBcd(result);
} }
else if(!(P2 & 0x08) && config_ok == 0)
//NEXT
{ for(i = 0;i
if(!(P2 & 0x08) && config_ok == 0) { pos++; pos %= 7; if(pos == 1)
pos = 2;
} }
else if(!(P2 & 0x10) && config_ok == 0)
{ for(i = 0;i
if(!(P2 & 0x10) && config_ok == 0) { pos--; if(pos == -1) pos = 6; if(pos == 1)
pos = 0;
}
}
else if(!(P2 & 0x80) && config_ok == 0) { for(i = 0;i
DS1302_Reset();
DS1302_SettingData(time);
}
}
else if(!(P2 & 0x80) && config_ok == 1) { for(i = 0;i
if(!(P2 & 0x80) && config_ok == 1) { config_ok = 0;
}
}
else if(!(P1 & 0x08) && config_ok == 1) {
//PREVIOUS
//ENTER
//CONFIG
}
}
for(i = 0;i
if(!(P1 & 0x08) && config_ok == 1) { pause = ~pause; EX0 = 0; }
if(config_ok == 0) { }
WriteInt(BcdToInt(time[pos]),1,2,time_pos[pos],pos > 3 ?1:0 ); LcdPos(time_pos[pos]+1,pos > 3 ?1:0);
【出租车计价器】相关文章:
出租车计价器作弊与预防07-31
出租车计价器抗干扰问题分析07-26
出租车多功能计价器安装与调测07-31
旧计价器的汽笛响了08-20
计价器外围故障的调修07-08
出租汽车计价器的发展与车载GPS07-06
出租汽车计价器抗干扰硬件设计07-31
出租汽车计价器检定应注意的问题07-06