基于C51单片机的出租车计价器设计详解

摘 要

随着我国经济的快速发展,出行选择乘坐出租车的人越来越多。与此同时电子信息技术的发展更新,更加准确、便捷、稳定的出租车计价收费系统随之出现。基于单片机的出租车计价系统的设计,不仅可以更加准确、稳定的反映计价情况,也能促进出租车行业健康稳定的发展。

本设计以STC89C52单片机为核心,设计包括硬件电路设计、软件流程设计、组装与调试,硬件电路包括单片机核心电路、电源电路、液晶显示电路、蓝牙模块电路等各模块电路,对各模块电路的连接及功能进行了详细介绍;软件流程设计包括软件整体设计流程、具体程序的运行流程,通过他们了解软件设计的整体方向;组装与调试主要测量各元件接口电压、脉冲值,对不达标的接口校准修改,同时列出了在组装设计时遇到的问题及解决方案。设计最后附上总体原理图、设计所需元件清单及设计源代码。设计基本满足了出租车计价器的需求,具有结构简单、操作方便、显示清晰、功能强大等特点。   

  

关键词:出租车; STC89C52;计价器 

   

摘 要

目   录

一、引言

二、总体设计

2.1基于单片机的出租车计价器设计原理

2.2 系统元件选型及参数介绍

三、硬件设计

3.1单片机核心电路

3.2 电源电路

3.3 液晶显示电路

3.4 蓝牙模块电路

3.5 霍尔元件电路

3.6 DS1302时钟电路

3.7直流电机电路

四、软件设计

4.1 编程语言选择及开发环境

4.2 软件流程框图

五、 组装与调试

5.1 实物组装焊接

5.2 通电测试与校准

5.3 遇到问题及解决方案

六、 总结

致   谢

参考文献

附录一 、计价器各个部位原理图设计

附录二、硬件电路清单明细

附录源程序代码

基于单片机的出租车计价器设计

一、引言

出租汽车计价器是出租车计价结算的计量器具,计价器的计量结果是否准确直接关系到车辆运营者和人民群众的利益[1]。

国内出租车计价器的发展已经经历了4个阶段, 从传统的全部由机械元器件组成的机械式到半电子式出租车计价器, 再从集成电路式到目前的基于单片机系统设计的出租车计价器[2]。现如今的出租车计价器不仅可以完成基本的计价、计程、计时等功能,而且其精度等级和使用体验也更加完善。

目前市面上出租车计价器一般是通过磁敏传感器组成的霍尔元件,采集出租车发动机转动信号,将转动信号转化为脉冲信号发送到中央处理器。中央处理器结合计价器的计时功能根据相应的算法计算得出乘客乘坐的里程和应付金额。本文以单片机STC89C52为核心设计一款多功能出租车计价器,该计价器能实现按里程综合计算车价,能显示时间、里程、单价、总车价等相关信息显示。

二、总体设计

2.1基于单片机的出租车计价器设计原理

本系统由STC89C52单片机为核心、液晶显示模块、时钟模块、蓝牙模块、霍尔测速模块、和电源模块组成,结构图如图2. 1单片机计价器原理结构图所示。

 

图2. 1单片机计价器原理结构图

以单片机STC89C52作为核心,通过液晶显示模块实时显示时间年、月、日、周、时、分、秒,起步价,运行里程,起步价格,收费标准,实际价格。用直流电机模拟出租车运行状态,霍尔测速模块测量运动状态,输出电压使能变化的方脉冲,进而模拟出租车实际行驶的里程。时种模块用来计时,可通过蓝牙模块向时钟发送数据来更新时间。

2.2 系统元件选型及参数介绍

2.2.1、单片机选型

选取51单片机系列中的STC89C52芯片,该单片机是STC公司生产的一种低功 耗、高性能CMOS8位微控制器,具有 8K字节系统可编程Flash存储器,STC89C52使用经典的MCS-51内核,但做了很多的改进使得芯片具有传统51单片机不具备的功能[3]。单片机引脚如图2. 2 STC89C52单片机引脚图所示:

 

图2. 2 STC89C52单片机引脚图

单片机引脚功能:

  • 电源引脚(2根)
  • VCC(40脚):电源输入,接+5V电源。

    GND(20脚):接数字地。
    ②时钟引脚(2根)
    XTAL1(19脚):片内振荡器的反相放大器的输入端。

    XTAL2(20脚):片内振荡器的反相放大器的输出端
    ③控制引脚(4根)
    RST/VPP(9脚):复位引脚,引脚上加持续时间大于2个机器周期的高电平将使单片机复位。
    ALE/PROG(30脚 ):ALE为引脚第一功能,为CPU访问外部程序存储器或外部数据存储器提供低8位地址锁存信号,PROG为引脚第二功能对片内Flash进行编程时,Vpp引脚接入编程电压。
    PSEN(29脚):片外程序存储器的读选通信号,低电平有效。
    EA/Vpp(31脚):EA为引脚第一功能:外部程序存储器访问允许控制端。Vpp为引脚第二功能:对片内Flash编程时,Vpp引脚接入编程电压[4]。
    ④并行I/O口引脚(32根)
    STC89C52单片机有4组8位的可编程I/O口,分别位P0、P1、P2、P3口,每个口有8位(8根引脚),共32根[4]。

    PO口(P0.7~P0.0引脚): 漏极开路的双向I/O口。

    P1口(P2.7~P2.0引脚): 准双向I/O口,具有内部上拉电阻,可驱动4个LS型TTL负载。 

    P2口(P2.7~P2.0引脚): 准双向I/O口,引脚内部接有上拉电阻,可驱动4个LS型TTL负载[4]。 

    P3口(P3.7~P3.0引脚):第一功能作为通用I/O口使用,可驱动4个LS型TTL负载。

    第二功能如表2.1所示。

    表2-1 P3口第二引脚功能

    引脚

    第二功能

    说明

    P3.0

    RXD

    串行数据输入口

    P3.1

    TXD

    串行数据输出口

    P3.2

    INT0

    外部中断0输入

    P3.3

    INT1

    外部中断1输入

    P3.4

    T0

    定时器0外部计数输入

    P3.5

    T1

    定时器1外部计数输入

    P3.6

    WR

    外部数据存储器的写选通控制信号

    P3.7

    RD

    外部数据存储器的读选通控制信号

    2.2.2、显示器选型

    此次设计选用LCD12864液晶显示屏,LCD12864液晶屏具有功耗低、体积小、重量轻等优点。这几年来此显示屏广泛用于单片机控制的智能仪器、仪表和低功耗的电子产品中。LCD液晶显示屏实物图如图2. 3液晶显示模块实物图所示。

     

    图2. 3液晶显示模块实物图

    该液晶模块采用ST7920控制器, 5V电压驱动, 带背光, 带中文字库, 内置8192个16*16点阵、128个8*16字符点阵以及64*256点阵显示RAM[5]。利用该模块灵活的接口方式和操作指令,可构成全中文人机交互图形界面。该模块构成的液晶显示方案与同类型的图形点阵液晶显示模块相比,不论硬件电路结构还是软件程序都要简洁得多,而且该模块的价格也低于相同点阵的图形液晶模块[6]。

    LCD显示屏引脚说明如表2-2所示。

    表2-2 LCD12864液晶显示屏引脚定义

    引脚

    符号

    引脚说明

    引脚

    符号

    引脚说明

    1

    VSS

    电源地(0V)

    11

    DB4

    Data I/O

    2

    VDD

    电源正极(+5V)

    12

    DB5

    Data I/O

    3

    VO

    对比度调节(+5V)

    13

    DB6

    Data I/O

    4

    RS(CS)

    数据/命令选择器(H/L)

    14

    DB7

    Data I/O

    5

    R/W

    读/写选择器(H/L)

    15

    PSB

    H:8位或4位并行方式

    L:串行方式

    6

    E

    使能信号

    16

    NC

    空脚

    7

    DB0

    Data I/O

    17

    /RST

    Reset

    8

    DB1

    Data I/O

    18

    NC

    空脚

    9

    DB2

    Data I/O

    19

    LEDA

    背光源正极

    10

    DB3

    Data I/O

    20

    LEDK

    背光源负极

    2.2.3 、霍尔元件选型

    霍尔元件采用A3144芯片设计制作,用它可以通过磁场变化测得相应数据。A3144芯片是由电压调整器、霍尔电压发生器、史密特触发器、差分放大器、集电极开路和温度补偿电路的输出极组成的磁敏传感电路[7]。霍尔元器件具有很多优点,它的结构牢固、体积小、重量轻、寿命长、安装方便、功耗低、频率高、耐振动、不怕灰尘、盐雾等的污染或腐蚀。其管脚定义如表2-3所示。

    表2-3 霍尔元件引脚定义

    引脚

    符号

    功能

    1

    VCC

    电源正极

    2

    GND

    电源负极

    3

    DO

    数字量输出,有磁感应是输出低电平

    4

    AO

    模拟量输出(不同距离输出不同电压)

    三、硬件设计

    基于单片机的出租车计价器设计硬件部分由单片机核心电路、直流电源电路、液晶显示电路、蓝牙模块电路、霍尔元件电路、DS1302时钟电路、直流电机电路共同组成。各种电路模块电路组合一起完成了出租车计价器的基本功能。

    3.1单片机核心电路

    单片机核心电路由复位电路、时钟电路和STC89C52单片机共同构成。单片机核心电路原理图如图3. 1单片机核心电路原理图所示。

     

    图3. 1单片机核心电路原理图

    VCC和GND为单片机的电源引脚,为单片机提供电源。

    复位电路由S1按钮、10uf电容、10kΩ电阻组成。VCC电源先连接s1按钮,在和10uf电容并联一起接人单片机的RST复位接口,按钮再经10KΩ电阻接地接线图如图3. 1单片机核心电路原理图。当系统上电时,单片机40引脚接人5V电压,单片机自动复位,输出信号至显示屏,按下S1按钮后,单片机被动复位,更新数据输出数据至显示屏。

     

    图3. 2单片机核心电路实物图

    时钟电路由11.0592MHZ晶振Y1、30PF瓷片电容C1和C2组成, 电容一端接地,一端接单片机XTAL2接口,再用同样大小电容接单片机XRAL1接口,两个电容之间连接一晶振,连接图如图3. 1单片机核心电路原理图。他们组合在一起构成时钟电路,为单片机的起振准备。

    原理图中JD1为单片机的下载接口,接口采用USB接口有三个引脚,其中1、2引脚作为信息传输接口分别连接单片机的串行数据输入口RXD和串行数据输出口TXD。

    3.2  电源电路

    设计中各芯片工作电压均在5V范围内,选择5V直流电源为整个电路供电。电源电路原理图如图3. 3电源电路原理图所示。

     

    图3. 3电源电路原理图

    选择一个有三个引脚的直流电源插座,2、3引脚接地,1号引脚通过按钮一端接VCC用作输出电压,另一端通过1KΩ电阻连接LED灯,按钮自然状态下为常开,按下之后自锁长闭,LED显示灯亮,系统上电。直流供电源可以选择手机充电器、充电宝等。

    3.3 液晶显示电路

    本设计需要显示时间、路程、起步价、金额等信息,信息量多选用128*64LCD显示屏,可以更加直观看到信息。其电路原理图如图3. 4液晶显示电路原理图所示。

     

    图3. 4液晶显示电路原理图

    1脚和2脚为LED12864显示屏接地和电源引脚,3脚为背光调节引脚,通过10K电位器接地,背光可通过电位器来调节亮度;4脚、5脚、6脚为液晶片选控制引脚,分别连接到单片机的P2.0、P2.1、P2.2端口,7~14脚为数据接口,与单片机的P0口相连实现数据的传输,15、16、脚为液晶的背光控制脚,分别接到电源和地。

    3.4  蓝牙模块电路

    本设计需要显示实时时间,但是系统每次断电再上电都要复位,导致数据不准确,选择蓝牙模块用来校时,方便快捷。蓝牙模块用无线通信连接手机上,用手机发送时间数据实时修改,蓝牙模块有4个引脚,引脚1接单片机串行数据输出口TXD,引脚2接单片机串行数据输入口RXD,3、4引脚分别接地和5V电源。连接原理图如图3. 5蓝牙模块原理图所示。

     

    图3. 5蓝牙模块原理图

    开启手机蓝牙连接蓝牙模块,通过软件发送例如:*2021050516003005#,表示:2021年05月05日16时00分30秒,周05。校时如图3. 6蓝牙校时实物图所示。

     

     

    图3. 6蓝牙校时实物图

    3.5  霍尔元件电路

    设计需要通过霍尔元件采集直流电机在模拟出租车行驶时转动产生的脉冲信号,将信号传送至单片机计算出行驶里程。将一磁铁粘连在直流电机转动码盘上,电机每转动以切,霍尔元件接收一个脉冲信号,霍尔元件主芯片是A3144,它感受到周围磁场的变化,产生脉冲信号输出至单片机,如图3. 7A3144芯片原理图所示。霍尔元件模块有四个引脚,引脚1空置,引脚2接单片机INT0引脚,3、4号引脚分别接地和5V电源。

     

    图3. 7A3144芯片原理图

    霍尔元件电路接口原理图如图3. 8霍尔模块电路原理图所示。

     

    图3. 8霍尔模块电路原理图

    模块实物图如图3. 9霍尔元件实物图所示。

     

    图3. 9霍尔元件实物图

    3.6  DS1302时钟电路

    本设计选用DS1302芯片做时钟电路做主芯片,有8个引脚,1引脚接5V电源作为电源输入;2、3引脚之间串联一个32.768KHZ晶振,用来完成电路起振;4引脚接地;5、6、7引脚分别接一个10kΩ的上拉电阻接人单片机的T1、WR、RD接口,用来传递时间信息;8引脚外接一电池,起到掉电维持时间作用,这样时间即使出租车断电,下次打开时时间依然准确,需要定时更换电池。时钟电路原理图如图3. 10时钟电路原理图所示。

     

    图3. 10时钟电路原理图

    3.7 直流电机电路

    为模拟出租车运行状态计算出租车行驶距离,本设计使用直流电机来模拟出租车行驶,电位器模拟出租车油门状态。为保证电路稳定单独采用5V电源接口,DC电源1引脚通过常开电源开关经电位器连接到直流电机,2、3引脚接地。当按下按钮,电机转动开始模拟出租车运行状态。其具体原理图如图3. 11直流电机电路原理图所示。

     

    图3. 11直流电机电路原理图

    四、软件设计

    4.1 编程语言选择及开发环境

    语言选择主要考虑的是汇编语言和C语言,经过对比C语言更加简洁紧凑、执行效率高、可移植性强,所以本设计程序采用了C语言。

    软件开发环境考虑的有Visual C ++开发调试系统和Keil uVision开发调试系统,通过对比综合平时积累选择了Keil开发环境。Keil是美国Keil Software公司出品的51系列兼容单片机C语言软件开发系统, ,它的源文件既可以是C语言, 也可以是汇编语言,但与汇编相比,C语言在功能、结构性、 可读性、可维护性等方面有明显的优势[8]。Keil集成开发环境包含:编译器、汇编器、实时操作系统、项目管理器、调试器。使用此开发环境可以使软件程序的编写事半功倍。

    本设计通过CH340串口烧写模块实现对单片机程序的烧写。

      1. 软件流程框图

     

    图4.1软件流程总体设计图

    程序开始,准备初始化。设置外部开中断,设置外部定时器中断寄存器(TCON)ITO=1,外部中断为0触发方式,控制位为边缘触发方式(下降沿有效),中断允许寄存器(IE)EXO=1外部中断0允许位,然后开总中断EA=1。然后进行初始化定时器0、1302时钟、延时控制 ,随后通过lcd显示屏显示时间并是否接收到蓝牙模块传送新的时钟信号,如果接收到则更新时间信息。判断电机是否启动,启动后开始计费,计费标准按初始价格=5元,三公里后价格=5+(距离-3)*3每公里按3元计算,LCD显示屏动态显示当前时间、价格,如果电机未启动,表示出租车在未载客状态,LCD显示屏只显示时间和起步费。

    DS1302时钟模块程序流程,首先定义时钟BUF函数为无符号字符型,储存空年月日时分秒周,定义Write_Byte函数向DS1302时钟写入一字节数据,定义Read_Byte函数读出一字节数据,定义从1302读年月日时分秒周的函数。最后定义DS1302初始化函数令DS1302的RST脚置0,SCK脚置0.

     

    图4.2 时钟模块软件流程图

    LCD12864液晶显示模块程序流程,首先定义忙位检测函数,忙则等待。再定义写命令写数据函数。定义液晶屏初始化函数,设置40MS延时,PSB=1设置为8bit并口工作模式,复位置高,选择基本指令集0X30加延时,选择8bit数据流加延时,开显示(无游标、不反白)加延时,清除显示设定地址指针为00H。

     

    图4.3显示模块软件流程图

  • 组装与调试
  • 5.1 实物组装焊接

    实物焊接时首先将5V电源接口焊接在开发板上,为了保证系统工作的稳定性,我们采用2个5v电源接口既单片机系统和电机系统分别使用各自电源。随后将按钮开关(采用按下为1再次按下为零的开关)和5v供电电源连接,以便控制系统的启停。在电机系统的按钮开关后焊接一个型号B10K的电位器,控制电机输入电流大小,以便控制电机的转速。随后按电路原理图依次焊接直流电机、霍尔测测速模块、蓝牙模块、单片机核心模块。焊接完成实物图如图5. 1焊接连接实物图。

     

     

    图5. 1焊接连接实物图

    5.2 通电测试与校准

    实物焊接完成,通电测试。连接usb接口线路,用电压表测量各模块电路电压是否达标。首先测量电源模块5V电压如图5. 2电源模块电压测量图,测量显示为直流4.90V达标。

     

    图5. 2电源模块电压测量图

    测量直流电机模块电源,并且测量电位器是否可以调节电压来影响转速,测量图如图5. 3直流电机模块电压测量图,通过电位器出来电压分别是0.33V、2.37V、4.25V,电压满足条件,达标。

     

    图5. 3直流电机模块电压测量图

    测量蓝牙模块电源电压,第一次测量时显示3.0V,达不到预算值,用电流表的导通档进行检查后发现,电源模块GND接口到蓝牙模块的GND接口存在虚焊,测量电压不稳定,测量蓝牙模块VCC和电源模块GND为4.9V正常电源,重新焊接蓝牙模块GND接口导线,测量恢复正常,如图5. 4蓝牙模块电压测量图。

     

     

    图5. 4蓝牙模块电压测量图

    测量单片机核心系统电压和脉冲接受信号,测量STC89C52单片机的VCC和GND接口,显示直流电压4.90V,达到预定值。测量单片机12号接口P3.2/INTO和GND脉冲信号,符号预定值,如图5. 5单片机电压测量图。

    图5. 5单片机电压测量图

     

    总体测量电压正常,脉冲信号正常,将各模块插入,通电观察,导入程序开始运行,运行一切正常,如图5. 6出租车计价器整体通电图。

     

    图5. 6出租车计价器整体通电图

    5.3 遇到问题及解决方案

    1. 电子电路的设计中对各种影响因素的考虑不够完全,起始电压过大,烧毁直流电机。解决方案:设计一个电位器,将电阻值调到最大,以便保护电路。
    2. 系统设计不够优化,时钟断电时间不能保存数据,每次开机都需重新晓时。解决方案:加装一纽扣电池为时钟电路断电提供电流,以便保存数据
    3. 一个5V供电电压不稳定,直流电机模块耗能高,对单片机电路的稳定性产生影响。解决方案:使用双5V电压模式,分别为电机模块和其他模块供电,保持电路的稳定性。
  • 总结
  • 此篇文章设计是以单片机为核心的出租车计价器设计,详细介绍了计价系统的原理及实现。系统不仅可以进行行驶速度检测、显示总车价,还可以通过电位器调节电机转速来模拟出租车运行状态反映出租车的时速,同时增加了蓝牙调时功能,方便司机对时间的把握。基于单片机的出租车计价器的设计最终实现的功能看似简单,但是在设计时还是遇到了很多问题,好在有老师同学的帮助,这些问题迎刃而解。

    在设计过程中首先清楚自己设计要达成的目的—完成出租车计价。然后为达到这目的我们首先要模拟出出租车运行状态,这时我想到的是用直流电机模拟,用电位器充当油门,实际测试可行。有了出租车转速数据就想着收集转速并转换机器可读的电信号,利用霍尔元件的磁效应可以很好采集电机转速并转换为脉冲信号。计时是出租车不可缺少的功能,我采用DS1302作为计时单元,添加蓝牙模块向单片机发出信号来调整时间,将1302连接备用电池用来断电保存时间,减少时间调整次数。需要选用一功能强大的单片机作为中央处理器,我选择的是STC89C52,功能强大、方便快捷,将采集到的各路信号依次连接到单片机,结合所需功能使用C语言编写程序,仿真调试后导入单片机。通过LCD12864与单片机的连接,观察各路数据是否正常显示,随着电机的运转显示屏上公里数、总价金额是否会变化,实际测试成功。在设计过程中一定要思路清晰,然后一步一步向设计目的靠近,遇到问题及时查阅资料或者向老师请教,好事多磨相信在自己的不断努力下设计肯定可以圆满完成。

    附录一 计价器各个部位原理图设计

     

    附录二、硬件电路清单明细

    序号

    元器件

    型号

    标志

    数量

    1

    CR2032纽扣电池

    CR2032

    BAT1

    1

    2

    无极性电容

    30P

    C1, C2

    2

    3

    DC座(小)

    DC座(小)

    DC1, DC2

    2

    4

    极性电容

    10uF

    EC1

    1

    5

    直流减速电机

    直流减速电机

    J1

    1

    6

    下载口2.54排针

    3pin

    JD1

    1

    7

    LCD12864液晶屏

    LCD12864

    LCD1

    1

    8

    LED灯

    RED

    LED1

    1

    9

    蓝白电位器

    103

    PR1

    1

    10

    单联电位器

    103

    PR2

    1

    11

    电阻

    10K

    R1

    1

    12

    电阻

    1K

    R2

    1

    13

    电阻

    10K

    R3, R4, R5

    3

    14

    按键

    BUTTOM

    S1

    1

    15

    51单片机

    STC89C52

    STC1

    1

    16

    电源开关

    SW-DPDT

    SW1

    1

    17

    电源开关

    SW-DPDT

    SW2

    1

    18

    A3144霍尔模块

    霍尔简易MODE

    U1

    1

    19

    DS1302时钟芯片

    DS1302

    U2

    1

    20

    蓝牙模块

    蓝牙MODE

    U3

    1

    21

    晶振

    11.0592M

    Y1

    1

    22

    晶振

    32.768KHZ

    Y2

    1

    23

    CR2032电池座

    CR2032

    /

    1

    24

    码盘

    码盘

    /

    1

    25

    圆磁铁

    圆磁铁

    /

    1

    26

    焊接线-短线

    红色

    /

    1

    27

    焊接线-短线

    黑色

    /

    1

    28

    胶棒

    固定作用

    /

    4

    29

    2.54单排针

    20pin

    /

    1

    30

    2.54单排座

    4pin

    /

    2

    31

    2.54单排座

    20pin

    /

    1

    32

    IC座

    8pin

    /

    1

    33

    IC座

    40pin

    /

    1

    34

    覆铜板或万用板

    /

    /

    1

    35

    普通USB线

    /

    /

    2

    36

    导线(只万用板有)

    /

    /

    1

    附录三、源程序代码

    #include "system.h"
    
    #include "lcd12864_st7920.h"
    
    #include "delay.h"
    
    #include "ds1302.h"
    
    #include <stdio.h>
    
    
    
    sbit relay = P3^4 ;
    
    sbit buzzer = P2^0 ;
    
    unsigned char xdata dis0[16];//定义显示区域临时存储数组
    
    unsigned char xdata dis1[16];
    
    unsigned char xdata dis2[16];
    
    unsigned char ReadTimeFlag= 0;//读取时间标志
    
    unsigned char SetFlag =0; //时间设置标志
    
    unsigned char i;
    
    
    
    xdata unsigned char firstin =0;   //首次接收到标志
    
    xdata unsigned char tab[20];   //串口数据暂存
    
    xdata unsigned char Count=0;   //串口接收计数
    
    xdata unsigned char  uartbusy =0;   //串口判忙
    
    
    
    unsigned long time_20ms=0; //定时器计数
    
    unsigned char time_buf2[17];   //时间暂存
    
    
    
    float Sudu =0;  //速度值
    
    bit dealSuduFlag =0;  //处理速度标志
    
    xdata unsigned int PluNum = 0; //脉冲数
    
    
    
    xdata float jiaG=0;   //实际价格
    
    xdata float juli=0;  //距离
    
    void main(void)
    
    {
    
    
    
    EX0=1;         //外部中断0开
    
    IT0=1;         //边沿触发
    
        EA=1;          //全局中断开
    
    
    
    Init_Timer0();        //定时器0初始化
    
    UART_Init();
    
    DelayMs(200);          //延时有助于稳定
    
    
    
    Init_ST7920();   //初始化
    
    ClrScreen();
    
    
    
    Ds1302_Init(); //初始化ds1302
    
    
    
    relay =1;    //初始化控制
    
    buzzer =1;
    
    
    
    // Ds1302_Write_Time();
    
    DelayMs(20);
    
    Ds1302_Read_Time();//读取时间参数
    
    
    
    sprintf(dis0,"20%02d-%02d-%02d      ",(int)time_buf1[1],(int)time_buf1[2],(int)time_buf1[3],(int)time_buf1[7]);//年月日周
    
    LCD_PutString(0,1,dis0,16);//显示第时间
    
    
    
    sprintf(dis0,"%02d:%02d:%02d    ",(int)time_buf1[4],(int)time_buf1[5],(int)time_buf1[6]);//时分秒
    
    LCD_PutString(0,2,dis0,16);//显示第时间
    
    
    
    LCD_PutString(0,3,"起:5元   3元/km ",16); //固定显示价格
    
    LCD_PutString(0,4,"实际价格",8);
    
    
    
    uartSendStr("ready ok !",10);
    
    
    
    while(1)
    
    {
    
    if(dealSuduFlag == 1)
    
    {
    
    Sudu=(float)PluNum*0.2*3.6/2; //m/s 20个脉冲为1圈 3s时间进行检测
    
    PluNum=0;
    
    dealSuduFlag=0;
    
    juli = juli+Sudu*0.2; //公里
    
    if(juli<3) //3公里内5元
    
    {
    
    jiaG =5;
    
    }
    
    else
    
    {
    
    jiaG = 5+(juli-3)*3;    //计算价格
    
    }
    
    }
    
    
    
    if(SetFlag==1)     //如果接收到串口信息则更新时钟
    
    {
    
    for(i=0;i<8;i++)
    
    {
    
    time_buf1[i]=time_buf2[2*i]*10+time_buf2[2*i+1];//数据整合,如2个数 1和5整合成15
    
    }
    
    Ds1302_Write_Time();//接收更新的时间然后写入ds1302
    
    SetFlag=0;          //时钟信息更新后标志位清零
    
    }
    
    if(ReadTimeFlag==1) //定时读取ds1302 定时时间到 则标志位置1,处理过时间参数标志位清零
    
    {
    
    ReadTimeFlag=0;  //标志位清零
    
    Ds1302_Read_Time();//读取时间参数
    
    sprintf(dis0,"20%02d-%02d-%02d  %d   ",(int)time_buf1[1],(int)time_buf1[2],(int)time_buf1[3],(int)time_buf1[7]);//年月日周
    
    LCD_PutString(0,1,dis0,16);//显示第时间
    
    
    
    sprintf(dis1,"%02d:%02d:%02d %4.1fkm ",(int)time_buf1[4],(int)time_buf1[5],(int)time_buf1[6],juli);//时分秒
    
    LCD_PutString(0,2,dis1,16);//显示第时间
    
    sprintf(dis2,"%6.1f元",jiaG);//时分秒
    
    LCD_PutString(4,4,dis2,8);//显示第时间
    
    }
    
    }
    
    }
    
    
    
    void ISR_Key(void) interrupt 0 using 1
    
    {
    
    PluNum++; //速度脉冲量计数
    
    }
    
    
    
    void Init_Timer0(void)
    
    {
    
      TMOD |= 0x10;   //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响      
    
    TH0=(65536-20000)/256;   //重新赋值 20ms
    
    TL0=(65536-20000)%256;
    
    EA=1;            //总中断打开
    
    ET0=1;           //定时器中断打开
    
    TR0=1;           //定时器开关打开
    
    }
    
    
    
    void Timer0_isr(void) interrupt 1
    
    {
    
    TH0=(65536-20000)/256;   //重新赋值 20ms
    
    TL0=(65536-20000)%256;
    
    
    
    time_20ms++;
    
    if(time_20ms%30==0)    //定时读取时间标志
    
    {
    
      ReadTimeFlag=1;
    
    if(time_20ms%90==0)  //定时处理速度
    
    {
    
    dealSuduFlag =1;  //处理速度标志置位
    
    }
    
    }
    
    }
    
    
    
    
    
    void UART_Init(void)
    
    {
    
        SCON  = 0x50;         // SCON: 模式 1, 8-bit UART, 使能接收  
    
        TMOD |= 0x20;               // TMOD: timer 1, mode 2, 8-bit 重装
    
        TH1   = 0xF3;               // TH1:  重装值 9600 波特率 晶振 11.0592MHz//**All notes can be deleted and modified**//
    
    TL1 = TH1;  
    
        TR1   = 1;                  // TR1:  timer 1 打开                         
    
        EA    = 1;                  //打开总中断
    
        ES    = 1;                  //打开串口中断
    
    }
    
    
    
    
    
    void uartSendByte(unsigned char dat)
    
    {
    
    unsigned char time_out;
    
    time_out=0x00;
    
    SBUF = dat;   //将数据放入SBUF中
    
    while((!TI)&&(time_out<100))  //检测是否发送出去
    
    {time_out++;DelayUs2x(10);} //未发送出去 进行短暂延时
    
    TI = 0; //清除ti标志
    
    }
    
    
    
    void uartSendStr(unsigned char *s,unsigned char length)
    
    {
    
    unsigned char NUM;
    
    NUM=0x00;
    
    while(NUM<length) //发送长度对比
    
    {
    
    uartSendByte(*s);  //放松单字节数据
    
    s++;   //指针++
    
    NUM++;   //下一个++
    
        }
    
    }
    
    
    
    
    
    void UART_SER (void) interrupt 4 //串行中断服务程序
    
    {
    
    unsigned char r_buf ;
    
    if(RI)                        //判断是接收中断产生
    
    {
    
    RI=0;                      //标志位清零
    
      r_buf =SBUF;                 //读入缓冲区的值
    
    uartbusy = 10;
    
    if(r_buf=='*') //接收到起始标志
    
    {
    
    firstin = 1; //接收标志成功
    
    Count = 0;
    
    tab[Count++]=r_buf;
    
    }
    
    else if(firstin == 1)   //接收到其实标志成功
    
    {
    
    tab[Count++]=r_buf;
    
    if((Count>=18)&&(tab[17] == '#'))
    
    {
    
    for(i=0;i<16;i++)
    
    {
    
      time_buf2[i]=tab[1+i];//**All notes can be deleted and modified**//
    
    }//**All notes can be deleted and modified**//
    
    }
    
    }
    
         SBUF = r_buf; //把接收到的值再发回电脑端
    
    }
    
    if(TI)  //如果是发送标志位,清零
    
    TI=0;
    
    }

    物联沃分享整理
    物联沃-IOTWORD物联网 » 基于C51单片机的出租车计价器设计详解

    发表评论