找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2907|回复: 1
打印 上一主题 下一主题
收起左侧

单片机计程车计价器程序+Proteus仿真

[复制链接]
跳转到指定楼层
楼主
大家可以参考一下
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)


单片机源程序如下:
  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. uchar i;

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



  28. #include "lcd1602.h"

  29. /***********************1ms延时函数*****************************/
  30. void delay_1ms(uint q)
  31. {
  32.         uint i,j;
  33.         for(i=0;i<q;i++)
  34.                 for(j=0;j<120;j++);
  35. }

  36. #include "iic.h"

  37. void write_iic_data()
  38. {
  39.         write_24c02(0,flag_bai_hei);
  40.         delay_1ms(10);       
  41.         write_24c02(1,bai_3l_price % 256);   //保存数据
  42.         delay_1ms(10);       
  43.         write_24c02(2,bai_3l_price / 256);   //保存数据
  44.         delay_1ms(10);       
  45.         write_24c02(3,bai_3w_price % 256);   //保存数据                 
  46.         delay_1ms(10);       
  47.         write_24c02(4,bai_3w_price / 256);   //保存数据               
  48.         delay_1ms(10);       
  49.         write_24c02(5,bai_wait_price % 256);   //保存数据               
  50.         delay_1ms(10);       
  51.         write_24c02(6,bai_wait_price / 256);   //保存数据            
  52.         delay_1ms(10);       
  53.         write_24c02(7,wan_3l_price % 256);   //保存数据
  54.         delay_1ms(10);       
  55.         write_24c02(8,wan_3l_price / 256);   //保存数据
  56.         delay_1ms(10);       
  57.         write_24c02(9,wan_3w_price % 256);   //保存数据                 
  58.         delay_1ms(10);       
  59.         write_24c02(10,wan_3w_price / 256);   //保存数据               
  60.         delay_1ms(10);       
  61.         write_24c02(11,wan_wait_price % 256);   //保存数据               
  62.         delay_1ms(10);       
  63.         write_24c02(12,wan_wait_price / 256);   //保存数据            
  64.         delay_1ms(10);       
  65. }

  66. /****************自动初始化保存的数据*******************/          
  67. void zidong_chud_shifa_iic()
  68. {
  69.         static uchar value;
  70. //        value = read_24c02(100);
  71.         value = read_24c02(100);
  72.         if(value != 47)                                        //新的单片机初始单片机内问EEPOM
  73.         {
  74.                 value = 47;
  75.                 bai_3l_price = 60;        //白天3千米内的单价       6元
  76.                 bai_3w_price = 18;        //白天3千米外的单价/千米         1.8元
  77.                 bai_wait_price = 5;       //白天等待时的单价/分钟         0.5元
  78.                
  79.                 wan_3l_price = 70;        //晚上3千米内的单价/千米         7元
  80.                 wan_3w_price = 22;        //晚上3千米外的单价/千米         2.2元
  81.                 wan_wait_price = 10;       //晚上等待时的单价/分钟         1元

  82.                 write_iic_data();
  83.                 write_24c02(100,value);   //保存数据
  84.         }
  85.         delay_1ms(500);       
  86. }

  87. /****************读出来保存的数据**********************/          
  88. void read_iic_data()
  89. {       
  90.         flag_bai_hei = read_24c02(0);       
  91.         bai_3l_price = read_24c02(2);
  92.         bai_3l_price = bai_3l_price * 256 + read_24c02(1);
  93.         bai_3w_price = read_24c02(4);
  94.         bai_3w_price = bai_3w_price * 256 + read_24c02(3);
  95.         bai_wait_price = read_24c02(6);
  96.         bai_wait_price = bai_wait_price * 256 + read_24c02(5);

  97.         wan_3l_price = read_24c02(8);
  98.         wan_3l_price = wan_3l_price * 256 + read_24c02(7);
  99.         wan_3w_price = read_24c02(10);
  100.         wan_3w_price = wan_3w_price * 256 + read_24c02(9);
  101.         wan_wait_price = read_24c02(12);
  102.         wan_wait_price = wan_wait_price * 256 + read_24c02(11);

  103. }

  104. /****************独立按键处理函数************************/          
  105. uchar key_can;

  106. //按键处理函数
  107. sbit Key1        =        P3^4;//时间清零/确定
  108. sbit Key2        =        P3^2;//减小
  109. sbit Key3        =        P3^0;//路程增加
  110. sbit Key4        =        P1^7;//增加
  111. sbit Key5        =        P1^3;//设置
  112. sbit Key6        =        P1^5;//路程清零
  113. //返回按键值
  114. //mode:0,不支持连续按;1,支持连续按;
  115. //0,没有任何按键按下
  116. //1,KEY0按下
  117. //2,KEY1按下
  118. //3,KEY2按下
  119. //4,KEY3按下 WK_UP
  120. //注意此函数有响应优先级,KEY0>KEY1>KEY2>KEY3!!
  121. //========================================================================
  122. // 函数: uchar Key_Scan()
  123. // 应用: temp=uchar Key_Scan();
  124. // 描述: 按键扫描并返回按下的键值
  125. // 参数: NONE
  126. // 返回: 按下的键值
  127. // 版本: VER1.0
  128. // 日期: 2015-05-29
  129. // 备注: 该函数带松手检测,按下键返回一次键值后返回0,直至第二次按键按下
  130. //========================================================================
  131. uchar Key_Scan()
  132. {         
  133.         static uchar key_up=1;//按键按松开标志
  134.         if(key_up&&(Key1==0||Key2==0||Key3==0||Key4==0||Key5==0||Key6==0))
  135.         {
  136.                 delay_1ms(10);//去抖动
  137.                 key_up=0;
  138.                 if(Key1==0)                        return 1;
  139.                 else if(Key2==0)return 2;
  140.                 else if(Key3==0)return 3;
  141.                 else if(Key4==0)return 4;
  142.                 else if(Key5==0)return 5;
  143.                 else if(Key6==0)return 6;
  144.         }
  145.         else if(Key1==1&&Key2==1&&Key3==1&&Key4==1&&Key5==1&&Key6==1)
  146.                 key_up=1;             
  147.         return 20;// 无按键按下
  148. }

  149. /*************写一个数据到对应的地址里***************/
  150. void write_ds1302(uchar add,uchar dat)
  151. {               
  152.         rst = 1;                         //把复位线拿高
  153.         for(i=0;i<8;i++)
  154.         {                                     //低位在前
  155.                 clk = 0;                 //时钟线拿低开始写数据
  156.                 io = add & 0x01;           
  157.                 add >>= 1;                 //把地址右移一位
  158.                 clk = 1;                 //时钟线拿高
  159.         }       
  160.         for(i=0;i<8;i++)
  161.         {
  162.                 clk = 0;                 //时钟线拿低开始写数据
  163.                 io = dat & 0x01;
  164.                 dat >>= 1;                 //把数据右移一位
  165.                 clk = 1;                 //时钟线拿高
  166.         }
  167.         rst = 0;                         //复位线合低
  168.         clk = 0;
  169.         io = 0;
  170. }

  171. /*************从对应的地址读一个数据出来***************/
  172. uchar read_ds1302(uchar add)
  173. {
  174.         uchar value,i;
  175.         rst = 1;                         //把复位线拿高
  176.         for(i=0;i<8;i++)
  177.         {                                     //低位在前
  178.                 clk = 0;                 //时钟线拿低开始写数据
  179.                 io = add & 0x01;           
  180.                 add >>= 1;                 //把地址右移一位
  181.                 clk = 1;                 //时钟线拿高
  182.         }               
  183.         for(i=0;i<8;i++)
  184.         {
  185.                 clk = 0;                 //时钟线拿低开始读数据
  186.                 value >>= 1;
  187.                 if(io == 1)
  188.                         value |= 0x80;
  189.                 clk = 1;                 //时钟线拿高
  190.         }
  191.         rst = 0;                         //复位线合低
  192.         clk = 0;
  193.         io = 0;
  194.         return value;                 //返回读出来的数据
  195. }



  196. /*************把要的时间 年月日 都读出来***************/
  197. void read_time()
  198. {
  199.         miao = read_ds1302(read_add[0]);        //读秒
  200.         fen  = read_ds1302(read_add[1]);        //读分
  201.         shi  = read_ds1302(read_add[2]);        //读时
  202.         ri   = read_ds1302(read_add[3]);        //读日
  203.         yue  = read_ds1302(read_add[4]);        //读月
  204.         nian = read_ds1302(read_add[5]);        //读年
  205.         week = read_ds1302(read_add[6]);        //读星期
  206. }

  207. /*************把要写的时间 年月日 都写入ds1302里***************/
  208. void write_time()
  209. {
  210.         write_ds1302(0x8e,0x00);                        //打开写保护
  211.         write_ds1302(write_add[0],miao);        //写秒
  212.         write_ds1302(write_add[1],fen);                //写分
  213.         write_ds1302(write_add[2],shi);                //写时
  214.         write_ds1302(write_add[3],ri);                //写日
  215.         write_ds1302(write_add[4],yue);                //写月
  216.         write_ds1302(write_add[5],nian);        //写星期
  217.         write_ds1302(write_add[6],week);        //写年
  218.         write_ds1302(0x8e,0x80);                        //关闭写保护
  219. }

  220. /*************把数据保存到ds1302 RAM中**0-31*************/
  221. void write_ds1302ram(uchar add,uchar dat)
  222. {
  223.         add <<= 1;     //地址是从第二位开始的
  224.         add &= 0xfe;   //把最低位清零  是写的命令
  225.         add |= 0xc0;   //地址最高两位为 1  
  226.         write_ds1302(0x8e,0x00);
  227.         write_ds1302(add,dat);       
  228.         write_ds1302(0x8e,0x80);
  229. }

  230. /*************把数据从ds1302 RAM读出来**0-31*************/
  231. uchar read_ds1302ram(uchar add)
  232. {
  233.         add <<= 1;     //地址是从第二位开始的
  234.         add |= 0x01;   //把最高位置1  是读命令
  235.         add |= 0xc0;   //地址最高两位为 1  
  236.         return(read_ds1302(add));       
  237. }



  238. /**********************设置ds1302时间函数**********************/
  239. void set_ds1302time(uchar num,uchar *shi,uchar dat)         //调时
  240. {
  241.           if(num == 1)
  242.     {
  243.             *shi+=0x01;
  244.                 if((*shi & 0x0f) >= 0x0a)
  245.                         *shi = (*shi & 0xf0) + 0x10;
  246.                 if(*shi >= dat)
  247.                         *shi = 0;
  248.     }
  249.     else
  250.     {
  251.                 if(*shi == 0x00)
  252.                         *shi = dat;
  253.                 if((*shi & 0x0f) == 0x00)
  254.                         *shi = (*shi | 0x0a) - 0x10;
  255.                 *shi -=0x01 ;
  256.     }  
  257. }


  258. /*************初始化ds1302时间***************/
  259. void init_ds1302()
  260. {
  261.         uchar i;
  262.         rst = 0;        //第一次读写数据时要把IO品拿低
  263.         clk = 0;
  264.         io = 0;
  265.         i = read_ds1302ram(30);   
  266.         if(i != 3)
  267.         {       
  268.                 i = 3;
  269.                 write_ds1302ram(30,i);
  270.                 write_ds1302(0x8e,0x00);                    //打开写保护
  271.                 for(i=0;i<7;i++)
  272.                         write_ds1302(write_add[i],init_ds[i]);        //把最高位值0 允许ds1302工作
  273.                 write_ds1302(0x8e,0x80);        //关写保护
  274.         }

  275.         read_time();                  //读时间
  276.         if(miao >= 0x60)
  277.         {
  278.                 write_ds1302(0x8e,0x00);                    //打开写保护
  279.                         write_ds1302(write_add[0],init_ds[0]);        //把最高位值0 允许ds1302工作
  280.                 write_ds1302(0x8e,0x80);        //关写保护
  281.                
  282.         }
  283. }

  284. void init_ds1302_io()
  285. {
  286.         rst = 0;        //第一次读写数据时要把IO品拿低
  287.         clk = 0;
  288.         io = 0;       
  289. }


  290. #include "menu.h"


  291. /*********************对应菜单内的处理函数******************/
  292. void menu_dis()
  293. {
  294.         if(menu_1 == 0)
  295.         {
  296.                 if(key_can == 3)        //按键模拟加里程  每按一下加0.1KM
  297.                 {
  298.                         distance ++;
  299.                         if(flag_time_xs != 0)
  300.                                 write_sfm4(1,0,distance);           //显示里程
  301.                 }
  302.                 if(key_can == 6)                   //清零 从新计价
  303.                 {
  304.                         flag_time_en = 0;       
  305.                         d_shi = 0;
  306.                         d_fen = 0;
  307.                         d_miao = 0;
  308.                         zong_jia = 0;
  309.                         distance = 0;
  310.                 }
  311.                 if(key_can == 1)         //时间和等待的时间的切换
  312.                 {
  313.                         flag_time_xs ++;    //为1显示当前时间
  314.                         if(flag_time_xs > 2)       
  315.                                 flag_time_xs = 0;

  316.                         if(flag_time_xs == 0)        //显示时间
  317.                         {
  318.                                 write_string(1,0,"    :  :    W:  ");                       
  319.                                 write_string(2,0," 20  -  -       ");       
  320.                         }
  321.                         if(flag_time_xs == 1)//显示当前时间
  322.                         {
  323.                                 init_1602_dis_csf();
  324.                         }       
  325.                         if(flag_time_xs == 2)//显示等待时间
  326.                         {
  327.                                 write_string(2,0,"        ");
  328.                         }                       
  329.                 }
  330. //                        write_sfm2(1,0,flag_time_xs);
  331.                 if(key_can == 2)                  //按键模拟控制停车计时
  332.                 {
  333.                         flag_time_en = ~flag_time_en;
  334.                 }
  335.                 if(flag_200ms == 1)
  336.                 {
  337. //                        flag_200ms = 0;
  338.                         if(distance <= 30)//3公里内的价格
  339.                         {
  340.                                 if(flag_bai_hei == 0)
  341.                                 {
  342.                                         if(d_fen <= 3)
  343.                                                 zong_jia = bai_3l_price;
  344.                                         else
  345.                                                 zong_jia = bai_3l_price + (d_shi * 60 +  d_fen - 3) * bai_wait_price;       
  346.                                 }                               
  347.                                 else
  348.                                 {
  349.                                         if(d_fen <= 3)
  350.                                                 zong_jia = wan_3l_price;
  351.                                         else
  352.                                                 zong_jia = wan_3l_price + (d_shi * 60 +  d_fen - 3) * wan_wait_price;
  353.                                 }
  354.                                        
  355.                         }else                          //3公里外的价格
  356.                         {
  357.                                 if(flag_bai_hei == 0)
  358.                                 {
  359.                                         if(d_fen <= 3)
  360.                                                 zong_jia = bai_3l_price + bai_3w_price * (distance - 30) / 10 ;
  361.                                         else
  362.                                                 zong_jia = bai_3l_price + bai_3w_price * (distance - 30) / 10 + (d_shi * 60 +  d_fen - 3) * bai_wait_price;
  363.                                 }
  364.                                 else
  365.                                 {
  366.                                         if(d_fen <= 3)
  367.                                                 zong_jia = wan_3l_price + wan_3w_price * (distance - 30) / 10 ;       
  368.                                         else
  369.                                                 zong_jia = wan_3l_price + wan_3w_price * (distance - 30) / 10 + (d_shi * 60 +  d_fen - 3) * wan_wait_price;       
  370.                                 }
  371.                         }
  372.                         if(flag_time_xs == 1)          //显示当前的时间
  373.                         {
  374.                                 write_sfm2_ds1302(2,0,shi);  //显示时       
  375.                                 write_data(':');   
  376.                                 write_sfm2_ds1302(2,3,fen);  //显示时       
  377.                                 write_data(':');   
  378.                                 write_sfm2_ds1302(2,6,miao); //显示秒
  379.                                 write_sfm4(1,10,zong_jia);
  380.                                         write_sfm4(1,0,distance);  
  381.                                 if(flag_bai_hei == 0)
  382.                                         write_sfm2_dian(2,9,bai_3w_price);       
  383.                                 else
  384.                                         write_sfm2_dian(2,9,wan_3w_price);
  385.                                 write_zifu(1,15,0x5c);        //¥               
  386.                                 write_zifu(2,12,0x5c);        //¥       

  387.                         }
  388.                         else if(flag_time_xs == 2)            //显示等待时间
  389.                         {
  390.                                 write_sfm2(2,1,d_fen);  //显示分
  391.                                 write_data(':');   
  392.                                 write_sfm2(2,4,d_miao); //显示秒
  393.                                 write_sfm4(1,10,zong_jia);
  394.                                         write_sfm4(1,0,distance);  
  395.                                 if(flag_bai_hei == 0)
  396.                                         write_sfm2_dian(2,9,bai_3w_price);         //显示白天每公里的价格
  397.                                 else
  398.                                         write_sfm2_dian(2,9,wan_3w_price);         //显示晚上每公里的价格
  399.                                 write_zifu(1,15,0x5c);        //¥               
  400.                                 write_zifu(2,12,0x5c);        //¥       
  401.                         }
  402.                         else    //显示当前的时间
  403.                         {
  404.                                 write_sfm2_ds1302(1,2,shi);           //显示时
  405.                                 write_sfm2_ds1302(1,5,fen);           //显示分
  406.                                 write_sfm2_ds1302(1,8,miao);        //显示秒
  407.                                 write_sfm1(1,14,week);                           //显示星期                                       
  408.                                 write_sfm2_ds1302(2,3,nian);        //显示年
  409.                                 write_sfm2_ds1302(2,6,yue);           //显示月
  410.                                 write_sfm2_ds1302(2,9,ri);           //显示日
  411.                
  412.                         }
  413.                 }
  414.         }
  415. }

  416. /*******************停车计时函数 *****************/
  417. void jishu_chashu()
  418. {       
  419.         if((flag_1s == 1) && (flag_time_en == 1))
  420.         {
  421.                 flag_1s = 0;
  422.                 d_miao++;                        //秒钟加1
  423.                 if(d_miao >= 60)
  424.                 {
  425.                         d_miao = 0;
  426.                         d_fen ++;                //分钟加1
  427.                         if(d_fen >= 60)
  428.                         {
  429.                                 d_fen = 0;
  430.                                 d_shi++;
  431.                                 if(d_shi >= 24)
  432.                                 {
  433.                                         d_shi = 0;
  434.                                 }
  435.                         }
  436.                 }
  437.                        
  438.         }
  439. }


  440. /*************定时器0初始化程序***************/
  441. void time_init()          
  442. {
  443.         EA   = 1;                   //开总中断
  444.         TMOD = 0X01;          //定时器0、工作方式1
  445.         ET0  = 1;                  //开定时器0中断
  446.         TR0  = 1;                  //允许定时器0定时
  447. }



  448. /******************主函数*******************/
  449. void main()
  450. {
  451.         P0 = P1 = P2 = P3 = 0XFF;          //让IO口全部输出高电平
  452.         init_1602();                                  //初始化1602液晶
  453.         init_1602_dis_csf();                   //初始化1602液晶显示
  454.         zidong_chud_shifa_iic();
  455.         read_iic_data();                          //把保存的数据读出来
  456.         time_init();                                  //定时器初始化
  457.         init_menu();                                  //菜单程序
  458.         init_ds1302_io();
  459.         init_ds1302();                                        //ds1302初始化
  460.         while(1)
  461.         {
  462.                 key_can=Key_Scan();                                          //按键程序
  463.                 menu_dis();       
  464.                 if(key_can < 20)
  465.                         key_with();

  466.                 jishu_chashu();                          //停车计时函数
  467.                 if(flag_200ms == 1)
  468.                 {
  469.                         flag_200ms = 0;
  470.                         if(menu_1 == 0)
  471.                                 read_time();                  //读时间
  472.                         if((shi >= 0x22) || (shi <= 8))
  473.                                 flag_bai_hei = 1;     //晚上模式
  474.                         else
  475.                                 flag_bai_hei = 0;          //白天模式
  476.                 }
  477.         }
  478. }

  479. /*************定时器0中断服务程序***************/
  480. void time0_int() interrupt 1
  481. {       
  482.         static uchar value;
  483.         TH0 = 0x3c;
  484.         TL0 = 0xb0;     // 50ms
  485.         value ++;
  486.         if(value % 4 == 0)
  487.                 flag_200ms = 1;
  488.         if(value >= 20)
  489.         {
  490.                 flag_1s = 1;
  491.                 value = 0;
  492.         }

  493. }
复制代码

所有资料51hei提供下载:
出租车计价器的设计.zip (190.06 KB, 下载次数: 71)

评分

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

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏6 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:1060245 发表于 2023-1-4 11:35 | 只看该作者
能问一下 使用的STC哪一型号吗
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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