找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 10460|回复: 3
收起左侧

基于单片机控制的出租车计价器Proteus仿真程序设计

[复制链接]
ID:775278 发表于 2020-10-18 12:04 | 显示全部楼层 |阅读模式
本次出租车计价器设计以AT89C52单片机为中心,采用AMPIRE28*64液晶屏显示出租车计价单价、里程数和金额;采用时钟芯片DS1302来显示时间和在系统需要时进行计时。其中有三个按键代表“开始/暂停”、“清零”和设置“白天/黑夜”。
实验要求
基本功能
1)显示: 可以显示 单价、里程、总金额
2)停车计费功能:中途因故停车超过5分钟后每分钟按当时单价的50%收费
3)自动分时计费功能:白天和夜间应能自动更换单价
4)性能  里程误差小于2%
扩展功能
1)可增加时钟功能
2)可增加数据掉电保护功能
已完成显示、分时计费、时钟三个功能,另外增添了暂停和清零功能。

仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)

原理图

原理图
AMPIRE128*64液晶显示屏
单片机1.png
按键电路的设计
单片机2.png


话不多说,直接上单片机代码
  1. #include<reg52.h>
  2. #include<intrins.h>
  3. #include"lcd12864.c"
  4. #include"code.h"
  5. #include"ds1302.c"
  6. #include"display.c"
  7. sbit P34=P3^4;        //按钮
  8. sbit P33=P3^3;        //按钮
  9. sbit P12=P1^2;        //灯
  10. float p,price,distance_km,money;   //路程,金额
  11. unsigned int b,n;
  12. bit flag=1;
  13. voidmain(void)     //主函数
  14. {
  15.        init_lcd();               //液晶显示屏
  16.        clearscreen(0);        //清屏
  17.        setline(0);               //起始行
  18.        TMOD=0x01;         //方式1 定时功能
  19.        TH0=0x3c;             //00111100
  20.        TL0=0xaf;              //10101111      50ms计数一次
  21.        IE=0x87;
  22.        IT0=1;
  23.        IP=0x01;
  24.        distance_km=0;        //路程=0
  25.        Init_DS1302();       //时钟芯片
  26.        while(1)
  27.        {
  28.        if(flag)
  29.        {
  30.               TR0=0;
  31.               P12=1;
  32.               price=p;
  33.               display(price);
  34.               display1(distance_km);   //显示路程
  35.               display2(money);          //显示金额
  36.        }
  37.        else
  38.        {
  39.               TR0=1;     //T0中断
  40.               P12=0;      //灯亮
  41.               price=p;
  42.               display(price);
  43.               display1(distance_km);   //显示路程
  44.               display2(money);          //显示金额
  45.        }
  46.               displayc(1,0,0*16,dan);          //显示“单”
  47.               displayc(1,0,1*16,jia);       //显示“价”
  48.               displaye(1,0,4*8,num,15);       //显示“:”
  49.               displayc(1,3,0*16,li);        //显示“里”
  50.               displayc(1,3,1*16,chen);    //显示“程”
  51.               displayc(1,3,2*16,shu);          //显示“数”
  52.               displaye(1,3,6*8,num,15);       //显示“:”
  53.               displayc(1,6,0*16,jin);           //显示“金”
  54.               displayc(1,6,1*16,e);        //显示“额”
  55.               displaye(1,6,4*8,num,15);       //显示“:”              
  56.        }
  57. }
  58. void timer1(void)interrupt 1               //定时器0中断
  59. {
  60.        TH0=0x3c;             //00111100
  61.        TL0=0xaf;              //10101111      50ms计数一次
  62.        b++;
  63.        if(b==10)
  64.        {
  65.               if(P34==1)
  66.               {
  67.                      p=1.5;
  68.                      distance_km+=0.1;                //路程+0.1
  69.                      if(distance_km<=3)money=5;        //小于3km,计价5元
  70.                             elsemoney=4.9+(distance_km-3)*p;    //大于3km部分1.5元每km
  71.                      b=0;
  72.               }
  73.               else
  74.               {
  75.                      p=2;
  76.                      distance_km+=0.1;                //路程+0.1
  77.                      if(distance_km<=3)money=6;        //小于3km,计价6元
  78.                      elsemoney=5.9+(distance_km-3)*p;    //大于3km部分2元每km
  79.                      b=0;
  80.               }
  81.        }
  82. }
  83. void timer0(void)interrupt 0           //外部中断0  按键1
  84. {
  85.        flag=~flag;
  86. }     
  87. void timer2(void)interrupt 2                //外部中断1  按键2
  88. {
  89.        distance_km=0;        //路程=0
  90.        money=0;
  91.        price=p;
  92. }     
  93. LCD12864.C
  94. #include<reg52.h>
  95. #include<intrins.h>
  96. #define uchar unsigned char
  97. #define uint unsigned int
  98. sbit cs1=P2^0;
  99. sbit cs2=P2^1;
  100. sbit EN=P2^2;
  101. sbit RW=P2^3;
  102. sbit RS=P2^4;
  103. void delay(uchar i)
  104. {
  105.        while(i--);              //延时
  106. }
  107. void readbusy()         //忙碌
  108. {
  109.        P0=0x00;   //00000000
  110.        RS=0;      
  111.        RW=1;      //读出忙标志(BF)及地址记数器(AC)的状态
  112.        EN=1;       //读写使能,下降沿锁定数据
  113.        while(P0&0x80);     //当BF=0,while(0),当BF=1,while(1)
  114.        EN=0;            //EN=1-0,配合RW写数据或指令
  115. }
  116. void lcd_wcmd(uchar cmd)
  117. {
  118.        readbusy();       //判断忙碌
  119.        RS=0;
  120.        RW=0;            //MPU写指令到指令暂存器
  121.        P0=cmd;         
  122.        EN=1;             //配合RS进行读数据或指令
  123.        _nop_();    //延时2个指令周期
  124.        _nop_();
  125.        EN=0;             //EN=1-0,配合RW写数据或指令
  126. }
  127. void lcd_wdat(uchar dat)
  128. {
  129.        readbusy();            //判断忙碌
  130.        RS=1;
  131.        RW=0;            //MPU写数据到数据暂存器
  132.        P0=dat;
  133.        EN=1;             //配合RS进行读数据或指令
  134.        _nop_();    //延时2个指令周期
  135.        _nop_();
  136.        EN=0;             //EN=1-0,配合RW写数据或指令
  137. }
  138. void setpage(uchar page)
  139. {
  140.        page=0xb8|page;    //起始页         10111000
  141.        lcd_wcmd(page);       //写指令
  142. }
  143. void setline(uchar line)
  144. {
  145.                                                          
  146.        line=line&0x3f;        //最终行  00000111
  147.        line=line|0xc0;    //起始行    11000000
  148.        lcd_wcmd(line);        //写指令
  149. }
  150. void setcolumn(uchar column)
  151. {
  152.        column=column&0x3f;   //最终列       00111111
  153.        column=column|0x40;   //起始列         01000000
  154.        lcd_wcmd(column);        //写指令
  155. }
  156. void setonoff(uchar onoff)
  157. {
  158.        onoff=0x3e|onoff;   //00111110
  159.        lcd_wcmd(onoff);    //写指令
  160. }
  161. void selectscreen(uchar screen)            //选择屏幕
  162. {
  163.        switch(screen)
  164. {
  165.        case0:cs1=0;delay(2);cs2=0;delay(2);break;        //全屏
  166.        case1:cs1=0;delay(2);cs2=1;delay(2);break;        //左屏
  167.        case2:cs1=1;delay(2);cs2=0;delay(2);break;        //右屏
  168.        default:break;
  169. }
  170. }
  171. void clearscreen(uchar screen)        //清屏
  172. {
  173.        uchari,j;
  174.        selectscreen(screen);               //选屏
  175.        for(i=0;i<8;i++)
  176.        {
  177.               setpage(i);                      //0-7页
  178.               setcolumn(0);          //起始行
  179.               for(j=0;j<64;j++)
  180.               {
  181.                      lcd_wdat(0x00);            //写数据 0-63
  182.               }
  183.        }
  184. }
  185. void init_lcd()
  186. {
  187.        readbusy();
  188.        selectscreen(0);       //全屏
  189.        setonoff(0);            //关
  190.        selectscreen(0);       //全屏
  191.        setonoff(1);            //开
  192.        selectscreen(0);       //全屏
  193.        clearscreen(0);               //清屏
  194.        setline(0);                      //起始行
  195. }
  196. Code.h
  197. unsigned char code dan[]={0x00,0x00,0x00,0xf8,0x4b,0x4e,0x4c,0xf8,0x4c,0x4e,0x4b,0xf8,0x00,0x00,0x00,0x00,
  198. 0x00,0x08,0x08,0x0b,0x0a,0x0a,0x0a,0xff,0x0a,0x0a,0x0a,0x0b,0x08,0x08,0x00,0x00};
  199. unsigned char code jia []={0x00,0x20,0x30,0x18,0xfc,0x07,0x20,0x30,0xf8,0x0c,0x07,0x0c,0xf8,0x30,0x20,0x00,
  200. 0x00,0x00,0x00,0x00,0xff,0x00,0xf0,0x1c,0x07,0x00,0x00,0x00,0xff,0x00,0x00,0x00};
  201. unsigned char code li []={0x00,0x00,0xFE,0x92,0x92,0x92,0x92,0xFE,0x92,0x92,0x92,0x92,0xFE,0x00,0x00,0x00,
  202. 0x40,0x40,0x44,0x44,0x44,0x44,0x44,0x7F,0x44,0x44,0x44,0x44,0x44,0x40,0x40,0x00};
  203. unsigned char code chen []={0x24,0x24,0xA4,0xFE,0x23,0x22,0x00,0x3E,0x22,0x22,0x22,0x22,0x22,0x3E,0x00,0x00,
  204. 0x08,0x06,0x01,0xFF,0x01,0x06,0x40,0x49,0x49,0x49,0x7F,0x49,0x49,0x49,0x41,0x00};
  205. unsigned char code shu []={0x90,0x52,0x34,0x10,0xFF,0x10,0x34,0x52,0x80,0x70,0x8F,0x08,0x08,0xF8,0x08,0x00,
  206. 0x82,0x9A,0x56,0x63,0x22,0x52,0x8E,0x00,0x80,0x40,0x33,0x0C,0x33,0x40,0x80,0x00};
  207. unsigned char code jin []={0x00,0x80,0x80,0x40,0x20,0x50,0x48,0x44,0xC3,0x44,0x48,0x50,0x20,0x40,0x80,0x80,
  208. 0x00,0x40,0x40,0x42,0x4A,0x72,0x42,0x42,0x7F,0x42,0x42,0x62,0x5A,0x42,0x40,0x40};
  209. unsigned char code e []={0x00,0x00,0x8C,0x44,0xB5,0x26,0xA4,0x64,0x0C,0x02,0xF2,0x1A,0xD6,0x12,0xF2,0x02,
  210. 0x00,0x10,0x08,0xFC,0x4A,0x49,0x4A,0xFC,0x08,0x80,0x4F,0x30,0x0F,0x10,0x2F,0xC0};
  211. unsigned char code gong []={0x00,0x00,0x80,0x40,0x20,0x18,0x06,0x80,0x00,0x07,0x18,0x20,0x40,0x80,0x00,0x00,
  212. 0x00,0x01,0x00,0x20,0x70,0x28,0x26,0x21,0x20,0x20,0x24,0x38,0x60,0x00,0x01,0x01};
  213. unsigned char code yuan []={0x00,0x20,0x20,0x22,0x22,0x22,0xE2,0x22,0x22,0x22,0xE2,0x22,0x22,0x22,0x20,0x20,
  214. 0x00,0x80,0x40,0x20,0x10,0x0C,0x03,0x00,0x00,0x00,0x3F,0x40,0x40,0x40,0x40,0x78};
  215. unsigned int code num[16][16]=
  216. {
  217.        {0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x0F,0x10,0x20,0x20,0x10,0x0F,0x00},  //0
  218.        {0x00,0x10,0x10,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00},  //1
  219.        {0x00,0x70,0x08,0x08,0x08,0x88,0x70,0x00,0x00,0x30,0x28,0x24,0x22,0x21,0x30,0x00},   //2
  220.        {0x00,0x30,0x08,0x88,0x88,0x48,0x30,0x00,0x00,0x18,0x20,0x20,0x20,0x11,0x0E,0x00},  //3
  221.        {0x00,0x00,0xC0,0x20,0x10,0xF8,0x00,0x00,0x00,0x07,0x04,0x24,0x24,0x3F,0x24,0x00},  //4
  222.        {0x00,0xF8,0x08,0x88,0x88,0x08,0x08,0x00,0x00,0x19,0x21,0x20,0x20,0x11,0x0E,0x00},  //5
  223.        {0x00,0xE0,0x10,0x88,0x88,0x18,0x00,0x00,0x00,0x0F,0x11,0x20,0x20,0x11,0x0E,0x00},  //6
  224.        {0x00,0x38,0x08,0x08,0xC8,0x38,0x08,0x00,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x00},  //7
  225.        {0x00,0x70,0x88,0x08,0x08,0x88,0x70,0x00,0x00,0x1C,0x22,0x21,0x21,0x22,0x1C,0x00},  //8
  226.        {0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x00,0x31,0x22,0x22,0x11,0x0F,0x00},  //9
  227.        {0x00,0x10,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x7F,0x48,0x0C,0x53,0x61,0x41},  //k
  228.        {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x7F,0x41,0x01,0x7F,0x41,0x01,0x7E},  //m
  229.        {0x00,0x00,0x00,0x80,0xe0,0x38,0x0f,0x00,0x00,0xf0,0x1c,0x07,0x00,0x00,0x00,0x00},    // /
  230.        {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01},   // -
  231.        {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,0x00,0x00},   //   .
  232.        {0x00,0x00,0x00,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x61,0x00,0x00,0x00}}; //   :
  233. Display.c
  234. void displayc(unsigned char screen,unsignedchar page,unsigned char column,unsigned char table[])  //写汉字
  235.                         //选择屏幕,页,列,数组
  236. {
  237.        unsignedchar i;
  238.        selectscreen(screen);       //选择屏幕
  239.        setpage(page);                //选择页
  240.        setcolumn(column);               //选择列
  241.        for(i=0;i<16;i++)//上半部分
  242.        {
  243.               lcd_wdat(table);_nop_();   //写数据 0-15
  244.        }
  245.        setpage(page+1);            //页+1
  246.        setcolumn(column);               //选择列
  247.        for(i=0;i<16;i++)//下半部分
  248.        {
  249.               lcd_wdat(table[i+16]);_nop_();           //写数据 16-31
  250.        }
  251. }
  252. void displaye(unsigned char screen,unsignedchar page,unsigned char column,unsigned int table[][16],unsigned char n)        //写数字
  253.                        //选择左右屏幕,页,列,数组,数字/汉字
  254. {
  255.        unsignedchar i;
  256.        selectscreen(screen);       //选择屏幕
  257.        setpage(page);                //选择页
  258.        setcolumn(column);               //选择列
  259.        for(i=0;i<8;i++)             //上半部分
  260.        {
  261.               lcd_wdat(table[n]);_nop_();        //选择第n行,i 0-7循环显示一个数字
  262.        }
  263.        setpage(page+1);            //页+1
  264.        setcolumn(column);               //选择列
  265.        for(i=0;i<8;i++)             //下半部分
  266.        {
  267.               lcd_wdat(table[n][i+8]);_nop_();   //选择第n行,i 8-15循环显示一个数字
  268.        }
  269. }
  270. void display(float price)   //单价
  271. {
  272.        unsignedchar x,y,n;
  273.        n=(int)(price);
  274.        x=n;
  275.        y=(price-n)*10;
  276.        displaye(1,0,6*8,num,x);
  277.        displaye(1,0,7*8,num,14);
  278.        displaye(2,0,0*8,num,y);
  279.        displayc(2,0,1*8,yuan);
  280.        displaye(2,0,3*8,num,12);
  281.        displayc(2,0,2*16,gong);
  282.        displayc(2,0,3*16,li);
  283. }
  284. void display1(float distance_km)   //显示路程
  285. {
  286.        unsignedchar counta,countb,countc,countd,n;
  287.        n=(int)(distance_km);       //强行转换成整型
  288.        counta=n/100;
  289.        countb=n%100/10;
  290.        countc=n%10;
  291.        countd=(distance_km-n)*10;
  292.        displaye(1,3,7*8,num,counta);      
  293.        displaye(2,3,0*8,num,countb);
  294.        displaye(2,3,1*8,num,countc);
  295.        displaye(2,3,2*8,num,14);
  296.        displaye(2,3,3*8,num,countd);
  297.        displayc(2,3,2*16,gong);
  298.        displayc(2,3,3*16,li);
  299. }
  300. void display2(float money)      //金额
  301. {
  302.        unsignedchar a,b,c,d,n;
  303.        n=(int)(money);
  304.        a=n/100;
  305.        b=n%100/10;
  306.        c=n%10;
  307.        d=(money-n)*10;
  308.        displaye(2,6,1*8,num,a);
  309.        displaye(2,6,2*8,num,b);
  310.        displaye(2,6,3*8,num,c);
  311.        displaye(2,6,4*8,num,14);
  312.        displaye(2,6,5*8,num,d);
  313.        displayc(2,6,3*16,yuan);
  314. }
复制代码

单片机综合实验51hei.docx (554.39 KB, 下载次数: 100)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:861430 发表于 2020-12-18 10:37 | 显示全部楼层
代码有错
回复

使用道具 举报

ID:964826 发表于 2021-9-9 11:06 来自手机 | 显示全部楼层
你这仿真图似曾相识
回复

使用道具 举报

ID:1036107 发表于 2022-6-23 09:35 | 显示全部楼层
#为什么我在proteus上面运行了你的程序,他那个LCD1不亮,是因为什么呀#
回复

使用道具 举报

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

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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