这是我做的一个车租车计费作品,用了两个星期,附件里包含作品源代码和芯片资料,清大家多多指教
电路原理图如下:
单片机源程序如下:
- /*************************************************************
- 多功能出租车计价系统
- 补充说明:
- ***************************************************************/
- #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) //死循环
- ……………………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
所有资料51hei提供下载:
程序+原理图.7z
(3.35 MB, 下载次数: 302)
|