电工学习网

 找回密码
 立即注册
查看: 4047|回复: 1
打印 上一主题 下一主题

出租车计价器原理与构造

[复制链接]
跳转到指定楼层
楼主
发表于 2019-5-12 08:29:03 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
单片机好做,但如果用模拟电路和数字电路来搭建这样复杂的功能,恐怕做出来要比现有的成本计价器大几十倍,而且耗电巨大,成本更高,何必要这样做呢?只因为没有学到就要这样不计成本的浪费吗?
如果是急求的话,可以花钱招一个懂单片机的人来搞,没有人能提供不用单片机的电路的,太复杂了,不可能实现。
首先要看里程传感器的输出是模拟的还是数字的。
无论何种里程传感器,
可以用数字积分器,简单些;也可以用模拟积分器,这样设计和调试的难度就很大。电路原理图如下:
出租车计价器原理与构造

回复

使用道具 举报

沙发
 楼主| 发表于 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)                                                         //死循环
……………………

回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

电工学习网 ( )

GMT+8, 2024-8-29 12:08

Powered by © 2011-2022 www.shop-samurai.com 版权所有 免责声明 不良信息举报

技术驱动未来! 电工学习网—专业电工基础知识电工技术学习网站。

栏目导航: 工控家园 | 三菱plc | 西门子plc | 欧姆龙plc | plc视频教程

快速回复 返回顶部 返回列表