這是我做的一個車租車計費作品,用了兩個星期,附件里包含作品源代碼和芯片資料,清大家多多指教
電路原理圖如下:
多功能出租車計價器設計原理圖.png (158.8 KB, 下載次數: 116)
下載附件
2018-3-26 17:29 上傳
0.png (44.03 KB, 下載次數: 91)
下載附件
2018-3-27 01:48 上傳
單片機源程序如下:
- /*************************************************************
- 多功能出租車計價系統
- 補充說明:
- ***************************************************************/
- #include<reg52.h> //頭文件
- #include<LCD1602.h>
- #include<AT24C02.h>
- #include<INTERRUPT.h>
- #include<SC8065.h>
- #include<DS1302.h>
- /*****************燈、蜂鳴器、按鍵引腳定義*******************/
- sbit led =P3^0; //紅色LED燈
- sbit led2 =P3^1; //綠色LED燈
- sbit key_start =P1^0; //開始/結束計價
- sbit key_Wait =P1^1; //電機開始/結束
- sbit key_set =P1^2; //設置
- sbit key_jia =P1^3; //加值
- sbit key_jian =P1^4; //減值
- /************************變量定義***********************/
- uint start_price; //起步價
- uint white_price; //白天單價
- uint white_Wait; //白天等待超10分鐘后每分鐘價錢。
- bit start; //開始計價標志,=0非計價模式,=1計價模式
- double price1; //應收總價錢(帶小數)
- uint mil,Wait,price2; //里程數、等待時間、總價
- uchar set_f; //設置選擇標記,=0未設置,=1設置起步價,=2設置白天公里價,=3設置時,=4設置分,=5設置秒
- bit strat_f; //初始界面顯示標志,=0顯示初始界面,=1可能計價、設置、總價顯示
- uchar num; //循環計數變量
- bit moto_f=0; //電機控制標志,=0關閉電機,1打開電機
- /********************************************************
- 函數名稱:void baojia()
- 函數作用:乘坐結束進行報價
- 參數說明:
- ********************************************************/
- void baojia()
- {
- uint temp;
- SC_Speech(1); //先播放一次空的內容,防止語音混亂
- //以下里程播報
- SC_Speech(55); //播放【本次】
- SC_Speech(56); //播放【行程】
- if(mil>=1000) //里程【大于100KM】
- {
- SC_Speech(10+mil/1000); //播放 里程的百位
- SC_Speech(21); //播放【百】
- }
- if(mil>=100) //里程【大于10KM】
- {
- if(mil%1000/100!=0) //如果 里程十位 不為0
- {
- if(mil<1000&&mil%1000/100==1);//只有十幾的時候不用報【一】
- else
- SC_Speech(10+mil%1000/100);//播放 里程的十位
- SC_Speech(20); //播放【十】
- }
- else //否則 里程十位 為0
- {
- if(mil%100/10!=0) //如果 里程個位 不為0
- SC_Speech(10); //播放【零】
- }
- }
- if(mil>=10) //里程【大于1KM】
- {
- if(mil%100/10!=0) //如果 里程個位 不為0
- SC_Speech(10+mil%100/10); //播放 里程的個位
- }
- else
- SC_Speech(10); //播放【零】
- if(mil%10!=0) //如果 里程小數 不為0
- {
- SC_Speech(24); //播放【點】
- SC_Speech(10+mil%10); //播放 里程的小數位
- }
- SC_Speech(4); //播放【千米】
-
- //以下價格播報
- temp=price2/10;
- SC_Speech(58); //播放【共計】
- if(temp>=1000) //總價【大于100元】
- {
- SC_Speech(10+temp/1000); //播放 總價的百位
- SC_Speech(21); //播放【百】
- }
- if(temp>=100) //總價【大于10元】
- {
- if(temp%1000/100!=0) //如果 總價十位 不為0
- {
- if(temp<1000&&temp%1000/100==1);//只有十幾的時候不用報【一】
- else
- SC_Speech(10+temp%1000/100);//播放 總價的十位
- SC_Speech(20); //播放【十】
- }
- else //否則 總價十位 為0
- {
- if(temp%100/10!=0) //如果 總價個位 不為0
- SC_Speech(10); //播放【零】
- }
- }
- if(temp>=10) //總價【大于1元】
- {
- if(temp%100/10!=0) //如果 總價個位 不為0
- SC_Speech(10+temp%100/10); //播放 總價的個位
- }
- else
- SC_Speech(10); //播放【零】
- if(temp%10==0) //如果 總價小數位 為0
- {
- SC_Speech(6); //播放【元】
- SC_Speech(38); //播放【整】
- }
- else //否則 總價小數位 不為0
- {
- SC_Speech(24); //播放【點】
- SC_Speech(10+temp%10); //播放 總價的小數位
- SC_Speech(6); //播放【元】
- }
- SC_Speech(64); //播放【謝謝】
- }
- /********************************************************
- 函數名稱:void display()
- 函數作用:計價時顯示里程、等待時間函數
- 參數說明:
- ********************************************************/
- void display()
- {
- if(mil_f==1) //檢測到一次信號
- {
- mil_f=0;
- //顯示里程數
- //LCD_disp_char(9,1,ASCII[mil/1000]); 最大里程為99.9公里
- LCD_disp_char(10,1,ASCII[mil%1000/100]);
- LCD_disp_char(11,1,ASCII[mil%100/10]);
- LCD_disp_char(12,1,'.');
- LCD_disp_char(13,1,ASCII[mil%10]);
- lcd1602_write_character(14,1,"KM");
- if(mil>30) //里程超3公里
- {
- if(time[2]>=7&&time[2]<22) //在白天時間段
- price1=price1+white_price; //計算白天總價【white_price/10=公里價】
- else //在晚上時間段
- price1=price1+white_price*1.5; //計算晚上總價
- }
- else //小于三公里只收起步價
- price1=start_price; //計算總價【price1/100=總價】
- }
- if(wait_f==1) //計時一秒到
- {
- wait_f=0;
- //顯示等待時間
- LCD_disp_char(11,2,ASCII[Wait%3600/60/10]);
- LCD_disp_char(12,2,ASCII[Wait%3600/60%10]);
- LCD_disp_char(13,2,':');
- LCD_disp_char(14,2,ASCII[Wait%60/10]);
- LCD_disp_char(15,2,ASCII[Wait%60%10]);
- if(Wait>600&&Wait%60==0) //等待時間超過10分鐘后每1分鐘計費
- price1=price1+10; //每分鐘+0.1元
- }
- price2=price1;
- //顯示應付金額
- LCD_disp_char(0,1,ASCII[price2/10000]); //顯示應付金額百位
- LCD_disp_char(1,1,ASCII[price2%10000/1000]); //顯示應付金額十位
- LCD_disp_char(2,1,ASCII[price2%1000/100]); //顯示應付金額個位【price2/100=應付金額】
- LCD_disp_char(3,1,'.');
- LCD_disp_char(4,1,ASCII[price2%100/10]);
- LCD_disp_char(5,1,0X01); //顯示字符¥
- //顯示當前時間
- LCD_disp_char(0,2,ASCII[time[2]/10]);
- LCD_disp_char(1,2,ASCII[time[2]%10]);
- LCD_disp_char(2,2,':');
- LCD_disp_char(3,2,ASCII[time[1]/10]);
- LCD_disp_char(4,2,ASCII[time[1]%10]);
- LCD_disp_char(5,2,':');
- LCD_disp_char(6,2,ASCII[time[0]/10]);
- LCD_disp_char(7,2,ASCII[time[0]%10]);
- }
- /********************************************************
- 函數名稱:void display2()
- 函數作用:計價結束時顯示總價函數
- 參數說明:
- ********************************************************/
- void display2()
- {
- lcd1602_write_character(3,1,"A total of"); //顯示字符串
-
- LCD_disp_char(5,2,ASCII[price2/10000]);
- LCD_disp_char(6,2,ASCII[price2%10000/1000]);
- LCD_disp_char(7,2,ASCII[price2%1000/100]);
- LCD_disp_char(8,2,'.');
- LCD_disp_char(9,2,ASCII[price2%100/10]);
- LCD_disp_char(10,2,0X01); //顯示字符¥
- }
- /********************************************************
- 函數名稱:void display3()
- 函數作用:設置收費參數時顯示函數
- 參數說明:
- ********************************************************/
- void display3()
- {
- if(set_f==1) //顯示起步價的設置
- {
- lcd1602_write_character(0,1,"Starting price:"); //顯示字符串
- LCD_disp_char(6,2,ASCII[start_price%1000000/100000]); //起步價百位
- LCD_disp_char(7,2,ASCII[start_price%10000/1000]); //起步價十位
- LCD_disp_char(8,2,ASCII[start_price%1000/100]); //起步價個位
- LCD_disp_char(9,2,0x01); //顯示字符¥
- }
- if(set_f==2) //顯示設置每加一公里價格
- {
- lcd1602_write_character(0,1,"Set unit price:");
- LCD_disp_char(4,2,ASCII[white_price/100]); //顯示公里價十位【white_price/10=公里價】
- LCD_disp_char(5,2,ASCII[white_price%100/10]); //顯示公里價個位
- LCD_disp_char(6,2,'.');
- LCD_disp_char(7,2,ASCII[white_price%10]); //顯示公里價十分位
- lcd1602_write_character(9,2,"/KM");
- lcd1602_write_character(8,2,0x01); //顯示字符¥
- }
- }
- /********************************************************
- 函數名稱:void display4(void)
- 函數作用:顯示校準時間函數
- 參數說明:
- ********************************************************/
- void display4()
- {
- num++;
- lcd1602_write_character(4,1,"Set Time:");
- if(num%2==0) //偶數次顯示,奇數次不顯示。這樣就會有閃爍效果,可以清楚看到當前設置的是哪個值
- {
- LCD_disp_char(4,2,ASCII[time[2]/10]); //顯示設置時
- LCD_disp_char(5,2,ASCII[time[2]%10]);
- LCD_disp_char(6,2,':');
- LCD_disp_char(7,2,ASCII[time[1]/10]); //顯示設置分
- LCD_disp_char(8,2,ASCII[time[1]%10]);
- LCD_disp_char(9,2,':');
- LCD_disp_char(10,2,ASCII[time[0]/10]);//顯示設置秒
- LCD_disp_char(11,2,ASCII[time[0]%10]);
- }
- else //奇數次不顯示
- {
- switch(set_f)//根據當前設置的內容,對應位置閃爍
- {
- case 3:lcd1602_write_character(4,2," "); break; //按三下設置時
- case 4:lcd1602_write_character(7,2," "); break; //按四下設置分
- case 5:lcd1602_write_character(10,2," "); break; //按五下設置秒
- default: break;
- }
- }
- }
- /********************************************************
- 函數名稱:void scan(void)
- 函數作用:按鍵檢測函數
- 參數說明:
- ********************************************************/
- void scan(void)
- {
- //開始/結束計價鍵
- if(key_start==0&&set_f==0) //在設置模式下無效
- {
- delayms(7); //延時消抖
- if(key_start==0) //再次確認開始計價按鍵按下
- {
- LCD_write_command(0x01);//清除屏幕顯示
- delay_n40us(100); //延時等待清除完成
- start=~start; //切換開始/結束計價
- strat_f=1; //顯示計價界面
- if(start==0) //非計價模式下,計價結束。計算價格
- {
- led=1; //關閉紅色指示燈
- led2=0; //開啟綠色指示燈
- EX0=0; //關閉外部中斷
- TR1=1; //開啟定時20S左右自動回到初始界面
- moto=1; //關閉電機轉動
- moto_f=0; //關閉電機控制標志
- display2(); //顯示總價
- baojia(); //播報行駛里程和總價
- mil=0; //清除里程數
- Wait=0; //清除等待時間
- TR0=0; //關閉等待計時的定時器
- }
- else //計價開始
- {
- led=0; //開啟紅色指示燈
- led2=1; //關閉綠色指示燈
- TR1=0; //關閉定時1
- T1_num=0; //重置定時計數變量
- mil_f=1; //計價時顯示里程
- wait_f=1; //計價時顯示等待時間
- TR0=1; //開啟計等待時間的定時器
- EX0=0; //此時電機未開啟,關閉外部中斷0,不進行里程檢測
- moto_f=0; //標記電機關閉
- }
- }
- while(!key_start); //檢測按鍵松開
- }
- if(start==0) //非計價模式下
- {
- //設置鍵
- if(key_set==0) //只有在結束計價才有效
- {
- delayms(7); //延時消抖
- if(key_set==0) //再次確認按鍵按下
- {
- Writeds1302 (WRITE_PROTECT,0X00);//DS1302禁止寫保護
- if(set_f<3)
- {
- TR1=1; //開啟定時1
- T1_num=0; //重置定時計數變量
- LCD_write_command(0x01);//清除屏幕顯示
- delay_n40us(100); //延時等待清除完成
- }
- set_f++; //設置選擇變量+1
- strat_f=1; //進入設置界面
- if(set_f==6) //全部參數設置完成,退出設置
- {
- TR1=0; //關閉定時器1
- T1_num=0; //重置定時計數變量
- f=1; //標記設置操作完成
- strat_f=0; //退出設置顯示初始界面
- }
- }
- while(!key_set); //檢測按鍵松開
- }
-
- //加值鍵
- if(key_jia==0)
- {
- delayms(7); //延時消抖
- T1_num=0; //重置定時計數變量,防止定時恢復初始界面
- if(key_jia==0) //再次確認按鍵按下
- {
- if(set_f==1) //設置起步價
- {
-
- if(start_price<3000) //最大值可設置3000/100=30元【start_price/100=起步價】
- start_price+=100; //起步價+1元
- }
- if(set_f==2) //設置白天每加一公里價格
- {
- if(white_price<100) //最大值可設置100/10=10元【white_price/10=公里價】
- white_price++; //白天公里價+0.1元
- }
- if(set_f==3) //設置小時
- {
- time[2]++; //小時+1
- time[2]=(time[2]/10)*16+time[2]%10;//將小時轉換成16進制
- if(time[2]>0x23) //判斷是否達到最大小時23時
- time[2]=0x00; //重新回到00時
- Writeds1302 (WRITE_HOUR,time[2]); //將設置好的小時寫入到DS1302存儲起來
- time[2]=Read1302(0x85); //讀取當前小時
- }
- if(set_f==4) //設置分
- {
- time[1]++;
- time[1]=(time[1]/10)*16+time[1]%10;
- if(time[1]>0x59)
- time[1]=0x00;
- Writeds1302 (WRITE_MINUTE,time[1]);
- time[1]=Read1302(0x83);
- }
- if(set_f==5) //設置秒
- {
- time[0]++;
- time[0]=(time[0]/10)*16+time[0]%10;
- if(time[0]>0x59)
- time[0]=0x00;
- Writeds1302 (WRITE_SECOND,time[0]);
- time[0]=Read1302(0x81);
- }
- }
- }
- //減值鍵
- if(key_jian==0)
- {
- delayms(7); //延時消抖
- T1_num=0; //重置定時計數變量
- if(key_jian==0) //再次確認按鍵按下
- {
- if(set_f==1) //設置起步價
- {
- if(start_price>=100) //最小值可設置0元
- start_price-=100; //起步價-1元
- }
- if(set_f==2) //設置白天每加一公里價格
- {
- if(white_price!=0) //最小值可設置0元
- white_price--; //白天公里價-0.1元
- }
- if(set_f==3) //設置小時
- {
- if(time[2]==0) //判斷小時是否到達最小小時0時
- time[2]=23; //重新回到23時
- else
- time[2]--; //否則小時-1
- time[2]=(time[2]/10)*16+time[2]%10;//將小時轉換成16進制
- Writeds1302 (WRITE_HOUR,time[2]); //將設置好的小時寫入到DS1302存儲起來
- time[2]=Read1302(0x85); //重新讀取小時
- }
- if(set_f==4) //設置分
- {
- if(time[1]==0)
- time[1]=59;
- else
- time[1]--;
- time[1]=(time[1]/10)*16+time[1]%10;
- Writeds1302 (WRITE_MINUTE,time[1]);
- time[1]=Read1302(0x83);
- }
- if(set_f==5) //設置秒
- {
- if(time[0]==0)
- time[0]=59;
- else
- time[0]--;
- time[0]=(time[0]/10)*16+time[0]%10;
- Writeds1302 (WRITE_SECOND,time[0]);
- time[0]=Read1302(0x81);
- }
- }
- }
- }
- else //計價模式下
- {
- if(key_Wait==0) //開啟/關閉電機
- {
- delayms(7); //延時消抖
- if(key_Wait==0) //再次確認按鍵按下
- {
- if(TR0==0) //當TR0=0時moto_f=1,此時電機為開啟狀態
- {
- TR0=1; //打開定時器0,開始計等待時間
- EX0=0; //禁止外部中斷0,不進行里程檢測
- moto_f=0; //標記電機關閉
- }
- else //當TR0=1時moto_f=0,此時電機為關閉狀態
- {
- TR0=0; //關閉定時器0,停止計等待時間
- EX0=1; //INT0中斷允許,檢測霍爾信號
- moto_f=1; //標記電機打開
- }
- }
- while(!key_Wait); //檢測按鍵松開
- }
- if(key_jia==0) //電機加速
- {
- delayms(7); //延時消抖
- if(key_jia==0&&vs<9)//再次確認按鍵按下,并且速度還沒最大9擋
- {
- vs++; //速度等級+1
- }
- while(!key_jia); //檢測按鍵松開
- }
- if(key_jian==0) //電機減速
- {
- delayms(7); //延時消抖
- if(key_jian==0&&vs>4)//再次確認按鍵按下,并且速度還沒最小4擋
- {
- vs--; //速度等級-1
- }
- while(!key_jian); //檢測按鍵松開
- }
- }
- }
- /********************************************************
- 函數名稱:void main()
- 函數作用:主函數
- 參數說明:
- ********************************************************/
- void main()
- {
- led=1; //紅燈關閉
- led2=0; //綠燈點亮
- LCD_init(); //LCD1602初始化
- T0_init(); //定時器0初始化
- Int0_init(); //外部中斷初始化
- if(key_jian==0) //手動復位初始默認價格
- {
- delayms(100);
- if(key_jian==0)
- {
- AT24C02_write_date(1,18); //寫入【公里價】數據保存,地址0~255均可
- AT24C02_write_date(5,10); //寫入【起步價】數據保存
- }
- }
-
- white_price=AT24C02_read_date(1); //讀取存儲的【公里價】數據
- start_price=AT24C02_read_date(5)*100;//讀取存儲的【起步價】數據
- lcd1602_write_pic(0x01,pic2); //將自定義字符“¥”寫入LCD1602
- while(1) //死循環
- ……………………
- …………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼
所有資料51hei提供下載:
程序+原理圖.7z
(3.35 MB, 下載次數: 302)
2022-11-15 18:14 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|