基于单片机的出租车计价器设计
出租车计价器电路原理图如下:
实物图:
单片机源程序:
- #include
//调用单片机头文件
- #define uchar unsigned char //无符号字符型 宏定义 变量范围0~255
- #define uint unsigned int //无符号整型 宏定义 变量范围0~65535
- uchar d_miao,d_fen = 0,d_shi;
- uchar flag_bai_hei; //白天的晚上的标志位
- uchar value;
- uint bai_3l_price = 60; //白天3千米内的单价 6元
- uint bai_3w_price = 18; //白天3千米外的单价/千米 1.8元
- uint bai_wait_price = 5; //白天等待时的单价/分钟 0.5元
- uint wan_3l_price = 70; //晚上3千米内的单价/千米 7元
- uint wan_3w_price = 22; //晚上3千米外的单价/千米 2.2元
- uint wan_wait_price = 10; //晚上等待时的单价/分钟 1元
- uint distance = 0; //行使的距离
- uint zong_jia; //总的价
- bit flag_200ms = 0;
- bit flag_1s ;
- bit flag_time_en = 0;
- uchar flag_time_xs = 1; //显示时间和等待时间切换
- sbit beep = P3^7; //蜂鸣器IO口定义
- uchar i;
- sbit clk = P1^3; //ds1302时钟线定义
- sbit io = P1^4; //数据线
- sbit rst = P1^5; //复位线
- //秒 分 时 日 月 年 星期
- uchar code write_add[]={0x80,0x82,0x84,0x86,0x88,0x8c,0x8a}; //写地址
- uchar code read_add[] ={0x81,0x83,0x85,0x87,0x89,0x8d,0x8b}; //读地址
- uchar code init_ds[] ={0x55,0x17,0x15,0x01,0x05,0x15,0x13};
- uchar idata miao,fen,shi,ri,yue,week,nian;
- uchar t1_num,t2_num; //计时间中断的次数
- unsigned long speed1,juli,time2;
- float f_hz,speed_km,speed_m;
- uchar TH11,TL11;
- uchar flag_en; //开始计算速度使能
- uchar flag_stop_en; //要确定车子是否停下了
- uint juli_s; //每秒走的距离
- uint juli_z; //总路程
- float zhijing = 0.75; //直径 0.55M
- bit flag_1s = 1; //1s
- uchar menu_1; //菜单设置变量
- uchar menu_2; //菜单设置变量
- uint shudu; //定义速度的变量
- uint bj_shudu = 80; //报警速度
- uchar flag_ds_en;
- long zong_lc; //总量程
- #include "lcd1602.h"
- /***********************1ms延时函数*****************************/
- void delay_1ms(uint q)
- {
- uint i,j;
- for(i=0;i
- for(j=0;j<120;j++);
- }
- #include "iic.h"
- void write_iic_data()
- {
- write_24c02(0,flag_bai_hei);
- write_24c02(1,bai_3l_price % 256); //保存数据
- write_24c02(2,bai_3l_price / 256); //保存数据
- write_24c02(3,bai_3w_price % 256); //保存数据
- write_24c02(4,bai_3w_price / 256); //保存数据
- write_24c02(5,bai_wait_price % 256); //保存数据
- write_24c02(6,bai_wait_price / 256); //保存数据
- write_24c02(7,wan_3l_price % 256); //保存数据
- write_24c02(8,wan_3l_price / 256); //保存数据
- write_24c02(9,wan_3w_price % 256); //保存数据
- write_24c02(10,wan_3w_price / 256); //保存数据
- write_24c02(11,wan_wait_price % 256); //保存数据
- write_24c02(12,wan_wait_price / 256); //保存数据
- }
- /****************读出来保存的数据**********************/
- void read_iic_data()
- {
- flag_bai_hei = read_24c02(0);
- bai_3l_price = read_24c02(2);
- bai_3l_price = bai_3l_price * 256 + read_24c02(1);
- bai_3w_price = read_24c02(4);
- bai_3w_price = bai_3w_price * 256 + read_24c02(3);
- bai_wait_price = read_24c02(6);
- bai_wait_price = bai_wait_price * 256 + read_24c02(5);
- wan_3l_price = read_24c02(8);
- wan_3l_price = wan_3l_price * 256 + read_24c02(7);
- wan_3w_price = read_24c02(10);
- wan_3w_price = wan_3w_price * 256 + read_24c02(9);
- wan_wait_price = read_24c02(12);
- wan_wait_price = wan_wait_price * 256 + read_24c02(11);
- }
- /********************独立按键程序*****************/
- uchar key_can; //按键值
- void key() //独立按键程序
- {
- static uchar key_new;
- key_can = 20; //按键值还原
- P3 |= 0x78; //对应的按键IO口输出为1
- if((P3 & 0x78) != 0x78) //按键按下
- {
- delay_1ms(1); //按键消抖动
- if(((P3 & 0x78) != 0x78) && (key_new == 1))
- { //确认是按键按下
- key_new = 0;
- switch(P3 & 0x78)
- {
- case 0x70: key_can = 1; break; //得到按键值
- case 0x68: key_can = 2; break; //得到按键值
- case 0x58: key_can = 3; break; //得到按键值
- case 0x38: key_can = 4; break; //得到按键值
- }
- beep = 0;
- delay_1ms(50);
- beep = 1;
- }
- }
- else
- key_new = 1;
- }
- /*************写一个数据到对应的地址里***************/
- void write_ds1302(uchar add,uchar dat)
- {
- rst = 1; //把复位线拿高
- for(i=0;i<8;i++)
- { //低位在前
- clk = 0; //时钟线拿低开始写数据
- io = add & 0x01;
- add >>= 1; //把地址右移一位
- clk = 1; //时钟线拿高
- }
- for(i=0;i<8;i++)
- {
- clk = 0; //时钟线拿低开始写数据
- io = dat & 0x01;
- dat >>= 1; //把数据右移一位
- clk = 1; //时钟线拿高
- }
- rst = 0; //复位线合低
- clk = 0;
- io = 0;
- }
- /*************从对应的地址读一个数据出来***************/
- uchar read_ds1302(uchar add)
- {
- uchar value,i;
- rst = 1; //把复位线拿高
- for(i=0;i<8;i++)
- { //低位在前
- clk = 0; //时钟线拿低开始写数据
- io = add & 0x01;
- add >>= 1; //把地址右移一位
- clk = 1; //时钟线拿高
- }
- for(i=0;i<8;i++)
- {
- clk = 0; //时钟线拿低开始读数据
- value >>= 1;
- if(io == 1)
- value |= 0x80;
- clk = 1; //时钟线拿高
- }
- rst = 0; //复位线合低
- clk = 0;
- io = 0;
- return value; //返回读出来的数据
- }
- /*************把要的时间 年月日 都读出来***************/
- void read_time()
- {
- miao = read_ds1302(read_add[0]); //读秒
- fen = read_ds1302(read_add[1]); //读分
- shi = read_ds1302(read_add[2]); //读时
- ri = read_ds1302(read_add[3]); //读日
- yue = read_ds1302(read_add[4]); //读月
- nian = read_ds1302(read_add[5]); //读年
- week = read_ds1302(read_add[6]); //读星期
- }
- /*************把要写的时间 年月日 都写入ds1302里***************/
- void write_time()
- {
- write_ds1302(write_add[0],miao); //写秒
- write_ds1302(write_add[1],fen); //写分
- write_ds1302(write_add[2],shi); //写时
- write_ds1302(write_add[3],ri); //写日
- write_ds1302(write_add[4],yue); //写月
- write_ds1302(write_add[5],nian); //写星期
- write_ds1302(write_add[6],week); //写年
- }
- /**********************设置ds1302时间函数**********************/
- void set_ds1302time(uchar num,uchar *shi,uchar dat) //调时
- {
- if(num == 1)
- {
- *shi+=0x01;
- if((*shi & 0x0f) >= 0x0a)
- *shi = (*shi & 0xf0) + 0x10;
- if(*shi >= dat)
- *shi = 0;
- }
- else
- {
- if(*shi == 0x00)
- *shi = dat;
- if((*shi & 0x0f) == 0x00)
- *shi = (*shi | 0x0a) - 0x10;
- *shi -=0x01 ;
- }
- }
- #include "menu.h"
- /*********************对应菜单内的处理函数******************/
- void menu_dis()
- {
- if(menu_1 == 0)
- {
- if(key_can == 2) //清零 从新计价
- {
- flag_time_en = 0;
- d_shi = 0;
- d_fen = 0;
- flag_ds_en = 0;
- }
- if(key_can == 4) //时间和等待的时间的切换
- {
- flag_time_xs ++; //为1显示当前时间
- if(flag_time_xs > 2)
- flag_time_xs = 0;
- if(flag_time_xs == 0) //显示时间
- {
- write_string(1,0," : : W: ");
- write_string(2,0," 20 - - ");
- }
- }
- if(flag_200ms == 1)
- {
- if(distance <= 30)//3公里内的价格
- {
- if(flag_bai_hei == 0)
- {
- if((d_fen == 0) && (d_miao <= 10))
- zong_jia = bai_3l_price;
- else
- zong_jia = bai_3l_price + (d_shi * 60*60 + d_fen*60 + d_miao) * bai_wait_price -bai_wait_price*10;
- }
- else
- {
- if((d_fen == 0) && (d_miao <= 10))
- zong_jia = wan_3l_price;
- else
- zong_jia = wan_3l_price + (d_shi * 60*60 + d_fen*60 + d_miao) * wan_wait_price -bai_wait_price*10;
- }
-
- }else //3公里外的价格
- {
- if(flag_bai_hei == 0)
- {
- if((d_fen == 0) && (d_miao <= 10))
- zong_jia = bai_3l_price + bai_3w_price * (distance - 30) / 10 ;
- else
- 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;
- }
- else
- {
- if((d_fen == 0) && (d_miao <= 10))
- zong_jia = wan_3l_price + wan_3w_price * (distance - 30) / 10 ;
- else
- 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;
- }
- }
- if(flag_time_xs == 1) //显示当前的时间
- {
- write_sfm2_ds1302(2,0,shi); //显示时
- write_data(':');
- write_sfm2_ds1302(2,6,miao); //显示秒
- write_sfm4(2,10,zong_jia);
- write_sfm2(1,1,shudu);
- write_sfm4(1,9,juli_z);
- }
- else if(flag_time_xs == 2) //显示等待时间
- {
- write_sfm2(2,1,d_fen); //显示分
- write_data(':');
- write_sfm2(2,4,d_miao); //显示秒
-
- write_sfm2(1,1,shudu);
- write_sfm4(1,9,juli_z);
- }
- else //显示当前的时间
- {
- write_sfm2_ds1302(1,2,shi); //显示时
- write_sfm2_ds1302(1,5,fen); //显示分
- write_sfm2_ds1302(1,8,miao); //显示秒
- write_sfm1(1,14,week); //显示星期
- write_sfm2_ds1302(2,6,yue); //显示月
- write_sfm2_ds1302(2,9,ri); //显示日
-
- }
- }
- }
- }
- /*******************停车计时函数 *****************/
- void jishu_chashu()
- {
- if((flag_1s == 1) && (flag_time_en == 1))
- {
- if(flag_ds_en == 1)
- {
- d_miao++; //秒钟加1
- if(d_miao >= 60)
- {
- d_miao = 0;
- d_fen ++; //分钟加1
- if(d_fen >= 60)
- {
- d_fen = 0;
- d_shi++;
- if(d_shi >= 24)
- {
- d_shi = 0;
- }
- }
- }
- }
- }
- }
- /*************定时器0初始化程序***************/
- void time_init()
- {
- EA = 1; //开总中断
- TMOD = 0X11; //定时器0、工作方式1
- ET0 = 1; //开定时器0中断
- TR0 = 1; //允许定时器0定时
- ET1 = 1; //开定时器1中断
- TR1 = 1; //允许定时器1定时
- }
- /***********外部中断0初始化程序****************/
- void init_int0()
- {
- EX0=1; //允许外部中断0中断
- EA=1; //开总中断
- IT0 = 1; //外部中断0负跳变中断
- }
- /***********计算速度函数**************/
- void shudu_dis() //计算速度函数
- {
- static uchar value,value1;
- if(menu_1 == 0)
- {
- if(flag_1s == 1)
- {
- flag_1s = 0;
- if(flag_en == 0)
- {
- value ++;
- if(value >= 3) //2秒
- {
- speed_km = 0; //速度为0
- shudu = (uint)speed_km;
- value = 0;
- flag_time_en = 1;
- }
- }
- if((flag_en == 1))
- {
- value = 0;
- flag_en = 0;
- //1s = 1 / 1000000us; // 1m/s=0.001km除以1/3600h=3.6km/h
- f_hz =(t2_num * 65536.0 + TH11 * 256 + TL11) / 1000000; //算出来就是秒
- speed_m = f_hz * zhijing * 3.14 ; //算出来的是m/s
- juli_z = (juli_z + (uint)speed_m) ; //总路程m
- speed_km = speed_m * 3.6 ; //(带个小数点) km/s
- shudu = (uint)speed_km;
- zong_lc += speed_m;
- distance = juli_z;
- value1++;
- flag_time_en = 0;
- }
- }
- }
- }
- /******************主函数*******************/
- void main()
- {
- P0 = P1 = P2 = P3 = 0XFF; //让IO口全部输出高电平
- init_1602(); //初始化1602液晶
- init_1602_dis_csf(); //初始化1602液晶显示
- read_iic_data(); //把保存的数据读出来
- time_init(); //定时器初始化
- init_int0();
- while(1)
- {
- key(); //按键程序
- menu_dis();
- if(key_can < 20)
- key_with();
- shudu_dis(); //计算速度函数
- if(flag_200ms == 1)
- {
- flag_200ms = 0;
- if(menu_1 == 0)
- read_time(); //读时间
- if((shi >= 0x21) || (shi <= 5))
- flag_bai_hei = 1; //晚上模式
- else
- flag_bai_hei = 0; //白天模式
- }
- }
- }
- /*************定时器0中断服务程序***************/
- void time0_int() interrupt 1
- {
- static uchar value;
- TH0 = 0x3c;
- TL0 = 0xb0; // 50ms
- value ++;
- if(value % 4 == 0)
- flag_200ms = 1;
- if(value >= 20)
- {
- flag_1s = 1;
- value = 0;
- jishu_chashu();
- }
- }
- /*********************外部中断0中断服务程序************************/
- void int0() interrupt 0
- {
- static uchar value;
- switch(value)
- {
- case 0:
- t1_num = 0; //第一次就把变量清零
- TH1 = 0;
- TL1 = 0;
- break;
- case 1:
- t2_num = t1_num; //保存
- TH11 = TH1;
- TL11 = TL1;
- flag_en = 1;
- break;
- }
- value ++;
- if(value >= 2)
- value =0;
- }
- /*************定时器1中断服务程序***************/
- void time1_int() interrupt 3
- {
- t1_num++;
- }
本主题由 bing680610 于 2019-1-15 16:15 移动
文件到原文下载,原文出自:https://bbs.usoftchina.com/thread-207818-1-1.html