出租车计价器源程序.docx
《出租车计价器源程序.docx》由会员分享,可在线阅读,更多相关《出租车计价器源程序.docx(25页珍藏版)》请在冰豆网上搜索。
出租车计价器源程序
/***********************************************
*课程设计出租车计价器C51源程序,实现出租车计
*价器基本功能。
*
*版权声明:
*未经本人允许不得应用于商业用途,可用
*于交流学习。
*
*Sunday,July012012
*****************
**********************************************/
#include
#include
#include
#defineucharunsignedchar
#defineuintunsignedint
#define_NOP_();{_nop_();_nop_();_nop_();_nop_();};
#defineOP_WRITE0xa0//器件地址以及写入操作
#defineOP_READ0xa1//器件地址以及读取操作
#definekey_set0//=P3^3;
#definekey_down1//=P3^4;
#definekey_up2//=P3^5;
#definekey_ok3//=P3^6;
/*
*USR_DAT,PRESET_DATsaveddaytime:
distance,price,
night:
distance,price
TIME:
hour,min,sec
*/
uchardataUSR_DAT[4]={3,2,3,6};
//ucharPRESET_DAT[4]={3,2,3,3};
uchardataITEMS[3]={0,0,0};//存放-里程,单价,费用
uchardataTIME[3]={0,0,12};//存放时间-秒,分,时
ucharcycle_time;//100->考虑到5km/h,运转周期是1.44s-->0.02s计数72次
uintstop_time,stop_time_all,mileometer,temp_s,speed;
ucharcycle_time_info,lock=1,lock_items=1;//信号量;
ucharkey_pressed_time,key_num;//set按键按下次数
ucharhour,min,sec,count;
ucharcodeSTR1[]="Time:
";
//ucharcodeSPACE[]="";
//ucharcodeSTR2[]="S:
P:
A:
";//里程,单价,应收取费用
ucharcodeSTR3[]="Stoptime:
min";
ucharcodeSTR_SET[]="Setting";
ucharcodeSTR_SET_HOUR[]="Settinghour";
ucharcodeSTR_SET_MIN[]="Settingmin";
ucharcodeSTR_SET_PRICE[]="Settingprice";
ucharcodeSTR_SET_START[]="Settingstart";
ucharcodeDAY[]="Day:
";
ucharcodeNIGHT[]="Night:
";
ucharcodeSTR_RST[]="Reset?
No<>Y";
sbitlcd_rs=P2^0;
sbitlcd_rw=P2^1;
sbitlcd_e=P2^2;
sbitLED=P1^1;
sbitSDA=P1^7;
sbitSCL=P1^6;
voiddelay(ucharz);
voidlcd_write_cmd(ucharcmd);
voidlcd_write_dat(uchardat);
voidlcd_init();
voidlcd_display(ucharaddr,uchardat);
voidlcd_display_2(ucharaddr,uchardat);
voidlcd_display_3(ucharaddr,uchardat);
voidlcd_write_str(ucharaddr,uchar*str);
voidtime0_init();
voidtime1_init();
voiddisplay_time();
voiddisplay_reset();
voiddisplay_items();
voiddisplay_set_time();
voiddisplay_stop_time();
voidex_int_init();
voidset_items();
ucharkey_scan();
voidkey_set_dat();
/*
24c02
相关
*/
voidstart();
voidstop();
ucharshin();
bitshout(ucharwrite_data);
voidwrite_byte(ucharaddr,ucharwrite_data);
ucharread_current();
ucharread_addr(ucharaddr);
voidsave_user_dat();
voidrestore_user_dat();
voidmain(void)
{
//ucharset_ok=0;
time0_init();
time1_init();
ex_int_init();
lcd_init();
restore_user_dat();
while
(1)
{
//lcd_display_2(0x02,cycle_time_info);
set_items();
key_num=key_scan();
if(!
key_pressed_time)
{
if(lock||(cycle_time>=72)||(stop_time>0))
display_stop_time();
else
display_time();
display_items();
}else{
key_set_dat();
}
}
}
/*
*函数名:
key_scan()
*函数作用:
扫描按下的按键并返回相应的键值
**/
ucharkey_scan()
{
P3|=0xfb;
if((P3&0xfb)!
=0xfb)
delay(200);
if((P3&0xfb)!
=0xfb){
switch(P3&0xfb){
case0xeb:
returnkey_down;
case0xdb:
returnkey_up;
case0xf9:
returnkey_ok;
default:
return0;
}
}
}
/*
*函数名:
ucharkey_set_dat(ucharkey_pressed_time)
*函数输入:
set键按下的次数,以及键值
*函数输出:
//完成设置返回0,未完成返回1
*函数作用:
根据set按键按下的次数,执行相应的设置:
*1.复位包括里程和费用
*2.时间设置:
时,分
*3.参数设置:
白天起步距离和单价
*4.参数设置:
晚上起步距离和单价
**/
voidkey_set_dat()
{
switch(key_pressed_time){
case1:
{display_reset();
if(key_num==key_up){//2
ITEMS[0]=0;
ITEMS[2]=0;
mileometer=0;
stop_time_all=0;
cycle_time=0;
key_pressed_time=0;
}
if(key_num==key_down){//1
key_pressed_time++;
}
if(key_num==key_ok){
key_pressed_time=0;
}
//key_num=0;
}break;
case2:
{
lcd_write_str(0x80,STR_SET_HOUR);
lcd_display(0x40+0x06,''-0x30);
lcd_display(0x40+0x07,''-0x30);
display_set_time();//hour
if(key_num==key_up)
TIME[2]++;
if(key_num==key_down)
TIME[2]--;
if(key_num==key_ok){
key_pressed_time=0;
}
//key_num=0;
}break;
case3:
{
lcd_write_str(0x80,STR_SET_MIN);
lcd_display(0x40+0x09,''-0x30);
lcd_display(0x40+0x0a,''-0x30);
display_set_time();
if(key_num==key_up)//min
TIME[1]++;
if(key_num==key_down)
TIME[1]--;
if(key_num==key_ok)
key_pressed_time=0;
}break;
case4:
{
lcd_write_str(0x80,STR_SET_PRICE);
lcd_write_str(0x80+0x40,DAY);
lcd_display_2(0x40+0x08,USR_DAT[1]);
//lcd_display(0x40+0x09,''-0x30);
//lcd_display(0x40+0x0a,''-0x30);
if(key_num==key_up)//min
USR_DAT[1]++;
if(key_num==key_down)
USR_DAT[1]--;
if(key_num==key_ok)
key_pressed_time=0;
}break;
case5:
{
lcd_write_str(0x80,STR_SET_PRICE);
lcd_write_str(0x80+0x40,NIGHT);
lcd_display_2(0x40+0x08,USR_DAT[3]);
//lcd_display(0x40+0x09,''-0x30);
//lcd_display(0x40+0x0a,''-0x30);
if(key_num==key_up)//min
USR_DAT[3]++;
if(key_num==key_down)
USR_DAT[3]--;
if(key_num==key_ok)
key_pressed_time=0;
}break;
case6:
{
lcd_write_str(0x80,STR_SET_START);
lcd_write_str(0x80+0x40,DAY);
lcd_display_2(0x40+0x08,USR_DAT[0]);
//lcd_display(0x40+0x09,''-0x30);
//lcd_display(0x40+0x0a,''-0x30);
if(key_num==key_up)//min
USR_DAT[0]++;
if(key_num==key_down)
USR_DAT[0]--;
if(key_num==key_ok)
key_pressed_time=0;
}break;
case7:
{
lcd_write_str(0x80,STR_SET_START);
lcd_write_str(0x80+0x40,NIGHT);
lcd_display_2(0x40+0x08,USR_DAT[2]);
//lcd_display(0x40+0x09,''-0x30);
//lcd_display(0x40+0x0a,''-0x30);
if(key_num==key_up)//min
USR_DAT[2]++;
if(key_num==key_down)
USR_DAT[2]--;
if(key_num==key_ok)
key_pressed_time=0;
}break;
default:
key_pressed_time=0;
}
//save_user_dat();_-->会引起WARNINGL15:
MULTIPLECALLTOSEGMENT
}
/*
*函数名:
set_items()
*函数作用:
设置计算显示的里程,设置相应时间的单价,计算应收取费用
*即是设置ITEMS数组
**/
voidset_items()
{
ITEMS[0]=(mileometer*2)/1000;
/*while(lock_items){
temp_s=ITEMS[0];
lock_items--;
lcd_display(0x0d,lock_items);
}*/
if(TIME[2]>18||TIME[2]<6)//晚上六点后,早上六点前实行夜间收费标准
{
ITEMS[1]=USR_DAT[3];
if(ITEMS[0]>USR_DAT[2]){
/*
if((ITEMS[0]-temp_s)!
=0){
ITEMS[2]+=ITEMS[1];
lock_items++;
}*/
ITEMS[2]=(ITEMS[0]-USR_DAT[2])*ITEMS[1]+5+stop_time_all/300;
}else
ITEMS[2]=5+stop_time_all/300;//起步价5元
}else{
ITEMS[1]=USR_DAT[1];//ITEMS[0]里程ITEMS[1]单价ITEMS[2]结算
if(ITEMS[0]>USR_DAT[0]){
/*if((ITEMS[0]-temp_s)!
=0){
ITEMS[2]+=ITEMS[1];
lock_items++;
}*/
ITEMS[2]=(ITEMS[0]-USR_DAT[0])*ITEMS[1]+5+stop_time_all/300;
}else
ITEMS[2]=5+stop_time_all/300;
}
}
/*
*函数名:
ex_int_init()
*函数作用:
初始化外部中断
**/
voidex_int_init()
{
EX0=1;
IT0=1;
IP=0x0a;//将定时器中断0,1优先级设为最高
EX1=1;
IT1=1;//下降沿触发
}
/*
*函数名:
ex1_int()interrupt2
*函数作用:
设置时间,用户数据:
白天和晚上的起步距离和单价USR_DAT
**/
voidex1_int()interrupt2
{
EX1=0;
delay(200);
EX1=1;
key_pressed_time++;
}
/*
*函数名:
voidex_int()interrupt0
**/
voidex0_int()interrupt0
{
if((cycle_time>=72)||(stop_time>0))//此时说明速度小于5km/h
{
stop_time_all+=(stop_time+cycle_time/50);
cycle_time_info++;
}else
cycle_time_info=10;
if(cycle_time_info>10)
lock=1;
else
lock=0;
stop_time=0;
cycle_time=0;
//if(stop_time_all>=300){
//ITEMS[2]+=stop_time_all/300;
//stop_time_all%=300;
//}
//else{
//while(lock){/*获取信号量*/
//lock--;
//stop_time=sec;//暂时借用stop_time寄存器
//};
//display_stop_time();
///*
//*完成工作在display_stop_time显示1s后返回显示display_time*/
//if((sec-stop_time)!
=0){
//display_time();
//stop_time=0;
//lock++;//释放信号量
//}
//}
mileometer++;
if(mileometer%2==0)
LED=!
LED;
}
/*
*函数名:
voidtime1_init()
*函数作用:
初始化定时器1,为工作方式一
**/
voidtime1_init()
{
TMOD=TMOD|0x10;
TH1=(65535-20000)/256;
TL1=(65535-20000)%256;
EA=1;
ET1=1;//定时器终端控制位
TR1=1;//定时器控制位
}
/*
*函数名称:
voidtime1()interrupt3
*函数作用:
时钟计数函数计时时间用于测速
**/
voidtime1()interrupt3
{
TH1=(65535-20000)/256;
TL1=(65535-20000)%256;
cycle_time++;
if(cycle_time==100){//100
stop_time+=2;
cycle_time=0;
}
//lcd_display_3(0x40+0x02,stop_time);
//lcd_display_3(0x40+0x06,cycle_time);
}
/*
*函数名:
voiddisplay_set_time()
*函数作用:
显示设置时间界面
**/
voiddisplay_set_time()
{
//lcd_write_str(0x80,STR_SET);
lcd_write_str(0x80+0x40,STR1);
lcd_display(0x40+0x08,'-'-0x30);
lcd_display(0x40+0x0b,'-'-0x30);
lcd_display(0x40+0x0e,''-0x30);
lcd_display_2(0x40+0x06,TIME[2]);
lcd_display_2(0x40+0x09,TIME[1]);
lcd_display_2(0x40+0x0c,TIME[0]);
}
/*
*函数名:
display_reset()
*函数作用:
复位确定界面
*Setting
*Reset?
No<>Y
**/
voiddisplay_reset()
{
lcd_write_str(0x80,STR_SET);
lcd_write_str(0x80+0x40,STR_RST);
}
/*
*函数名:
display_stop_time()
*函数作用:
显示停车或者小与5km/h的时间
*Stoptime:
00min
**/
voiddisplay_stop_time()
{
lcd_write_str(0x80,STR3);
lcd_display_2(0x0a,stop_time_all/60);
}
/*
*函数名:
display_items()
*函数作用:
显示里程,单价,应收取费用
*S:
P:
A:
**/
voiddisplay_items()
{
//lcd_write_str(0x80+0x40,STR2);//第二行
lcd_display(0x40+0x00,'S'-0x30);
lcd_display(0x40+0x01,':
'-0x30);
lcd_d