|
沙发
楼主 |
发表于 2019-5-12 08:29:29
|
只看该作者
单片机源程序如下:
/*************************************************************
多功能出租车计价系统
补充说明:
***************************************************************/
#include<reg52.h> //头文件
#include<LCD1602.h>
#include<AT24C02.h>
#include<INTERRUPT.h>
#include<SC8065.h>
#include<DS1302.h>
/*****************灯、蜂鸣器、按键引脚定义*******************/
sbit led =P3^0; //红色LED灯
sbit led2 =P3^1; //绿色LED灯
sbit key_start =P1^0; //开始/结束计价
sbit key_Wait =P1^1; //电机开始/结束
sbit key_set =P1^2; //设置
sbit key_jia =P1^3; //加值
sbit key_jian =P1^4; //减值
/************************变量定义***********************/
uint start_price; //起步价
uint white_price; //白天单价
uint white_Wait; //白天等待超10分钟后每分钟价钱。
bit start; //开始计价标志,=0非计价模式,=1计价模式
double price1; //应收总价钱(带小数)
uint mil,Wait,price2; //里程数、等待时间、总价
uchar set_f; //设置选择标记,=0未设置,=1设置起步价,=2设置白天公里价,=3设置时,=4设置分,=5设置秒
bit strat_f; //初始界面显示标志,=0显示初始界面,=1可能计价、设置、总价显示
uchar num; //循环计数变量
bit moto_f=0; //电机控制标志,=0关闭电机,1打开电机
/********************************************************
函数名称:void baojia()
函数作用:乘坐结束进行报价
参数说明:
********************************************************/
void baojia()
{
uint temp;
SC_Speech(1); //先播放一次空的内容,防止语音混乱
//以下里程播报
SC_Speech(55); //播放【本次】
SC_Speech(56); //播放【行程】
if(mil>=1000) //里程【大于100KM】
{
SC_Speech(10+mil/1000); //播放 里程的百位
SC_Speech(21); //播放【百】
}
if(mil>=100) //里程【大于10KM】
{
if(mil%1000/100!=0) //如果 里程十位 不为0
{
if(mil<1000&&mil%1000/100==1);//只有十几的时候不用报【一】
else
SC_Speech(10+mil%1000/100);//播放 里程的十位
SC_Speech(20); //播放【十】
}
else //否则 里程十位 为0
{
if(mil%100/10!=0) //如果 里程个位 不为0
SC_Speech(10); //播放【零】
}
}
if(mil>=10) //里程【大于1KM】
{
if(mil%100/10!=0) //如果 里程个位 不为0
SC_Speech(10+mil%100/10); //播放 里程的个位
}
else
SC_Speech(10); //播放【零】
if(mil%10!=0) //如果 里程小数 不为0
{
SC_Speech(24); //播放【点】
SC_Speech(10+mil%10); //播放 里程的小数位
}
SC_Speech(4); //播放【千米】
//以下价格播报
temp=price2/10;
SC_Speech(58); //播放【共计】
if(temp>=1000) //总价【大于100元】
{
SC_Speech(10+temp/1000); //播放 总价的百位
SC_Speech(21); //播放【百】
}
if(temp>=100) //总价【大于10元】
{
if(temp%1000/100!=0) //如果 总价十位 不为0
{
if(temp<1000&&temp%1000/100==1);//只有十几的时候不用报【一】
else
SC_Speech(10+temp%1000/100);//播放 总价的十位
SC_Speech(20); //播放【十】
}
else //否则 总价十位 为0
{
if(temp%100/10!=0) //如果 总价个位 不为0
SC_Speech(10); //播放【零】
}
}
if(temp>=10) //总价【大于1元】
{
if(temp%100/10!=0) //如果 总价个位 不为0
SC_Speech(10+temp%100/10); //播放 总价的个位
}
else
SC_Speech(10); //播放【零】
if(temp%10==0) //如果 总价小数位 为0
{
SC_Speech(6); //播放【元】
SC_Speech(38); //播放【整】
}
else //否则 总价小数位 不为0
{
SC_Speech(24); //播放【点】
SC_Speech(10+temp%10); //播放 总价的小数位
SC_Speech(6); //播放【元】
}
SC_Speech(64); //播放【谢谢】
}
/********************************************************
函数名称:void display()
函数作用:计价时显示里程、等待时间函数
参数说明:
********************************************************/
void display()
{
if(mil_f==1) //检测到一次信号
{
mil_f=0;
//显示里程数
//LCD_disp_char(9,1,ASCII[mil/1000]); 最大里程为99.9公里
LCD_disp_char(10,1,ASCII[mil%1000/100]);
LCD_disp_char(11,1,ASCII[mil%100/10]);
LCD_disp_char(12,1,'.');
LCD_disp_char(13,1,ASCII[mil%10]);
lcd1602_write_character(14,1,"KM");
if(mil>30) //里程超3公里
{
if(time[2]>=7&&time[2]<22) //在白天时间段
price1=price1+white_price; //计算白天总价【white_price/10=公里价】
else //在晚上时间段
price1=price1+white_price*1.5; //计算晚上总价
}
else //小于三公里只收起步价
price1=start_price; //计算总价【price1/100=总价】
}
if(wait_f==1) //计时一秒到
{
wait_f=0;
//显示等待时间
LCD_disp_char(11,2,ASCII[Wait%3600/60/10]);
LCD_disp_char(12,2,ASCII[Wait%3600/60%10]);
LCD_disp_char(13,2,':');
LCD_disp_char(14,2,ASCII[Wait%60/10]);
LCD_disp_char(15,2,ASCII[Wait%60%10]);
if(Wait>600&&Wait%60==0) //等待时间超过10分钟后每1分钟计费
price1=price1+10; //每分钟+0.1元
}
price2=price1;
//显示应付金额
LCD_disp_char(0,1,ASCII[price2/10000]); //显示应付金额百位
LCD_disp_char(1,1,ASCII[price2%10000/1000]); //显示应付金额十位
LCD_disp_char(2,1,ASCII[price2%1000/100]); //显示应付金额个位【price2/100=应付金额】
LCD_disp_char(3,1,'.');
LCD_disp_char(4,1,ASCII[price2%100/10]);
LCD_disp_char(5,1,0X01); //显示字符¥
//显示当前时间
LCD_disp_char(0,2,ASCII[time[2]/10]);
LCD_disp_char(1,2,ASCII[time[2]%10]);
LCD_disp_char(2,2,':');
LCD_disp_char(3,2,ASCII[time[1]/10]);
LCD_disp_char(4,2,ASCII[time[1]%10]);
LCD_disp_char(5,2,':');
LCD_disp_char(6,2,ASCII[time[0]/10]);
LCD_disp_char(7,2,ASCII[time[0]%10]);
}
/********************************************************
函数名称:void display2()
函数作用:计价结束时显示总价函数
参数说明:
********************************************************/
void display2()
{
lcd1602_write_character(3,1,"A total of"); //显示字符串
LCD_disp_char(5,2,ASCII[price2/10000]);
LCD_disp_char(6,2,ASCII[price2%10000/1000]);
LCD_disp_char(7,2,ASCII[price2%1000/100]);
LCD_disp_char(8,2,'.');
LCD_disp_char(9,2,ASCII[price2%100/10]);
LCD_disp_char(10,2,0X01); //显示字符¥
}
/********************************************************
函数名称:void display3()
函数作用:设置收费参数时显示函数
参数说明:
********************************************************/
void display3()
{
if(set_f==1) //显示起步价的设置
{
lcd1602_write_character(0,1,"Starting price:"); //显示字符串
LCD_disp_char(6,2,ASCII[start_price%1000000/100000]); //起步价百位
LCD_disp_char(7,2,ASCII[start_price%10000/1000]); //起步价十位
LCD_disp_char(8,2,ASCII[start_price%1000/100]); //起步价个位
LCD_disp_char(9,2,0x01); //显示字符¥
}
if(set_f==2) //显示设置每加一公里价格
{
lcd1602_write_character(0,1,"Set unit price:");
LCD_disp_char(4,2,ASCII[white_price/100]); //显示公里价十位【white_price/10=公里价】
LCD_disp_char(5,2,ASCII[white_price%100/10]); //显示公里价个位
LCD_disp_char(6,2,'.');
LCD_disp_char(7,2,ASCII[white_price%10]); //显示公里价十分位
lcd1602_write_character(9,2,"/KM");
lcd1602_write_character(8,2,0x01); //显示字符¥
}
}
/********************************************************
函数名称:void display4(void)
函数作用:显示校准时间函数
参数说明:
********************************************************/
void display4()
{
num++;
lcd1602_write_character(4,1,"Set Time:");
if(num%2==0) //偶数次显示,奇数次不显示。这样就会有闪烁效果,可以清楚看到当前设置的是哪个值
{
LCD_disp_char(4,2,ASCII[time[2]/10]); //显示设置时
LCD_disp_char(5,2,ASCII[time[2]%10]);
LCD_disp_char(6,2,':');
LCD_disp_char(7,2,ASCII[time[1]/10]); //显示设置分
LCD_disp_char(8,2,ASCII[time[1]%10]);
LCD_disp_char(9,2,':');
LCD_disp_char(10,2,ASCII[time[0]/10]);//显示设置秒
LCD_disp_char(11,2,ASCII[time[0]%10]);
}
else //奇数次不显示
{
switch(set_f)//根据当前设置的内容,对应位置闪烁
{
case 3:lcd1602_write_character(4,2," "); break; //按三下设置时
case 4:lcd1602_write_character(7,2," "); break; //按四下设置分
case 5:lcd1602_write_character(10,2," "); break; //按五下设置秒
default: break;
}
}
}
/********************************************************
函数名称:void scan(void)
函数作用:按键检测函数
参数说明:
********************************************************/
void scan(void)
{
//开始/结束计价键
if(key_start==0&&set_f==0) //在设置模式下无效
{
delayms(7); //延时消抖
if(key_start==0) //再次确认开始计价按键按下
{
LCD_write_command(0x01);//清除屏幕显示
delay_n40us(100); //延时等待清除完成
start=~start; //切换开始/结束计价
strat_f=1; //显示计价界面
if(start==0) //非计价模式下,计价结束。计算价格
{
led=1; //关闭红色指示灯
led2=0; //开启绿色指示灯
EX0=0; //关闭外部中断
TR1=1; //开启定时20S左右自动回到初始界面
moto=1; //关闭电机转动
moto_f=0; //关闭电机控制标志
display2(); //显示总价
baojia(); //播报行驶里程和总价
mil=0; //清除里程数
Wait=0; //清除等待时间
TR0=0; //关闭等待计时的定时器
}
else //计价开始
{
led=0; //开启红色指示灯
led2=1; //关闭绿色指示灯
TR1=0; //关闭定时1
T1_num=0; //重置定时计数变量
mil_f=1; //计价时显示里程
wait_f=1; //计价时显示等待时间
TR0=1; //开启计等待时间的定时器
EX0=0; //此时电机未开启,关闭外部中断0,不进行里程检测
moto_f=0; //标记电机关闭
}
}
while(!key_start); //检测按键松开
}
if(start==0) //非计价模式下
{
//设置键
if(key_set==0) //只有在结束计价才有效
{
delayms(7); //延时消抖
if(key_set==0) //再次确认按键按下
{
Writeds1302 (WRITE_PROTECT,0X00);//DS1302禁止写保护
if(set_f<3)
{
TR1=1; //开启定时1
T1_num=0; //重置定时计数变量
LCD_write_command(0x01);//清除屏幕显示
delay_n40us(100); //延时等待清除完成
}
set_f++; //设置选择变量+1
strat_f=1; //进入设置界面
if(set_f==6) //全部参数设置完成,退出设置
{
TR1=0; //关闭定时器1
T1_num=0; //重置定时计数变量
f=1; //标记设置操作完成
strat_f=0; //退出设置显示初始界面
}
}
while(!key_set); //检测按键松开
}
//加值键
if(key_jia==0)
{
delayms(7); //延时消抖
T1_num=0; //重置定时计数变量,防止定时恢复初始界面
if(key_jia==0) //再次确认按键按下
{
if(set_f==1) //设置起步价
{
if(start_price<3000) //最大值可设置3000/100=30元【start_price/100=起步价】
start_price+=100; //起步价+1元
}
if(set_f==2) //设置白天每加一公里价格
{
if(white_price<100) //最大值可设置100/10=10元【white_price/10=公里价】
white_price++; //白天公里价+0.1元
}
if(set_f==3) //设置小时
{
time[2]++; //小时+1
time[2]=(time[2]/10)*16+time[2]%10;//将小时转换成16进制
if(time[2]>0x23) //判断是否达到最大小时23时
time[2]=0x00; //重新回到00时
Writeds1302 (WRITE_HOUR,time[2]); //将设置好的小时写入到DS1302存储起来
time[2]=Read1302(0x85); //读取当前小时
}
if(set_f==4) //设置分
{
time[1]++;
time[1]=(time[1]/10)*16+time[1]%10;
if(time[1]>0x59)
time[1]=0x00;
Writeds1302 (WRITE_MINUTE,time[1]);
time[1]=Read1302(0x83);
}
if(set_f==5) //设置秒
{
time[0]++;
time[0]=(time[0]/10)*16+time[0]%10;
if(time[0]>0x59)
time[0]=0x00;
Writeds1302 (WRITE_SECOND,time[0]);
time[0]=Read1302(0x81);
}
}
}
//减值键
if(key_jian==0)
{
delayms(7); //延时消抖
T1_num=0; //重置定时计数变量
if(key_jian==0) //再次确认按键按下
{
if(set_f==1) //设置起步价
{
if(start_price>=100) //最小值可设置0元
start_price-=100; //起步价-1元
}
if(set_f==2) //设置白天每加一公里价格
{
if(white_price!=0) //最小值可设置0元
white_price--; //白天公里价-0.1元
}
if(set_f==3) //设置小时
{
if(time[2]==0) //判断小时是否到达最小小时0时
time[2]=23; //重新回到23时
else
time[2]--; //否则小时-1
time[2]=(time[2]/10)*16+time[2]%10;//将小时转换成16进制
Writeds1302 (WRITE_HOUR,time[2]); //将设置好的小时写入到DS1302存储起来
time[2]=Read1302(0x85); //重新读取小时
}
if(set_f==4) //设置分
{
if(time[1]==0)
time[1]=59;
else
time[1]--;
time[1]=(time[1]/10)*16+time[1]%10;
Writeds1302 (WRITE_MINUTE,time[1]);
time[1]=Read1302(0x83);
}
if(set_f==5) //设置秒
{
if(time[0]==0)
time[0]=59;
else
time[0]--;
time[0]=(time[0]/10)*16+time[0]%10;
Writeds1302 (WRITE_SECOND,time[0]);
time[0]=Read1302(0x81);
}
}
}
}
else //计价模式下
{
if(key_Wait==0) //开启/关闭电机
{
delayms(7); //延时消抖
if(key_Wait==0) //再次确认按键按下
{
if(TR0==0) //当TR0=0时moto_f=1,此时电机为开启状态
{
TR0=1; //打开定时器0,开始计等待时间
EX0=0; //禁止外部中断0,不进行里程检测
moto_f=0; //标记电机关闭
}
else //当TR0=1时moto_f=0,此时电机为关闭状态
{
TR0=0; //关闭定时器0,停止计等待时间
EX0=1; //INT0中断允许,检测霍尔信号
moto_f=1; //标记电机打开
}
}
while(!key_Wait); //检测按键松开
}
if(key_jia==0) //电机加速
{
delayms(7); //延时消抖
if(key_jia==0&&vs<9)//再次确认按键按下,并且速度还没最大9挡
{
vs++; //速度等级+1
}
while(!key_jia); //检测按键松开
}
if(key_jian==0) //电机减速
{
delayms(7); //延时消抖
if(key_jian==0&&vs>4)//再次确认按键按下,并且速度还没最小4挡
{
vs--; //速度等级-1
}
while(!key_jian); //检测按键松开
}
}
}
/********************************************************
函数名称:void main()
函数作用:主函数
参数说明:
********************************************************/
void main()
{
led=1; //红灯关闭
led2=0; //绿灯点亮
LCD_init(); //LCD1602初始化
T0_init(); //定时器0初始化
Int0_init(); //外部中断初始化
if(key_jian==0) //手动复位初始默认价格
{
delayms(100);
if(key_jian==0)
{
AT24C02_write_date(1,18); //写入【公里价】数据保存,地址0~255均可
AT24C02_write_date(5,10); //写入【起步价】数据保存
}
}
white_price=AT24C02_read_date(1); //读取存储的【公里价】数据
start_price=AT24C02_read_date(5)*100;//读取存储的【起步价】数据
lcd1602_write_pic(0x01,pic2); //将自定义字符“¥”写入LCD1602
while(1) //死循环
……………………
|
|