找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 12457|回复: 7
收起左侧

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

  [复制链接]
ID:321563 发表于 2018-7-7 12:56 | 显示全部楼层 |阅读模式
出租车计价器电路原理图如下:
TIM截图20180707125503.png

实物图:
TIM截图20180707125446.png

单片机源程序:
  1. #include <reg52.h>                 //调用单片机头文件
  2. #define uchar unsigned char  //无符号字符型 宏定义        变量范围0~255
  3. #define uint  unsigned int         //无符号整型 宏定义        变量范围0~65535

  4. uchar d_miao,d_fen = 0,d_shi;
  5. uchar flag_bai_hei;         //白天的晚上的标志位
  6. uchar value;
  7. uint bai_3l_price = 60;        //白天3千米内的单价       6元
  8. uint bai_3w_price = 18;        //白天3千米外的单价/千米         1.8元
  9. uint bai_wait_price = 5;       //白天等待时的单价/分钟         0.5元

  10. uint wan_3l_price = 70;        //晚上3千米内的单价/千米         7元
  11. uint wan_3w_price = 22;        //晚上3千米外的单价/千米         2.2元
  12. uint wan_wait_price = 10;       //晚上等待时的单价/分钟         1元

  13. uint distance = 0;    //行使的距离
  14. uint zong_jia;        //总的价
  15. bit flag_200ms = 0;
  16. bit flag_1s ;
  17. bit flag_time_en = 0;

  18. uchar flag_time_xs = 1;    //显示时间和等待时间切换

  19. sbit beep = P3^7;   //蜂鸣器IO口定义

  20. uchar i;

  21. sbit clk = P1^3;          //ds1302时钟线定义
  22. sbit io =  P1^4;          //数据线
  23. sbit rst = P1^5;          //复位线
  24.                                                 //秒  分   时   日   月  年   星期         
  25. uchar code write_add[]={0x80,0x82,0x84,0x86,0x88,0x8c,0x8a};   //写地址
  26. uchar code read_add[] ={0x81,0x83,0x85,0x87,0x89,0x8d,0x8b};   //读地址
  27. uchar code init_ds[]  ={0x55,0x17,0x15,0x01,0x05,0x15,0x13};   
  28. uchar idata miao,fen,shi,ri,yue,week,nian;

  29. uchar t1_num,t2_num;        //计时间中断的次数
  30. unsigned long  speed1,juli,time2;
  31. float f_hz,speed_km,speed_m;
  32. uchar TH11,TL11;
  33. uchar flag_en;   //开始计算速度使能
  34. uchar flag_stop_en;   //要确定车子是否停下了

  35. uint juli_s;             //每秒走的距离
  36. uint juli_z;         //总路程
  37. float zhijing = 0.75;  //直径 0.55M
  38. bit flag_1s = 1;             //1s
  39. uchar menu_1;        //菜单设置变量
  40. uchar menu_2;        //菜单设置变量
  41. uint shudu;   //定义速度的变量
  42. uint bj_shudu = 80;         //报警速度

  43. uchar flag_ds_en;

  44. long zong_lc;        //总量程


  45. #include "lcd1602.h"

  46. /***********************1ms延时函数*****************************/
  47. void delay_1ms(uint q)
  48. {
  49.         uint i,j;
  50.         for(i=0;i<q;i++)
  51.                 for(j=0;j<120;j++);
  52. }

  53. #include "iic.h"

  54. void write_iic_data()
  55. {
  56.         write_24c02(0,flag_bai_hei);
  57.         write_24c02(1,bai_3l_price % 256);   //保存数据
  58.         write_24c02(2,bai_3l_price / 256);   //保存数据
  59.         write_24c02(3,bai_3w_price % 256);   //保存数据                 
  60.         write_24c02(4,bai_3w_price / 256);   //保存数据               
  61.         write_24c02(5,bai_wait_price % 256);   //保存数据               
  62.         write_24c02(6,bai_wait_price / 256);   //保存数据            
  63.         write_24c02(7,wan_3l_price % 256);   //保存数据
  64.         write_24c02(8,wan_3l_price / 256);   //保存数据
  65.         write_24c02(9,wan_3w_price % 256);   //保存数据                 
  66.         write_24c02(10,wan_3w_price / 256);   //保存数据               
  67.         write_24c02(11,wan_wait_price % 256);   //保存数据               
  68.         write_24c02(12,wan_wait_price / 256);   //保存数据            
  69. }

  70. /****************读出来保存的数据**********************/           
  71. void read_iic_data()
  72. {        
  73.         flag_bai_hei = read_24c02(0);        
  74.         bai_3l_price = read_24c02(2);
  75.         bai_3l_price = bai_3l_price * 256 + read_24c02(1);
  76.         bai_3w_price = read_24c02(4);
  77.         bai_3w_price = bai_3w_price * 256 + read_24c02(3);
  78.         bai_wait_price = read_24c02(6);
  79.         bai_wait_price = bai_wait_price * 256 + read_24c02(5);

  80.         wan_3l_price = read_24c02(8);
  81.         wan_3l_price = wan_3l_price * 256 + read_24c02(7);
  82.         wan_3w_price = read_24c02(10);
  83.         wan_3w_price = wan_3w_price * 256 + read_24c02(9);
  84.         wan_wait_price = read_24c02(12);
  85.         wan_wait_price = wan_wait_price * 256 + read_24c02(11);

  86. }
  87. /********************独立按键程序*****************/
  88. uchar key_can;         //按键值

  89. void key()         //独立按键程序
  90. {
  91.         static uchar key_new;
  92.         key_can = 20;                   //按键值还原
  93.         P3 |= 0x78;                     //对应的按键IO口输出为1
  94.         if((P3 & 0x78) != 0x78)                //按键按下
  95.         {
  96.                 delay_1ms(1);                     //按键消抖动
  97.                 if(((P3 & 0x78) != 0x78) && (key_new == 1))
  98.                 {                                                //确认是按键按下
  99.                         key_new = 0;
  100.                         switch(P3 & 0x78)
  101.                         {
  102.                                 case 0x70:  key_can = 1;  break;         //得到按键值
  103.                                 case 0x68:  key_can = 2;  break;         //得到按键值
  104.                                 case 0x58:  key_can = 3;  break;         //得到按键值
  105.                                 case 0x38:  key_can = 4;  break;         //得到按键值
  106.                         }
  107.                         beep = 0;
  108.                         delay_1ms(50);
  109.                         beep = 1;               
  110.                 }        
  111.         }
  112.         else
  113.                 key_new = 1;        
  114. }
  115. /*************写一个数据到对应的地址里***************/
  116. void write_ds1302(uchar add,uchar dat)
  117. {               
  118.         rst = 1;                         //把复位线拿高
  119.         for(i=0;i<8;i++)
  120.         {                                     //低位在前
  121.                 clk = 0;                 //时钟线拿低开始写数据
  122.                 io = add & 0x01;            
  123.                 add >>= 1;                 //把地址右移一位
  124.                 clk = 1;                 //时钟线拿高
  125.         }        
  126.         for(i=0;i<8;i++)
  127.         {
  128.                 clk = 0;                 //时钟线拿低开始写数据
  129.                 io = dat & 0x01;
  130.                 dat >>= 1;                 //把数据右移一位
  131.                 clk = 1;                 //时钟线拿高
  132.         }
  133.         rst = 0;                         //复位线合低
  134.         clk = 0;
  135.         io = 0;
  136. }

  137. /*************从对应的地址读一个数据出来***************/
  138. uchar read_ds1302(uchar add)
  139. {
  140.         uchar value,i;
  141.         rst = 1;                         //把复位线拿高
  142.         for(i=0;i<8;i++)
  143.         {                                     //低位在前
  144.                 clk = 0;                 //时钟线拿低开始写数据
  145.                 io = add & 0x01;            
  146.                 add >>= 1;                 //把地址右移一位
  147.                 clk = 1;                 //时钟线拿高
  148.         }               
  149.         for(i=0;i<8;i++)
  150.         {
  151.                 clk = 0;                 //时钟线拿低开始读数据
  152.                 value >>= 1;
  153.                 if(io == 1)
  154.                         value |= 0x80;
  155.                 clk = 1;                 //时钟线拿高
  156.         }
  157.         rst = 0;                         //复位线合低
  158.         clk = 0;
  159.         io = 0;
  160.         return value;                 //返回读出来的数据
  161. }



  162. /*************把要的时间 年月日 都读出来***************/
  163. void read_time()
  164. {
  165.         miao = read_ds1302(read_add[0]);        //读秒
  166.         fen  = read_ds1302(read_add[1]);        //读分
  167.         shi  = read_ds1302(read_add[2]);        //读时
  168.         ri   = read_ds1302(read_add[3]);        //读日
  169.         yue  = read_ds1302(read_add[4]);        //读月
  170.         nian = read_ds1302(read_add[5]);        //读年
  171.         week = read_ds1302(read_add[6]);        //读星期
  172. }

  173. /*************把要写的时间 年月日 都写入ds1302里***************/
  174. void write_time()
  175. {
  176.         write_ds1302(write_add[0],miao);        //写秒
  177.         write_ds1302(write_add[1],fen);                //写分
  178.         write_ds1302(write_add[2],shi);                //写时
  179.         write_ds1302(write_add[3],ri);                //写日
  180.         write_ds1302(write_add[4],yue);                //写月
  181.         write_ds1302(write_add[5],nian);        //写星期
  182.         write_ds1302(write_add[6],week);        //写年
  183. }


  184. /**********************设置ds1302时间函数**********************/
  185. void set_ds1302time(uchar num,uchar *shi,uchar dat)         //调时
  186. {
  187.           if(num == 1)
  188.     {
  189.             *shi+=0x01;
  190.                 if((*shi & 0x0f) >= 0x0a)
  191.                         *shi = (*shi & 0xf0) + 0x10;
  192.                 if(*shi >= dat)
  193.                         *shi = 0;
  194.     }
  195.     else
  196.     {
  197.                 if(*shi == 0x00)
  198.                         *shi = dat;
  199.                 if((*shi & 0x0f) == 0x00)
  200.                         *shi = (*shi | 0x0a) - 0x10;
  201.                 *shi -=0x01 ;
  202.     }  
  203. }


  204. #include "menu.h"


  205. /*********************对应菜单内的处理函数******************/
  206. void menu_dis()
  207. {
  208.         if(menu_1 == 0)
  209.         {
  210.                 if(key_can == 2)                   //清零 从新计价
  211.                 {
  212.                         flag_time_en = 0;        
  213.                         d_shi = 0;
  214.                         d_fen = 0;
  215.                         flag_ds_en = 0;
  216.                 }
  217.                 if(key_can == 4)         //时间和等待的时间的切换
  218.                 {
  219.                         flag_time_xs ++;    //为1显示当前时间
  220.                         if(flag_time_xs > 2)        
  221.                                 flag_time_xs = 0;

  222.                         if(flag_time_xs == 0)        //显示时间
  223.                         {
  224.                                 write_string(1,0,"    :  :    W:  ");                        
  225.                                 write_string(2,0," 20  -  -       ");        
  226.                         }
  227.                 }
  228.                 if(flag_200ms == 1)
  229.                 {
  230.                         if(distance <= 30)//3公里内的价格
  231.                         {
  232.                                 if(flag_bai_hei == 0)
  233.                                 {
  234.                                         if((d_fen == 0) && (d_miao <= 10))
  235.                                                 zong_jia = bai_3l_price;
  236.                                         else
  237.                                                 zong_jia = bai_3l_price + (d_shi * 60*60 +  d_fen*60 + d_miao) * bai_wait_price -bai_wait_price*10;        
  238.                                 }                                
  239.                                 else
  240.                                 {
  241.                                         if((d_fen == 0) && (d_miao <= 10))
  242.                                                 zong_jia = wan_3l_price;
  243.                                         else
  244.                                                 zong_jia = wan_3l_price + (d_shi * 60*60 +  d_fen*60 + d_miao) * wan_wait_price -bai_wait_price*10;
  245.                                 }
  246.                                        
  247.                         }else                          //3公里外的价格
  248.                         {
  249.                                 if(flag_bai_hei == 0)
  250.                                 {
  251.                                         if((d_fen == 0) && (d_miao <= 10))
  252.                                                 zong_jia = bai_3l_price + bai_3w_price * (distance - 30) / 10 ;
  253.                                         else
  254.                                                 zong_jia = bai_3l_price + bai_3w_price * (distance - 30) / 10 + (d_shi * 60*60 +  d_fen*60 + d_miao) *  bai_wait_price -bai_wait_price*10;
  255.                                 }
  256.                                 else
  257.                                 {
  258.                                         if((d_fen == 0) && (d_miao <= 10))
  259.                                                 zong_jia = wan_3l_price + wan_3w_price * (distance - 30) / 10 ;        
  260.                                         else
  261.                                                 zong_jia = wan_3l_price + wan_3w_price * (distance - 30) / 10 + (d_shi * 60*60 +  d_fen*60 + d_miao) *  wan_wait_price -bai_wait_price*10;        
  262.                                 }
  263.                         }
  264.                         if(flag_time_xs == 1)          //显示当前的时间
  265.                         {
  266.                                 write_sfm2_ds1302(2,0,shi);  //显示时        
  267.                                 write_data(':');   
  268.                                 write_sfm2_ds1302(2,6,miao); //显示秒
  269.                                 write_sfm4(2,10,zong_jia);

  270.                                 write_sfm2(1,1,shudu);               
  271.                                 write_sfm4(1,9,juli_z);        

  272.                         }
  273.                         else if(flag_time_xs == 2)            //显示等待时间
  274.                         {
  275.                                 write_sfm2(2,1,d_fen);  //显示分
  276.                                 write_data(':');   
  277.                                 write_sfm2(2,4,d_miao); //显示秒
  278.         
  279.                                 write_sfm2(1,1,shudu);               
  280.                                 write_sfm4(1,9,juli_z);        
  281.                         }
  282.                         else    //显示当前的时间
  283.                         {
  284.                                 write_sfm2_ds1302(1,2,shi);           //显示时
  285.                                 write_sfm2_ds1302(1,5,fen);           //显示分
  286.                                 write_sfm2_ds1302(1,8,miao);        //显示秒
  287.                                 write_sfm1(1,14,week);                           //显示星期                                       
  288.                                 write_sfm2_ds1302(2,6,yue);           //显示月
  289.                                 write_sfm2_ds1302(2,9,ri);           //显示日
  290.                
  291.                         }
  292.                 }
  293.         }
  294. }

  295. /*******************停车计时函数 *****************/
  296. void jishu_chashu()
  297. {        
  298.         if((flag_1s == 1) && (flag_time_en == 1))
  299.         {
  300.                 if(flag_ds_en == 1)
  301.                 {
  302.                         d_miao++;                        //秒钟加1
  303.                         if(d_miao >= 60)
  304.                         {
  305.                                 d_miao = 0;
  306.                                 d_fen ++;                //分钟加1
  307.                                 if(d_fen >= 60)
  308.                                 {
  309.                                         d_fen = 0;
  310.                                         d_shi++;
  311.                                         if(d_shi >= 24)
  312.                                         {
  313.                                                 d_shi = 0;
  314.                                         }
  315.                                 }
  316.                         }
  317.                 }               
  318.         }
  319. }


  320. /*************定时器0初始化程序***************/
  321. void time_init()         
  322. {
  323.         EA   = 1;                   //开总中断
  324.         TMOD = 0X11;          //定时器0、工作方式1
  325.         ET0  = 1;                  //开定时器0中断
  326.         TR0  = 1;                  //允许定时器0定时
  327.         ET1  = 1;                  //开定时器1中断
  328.         TR1  = 1;                  //允许定时器1定时
  329. }


  330. /***********外部中断0初始化程序****************/
  331. void init_int0()
  332. {
  333.         EX0=1;                          //允许外部中断0中断
  334.         EA=1;                           //开总中断
  335.         IT0 = 1;                   //外部中断0负跳变中断
  336. }

  337. /***********计算速度函数**************/
  338. void shudu_dis()          //计算速度函数
  339. {
  340.         static uchar value,value1;
  341.         if(menu_1 == 0)
  342.         {        
  343.                 if(flag_1s == 1)   
  344.                 {        
  345.                         flag_1s = 0;                 
  346.                         if(flag_en == 0)
  347.                         {
  348.                                 value ++;
  349.                                 if(value >= 3)        //2秒
  350.                                 {        
  351.                                         speed_km = 0;  //速度为0
  352.                                         shudu = (uint)speed_km;        
  353.                                         value = 0;        
  354.                                         flag_time_en = 1;                        
  355.                                 }
  356.                         }
  357.                         if((flag_en == 1))
  358.                         {        
  359.                                 value = 0;               
  360.                                 flag_en = 0;         
  361.                                  //1s = 1 / 1000000us;          // 1m/s=0.001km除以1/3600h=3.6km/h                        
  362.                                 f_hz =(t2_num * 65536.0 + TH11 * 256 + TL11)  / 1000000;  //算出来就是秒
  363.                                 speed_m = f_hz * zhijing * 3.14  ;        //算出来的是m/s
  364.                                 juli_z = (juli_z + (uint)speed_m) ;        //总路程m        
  365.                                 speed_km = speed_m * 3.6 ;        //(带个小数点) km/s               
  366.                             shudu = (uint)speed_km;
  367.                                 zong_lc += speed_m;
  368.                                 distance = juli_z;
  369.                                 value1++;
  370.                                 flag_time_en = 0;
  371.                         }               
  372.                 }
  373.         }
  374. }
  375. /******************主函数*******************/
  376. void main()
  377. {
  378.         P0 = P1 = P2 = P3 = 0XFF;          //让IO口全部输出高电平
  379.         init_1602();                                  //初始化1602液晶
  380.         init_1602_dis_csf();                   //初始化1602液晶显示
  381.         read_iic_data();                          //把保存的数据读出来
  382.         time_init();                                  //定时器初始化
  383.         init_int0();
  384.         while(1)
  385.         {
  386.                 key();                                          //按键程序
  387.                 menu_dis();        
  388.                 if(key_can < 20)
  389.                         key_with();
  390.                 shudu_dis();          //计算速度函数
  391.                 if(flag_200ms == 1)
  392.                 {
  393.                         flag_200ms = 0;

  394.                         if(menu_1 == 0)
  395.                                 read_time();                  //读时间
  396.                         if((shi >= 0x21) || (shi <= 5))
  397.                                 flag_bai_hei = 1;     //晚上模式
  398.                         else                                                         
  399.                                 flag_bai_hei = 0;  //白天模式
  400.                 }
  401.         }
  402. }

  403. /*************定时器0中断服务程序***************/
  404. void time0_int() interrupt 1
  405. {        
  406.         static uchar value;
  407.         TH0 = 0x3c;
  408.         TL0 = 0xb0;     // 50ms
  409.         value ++;
  410.         if(value % 4 == 0)
  411.                 flag_200ms = 1;
  412.         if(value >= 20)
  413.         {
  414.                 flag_1s = 1;
  415.                 value = 0;
  416.                 jishu_chashu();
  417.         }

  418. }


  419. /*********************外部中断0中断服务程序************************/
  420. void int0() interrupt 0
  421. {
  422.         static uchar value;
  423.         switch(value)
  424.         {
  425.                 case 0:
  426.                         t1_num = 0;                 //第一次就把变量清零
  427.                         TH1 = 0;
  428.                         TL1 = 0;
  429.                         break;
  430.                 case 1:
  431.                                 t2_num = t1_num;  //保存
  432.                                 TH11 = TH1;
  433.                                 TL11 = TL1;
  434.                                 flag_en = 1;
  435.                         break;
  436.         }               
  437.         value ++;
  438.         if(value >= 2)
  439.                 value =0;
  440. }

  441. /*************定时器1中断服务程序***************/
  442. void time1_int() interrupt 3
  443. {
  444.         t1_num++;
  445. }


复制代码

评分

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

查看全部评分

回复

使用道具 举报

ID:436272 发表于 2018-11-30 15:08 | 显示全部楼层
求PCB加原理图啊
回复

使用道具 举报

ID:657581 发表于 2019-12-6 15:07 | 显示全部楼层
你好大神 这个原理图有bom吗 我是新手
回复

使用道具 举报

ID:707219 发表于 2020-3-12 18:19 | 显示全部楼层
程序运行有错啊????
回复

使用道具 举报

ID:421783 发表于 2020-4-3 23:16 | 显示全部楼层
uchar key_can;        这个是什么意思 求大佬告知
回复

使用道具 举报

ID:769774 发表于 2020-6-5 12:16 | 显示全部楼层
#include "lcd1602.h"
#include "iic.h"
#include "menu.h"

这三个源文件可以发一下吗
回复

使用道具 举报

ID:778730 发表于 2020-6-14 09:50 来自手机 | 显示全部楼层
有仿真吗?
回复

使用道具 举报

ID:900242 发表于 2021-4-3 11:25 | 显示全部楼层
求各部分的原理图
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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