单片机源程序如下: /************************************************************* 多功能出租车计价系统 补充说明: ***************************************************************/ #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) //死循环 …………………… |
电工学习网 ( )
GMT+8, 2024-8-29 12:08