第一篇:出租車計價器
基于單片機的出租車計價器設(shè)計
摘要
出租車計價器的數(shù)字系統(tǒng)的設(shè)計正是基于一些專用的芯片,才發(fā)揮其有效特性,從而實現(xiàn)出租車的計價功能。此數(shù)字系統(tǒng)主要分為三個單元,即里程計數(shù)及顯示單元、價格計數(shù)及顯示單元、脈沖產(chǎn)生。本設(shè)計是一個基于單片機AT89C51的出租車自動計費設(shè)計,附有復(fù)位電路,時鐘電路等。關(guān)鍵詞:出租車計費器;單片機;控制
Abstract Taximeter design digital system is based on some special chip, to play their effective characteristics, thus realizing the taxi valuation function.This system is mainly divided into there modules, namely the mileage counting and display unit, and display unit price counting, pulsing.The design is based on a single chip AT89C51taxis design, a reset circuit, clock circuit.Keywords:taximeter,a single-chip microcomputer,control
1引言
1.1 設(shè)計目的
近幾年來,出租汽車行業(yè)在各地得以蓬勃發(fā)展,但采用模擬電路和數(shù)字電路設(shè)計的計價器整體電路的規(guī)模較大,用到的器件多,造成故障率高,難調(diào)試。而采用單片機進行的設(shè)計,相對來說功能強大,用較少的硬件和適當?shù)能浖嗷ヅ浜峡梢院苋菀椎貙崿F(xiàn)設(shè)計要求,且靈活性強。
1.2 功能要求
(1)用前4位數(shù)碼管實時顯示里程數(shù),單位為千米,最后一位為小數(shù)位;用后4位數(shù)碼管時時顯示金額數(shù),單位為元,最后一位為小數(shù)位。
(2)規(guī)定出租車里程小于2千米收費5元,超過2千米收費為8*(way-20)/5。
1.3 設(shè)計方法
本設(shè)計采用AT89C51單片機為主控器,并用頻率信號發(fā)生器模擬車速,利用AT89C51的定時器工作在方式1下定時實現(xiàn)對出租車的計價設(shè)計,輸出采用共陰極的集成8位7段數(shù)碼顯示管。設(shè)計方案及原理
2.1 設(shè)計方案
采用AT89C51單片機為主控器,并用頻率信號發(fā)生器模擬車速,利用AT89C51的定時器/定時器T1工作在方式1下定時實現(xiàn)對出租車的計價設(shè)計,輸出采用共陰極的集成8位7段數(shù)碼顯示管。本電路設(shè)計的計價器不但能實現(xiàn)基本的計價,而且
單片機原理及系統(tǒng)課程設(shè)計報告
還能根據(jù)里程來調(diào)節(jié)單價。
2.2 設(shè)計原理
出租車計價是根據(jù)車所行駛的路程以及乘客乘車的里程綜合決定的。出租車行駛總路程可以通過車輪的周長乘車輪旋轉(zhuǎn)圈數(shù)得到。即可計算得到車輪旋轉(zhuǎn)幾周出租車能行駛一公里的路程。通過計數(shù)接收到的脈沖個數(shù),計算出當前所行駛的路程。同時,通過數(shù)碼管顯示當前的行駛里程和需支付的車費。出租車計價器用于記錄里程、起步公里數(shù)與價格的關(guān)系。模擬出租車計價器能根據(jù)總里程數(shù)、起步公里數(shù)的情況作出相應(yīng)報價等。這個系統(tǒng)以AT89C51單片機為主控器,單片機的計數(shù)器/定時器T1工作在方式1下來對外部脈沖計數(shù),最后通過集成的8位7段LED數(shù)碼管顯示里程數(shù)和價錢??傮w模塊框圖如圖1所示。
總金額顯示單價顯示AT89C51脈沖產(chǎn)生動態(tài)掃描數(shù)碼管顯示
圖1 總體框圖 硬件設(shè)計
對于AT89C51的計數(shù)器/定時器T1,通過對寄存器TCON的設(shè)置,即使它的M1M0=01,計數(shù)器/定時器T1工作在方式1下,構(gòu)成16位計數(shù)器/定時器。此時TH0、TL0都是8位加法計數(shù)器。此設(shè)計中,T1為計數(shù)工作方式,計數(shù)范圍為1~2^16=1~65536(個外部脈沖)。當計數(shù)溢出時則置位并申請中斷,進入中斷服務(wù) 執(zhí)行中斷程序。
通過74HC138接P20、P21、P22輸出來對8位7段的智能掃描LED進行段選,并且通過P1口對LED進行位選,最后將結(jié)果顯示在LED上。硬件設(shè)計圖如圖2所示。
74HC138是三八譯碼器,在工作之前,使74HC138的使能端有效,再使74HC138的A、B、C接P20、P21、P22的輸出達到對LED位選線的控制,使相應(yīng)的位顯示相應(yīng)的結(jié)果。硬件總設(shè)計圖如圖2所示。
第二篇:出租車計價器調(diào)試報告
出租車計價器調(diào)試報告
本設(shè)計可分為單片機主控模塊、鍵盤、顯示器、溫度檢測、狀態(tài)指示、時鐘日歷、語音收錄播報、分頻器電路、脈沖信號發(fā)生器等9部分。仔細分析系統(tǒng)的工作原理,分別按照模塊在系統(tǒng)中的作用,對各個模塊分別單獨調(diào)試,最后形成該系統(tǒng)的用戶程序,實現(xiàn)功能要求。
一、接通電源
調(diào)試要求:1.首先仔細檢查該系統(tǒng)板的電源和地是否有短路問題,在未接入電源輕快下,使用萬用表檢驗電源和地檢查是否短路,如果沒有短路,再仔細核查電源極性后予以通電,觀察電源指示燈D1是否點亮。如果電源指示的燈不亮應(yīng)立即關(guān)閉電源,并用手觸摸各個芯片,檢查是否用某芯片發(fā)熱。如果沒有發(fā)熱的器件,很可能是電源指示二極管極性安裝錯誤,或者是該發(fā)光二極管的串聯(lián)電阻阻值偏大。
2.黑板上調(diào)試要求:(1)焊接好電路板加電前,用萬用表測量板上Vcc 和
GND之間的電阻,應(yīng)大于1KΩ
(2)加電后測量電路板上各電壓,應(yīng)大于4.2V 調(diào)試結(jié)果:1.經(jīng)萬用表檢驗,電路板無短路問題。
2.通電后,D1指示燈點亮。
3.測量Vcc 與 地之間的電阻,1.14KΩ > 1KΩ
4.測量Vcc與 地之間的電壓:4.28V > 4.20V
二、測試狀態(tài)指示
本系統(tǒng)中狀態(tài)指示二極管共有3個,它們分別是D1、D2、D3。D1是指示電源的,可以在電源接通時直接看到,D2用于指示語音芯片的工作狀態(tài),留作語音模塊調(diào)試時觀察。D3是可以由單片機的引腳控制的。
編寫測試D3的程序: #include
sbit a_c=P1^0;extern serial_initial();
main(){ serial_initial();a_c=0;while(1);}
測試結(jié)果: 1.2.三、脈沖信號發(fā)生器測試
測試要求:該模塊由5G555芯片構(gòu)成一個多諧振蕩器,使用示波器觀察該芯片的第3引腳的波形,并調(diào)節(jié)電位器W1,觀察輸出波形及頻率變化。
測試結(jié)果:
調(diào)整W1前,f=147.1Hz
調(diào)整W1后,f=130.5Hz
四、分頻電路測試
測試要求:該模塊由一個4位二進制計數(shù)器74HC161和一個多路選擇器74HC153構(gòu)成。調(diào)試時可以利用由5G555芯片構(gòu)成一個多諧振蕩器的輸出,或信號發(fā)生器作為計數(shù)器74HC161的計數(shù)輸入信號。值得注意的是控制多路選擇器74HC153的S0、S1與單片機調(diào)試時所使用的引腳復(fù)用,要采取特殊措施才能正確試驗檢測。
測試結(jié)果:利用函數(shù)信號發(fā)生器生成一個方波,周期/頻率如圖:
其在輸出端輸出的波形為:
f1=3.881kHz
f2 =1.235kHz 分頻功能無誤。
五、鍵盤測試
測試要求:本系統(tǒng)相對比較簡單,僅有5個按鍵,其中4個為系統(tǒng)功能鍵,它們分別是S1、S2、S3、S4,另一個是系統(tǒng)復(fù)位按鍵S6。對于系統(tǒng)復(fù)位按鍵S6可以在上電之后,使用萬用表予以檢查,按下該按鍵,單片機的第9腳應(yīng)該為高電平,釋放后應(yīng)該為點電平。
對于系統(tǒng)功能鍵,編寫如下程序予以測試檢查:
#include
#define BIT_LED XBYTE[0x0a000] void display();sbit k1=P1^0;sbit k2=P1^1;sbit k3=P1^2;sbit k4=P1^3;unsigned char a;unsigned
char table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x67,0x40,0x00,0x63,0x39,};void delay(unsigned int i);main(){ while(1){ if(k1==0)a=0x06;if(k2==0)a=0x5b;if(k3==0)a=0x4f;if(k4==0)a=0x66;display();} } 測試結(jié)果:對于復(fù)位鍵S6,按下前應(yīng)為低電平,按下后應(yīng)為高電平
按下前
按下后
對于S1—S4,按下前為高電平,按下后為低電平。其測試結(jié)果均符合預(yù)期。
六、動態(tài)數(shù)碼管測試
測試要求:本系統(tǒng)中的數(shù)碼管的原理采用的是動態(tài)掃描方式,即某一時刻只用一個數(shù)碼管在顯示,利用人的視覺暫留特性,讓數(shù)碼管高速輪流顯示,達到完整顯示的目的。
編寫如下程序進行測試: #include
#define BIT_LED XBYTE[0x0a000] void displayhello();sbit k1=P1^0;sbit k2=P1^1;sbit k3=P1^2;sbit k4=P1^3;unsigned char a;unsigned char table[]={0x06,0x06,0x3f,0x3e,0x79,0x6e,0x3f,0x3e,0x7f,0x67,0x40,0x00,0x63,0x39,};void delayms(unsigned int i);main(){ while(1){ displayhello();} }
void displayhello(){
unsigned char BIT=1;
unsigned int i;
BIT_LED=1;
for(i=0;i<=7;i++)
{
SEGMENT=table[i];
BIT_LED=BIT;
BIT=BIT<<1;
delayms(1);
}
} void delayms(unsigned int i){ unsigned int n;while(i--){
for(n=0;n<125;n++);
} }
測試結(jié)果:顯示“I love you”
由于是動態(tài)顯示,所以按下復(fù)位鍵后,只有一個數(shù)碼管點亮
七、溫度傳感器測試
測試要求:本系統(tǒng)使用的是一款單線溫度傳感器(DS18B20),可將溫度穿換成12的數(shù)字量,以表示溫度。
編寫如下程序予以測試檢查: #include
//段碼寄存器地址 #define BIT_LED XBYTE[0x0a000]
//位碼寄存器地址 #define fosc 11.0592
unsigned char table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x67,0x40,0x00,0x63,0x39,};//分別顯示0 1 2 3 4 5 6 7 8 9-o C
unsigned char table1[]={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef};//分別顯示0.1.2.3.4.5.6.7.8.9.unsigned char table2[]={0x76,0x79,0x38,0x38,0x3f};sbit k1=P1^0;sbit k2=P1^1;sbit k3=P1^2;unsigned char data display_buffer[13];unsigned char bdata data_ds1302;
unsigned char disbuf[]={0,0,0,0};sbit k4=P1^3;
sbit TMDAT=P3^4;
//溫度入口
void dmsec(unsigned int count);void tmreset(void);
//ds18b20 reset void tmstart(void);
// void tmrtemp(void);void Disbuf(unsigned int temper);void displaytemper();void delay(unsigned int);main(){ display_buffer[0]=0x01;
display_buffer[1]=0x00;
display_buffer[2]=0x00;display_buffer[3]=0x08;
display_buffer[4]=0x05;
display_buffer[5]=0x00;display_buffer[6]=0x01;
display_buffer[7]=0x04;
display_buffer[8]=0x00;display_buffer[9]=0x05;
display_buffer[10]=0x00;
display_buffer[11]=0x01;
display_buffer[12]=0x04;while(1){ tmstart();
tmrtemp();
displaytemper();} }
void tmreset(void){
unsigned int i;
TMDAT = 0;
i = 103;while(i>0)i--;
TMDAT = 1;
i = 4;while(i>0)i--;}
void tmpre(void){
unsigned int i;
while(TMDAT);
while(~TMDAT);
i = 4;while(i>0)i--;}
bit tmrbit(void){
// ds1820
// Reset TX
unsigned int i;
bit dat;
TMDAT = 0;i++;
TMDAT = 1;i++;i++;
dat = TMDAT;
i = 8;while(i>0)i--;
return(dat);}
unsigned char tmrbyte(void){
unsigned char i,j,dat;
dat = 0;
for(i=1;i<=8;i++){
j = tmrbit();
dat =(j << 7)|(dat >> 1);
}
return(dat);}
void tmwbyte(unsigned char dat){
unsigned int i;
unsigned char j;
bit testb;
for(j=1;j<=8;j++){
testb = dat & 0x01;
dat = dat >> 1;
if(testb){
TMDAT = 0;
i++;i++;
TMDAT = 1;
i = 8;while(i>0)i--;
}
else {
TMDAT = 0;
i = 8;while(i>0)i--;
TMDAT = 1;
i++;i++;
}
} }
void tmstart(void){
tmreset();
tmpre();
// ds1820
displaytemper();//delay(100);
tmwbyte(0xcc);
tmwbyte(0x44);
}
void tmrtemp(void){
unsigned char a,xiao,b,y1,y2,y3;
tmreset();
tmpre();
delay(1);
tmwbyte(0xcc);
tmwbyte(0xbe);
a = tmrbyte();
b = tmrbyte();
xiao=a&0x0f;//小數(shù)部分
y1=a>>4;
y2=b<<4;
y3=y1|y2;if((b&0x0f8)==0x0f8)
{y3=~y3+1;
disbuf[0]=10;//顯示符號
disbuf[1]=y3/10;
disbuf[2]=y3%10;
disbuf[3]=xiao*10*0.0625;} else
disbuf[0]=11;//不顯示
disbuf[1]=y3/10;
disbuf[2]=y3%10;
disbuf[3]=xiao*10*0.0625;}
void displaytemper()
//溫度顯示函數(shù)
{ unsigned int i;unsigned char e=0x01;//<<1;for(i=1;i<6;i++)
{ switch(i)
{
case 1:{SEGMENT=table[disbuf[1]];BIT_LED=e;break;}
case 2:{SEGMENT=table1[disbuf[2]];BIT_LED=e;break;}
case 3:{SEGMENT=table[disbuf[3]];BIT_LED=e;break;}
case 4:{SEGMENT=table[12];BIT_LED=e;break;}
case 5:{SEGMENT=table[13];BIT_LED=e;break;}
}
e=e<<1;
delay(80);
}
BIT_LED=0;
}
void delay(unsigned int i)
//delay函數(shù) {
while(i--);}
測試結(jié)果:
經(jīng)傳感器及數(shù)碼管延時,溫度重新顯示
八、時鐘日歷測試
測試要求:本系統(tǒng)使用了時鐘日歷專用芯片,該芯片是以串行方式實現(xiàn)控制和數(shù)據(jù)傳輸?shù)摹?/p>
編寫如下程序進行測試: #include
//段碼寄存器地址 #define BIT_LED XBYTE[0x0a000]
//位碼寄存器地址 #define fosc 11.0592
unsigned char table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x67,0x40,0x00,0x63,0x39,};unsigned char table1[]={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef};unsigned char table2[]={0x76,0x79,0x38,0x38,0x3f};sbit k1=P1^0;sbit k2=P1^1;sbit k3=P1^2;sbit k4=P1^3;//利用開關(guān)量實現(xiàn)切換
//頻率變量及子函數(shù)預(yù)定義 void displayfreq();void read_freq();unsigned char tcount=0,timecount=0;unsigned long freq=0.0;bit freqflag=0;unsigned char fr[6];unsigned int i=0,x=0;
//日期變量及子函數(shù)預(yù)定義 sbit SCL_ds1302=P2^0;sbit IO_ds1302=P2^1;sbit RST_ds1302=P2^2;
unsigned char data display_buffer[13];unsigned char bdata data_ds1302;
//傳輸符
unsigned char disbuf[]={0,0,0,0};void open_write_bit();void initial_ds1302();unsigned char read_ds1302(char command);void close_write_bit();void read_time();void set_time();void delay(unsigned int i);void delayms(unsigned int i);void displaytime();void displaydate();main(){ initial_ds1302();
//上電走時
read_time();
//讀取當前時間,放到數(shù)組中
display_buffer[0]=0x01;
display_buffer[1]=0x05;
display_buffer[2]=0x01;display_buffer[3]=0x07;
display_buffer[4]=0x04;
display_buffer[5]=0x00;display_buffer[6]=0x01;
display_buffer[7]=0x06;
display_buffer[8]=0x00;display_buffer[9]=0x05;
display_buffer[10]=0x00;
display_buffer[11]=0x01;
display_buffer[12]=0x04;
set_time();
//設(shè)置時間
while(1){
if(k1==0)
{
while(1){
read_time();
displaytime();
if(k2==0)break;
}
}
read_time();
displaydate();} }
void close_write_bit()//close write { unsigned int i;
SCL_ds1302=0;
_nop_();
RST_ds1302=1;_nop_();_nop_();data_ds1302=0x8e;
for(i=1;i<=8;i++){
SCL_ds1302=0;
IO_ds1302=(data_ds1302&0x01);
_nop_();
SCL_ds1302=1;
data_ds1302=data_ds1302>>1;} data_ds1302=0x80;
IO_ds1302=0;for(i=1;i<=8;i++){
SCL_ds1302=0;
IO_ds1302=(data_ds1302&0x01);
_nop_();
SCL_ds1302=1;
data_ds1302=data_ds1302>>1;} }
void open_write_bit()//open write { unsigned int i;SCL_ds1302=0;_nop_();
//打開寫保護//關(guān)閉寫保護
RST_ds1302=1;_nop_();_nop_();data_ds1302=0x8e;for(i=1;i<=8;i++){
SCL_ds1302=0;
IO_ds1302=data_ds1302&0x01;
_nop_();SCL_ds1302=1;
data_ds1302=data_ds1302>>1;} data_ds1302=0x00;
//0x00,書上為0x80 IO_ds1302=0;for(i=1;i<=8;i++){
SCL_ds1302=0;
IO_ds1302=data_ds1302&0x01;
_nop_();SCL_ds1302=1;
data_ds1302=data_ds1302>>1;} }
void initial_ds1302()
//初始化函數(shù) { unsigned int i;SCL_ds1302=0;_nop_();RST_ds1302=1;_nop_();_nop_();data_ds1302=0x8e;
for(i=1;i<=8;i++){
SCL_ds1302=0;
IO_ds1302=data_ds1302&0x01;
_nop_();SCL_ds1302=1;
data_ds1302=data_ds1302>>1;} IO_ds1302=0;data_ds1302=0x00;
for(i=1;i<=8;i++){
SCL_ds1302=0;
IO_ds1302=data_ds1302&0x01;
_nop_();SCL_ds1302=1;
data_ds1302=data_ds1302>>1;} RST_ds1302=0;SCL_ds1302=0;_nop_();RST_ds1302=1;_nop_();_nop_();data_ds1302=0x90;
for(i=1;i<=8;i++){ SCL_ds1302=0;IO_ds1302=data_ds1302&0x01;_nop_();SCL_ds1302=1;data_ds1302=data_ds1302>>1;}
data_ds1302=0x0a4;
for(i=1;i<=8;i++){ SCL_ds1302=0;IO_ds1302=data_ds1302&0x01;_nop_();SCL_ds1302=1;data_ds1302=data_ds1302>>1;} RST_ds1302=0;_nop_();SCL_ds1302=0;_nop_();RST_ds1302=1;
data_ds1302=0x8e;
for(i=1;i<=8;i++){ SCL_ds1302=0;IO_ds1302=data_ds1302&0x01;_nop_();SCL_ds1302=1;data_ds1302=data_ds1302>>1;}
data_ds1302=0x80;
for(i=1;i<=8;i++){ SCL_ds1302=0;IO_ds1302=data_ds1302&0x01;_nop_();SCL_ds1302=1;data_ds1302=data_ds1302>>1;} RST_ds1302=0;_nop_();SCL_ds1302=0;}
unsigned char read_ds1302(char command)
//read函數(shù) { unsigned int i;data_ds1302=command;SCL_ds1302=0;_nop_();RST_ds1302=1;for(i=1;i<=8;i++){
SCL_ds1302=0;IO_ds1302=data_ds1302&0x01;_nop_();SCL_ds1302=1;data_ds1302=data_ds1302>>1;}
SCL_ds1302=1;for(i=1;i<=8;i++){
SCL_ds1302=0;
if(IO_ds1302)data_ds1302=(data_ds1302>>1)|0x80;
//送入到data_ds1302中,準備送出
else data_ds1302>>=1;SCL_ds1302=1;} RST_ds1302=0;_nop_();SCL_ds1302=0;return(data_ds1302);}
void write_ds1302(unsigned char address,unsigned char numb){
unsigned int i;
SCL_ds1302=0;
RST_ds1302=0;
RST_ds1302=1;
data_ds1302=address;for(i=1;i<=8;i++){
SCL_ds1302=0;
IO_ds1302=data_ds1302&0x01;
//送入寫地址
_nop_();SCL_ds1302=1;
data_ds1302=data_ds1302>>1;} data_ds1302=numb;for(i=1;i<=8;i++){
SCL_ds1302=0;
IO_ds1302=data_ds1302&0x01;
_nop_();SCL_ds1302=1;
data_ds1302=data_ds1302>>1;} } void read_time(){ unsigned char second,minte,hour,d,date,month,year,zhou;second=0x81;
//讀秒
d=read_ds1302(second);display_buffer[5]=d&0x0f;display_buffer[4]=d>>4;minte=0x83;
//讀分
d=read_ds1302(minte);display_buffer[3]=d&0x0f;display_buffer[2]=d>>4;hour=0x85;
//讀時
d=read_ds1302(hour);display_buffer[1]=d&0x0f;display_buffer[0]=d>>4;year=0x8d;
//讀年
d=read_ds1302(year);display_buffer[7]=d&0x0f;display_buffer[6]=d>>4;month=0x89;
//讀月
d=read_ds1302(month);display_buffer[9]=d&0x0f;display_buffer[8]=d>>4;
//送入寫的內(nèi)容
zhou=0x8b;
//讀周d=read_ds1302(zhou);display_buffer[12]=d;date=0x87;
//讀日期
d=read_ds1302(date);display_buffer[11]=d&0x0f;display_buffer[10]=d>>4;}
void set_time(){ unsigned char data temp;unsigned char data hour_address=0x84,minte_address=0x82,second_address=0x80,date_address=0x86,month_address=0x88,zhou_address=0x8a,year_address=0x8c;//各個時間量的地址
open_write_bit();
temp=(display_buffer[0]<<4)|display_buffer[1];write_ds1302(hour_address,temp);
//寫小時
temp=(display_buffer[2]<<4)|display_buffer[3];write_ds1302(minte_address,temp);
//寫分鐘
temp=(display_buffer[4]<<4)|display_buffer[5];write_ds1302(second_address,temp);
//寫秒
temp=(display_buffer[6]<<4)|display_buffer[7];write_ds1302(year_address,temp);
//寫年
temp=(display_buffer[8]<<4)|display_buffer[9];write_ds1302(month_address,temp);
//寫月
temp=display_buffer[12];write_ds1302(zhou_address,temp);
//寫周temp=(display_buffer[10]<<4)|display_buffer[11];write_ds1302(date_address,temp);
//寫日期
close_write_bit();
}
void delay(unsigned int i)
//delay函數(shù) {
while(i--);}
void delayms(unsigned int i){ unsigned int n;while(i--){
for(n=0;n<125;n++);
} }
void displaytime(){ unsigned char e=0x01;unsigned int i;BIT_LED=0;
for(i=0;i<=5;i++){
if(i==5||i%2==0||i==11)
SEGMENT=table[display_buffer[i]];
else
SEGMENT=table1[display_buffer[i]];
BIT_LED=e;
e<<=1;
delayms(1);
}
}
void displaydate(){ unsigned char e=0x01;unsigned int i;BIT_LED=0;
for(i=6;i<=13;i++){
if(i==7||i==9)
SEGMENT=table1[display_buffer[i]];
else if(i==12)
SEGMENT=table[10];
else if(i==13)
SEGMENT=table[display_buffer[i-1]];
else
SEGMENT=table[display_buffer[i]];
BIT_LED=e;
e<<=1;delayms(1);
}
}
測試結(jié)果:
S1,S2實現(xiàn)年月日周與時分秒的切換
九、語音收錄播報測試:
測試要求:本系統(tǒng)中使用的是語音專用芯片IDS1760芯片,該芯片是以串行方式實現(xiàn)控制和數(shù)據(jù)傳輸?shù)摹?/p>
編寫如下程序進行測試: #include
unsigned char bdata SR0_L;unsigned char bdata SR0_H;unsigned char bdata SR1;unsigned char APCL=0,APCH=0;unsigned char PlayAddL=0,PlayAddH=0;unsigned char RecAddL=0,RecAddH=0;
sbit CMD=SR0_L^0;sbit FULL=SR0_L^1;sbit PU=SR0_L^2;sbit EOM=SR0_L^3;sbit INTT=SR0_L^4;sbit RDY=SR1^0;sbit ERASE=SR1^1;sbit PLAY=SR1^2;sbit REC=SR1^3;
unsigned char ISD_SendData(unsigned char dat);void ISD_PU(void);void ISD_Rd_Status(void);void ISD_WR_APC2(unsigned char apcdatl,apcdath);void ISD_SET_PLAY(unsigned char Saddl,Saddh,Eaddl,Eaddh);void ISD_SET_Rec(unsigned char Saddl,Saddh,Eaddl,Eaddh);void ISD_SET_Erase(unsigned char Saddl,Saddh,Eaddl,Eaddh);
sbit SS=P1^4;sbit SCK=P1^7;sbit MOSI=P1^5;sbit MISO=P1^6;
void Cpu_Init(void);void ISD_Init(void);void delay(unsigned int t);
void main(){ Cpu_Init();ISD_Init();
while(1){ ISD_SET_Erase(0,0,9,0);ISD_SET_Rec(0,0,9,0);ISD_SET_PLAY(0,0,9,0);} }
void Cpu_init(void){ P0=P1=P2=P3=0xff;TMOD=0x01;EA=0;} void ISD_Init(void){ uchar i=2;SS=1;SCK=1;MOSI=0;do { ISD_PU();//上電 delay(50);ISD_Rd_Status();//讀取狀態(tài)
}while(CMD||(!PU));
//if(CMD_Err==1||(PU!+1))則再次發(fā)送上電指令 ISD_WR_APC2(0x40,0x04);//將0x0440寫入APC寄存器
do { ISD_Rd_Status();}while(RDY==0);do { delay(300);delay(300);i--;}while(i>0);}
//向cpu讀回或發(fā)送數(shù)據(jù)
unsigned char ISD_SendData(unsigned char dat){ unsigned char i,j,BUF_ISD=dat;SCK=1;SS=0;for(j=4;j>0;j--){;}
for(i=0;i<8;i++){ SCK=0;for(j=2;j>0;j--){;} if(BUF_ISD&0x01)
{MOSI=1;} else
{MOSI=0;} BUF_ISD>>=1;if(MISO)
{BUF_ISD|=0x80;} SCK=1;for(j=6;j>0;j--){;} } MOSI=0;return(BUF_ISD);} void ISD_PU(void){
ISD_SendData(0x01);
ISD_SendData(0x00);
SS=1;} void ISD_Rd_Status(void){ unsigned char i;ISD_SendData(0x05);ISD_SendData(0x00);ISD_SendData(0x00);SS=1;for(i=2;i>0;i--){;} SR0_L=ISD_SendData(0x05);SR0_H=ISD_SendData(0x00);SR1=ISD_SendData(0x00);SS=1;}
void ISD_WR_APC2(unsigned char apcdatl,apcdath){ ISD_SendData(0x65);ISD_SendData(apcdatl);ISD_SendData(apcdath);SS=1;}
void ISD_SET_PLAY(unsigned char Saddl,Saddh,Eaddl,Eaddh){ ISD_SendData(0x80);ISD_SendData(0x00);ISD_SendData(Saddl);ISD_SendData(Saddh);ISD_SendData(Eaddl);ISD_SendData(Eaddh);ISD_SendData(0x00);SS=1;}
void ISD_SET_Rec(unsigned char Saddl,Saddh,Eaddl,Eaddh){
ISD_SendData(0x81);ISD_SendData(0x00);ISD_SendData(Saddl);ISD_SendData(Saddh);ISD_SendData(Eaddl);ISD_SendData(Eaddh);ISD_SendData(0x00);SS=1;}
void ISD_SET_Erase(unsigned char Saddl,Saddh,Eaddl,Eaddh){ ISD_SendData(0x82);ISD_SendData(0x00);ISD_SendData(Saddl);ISD_SendData(Saddh);ISD_SendData(Eaddl);ISD_SendData(Eaddh);ISD_SendData(0x00);SS=1;} void delay(unsigned int t){ for(;t>0;t--){ TH0=0xfc;TL0=0x18;TR0=1;while(TF0!=1){;} TF0=0;TR0=0;} }
測試結(jié)果:需要在程序中設(shè)置斷點,完成錄音,放音再錄音放音的循環(huán)操作。
測試功能正常。
十、單片機模塊調(diào)試
測試要求:該模塊的調(diào)試很復(fù)雜,牽扯面也很多。其實通過前面各個模塊的調(diào)試,已經(jīng)大部分得到了間接地驗證。例如在“動態(tài)數(shù)碼管測試”和“串行通訊測試”中就是用到了定時器。
如有必要可以再編寫一些測試程序。例如檢測單片機的某一口線的功能是否正常、測試某段程序運行時間,等等。
測試結(jié)論:因單片機大部分功能在前調(diào)試方案中大部分已使用過,此處不再進行其余調(diào)試。
第三篇:單片機出租車計價器源程序
出租車計價器設(shè)計與制作
設(shè)計并制作一臺出租車計價器。調(diào)試時采用10Hz方波信號模擬,每個方波代表10m?;疽螅?/p>
(1)不同情況具有不同的收費標準
白天 1元/公里 晚上 2元/ 公里 途中等待(30s)1元/30s
(2)數(shù)據(jù)輸出(6位LED數(shù)碼管顯示)
單價輸出2位 路途輸出2位 總金額輸出2位
(3)按鍵(3個)
啟動計價開關(guān) 數(shù)據(jù)復(fù)位(清零)白天/晚上轉(zhuǎn)換
3.4.1模塊1:系統(tǒng)設(shè)計
(1)分析任務(wù)要求,寫出系統(tǒng)整體設(shè)計思路
通過分析,需要實現(xiàn)四個主要的功能模塊,分別為脈沖計數(shù)模塊、定時器計時模塊、按鍵的處理以及
數(shù)碼管動態(tài)掃描等功能。
定時器計時模塊主要完成途中等待(即沒有脈沖來時)30秒的計時。在啟動鍵按下后,定時器就不停的計時,只要有脈沖來就將計時的值清除為零。如果沒有脈沖來,當計時超過30秒時,相應(yīng)的總金額要
按照收費標準計價。
中斷的管理:盡管中斷有嵌套以及優(yōu)先級的功能,但是由于定時器已經(jīng)使用一個了中斷資源,脈沖檢測不宜再采用中斷方式,而是采用查詢方式。由于需要不停的要清除30秒的計時,因此,脈沖的計數(shù)不
采用定時器的計數(shù)方式。
啟動鍵觸發(fā)定時器開始工作,而定時器的運行可以作為脈沖計數(shù)的標志,只要定時器計時在運行,每來一個中斷都應(yīng)該計數(shù)。
主程序完成鍵盤的掃描和按鍵的處理,查詢脈沖產(chǎn)生的中斷,并完成脈沖的計數(shù)。每個脈沖代表10米,則當計數(shù)到100時表示1千米的距離,相應(yīng)的總金額要按照收費標準計價
(2)選擇單片機型號和所需外圍器件型號,設(shè)計單片機硬件電路原理圖
采用MCS51系列單片機At89S51作為主控制器,外圍電路器件包括數(shù)碼管驅(qū)動、獨立式鍵盤、復(fù)位電
路等。硬件電路原理圖如圖3-9所示。
圖3-11 出租車計價器的硬件電路原理圖
數(shù)碼管驅(qū)動采用2個四聯(lián)共陰極數(shù)碼管顯示,由于單片機驅(qū)動能力有限,采用74HC244作為數(shù)碼管的驅(qū)動。在74HC244的7段碼輸出線上串聯(lián)100歐姆電阻起限流作用。
獨立式按鍵使用上提拉電路連接,在沒有鍵按下時,輸出高電平。P0口用于輸出7段LED共陰極顯示代碼,P2口用于輸出低電平有效的位選碼。0~9的7段LED共陰極顯示代碼:3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH。
(3)分析軟件任務(wù)要求,寫出程序設(shè)計思路,分配單片機內(nèi)部資源,畫出程序流程圖
軟件的任務(wù)要求包括定時器的設(shè)置、按鍵的掃描、按鍵的功能處理、脈沖的計數(shù)、路途等待超30秒的計
時以及總金額的計算等。
程序設(shè)計的思路:使用中斷方式對定時器的溢出進行計數(shù)實現(xiàn)30秒的計時。主程序采用查詢外部中斷標志實現(xiàn)脈沖的計數(shù),由于每個脈沖代表10m,因此,當脈沖計數(shù)超過100時,計價器按照收費標準計價。主程序在初始化變量和定時器參數(shù)設(shè)置之后,進入一個循環(huán)結(jié)構(gòu),循環(huán)掃描鍵盤、查詢脈沖的中斷、數(shù)碼管的動態(tài)掃描等功能,當脈沖的中斷標志被查詢到,若路途等待時間未超30秒時,要及時將路途等待時間的值清除為零。主程序的流程圖如圖3-12所示。
圖3-12 出租車計價器的主程序流程圖
中斷服務(wù)程序主要實現(xiàn)計時功能,當啟動鍵按下之后,定時器開始工作,用一個變量對定時器溢出中斷的次數(shù)進行計數(shù),達到計時功能,該變量在每次脈沖到來時被清零(在主程序中清零),當脈沖長時間沒有來,則當該變量計數(shù)超過30秒時,總金額按照途中等待計費標準進行計價。中斷程序的流程圖如圖
3-13所示。
圖3-13 出租車計價器的中斷服務(wù)程序流程圖
(4)設(shè)計系統(tǒng)軟件調(diào)試方案、硬件調(diào)試方案及軟硬件聯(lián)合調(diào)試方案
軟件調(diào)試方案:偉福軟件中,在“文件新建文件”中,新建C語言源程序文件,編寫相應(yīng)的程序。在“文件新建項目”的菜單中,新建項目并將C語言源程序文件包括在項目文件中。
在 “項目編譯”菜單中將C源文件編譯,檢查語法錯誤及邏輯錯誤。在編譯成功后,產(chǎn)生以 “*.hex”和“*.bin” 后綴的目標文件。
硬件調(diào)試方案:在設(shè)計平臺中,將單片機的P1.0-P1.2分別與3個獨立式鍵盤通過插線連接起來,將P3.2與脈沖信號源連接起來。
在偉福中將程序文件編譯成目標文件后,將下載線安裝在實驗平臺上,運行“MCU下載程序”,選擇相應(yīng)的flash 數(shù)據(jù)文件,點擊“編程”按鈕,將程序文件下載到單片機的Flash中。
然后,上電重新啟動單片機,檢查所編寫的程序是否達到題目的要求,是否全面完整地完成試題的內(nèi)容。3.4.2 程序設(shè)計
/*晶振:11.0592M T1-250微秒溢出中斷一次;P3.2(int0)-中斷100次,查詢IE0置位,P1^0為啟動鍵;P1^1為清除鍵;P1^2為白天/晚上的切換鍵 變量的定義: key_val: 返回按鍵的值 255-無鍵
T1_cnt: 定時器溢出數(shù)計數(shù)
cnt_30: 30秒鐘的計時
cnt_distance: 計算路程
cnt_cost: 總金額
state_val: 狀態(tài):0-白天 1 夜晚
cost_val[3]: 收費標準:白天單價cost_val[0]=1元/公里;晚上單價cost_val[1]=2元/公里; 等待單價cost_val[2]=1元/30s
led_seg_code:數(shù)碼管7段碼 */ //-------------------#include “reg51.h” unsigned char data cnt_30,cnt_distance,cnt_cost;unsigned int data T1_cnt,D_cnt;unsigned char data key_val,key_val_old;unsigned char data state_val;char code cost_val[3]={1,2,1};char code led_seg_code[10]={0x3f,0x06,0x05b,0x04f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//led_seg_code[0-9]代表0-9 //-------延時-----------------void delay(unsigned int i)//延時 { while(--i);} //-------初始化變量------------------void init_variant()//初始化一些變量的內(nèi)容 {unsigned char i;cnt_30=0;//30秒的計時 D_cnt=0;//脈沖的個數(shù) cnt_distance=0;//距離的計數(shù)
cnt_cost=0;//保存總價格 } //-------掃描鍵盤-----------------unsigned char scan_key(){ unsigned char i,k;i=P1;if(i==0xff){ k=255;} //無鍵按下
else //有鍵按下
{ delay(10);//延時去抖動
if(i!=P1){k=255;} else { switch(i){ case 0xfe: k=0;break;//P1.0按下,啟動鍵
case 0xfd: k=1;break;//P1.1按下,清除鍵
case 0xfb: k=2;break;//P1.2按下,切換鍵
} } } return k;} //-------數(shù)碼管動態(tài)掃描-------------void led_show(){unsigned char i,k;
//-----顯示單價----k=cost_val[state_val];i=k%10;//暫存?zhèn)€位 P0=led_seg_code[i];P2=0xbf;delay(10);i=k%100/10;P0=led_seg_code[i];P2=0x7f;delay(10);//-----顯示距離------k=cnt_distance;i=k%10;//暫存?zhèn)€位 P0=led_seg_code[i];P2=0xf7;delay(10);i=k%100/10;P0=led_seg_code[i];P2=0xef;delay(10);//-----顯示總價格-----------k=cnt_cost;i=k%10;//暫存?zhèn)€位 P0=led_seg_code[i];P2=0xfe;delay(10);i=k%100/10;P0=led_seg_code[i];P2=0xfd;delay(10);} //-------計時----------------void timer1()interrupt 3 //T1中斷 { T1_cnt++;if(T1_cnt>3999)//如果計數(shù)>3999, 計時1s { T1_cnt=0;if(cnt_30<30)//沒有超過30秒,繼續(xù)計時
{cnt_30++;} else //超過30秒,途中等待計價
{cnt_30=0;cnt_cost=cnt_cost+cost_val[2];} } } //---------主程序----------------
main(){//初始化各變量 T1_cnt=0;state_val=0;key_val_old=255;init_variant();//初始化51的寄存器
TMOD=0x20;//用T1計時 8位自動裝載定時模式,不用T0 TH1=0x19;//250微秒溢出一次;250=(256-x)*12/11.0592-> x= 230.4 TL1=0x19;EA=1;//開中斷 ET1=1;
TR1=0;//定時器T0 TCON=0x01;//Int0中斷取邊沿觸發(fā)模式 while(1){ key_val=scan_key();// 255;// if(key_val!=key_val_old){ key_val_old=key_val;if(key_val!=255){ switch(key_val){ case 0: //啟動鍵
TR1=1;//啟動計時,TR1=1為啟動了的標志
break;case 1: //清除鍵
init_variant();//清除變量
TR1=0;//關(guān)閉定時器
break;case 2: //白天/黑夜的切換
if(state_val==0){state_val=1;} else {state_val=0;} break;} } } if(IE0==1&& TR1==1)//每來1個脈沖,中斷一次
{ IE0=0;cnt_30=0;//30秒的計時清零
if(D_cnt<100)
{D_cnt++;} else //計數(shù)100次,每次10米,表示一公里
{D_cnt=0;cnt_distance=cnt_distance+1;
cnt_cost=cnt_cost+cost_val[state_val];} } led_show();} } //-----出租車計價器程序結(jié)束------------
第四篇:出租車計價器 硬件課程設(shè)計
硬件課程設(shè)計報告
題目:出租車計價器
目錄
1. 引言....................................................................................................................................錯誤!未定義書簽。
1.1設(shè)計目的................................................................................................................錯誤!未定義書簽。1.2設(shè)計任務(wù)................................................................................................................錯誤!未定義書簽。1.3設(shè)計思路................................................................................................................錯誤!未定義書簽。
2.需求分析.............................................................................................................................錯誤!未定義書簽。
2.1芯片原理................................................................................................................錯誤!未定義書簽。2.1.1可編程計數(shù)器/定時器8253/8254原理.............................................................錯誤!未定義書簽。2.1.2可編程外圍接口芯片8255原理.......................................................................錯誤!未定義書簽。2.1.3 12864液晶顯示器ST7920原理........................................................................錯誤!未定義書簽。2.2硬件設(shè)計................................................................................................................錯誤!未定義書簽。2.3軟件設(shè)計................................................................................................................錯誤!未定義書簽。2.3.1功能模塊圖.........................................................................................................錯誤!未定義書簽。2.3.2程序流程圖.........................................................................................................錯誤!未定義書簽。2.3.3模塊流程圖.........................................................................................................錯誤!未定義書簽。
3.詳細設(shè)計.............................................................................................................................錯誤!未定義書簽。
3.1程序模塊分析........................................................................................................錯誤!未定義書簽。3.1.1初始化模塊程序分析.........................................................................................錯誤!未定義書簽。3.1.2判斷開關(guān)程序模塊分析.....................................................................................錯誤!未定義書簽。3.1.3圈數(shù)統(tǒng)計模塊程序分析.....................................................................................錯誤!未定義書簽。3.1.4計算里程模塊程序分析.....................................................................................錯誤!未定義書簽。3.1.5顯示模塊程序分析.............................................................................................錯誤!未定義書簽。3.1.6結(jié)束模塊程序分析.............................................................................................錯誤!未定義書簽。3.2程序代碼................................................................................................................錯誤!未定義書簽。
4.5.6.程序結(jié)果.............................................................................................................................錯誤!未定義書簽。分析與測試.........................................................................................................................錯誤!未定義書簽。體會.....................................................................................................................................錯誤!未定義書簽。
附錄A:參考文獻.....................................................................................................................錯誤!未定義書簽。
一、引言
1.1設(shè)計目的
現(xiàn)在各大城市出租車已經(jīng)成為了一種重要的交通工具,當然出租車的收費問題也成了人們關(guān)注的焦點,那么怎么樣才能實現(xiàn)一種合理的收費方式讓大家都認可呢?在這種要求下,出租車自動計價器就走進了人們的生活,當然這就要求有一種合理公正的計價器收費方式。這不僅關(guān)系到出租車計價器的市場,也影響這出租車的市場,這就要求我們設(shè)計出更好的計價器來滿足人們的需求。
本設(shè)計是關(guān)于出租車計價器的設(shè)計。在本次設(shè)計中,我以計價器的基本功能作為設(shè)計的重點。為了完成上述設(shè)計,我們采用了8254、8255等芯片,用計算機匯編語言進行軟件功能的實現(xiàn)。
1.2設(shè)計任務(wù)
1.實現(xiàn)一個出租車計價器,可以顯示起步價。2.一個鍵來控制是否到達終點,是否計價要清零。3.基于路程的出租車計價方式。
1.3設(shè)計思路
利用直流電機來模仿出租車輪子的轉(zhuǎn)動來計算出租車行進的路程。將直流電機的直流端與滑動變阻器相連,通過人工控制滑動變阻器來模擬出租車的行進;并將計數(shù)端與8253CLK0端相連,GATE0接高電平,工作方式為方式二。直流電機每轉(zhuǎn)1000圈,8253輸出一個高電平,假設(shè)出租車已經(jīng)走了1公里。同時將8253OUT0接入8255方便CPU讀取。再將8255與ST7920顯示器相連,CPU通過控制8255來控制顯示,一旦8255從8253讀入一個高電平,則公里數(shù)加一,同時價格相應(yīng)增加。另有一個開關(guān)連入8255,用以判斷出租車計價器是否啟動。
二、需求分析
2.1芯片原理
本節(jié)主要在介紹本次設(shè)計所用到的芯片的原理,共有可編程計數(shù)器/定時器8253/8254、可編程外圍接口芯片8255和12864液晶顯示器ST7920原理三種芯片。
2.1.1可編程計數(shù)器/定時器8253/8254原理
圖2-1 8254內(nèi)部結(jié)構(gòu)圖
從圖2-1可見,8254內(nèi)部包含數(shù)據(jù)總線緩沖器、讀/寫控制邏輯、控制字寄存器和3個結(jié)構(gòu)完全相同的計數(shù)器,這3個計數(shù)器分別稱為計數(shù)器0、計數(shù)器1和計數(shù)器2。
圖2-2 8254管腳圖
A1、A0:地址輸入線,用來控制8253內(nèi)部的4個端口,即3個計數(shù)器和1個控制字寄存器與CPU系統(tǒng)地址線相連。
CLK0-2:時鐘脈沖輸入端,用于輸入定時脈沖或計數(shù)脈沖信號。CLK可以是系統(tǒng)的時鐘脈沖,也可以由系統(tǒng)時鐘分頻或者其他脈沖源提供。當用于定時時,這個脈沖必須是均勻的、連續(xù)的、周期精確的,而用于計數(shù)時,這個脈沖可以是不均勻的、斷續(xù)的、周期不定的。
GATE0-2:門控輸入端,用于外部控制計數(shù)器的啟動計數(shù)和停止計數(shù)的操
作。兩個或兩個以上計數(shù)器連用時,可用此信號同步,也可用于與外部某信號的同步。
OUT0-2:計數(shù)輸出,當計數(shù)器從初值開始完成計數(shù)操作進,OUT引腳輸出相應(yīng)的信號。
8253的方式控制字
圖2-3 8254控制字圖
本設(shè)計中8254的功能
只是用通道1,采用方式三。采用二進制計數(shù),輸入0FFFH。先輸入低字節(jié),再輸入高字節(jié)。當8254從0FFFFH遞減到159FH時(即轉(zhuǎn)了60000圈時),8254向總線發(fā)信號使程序向下進行。
2.1.2可編程外圍接口芯片8255原理
內(nèi)部結(jié)構(gòu)如圖所示,由以下4個部分組成:
圖2-4 8255內(nèi)部結(jié)構(gòu)圖
(1)輸入/輸出端口A、B、C。這三個端口均可看作是I/O端口,但它們的結(jié)構(gòu)和功能也稍有不同。A口和B口是一個獨立的8位I/O口。C口:可以看作是一個獨立的8位I/O口;也可以看作是兩個獨立的4位I/O口。
(2)A組和B組控制電路。這是兩組根據(jù)CPU命令控制8255A工作方式的電路,這些控制電路內(nèi)部設(shè)有控制寄存器,可以根據(jù)CPU送來的編程命令來控制8255A的工作方式,也可以根據(jù)編程命令來對C口的指定位進行置/復(fù)位的操作。A組控制電路用來控制A口及C口的高4位;B組控制電路用來控制B口及C口的低4位
(3)讀/寫控制邏輯。(同上:它負責管理8255A的數(shù)據(jù)傳輸過程。它接收CS*及RD*、WR*、RESET,還有來自系統(tǒng)地址總線的口地址選擇信號A0和A1。將這些信號組合后,得到對A組控制部件和B組控制部件的控制命令,并將命令發(fā)給這兩個部件,以完成對數(shù)據(jù)、狀態(tài)信息和控制信息的傳輸。)
(4)數(shù)據(jù)總緩沖器。(同上:它是8位的雙向的三態(tài)緩沖器。作為8255A與系統(tǒng)總線連接的界面,輸入/輸出的數(shù)據(jù),CPU的編程命令以及外設(shè)通過8255A傳送的工作狀態(tài)等信息,都是通過它來傳輸?shù)?。?/p>
如圖所示8255A的芯片引腳信號。除了電源和地以外,其他信號可以分為兩組:
圖2-5 8255管腳圖
1.和外設(shè)一邊相連的: PA7-PA0:A組數(shù)據(jù)信號
PB7-PB0:B組數(shù)據(jù)信號 PC7-PC0:C組數(shù)據(jù)信號 2.和CPU一邊相連的:
RESET:復(fù)位信號,低電平有效。當RESET信號來到時,所有內(nèi)部寄存器就被清除,同時,3個數(shù)據(jù)端口被自動設(shè)為輸入端口。
D7-D0:它們是8255A的數(shù)據(jù)線,和系統(tǒng)數(shù)據(jù)總線相連。
CS*:芯片選擇信號,低電平有效。在一個系統(tǒng)中,一般根據(jù)全部接口芯片來分配若干較低位地址(比如A5、A4、A3)來組成各種芯片選擇碼,當這幾位地址組成某一個代碼時,譯碼器便往8255A的CS*端輸出一個低電平,于是8255A被選中。只有當 CS*有效時,讀信號RD*和寫信號WR*才對8255A有效。
RD*:芯片讀出信號低電平有效。WR*:芯片寫入信號低電平有效。8255的方式控制字格式
圖2-6 8255控制字圖
本設(shè)計中8255的功能
8255PA0-PA7和PC0-PC2與ST7920相連,控制輸出。PB0與8253的OUT1相連,讀入8253OUT1 的數(shù)據(jù)。PB1與開關(guān)K0相連,讀入K0的數(shù)值用于確定是否開啟計價器。
2.1.3可編程外圍接口芯片8255原理
ST7920控制器系列中文圖形液晶模塊的軟件特性主要由ST7920控制驅(qū)動器決定。ST7920同時作為控制器和驅(qū)動器,它可提供33路com輸出和64路seg輸出。在驅(qū)動器ST7921的配合下,最多可以驅(qū)動256×32點陣液晶。
ST7920是臺灣矽創(chuàng)電子公司生產(chǎn)的中文圖形控制芯片,它是一種內(nèi)置12864漢字圖形點陣的液晶顯示控制模塊,用于顯示漢字及圖形。該芯片共內(nèi)置8192
個中文漢字(16×16點陣)、128個字符的ASCII字符庫(8×16點陣)及64×2256點陣顯示RAM(GDRAM)。
為了能夠簡單、有效地顯示漢字和圖形,該模塊內(nèi)部設(shè)計有2MB的中文字型CGROM和64×256點陣的GDRAM繪圖區(qū)域;同時,該模塊還提供有4組可編程控制的16×16點陣造字空間;除此之外,為了適應(yīng)多種微處理器和單片機接口的需要,該模塊還提供了4位并行、8位并行、2線串行以及3線串行等多種接口方式。利用上述功能可方便地實現(xiàn)漢字、ASCII碼、點陣圖形、自造字體的同屏顯示,所有這些功能(包括顯示RAM、字符產(chǎn)生器以及液晶驅(qū)動電路和控制器)都包含在集成電路芯片里,因此,只要一個最基本的微處理系統(tǒng)就可以通過ST7920芯片來控制其它的芯片
圖2-7 ST7920外觀尺寸圖
本設(shè)計中ST7920的功能
用于顯示出租車行駛路程與應(yīng)收費用。
2.2硬件設(shè)計
其中,8253GATE1連+5V高電平,直流電機連0~+5V,8253連280h~287h,8255連288h~28fh。8255PA0-PA7連ST7920顯示器D0-D7,PC0連DI,PC1連RW,PC2連E。開關(guān)K0連8255PB0。8253CLK1連直流電機計數(shù)端。
0~+5V直流電機D0-D7計數(shù)ST7920顯示屏DIRWE+5VGATE1CLK1PA0-PA7+5VPC0PC1PC2開關(guān)K0PB0+5V8253CS8255CS280H-288H289H-28FH總線圖2-8硬件連接圖
實際連接圖如下圖所示
圖2-9硬件實際連接圖
2.3軟件設(shè)計 2.3.1功能模塊圖
本節(jié)先給出一個程序的功能模塊圖。
出租車計價器系統(tǒng)計價器開關(guān)功能模塊讀入直流電機轉(zhuǎn)圈數(shù)模塊ST7920顯示功能模塊根據(jù)里程計算價格模塊
圖2-10軟件功能模塊圖
2.3.2程序流程圖
本節(jié)先給出一個程序的整體流程圖。
開始結(jié)束8253初始化液晶顯示屏初始化8255初始化是計價器是否開始工作通過8255讀入b0否是否有鍵盤輸入否液晶顯示屏初始化是液晶顯示屏調(diào)用顯示價格功能從直流電機讀入輸入圈數(shù)將更改過的路程在顯示器中顯示出來讀到一定圈數(shù)走的路程加一比較路程是否大于3公里是價格為(路程-3)*2+7 元將儲存的顯示字符串內(nèi)路程價格改為目前路程價格否價格為7元
圖2-11軟件程序流程圖
2.3.3模塊流程圖
如果對整個程序進行細分則可以分為初始化模塊,判斷開關(guān)模塊,圈數(shù)統(tǒng)計模塊,計算里程模塊、結(jié)束模塊和顯示模塊。其中初始化模塊是8253芯片、8255芯片和顯示屏的初始化。判斷開關(guān)模塊是對8255的b0端是否有高電平進行判斷。
圈數(shù)統(tǒng)計模塊是對直流電機傳入8253中高電平的數(shù)量進行圈數(shù)統(tǒng)計。計算里程模塊是對里程及價格進行計算的模塊。結(jié)束模塊是程序結(jié)束的操作與方法。顯示模塊是控制顯示屏顯示計算模塊的結(jié)果。
初始化模塊顯示模塊調(diào)用關(guān)判斷開關(guān)模塊開結(jié)束模塊圈數(shù)統(tǒng)計模塊計算里程模塊調(diào)用顯示模塊圖2-12軟件模塊流程圖
三、詳細設(shè)計
3.1程序模塊分析
我們將按模塊分析程序的功能并給出模塊內(nèi)的功能流程圖。
3.1.1初始化模塊分析
在初始化模塊中,我們定義了需要使用的8255和8254的接口,需要使用的變量如JSS,要輸出的字符串等,初始化了DS,完成了8255的初始化以及顯示屏的初始化。其流程圖為
開始圖3-1初始化模塊流程圖
3.1.2判斷開關(guān)模塊分析
以上為判斷開關(guān)模塊,在判斷開關(guān)模塊中,系統(tǒng)讀入8255PB0的電平,如果是高電平則程序繼續(xù)進行,如果是低電平則程序調(diào)用chushi函數(shù),用屏幕顯示“空車歡迎乘坐”,并繼續(xù)度8255PB0直到有高電平為止。其流程圖如下所示:
8255PB0是否為高電平是圈數(shù)統(tǒng)計模塊否Chushi函數(shù)計數(shù)變量和對應(yīng)的字符串置零顯示 空車 歡迎乘坐 調(diào)用顯示模塊
圖3-2判斷開關(guān)模塊流程圖
3.1.3圈數(shù)統(tǒng)計模塊分析
在圈數(shù)統(tǒng)計模塊中,我們將直流電機計數(shù)端連入8254CLK1中(8253采用方式三),在CLK1中讀所記的數(shù),從0FFFFH向下計,一直計到159FH,即轉(zhuǎn)了6000圈后,進入程序的下一段。其流程圖如下所示:
讀8254計數(shù)值否是否到159FH以下是重新將8254計數(shù)初值設(shè)為0FFFFH計算里程模塊
圖3-3圈數(shù)統(tǒng)計模塊流程圖
3.1.4計算里程模塊分析
我們用地址JSS里表示已經(jīng)走過的公里,即8254傳過來的高電平,同時我們采用價格公式來計算價格,將其里程和價格對應(yīng)的中文字碼表存入要顯示的字符串中。我們用地址JSS里表示已經(jīng)走過的公里,即8254傳過來的高電平,同時我們采用價格公式來計算價格,將其里程和價格對應(yīng)的中文字碼表存入要顯示的字符串中。
計算公式為: 價格=(里程-3)* 2……(里程>3)
價格= 7…………………..(里程<=3)并調(diào)用顯示模塊來顯示這些字碼其流程圖如下所示:
圈數(shù)統(tǒng)計模塊計數(shù)值JSS加一并十進制化里程數(shù)加一里程數(shù)是否是大于3是價格為(里程-3)*2調(diào)用顯示模塊否價格為7
圖3-4計算里程模塊流程圖
3.1.5顯示模塊分析
在顯示模塊中,我們使用ST7920顯示我們要顯示的兩行字符串。我們采取先顯示第一行,再顯示第二行的方法,只是用ST7920的中間兩行。
調(diào)整顯示屏指針指向第二行調(diào)整顯示屏指針指向第三行調(diào)整字符串指針指向第一個字調(diào)整字符串指針指向第九個字輸出輸出延時延時
圖3-5顯示模塊流程圖
3.1.6結(jié)束模塊分析
結(jié)束模塊在程序的尾部在結(jié)束模塊中,我們規(guī)定只要在鍵盤上按任意一個鍵就會結(jié)束整個程序。如果無鍵按下,則程序自動跳轉(zhuǎn)到程序頭部。其程序流程圖如下圖所示:
調(diào)用DOS中斷是否有鍵按下是結(jié)束否判斷開關(guān)模塊
圖3-6結(jié)束模塊流程圖
3.2程序代碼
IO8253A
EQU 280H IO8253B
EQU 281H IO8253C
EQU 283H
DATA
SEGMENT HZ DW 0C2B7H,0B3CCH,0A3B0H,0A3B0H,0A3AEH,0A3B0H,0B9ABH,0C0EFH
DW BCDBH,0B8F1H,0A3B0H,0A3B0H,0A3B0H,0A3AEH,0A3B0H,0D4AAH;存放原始輸出 HZ_TAB DW 0C2B7H,0B3CCH,0A3B0H,0A3B0H,0A3AEH,0A3B0H,0B9ABH,0C0EFH
DW 0BCDBH,0B8F1H,0A3B0H,0A3B0H,0A3B0H,0A3AEH,0A3B0H,0D4AAH;存放要輸出的值 HZ_BG DW 0BFD5H,0B3B5H,0A2A0H,0A2A0H,0BBB6H,0D3ADH,0B3CBH,0D7F8H
DW 0A2A0H,0A2A0H,0A2A0H,0A2A0H,0A2A0H,0A2A0H,0A2A0H,0A2A0H;存放“空車歡迎乘坐”
HZ_ADR DB ?
;存放顯示行起始端口地址 JSS
DW 0000H DII
DW 0000H GAO
DW 0000H ZHE
DW 0000H NUMBER
DW 0A3B0H,0A3B1H,0A3B2H,0A3B3H,0A3B4H,0A3B5H,0A3B6H,0A3B7H,0A3B8H,0A3B9H DATA
ENDS IO_ADDRESS
EQU 288H
CODE SEGMENT ASSUME CS:CODE,DS:DATA START:
MOV AX,DATA MOV DS,AX
MOV DX,IO_ADDRESS ADD DX,3 MOV AL,82H OUT DX,AL
;8255初始化 MOV AL,0FFH MOV DX,300H OUT DX, AL CALL CLEAR
;LCD 清除
LLL:
MOV DX,IO_ADDRESS ADD DX,1 IN AL,DX
;判斷開關(guān)是否打開 AND AL,01H CMP AL,01H JZ F0 CALL CHUSHI JMP LLL F0: MOV AL,01110110B MOV DX,IO8253C OUT DX,AL
;8254初始化 MOV AL,0FFH MOV DX,IO8253B OUT DX,AL MOV AL,0FFH
;設(shè)置計數(shù)初值0FFFFH OUT DX,AL F1: MOV AL,01000000B
MOV DX,IO8253C OUT DX,AL MOV DX,IO8253B
IN AL,DX MOV AH,AL IN AL,DX XCHG AH,AL CMP AX,159FH
;查看是否下降到159FH JA F1
;不滿足條件繼續(xù)讀值
MOV AL,01110110B
;重置8253 MOV DX,IO8253C OUT DX,AL MOV AL,0FFH MOV DX,IO8253B OUT DX,AL MOV AL,0FFH OUT DX,AL
CALL DISP
;調(diào)顯示子程序
CALL DDSP
CALL DELAY PUSH DX
MOV AH,06H MOV DL,0FFH INT 21H POP DX
JZ LLL
MOV AH,4CH
;退出
INT 21H L1:
JMP
START;L1
CHUSHI PROC NEAR
LEA SI, HZ_TAB LEA DI,HZ MOV CX,0FH F3: ADD SI,2 ADD DI,2 MOV AX,[DI] MOV [SI],AX LOOP F3
;重置HZ_TAB
MOV AX,0000H LEA BX,JSS MOV [BX],AX LEA BX, HZ_BG MOV CH,2
CALL LCD_DISP LEA BX, HZ_BG MOV CH,3
;顯示“空車歡迎乘坐” CALL LCD_DISP RET CHUSHI ENDP
DDSP
PROC NEAR
LEA DI,HZ_TAB LEA BX,JSS LEA SI,NUMBER MOV AX,WORD PTR[BX]
MOV BP,AX AND BP,00FFH ADD BP,BP
MOV DX,WORD PTR[BP+SI] MOV WORD PTR[DI+6],DX
;將JSS中低八位傳入HZ_TAB MOV BP,AX AND BP,0FF00H ROR BP,8 ADD BP,BP MOV DX,WORD PTR[BP+SI] MOV WORD PTR[DI+4],DX
LEA BX, HZ_TAB
MOV CH,2
息
CALL LCD_DISP LEA DI,HZ_TAB LEA BX,JSS LEA SI,NUMBER MOV AX,WORD PTR[BX] CMP AX,0003H
JBE L3 CALL BJ LEA BX,JSS JMP L4
L3:MOV BP,0007H
ADD BP,BP MOV DX,WORD PTR[BP+SI ] MOV WORD PTR[DI+24],DX JMP L4 L4:
LEA BX, HZ_TAB
MOV CH,3
CALL LCD_DISP RET DDSP
ENDP
BJ
PROC NEAR
LEA DI,HZ_TAB LEA BX,JSS LEA SI,NUMBER MOV AX,WORD PTR[BX] CMP AL,03H
;將JSS中高八位傳入HZ_TAB
;顯示第2行信;比較路程與3的大小;路程比3小的情況
;顯示第3行信息
JAE BJ1 SUB AH,01H ADD AL,0AH SUB AL,03H AAS
;路程減三并十進制化 JMP BJ2 BJ1:
SUB AX,0003H BJ2: MOV CX,AX AND AX,00FFH ADD AL,AL AAA ADD AX,07H AAA
LEA BX,DII MOV [BX],AX;DII MOV BP,AX AND BP,00FFH ADD BP,BP MOV DX,WORD PTR[BP+SI] MOV WORD PTR[DI+24],DX
MOV AX,CX SHR AX,8 AND AX,00FFH ADD AL,AL
AAA LEA BX,GAO MOV [BX],AX;GAO LEA BX,DII MOV DX,[BX];DII AND AX,00FFH AND DX,0FF00H SHR DX,8 AND DX,00FFH ADD AL,DL
AAA LEA BX,ZHE MOV [BX],AX;ZHE MOV BP,AX AND BP,00FFH ADD BP,BP MOV DX,WORD PTR[BP+SI]
;路程加七并十進制化;先計算個位
;十位相加
;再加進位
MOV WORD PTR[DI+22],DX
;再計算十位 LEA BX,ZHE MOV DX,[BX] LEA BX,GAO MOV AX,[BX] AND DX,0FF00H AND AX,0FF00H SHR AX,8 SHR DX,8 ADD DL,AL
;百位加進位 AAA MOV BP,DX AND BP,00FFH ADD BP,BP MOV DX,WORD PTR[BP+SI] MOV WORD PTR[DI+20],DX
;最后計算百位 RET BJ ENDP
DISP
PROC NEAR
;顯示子程序
PUSH DX
LEA BX, JSS
MOV AX,WORD PTR[BX]
ADD AL,01H
CMP AL,09H
;判斷是否<=9
JLE NUM
;若是則為'0'-'9',ASCII碼加30H
MOV AL,00H
ADD AH,01H
CMP AH,0AH
JZ L2 NUM:
MOV WORD PTR[BX],AX
ADD AL,30H
ADD AH,30H
MOV DL,AH
MOV DH,AL
MOV AH,02H
;屏幕顯示
INT 21H
MOV DL,DH
MOV AH,02H
;屏幕顯示
INT 21H
MOV DL,0DH
;加回車符
INT 21H
MOV DL,0AH
;加換行符
INT 21H
POP DX
RET
;子程序返回 DISP ENDP L2: MOV AH,4CH
;退出
INT 21H
CLEAR
PROC
MOV AL,0CH
CLEAR
FUNCUP
;
;
;
FUNCUP
LCD_DISP
;
址
DISP_SEC:
NEXT:
CONTINUE:
MOV DX, IO_ADDRESS OUT DX,AL
;設(shè)置CLEAR命令 CALL CMD_SETUP
;啟動LCD執(zhí)行命令 RET
ENDP
PROC MOV AL, 0FH
;LCD功能設(shè)置命令 OUT DX, AL CALL CMD_SETUP MOV AL, 34H
;LCD顯示狀態(tài)命令 OUT DX, AL CALL CMD_SETUP RET
ENDP PROC LEA BX, HZ_TAB CMP CH, 2 JZ DISP_SEC MOV BYTE PTR HZ_ADR, 88H
;第三行起始端口地ADD BX,16
;指向第二行信息 JMP NEXT MOV BYTE PTR HZ_ADR,90H MOV CL,8
PUSH CX MOV AL,HZ_ADR MOV DX, IO_ADDRESS OUT DX, AL CALL CMD_SETUP
;設(shè)定DDRAM地址命令 MOV AX,[BX] PUSH AX MOV AL,AH
;先送漢字編碼高位 MOV DX,IO_ADDRESS OUT DX,AL CALL DATA_SETUP
;輸出漢字編碼高字節(jié)
CALL DELAY
;延遲
POP AX
MOV DX,IO_ADDRESS
OUT DX, AL
CALL DATA_SETUP
;輸出漢字編碼低字節(jié)
CALL DELAY
INC BX
INC BX
;修改顯示內(nèi)碼緩沖區(qū)指針
INC BYTE PTR HZ_ADR
;修改LCD顯示端口地址
POP CX
DEC CL
JNZ CONTINUE
RET LCD_DISP
ENDP CMD_SETUP
PROC
MOV DX,IO_ADDRESS
制端口
ADD DX,2
NOP
MOV AL,00000000B
(LCD I端=0,W端=0)
OUT DX, AL
CALL DELAY
NOP
MOV AL,00000100B
=1)
OUT DX, AL
NOP
CALL DELAY
MOV AL, 00000000B
0)
OUT DX, AL
CALL DELAY
RET CMD_SETUP
ENDP DATA_SETUP
PROC
MOV DX,IO_ADDRESS
口
ADD DX,2
MOV AL,00000001B
(LCD I端=1)
OUT DX, AL
NOP
CALL DELAY
;指向8255端口控
;PC1置0,PC0置0
;PC2置1(LCD E端
;PC2置0,(LCD E端置
;指向8255控制端
;PC1置0,PC0=1
MOV AL,00000101B
;PC2置1(LCD E端=1)
OUT DX, AL
NOP
CALL DELAY
MOV AL, 00000001B
;PC2置0,(LCD E端=0)
OUT DX, AL
NOP
CALL DELAY
RET DATA_SETUP
ENDP DELAY
PROC
PUSH CX
PUSH DX
MOV CX, 0FFFH X1:
LOOP
X1
POP DX
POP CX
RET DELAY
ENDP
CODE ENDS
END START
四、程序結(jié)果
我們利用8254、8255、ST7920顯示屏、直流電機等制作出了一個出租車計價器有專用鍵可以表示是否空車,同時利用直流電機模擬車輪運動,通過路程計算價格,成果如下圖所示:
圖4-1程序結(jié)果圖
五、分析與測試
程序中,我遇到的最大的難題就是如何完成正確的十進制計算,因為所有的計算指令都是十六進制的,雖然有的計算里有類似AAA這樣的調(diào)整指令,但是很多時候就不一定記得起來加上。同時由于需要根據(jù)數(shù)字來查表對應(yīng)相應(yīng)的字符碼,而且我是建立一個從零到九的數(shù)組,而由于計算錯誤導(dǎo)致經(jīng)常出現(xiàn)亂碼,而且比較難找到相應(yīng)的錯誤。而且有些計算沒有十進制轉(zhuǎn)換指令,需要自己編寫。
同時我認為我利用提前存儲變量來表示走過的路程比利用堆棧要好,因為堆棧容易記混,而變量有獨特的名字,利于記憶與調(diào)用。而且易于清零、增減。
六、心得體會
這次課程設(shè)計中,令我印象最為深刻的就是我們應(yīng)該有一種堅持的精神,有時候幾個小時都沒有成果,找不到BUG。顯示的就是有問題,這時候我們應(yīng)該有一種堅持下去的毅力,積極詢問老師同學(xué),問題的解決就很快了。
同時我發(fā)現(xiàn)編程習慣非常重要,應(yīng)該有一個提前的規(guī)劃,不能想到哪寫到哪,這樣的話,后期的DEBUG會非常麻煩,因為自己也看不懂自己的代碼,我們都應(yīng)該有規(guī)范化的代碼意識,這樣的編程能力才能上升。
參考文獻
[1]周荷琴,吳秀清,《微型計算機原理與接口技術(shù)》,合肥:中國科學(xué)技術(shù)大學(xué)出版社 2008。[2] 曹國清,《數(shù)字電路與邏輯設(shè)計》,徐州:中國礦業(yè)大學(xué)出版社 2003。[3] 8255芯片原理:http://baike.baidu.com/link?url=KHojvZzBGmo26_6iYGTdrdqH6PxQbM1Hnnc8hWQNPIp60L7TWG5LZu_ppSkXo5maU5M4APs4qCGSudiqZ0bdl_ [4]ST7920芯片原理:http://wenku.baidu.com/view/0dafd9232f60ddccda38a0fa.html訪問時間2013/10/15 [5]ST7920中文字碼表:http://wenku.baidu.com/view/d4abe628647d27284b735127.html訪問時間:2013/10/15
第五篇:出租車計價器課程設(shè)計2
出租車計價器課程設(shè)計
目錄
前言
1、系統(tǒng)工作原理 1.1 功能說明 1.2 基本原理
2、硬件設(shè)計
2.1 單片機最小系統(tǒng)單元 2.2 A44E霍爾傳感器檢測單元 2.3 AT24C01存儲單元 2.4 鍵盤調(diào)整單元 2.5 顯示單元
3、軟件設(shè)計 3.1 系統(tǒng)主程序 3.2 中斷程序
3.2.1 里程計數(shù)中斷程序 3.2.2 中途等待中斷程序 3.3 計算程序 3.4 顯示程序 3.5 鍵盤程序
4、總結(jié) 參考文獻
附錄A 系統(tǒng)原理圖
附錄B 系統(tǒng)源程序
前言
隨著出租車行業(yè)的發(fā)展,出租車已經(jīng)是城市交通的重要組成部分,從加強行業(yè)管理以及減少司機與乘客的糾紛出發(fā),具有良好性能的計價器對出租車司機和乘客來說都是很必要的。而采用模擬電路和數(shù)字電路設(shè)計的計價器整體電路的規(guī)模較大,用到的器件多,造成故障率高,難調(diào)試。而采用單片機進行的設(shè)計,相對來說功能強大,用較少的硬件和適當?shù)能浖嗷ヅ浜峡梢院苋菀椎貙崿F(xiàn)設(shè)計要求,且靈活性強,可以通過軟件編程來完成更多的附加功能。本設(shè)計采用AT89S52單片機為主控器,以A44E霍爾傳感器測距,實現(xiàn)對出租車的多功能的計價設(shè)計,并采用AT24C01實現(xiàn)在系統(tǒng)掉電的時候保存單價等信息,輸出采用8段數(shù)碼顯示管。本電路設(shè)計的計價器不但能實現(xiàn)基本的計價,而且還能根據(jù)白天,黑夜和中途等待來調(diào)節(jié)單價。
第一章 系統(tǒng)工作原理
1.1 功能說明
出租車計價器根據(jù)乘客乘坐汽車行駛距離和等候時間的多少進行計價,并在行程中同步顯示車費值。從起步價開始,當汽車程行駛未滿3公里時,均按起步價計算。過3公里后,實現(xiàn)每1公里單價收費,中間遇暫停時,計程數(shù)不再增加,開始計時收費,測距收費和測時收費的和便構(gòu)成了一位乘客的車費。同時,白天和夜晚價格不同,可以進行切換。白天單價、夜晚單價、等待單價和起步價格都可通過獨立鍵盤進行調(diào)節(jié)。(默認起步價為5元/3公里,里程單價白天為1.5元/公里,夜晚為1.8元/公里,等待計時單價為0.5元/5分鐘)
1.2 基本原理
計數(shù)器系統(tǒng)主要由五部分組成:A44E霍爾傳感器、AT89S52單片機、獨立鍵盤、EEPROM AT24C01和顯示數(shù)碼管。
霍爾傳感器安裝在車輪上,主要檢測汽車行進的公里數(shù),并產(chǎn)生一系列相應(yīng)的脈沖輸出,脈沖送到單片機進行處理,單片機根據(jù)程序設(shè)定通過計算脈沖數(shù)換算出行駛公里數(shù),再根據(jù)從EEPROM中讀取的價格等相關(guān)數(shù)據(jù)進行金額的計算,計算好的金額、里程和單價都實時地顯示在數(shù)碼管上。獨立鍵盤可以調(diào)節(jié)價格等相關(guān)數(shù)據(jù),按下相應(yīng)的按鈕,產(chǎn)生信號交由單片機處理并實時顯示出來,調(diào)節(jié)好的數(shù)據(jù)存儲到EEPROM中,掉電后可以使調(diào)好的數(shù)據(jù)不丟失,下次得電后直接從EEPROM讀到單片機,系統(tǒng)結(jié)構(gòu)圖如圖1。
圖1 系統(tǒng)結(jié)構(gòu)圖
第二章 硬件設(shè)計
2.1 單片機最小系統(tǒng)單元
主控機系統(tǒng)采用了Atmel 公司生產(chǎn)的 AT89S52單片機,它含有256 字節(jié)數(shù)據(jù)存儲器,內(nèi)置8K 的電可擦除FLASH ROM,可重復(fù)編程,大小滿足主控機軟件系統(tǒng)設(shè)計,所以不必再擴展程序存儲器。復(fù)位電路和晶振電路是AT89S52 工作所需的最簡外圍電路。單片機最小系統(tǒng)電路圖如圖2所示。
圖2 單片機最小系統(tǒng)圖
AT89S52 的復(fù)位端是一個史密特觸發(fā)輸入,高電平有效。RST端若由低電平上升到高電平并持續(xù)2個周期,系統(tǒng)將實現(xiàn)一次復(fù)位操作。在復(fù)位電路中,按一下復(fù)位開關(guān)就使在RST端出現(xiàn)一段時間的高電平,外接11.0592M 晶振和兩個30pF 電容組成系統(tǒng)的內(nèi)部時鐘電路。
2.2 A44E霍爾傳感器檢測單元
A44E 屬于開關(guān)型的霍爾器件,其工作電壓范圍比較寬(4.5~18V),其輸出的信號符合TTL電平標準,可以直接接到單片機的IO 端口上,而且其最高檢測頻率可達到1MHZ。
A44E 集成霍耳開關(guān)由穩(wěn)壓器A、霍耳電勢發(fā)生器(即硅霍耳片)B、差分放大器C、施密特觸發(fā)器D和OC門輸出E五個基本部分組成。在輸入端輸入電壓Vcc,經(jīng)穩(wěn)壓器穩(wěn)壓后加在霍爾電勢發(fā)生器的兩端,根據(jù)霍爾效應(yīng)原理,當霍爾片處在磁場中時,在垂直于磁場的方向通以電流,則與這二者相垂直的方向上將會產(chǎn)生霍爾電勢差VH輸出,該VH信號經(jīng)放大器放大后送至施密特觸發(fā)器整形,使其成為方波輸送到OC門輸出。當施加的磁場達到工作點(即Bop)時,觸發(fā)器輸出高電壓(相對于地電位),使三極管導(dǎo)通,此時OC門輸出端輸出低電壓,三極管截止,使OC門輸出高電壓,這種狀態(tài)為關(guān)。這樣兩次電壓變換,使霍爾開關(guān)完成了一次開關(guān)動作。A44E霍爾傳感器原理如圖3所示。
圖3 A44E霍爾傳感器原理
里程計算是通過安裝在車輪上的霍爾傳感器檢測到的脈沖信號,送到單片機產(chǎn)生中斷,單片機再根據(jù)程序設(shè)定,計算出里程。其原理如圖4所示。
圖4 傳感器測距示意圖
本系統(tǒng)選擇了將A44E的脈沖輸出口接到P3.3口外部中斷1作為信號的輸入端(這樣可以減少程序設(shè)計的麻煩),車輪每轉(zhuǎn)一圈(設(shè)車輪的周長是1米),霍爾開關(guān)就檢測并輸出信號,引起單片機的中斷,對脈沖計數(shù),當計數(shù)達到1000次時,即1公里,單片機就控制將金額自動增加,如圖5。
圖5 A44E霍爾元件接線圖
2.3 AT24C01存儲單元 存儲單元的作用是在電源斷開的時候,存儲當前設(shè)定的單價信息。AT24C01 是Ateml公司的1KB的電可擦除存儲芯片,采用兩線串行的總線和單片機通訊,電壓最低可以到2.5V,額定電流為1mA,靜態(tài)電流10uA(5.5V),芯片內(nèi)的資料可以在斷電的情況下保存40年以上,而且采用8 腳的DIP 封裝,使用方便。
AT24C02芯片引腳配置如圖6所示。
存儲單元電路連接如圖7所示。
圖 7 存儲單元電路原理圖 圖中R4、R5 是上拉電阻,其作用是減少AT24C01 的靜態(tài)功耗。由于AT24C01的數(shù)據(jù)線和地址線是復(fù)用的,采用串口的方式傳送數(shù)據(jù),所以只用兩根線SCL(時鐘脈沖)和SDA(數(shù)據(jù)/地址)與單片機P2.2和P2.3口連接,進行傳送數(shù)據(jù)。
每當設(shè)定一次單價,系統(tǒng)就自動調(diào)用存儲程序,將單價信息保存在芯片內(nèi);當系統(tǒng)重新上電的時候,自動調(diào)用讀存儲器程序,將存儲器內(nèi)的單價等信息,讀到緩存單元中,供主程序使用。
2.4 鍵盤調(diào)整單元
當單價等信息需要進行修改時,就要用到鍵盤進行修改。由于調(diào)節(jié)信息不多,故采用4個獨立鍵盤即可,分別實現(xiàn)清零、切換、增大、減小和功能等作用。電路原理如圖8所示。
圖8 鍵盤調(diào)整單元接線圖
S1:接P1.0口,對上一次的計費進行清零,為下次載客準備
S2:接P1.1口,實現(xiàn)白天和夜晚單價的切換;當功能鍵S4按下時,S2可對數(shù)據(jù)進行增大。S3:接P1.2口,當功能鍵S4按下時,S3可對數(shù)據(jù)進行減小。S4:接P1.3口,按1次,進入調(diào)整白天單價;按2次,進入調(diào)整夜晚單價;按3次,進入調(diào)整等待單價;按4次,進入調(diào)整起步價;按5次,返回。
2.5 顯示單元
顯示單元由7個8段共陽數(shù)碼管組成,采用動態(tài)掃描進行顯示。前三個數(shù)碼管分別接P3.0、P3.1和P3.2,用于顯示總金額;中間兩個分別接P3.4和P3.5,用于顯示里程;后邊兩個分別接P3.6和P3.7,用于顯示單價。電路如圖9所示。
圖9 數(shù)碼管顯示圖
第三章 軟件設(shè)計
3.1 系統(tǒng)主程序
在主程序模塊中,需要完成對各參量和接口的初始化、出租車起價和單價的初始化以及中斷、計算、循環(huán)等工作。另外,在主程序模塊中還需要設(shè)置啟動/清除標志寄存器、里程寄存器和價格寄存器,并對它們進行初始化。然后,主程序?qū)⒏鶕?jù)各標志寄存器的內(nèi)容,分別完成啟動、清除、計程和計價等不同的操作。
當汽車運行起來時,就啟動計價,根據(jù)里程寄存器中的內(nèi)容計算和判斷行駛里程是否已超過起步價公里數(shù)。若已超過,則根據(jù)里程值、每公里的單價數(shù)和起步價數(shù)來計算出當前的總金額,并將結(jié)果存于總金額寄存器中;中途等待時,無脈沖輸入,不產(chǎn)生中斷,當時間超過等待設(shè)定值時,開始進行計時,并把等待價格加到總金額里,然后將總金額、里程和單價送數(shù)碼管顯示出來。程序流程如圖10所示。
圖10 主程序流程圖 圖11 計算程序流程圖
3.2 中斷程序
3.2.1 里程計數(shù)中斷程序
每當霍爾傳感器輸出一個低電平信號就使單片機中斷一次,當里程計數(shù)器對里程脈沖計滿1000次時,進入里程計數(shù)中斷服務(wù)程序中,里程變量加一。主函數(shù)中總金額也相應(yīng)地變化。
3.2.2 中途等待中斷程序
在中途等待中斷程序中,每1ms產(chǎn)生一次中斷,將當前里程值送入某個緩存變量,每5分鐘將緩存變量中的值和當前里程值比較,當汽車停止,霍爾傳感器5分鐘沒有輸出信號,當前里程值和緩存變量內(nèi)的值相同,則進入等待計時,每5分鐘記一次價格。
3.3 計算程序
計算程序根據(jù)里程數(shù)分別進入不同的計算公式。如果里程大于3公里,則執(zhí)行公式:總金額=起步價+(里程-3)*單價+等待時間*等待單價;否則,執(zhí)行公式:總金額=起步價+等待時間*等待單價。程序流程圖如圖11所示。
3.4 顯示程序
顯示程序利用定時器每1ms產(chǎn)生一次中斷,相應(yīng)變量置位,點亮一個數(shù)碼管,顯示一位數(shù)據(jù),利用主函數(shù)內(nèi)的循環(huán),實現(xiàn)動態(tài)掃描顯示,同時根據(jù)數(shù)碼管余輝和人眼暫留現(xiàn)象,即可實現(xiàn)顯示。
3.5 鍵盤程序
鍵盤采用查詢的方式,放在主程序中,當沒有按鍵按下的時候,單片機循環(huán)主程序,一旦右按鍵按下,便轉(zhuǎn)向相應(yīng)的子程序處理,處理結(jié)束再返回。流程圖如圖12。
圖12 鍵盤程序流程圖
第四章 總結(jié)
經(jīng)過這些天有關(guān)于出租車計價器的課程設(shè)計,使我對單片機的應(yīng)用有了更深的了解。在課程設(shè)計的過程中,還是碰到了許多的問題。比如,對于數(shù)碼管動態(tài)掃描顯示和鍵盤的延時防抖的綜合編程不能較好地解決;對于代碼的前后順序及調(diào)用掌握得還不夠好;對于一些相關(guān)的應(yīng)用軟件沒能熟練掌握。通過這幾天晚上的苦想和反復(fù)調(diào)試,以及參考網(wǎng)上的程序,最終還是把問題解決了。通過這次課程設(shè)計,我最大的收獲就是自己的動手能力和獨立解決問題的能力得到了很大的提高,也充分體會到了自己設(shè)計東西的樂趣、學(xué)會查閱資料和對別人的東西融會變通的重要性,也明白了很多知識光靠趴在書本上學(xué)是學(xué)不到其中的精髓的,必須親自去試著實踐,親自去經(jīng)歷才能對它們真正的掌握,凡事都要自己去動下手,去實踐一下,遇到困難,永遠不要沮喪氣餒。在動手的過程中,不僅能增強實踐能力,而且在理論上可以有更深的認識;這次設(shè)計給了我極大的鼓舞和信心,相信在以后的學(xué)習中可以通過不斷的摸索和實踐來提高其他方面的知識。
參考文獻
[1] 馬淑華,王鳳文,張美金編著.單片機原理與接口技術(shù)(第二版).北京:北京郵電大學(xué)出版社,2007.[2] 譚浩強著.C程序設(shè)計(第三版).北京:清華大學(xué)出版社,2005.附錄A 系統(tǒng)原理圖
源程序
#include
#include
#define uchar unsigned char
#define uint unsigned int
#define delayNOP();{_nop_();_nop_();_nop_();_nop_();_nop_();};
uchar code table[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90};
sbit exter=P3^3;
//外部中斷
sbit key0=P1^0;
//清零
sbit key1=P1^1;
//切換/+
sbit key2=P1^2;
//-
sbit key3=P1^3;
//功能鍵
sbit p30=P3^0;
//數(shù)碼管各位控制
sbit p31=P3^1;
sbit p32=P3^2;
sbit p34=P3^4;
sbit p35=P3^5;
sbit p36=P3^6;
sbit p37=P3^7;
sbit SDA=P2^3;
//IIC引腳
sbit SCL=P2^2;
uint inter,aa,bb,temp,temp1;
uint zongjine,licheng,dengdai;
uint key3num,qiehuantemp,delaytemp;
uchar danjia1,danjia2,danjia3,danjia,qibu;
void delay(uint x)
//延時時基為1ms {
int i,j;
for(i=x;i>0;i--)
for(j=340;j>0;j--);}
void start()
//IIC開始位
{
SDA = 1;
SCL = 1;
delayNOP();
SDA = 0;
delayNOP();
SCL = 0;
}
void stop()
// IIC停止位
{
SDA = 0;
delayNOP();
SCL = 1;
delayNOP();
SDA = 1;}
void respons()
//IIC應(yīng)答位
{
uchar i;
SCL=1;
delayNOP();
while((SDA==1)&&(i<250))
i++;
SCL=0;
delayNOP();}
uchar read_byte()
// 從EEPROM讀到MCU {
uchar i,j;
for(i=0;i<8;i++)
{
SCL=1;
j<<=1;
j|=SDA;
SCL=0;
}
return(j);}
void write_byte(uchar date)
{
uchar i,temp;
temp=date;
for(i=0;i<8;i++)
{
temp=temp<<1;
SCL=0;
delayNOP();
SDA=CY;
delayNOP();
SCL=1;
delayNOP();
}
SCL=0;
// 從MCU寫到EEPROM
delayNOP();
SDA=1;
delayNOP();}
void write_data(uchar addr, uchar date){
start();
write_byte(0xa0);
respons();
write_byte(addr);
respons();
write_byte(date);
respons();
stop();}
uchar read_data(uchar addr)
{
uchar date;
start();
write_byte(0xa0);
// 在指定地址addr處寫入數(shù)據(jù)date // 在指定地址addr讀取數(shù)據(jù)
respons();
write_byte(addr);
respons();
start();
write_byte(0xa1);
respons();
date=read_byte();
stop();
return date;}
void display(uint zongjine0,uint licheng0,uint danjia0){
uint jbai,jshi,jge,lshi,lge,dshi,dge;
uint numwei,numshu;
//數(shù)碼管位置分配
jbai=zongjine0/100;
jshi=zongjine0%100/10;
jge=zongjine0%100%10;
lshi=licheng0/10;
//數(shù)碼管顯示
lge=licheng0%10;
dshi=danjia0/10;
dge=danjia0%10;
//數(shù)碼管動態(tài)顯示
if(aa)
{
aa=0;numshu++;if(numshu==7)
numshu=0;P3=0xff;switch(numwei){
case 0:p30=0;P0=table[jbai];break;
case 1:p31=0;P0=table[jshi]&0x7f;break;
case 2:p32=0;P0=table[jge];break;
case 3:p34=0;P0=table[lshi];break;
case 4:p35=0;P0=table[lge];break;
case 5:p36=0;P0=table[dshi]&0x7f;break;
case 6:p37=0;P0=table[dge];break;
}
numwei++;
if(numwei==7)
numwei=0;
} }
void keyscan()
//鍵盤掃描
{
if(key3==0)
//功能鍵調(diào)節(jié)
{
delay(5);
if(key3==0)
{
key3num=1;
while(!key3);
delay(5);
while(!key3);
while(key3num)
{
if(key3num==1)
調(diào)白天單價
//
{
if(key1==0)
{
delay(5);
if(key1==0)
danjia1=0;
{
danjia1++;
if(danjia1==100)
while(!key1);
delay(5);
while(!key1);
} } if(key2==0){
delay(5);
if(key2==0)
{
danjia1--;
if(danjia1==-1)
danjia1=99;
while(!key2);
delay(5);
while(!key2);
}
調(diào)夜晚單價
danjia2=0;
}
display(1,0,danjia1);} if(key3num==2)
//{
write_data(1,danjia1);
if(key1==0)
{
delay(5);
if(key1==0)
{
danjia2++;
if(danjia2==100)
while(!key1);
delay(5);
while(!key1);
}
}
danjia2=99;
if(key2==0)
{
delay(5);
if(key2==0)
{
danjia2--;
if(danjia2==-1)
while(!key2);
delay(5);
while(!key2);
}
}
display(2,0,danjia2);} if(key3num==3)
//調(diào)等待單價
{
write_data(2,danjia2);
if(key1==0)
danjia3=0;
{
delay(5);
if(key1==0)
{
danjia3++;
if(danjia3==100)
while(!key1);
delay(5);
while(!key1);
} } if(key2==0){
delay(5);
if(key2==0)
{
danjia3--;
if(danjia3==-1)
danjia3=99;
while(!key2);
步價
delay(5);
while(!key2);
}
}
display(3,0,danjia3);} if(key3num==4)
//調(diào)起{
write_data(3,danjia3);
if(key1==0)
{
delay(5);
if(key1==0)
{
qibu++;
if(qibu==100)
qibu=0;
while(!key1);
delay(5);
qibu=99;
while(!key1);
} } if(key2==0){
delay(5);
if(key2==0)
{
qibu--;
if(qibu==-1)
while(!key2);
delay(5);
while(!key2);
} }
display(4,0,qibu);
}
if(key3num==5)
//退出功能鍵
{
}
}
write_data(4,qibu);
key3num=0;}
if(key3==0){
delay(5);
if(key3==0)
{
key3num++;
while(!key3);
delay(5);
while(!key3);
} }
} } void init(){ SDA=1;SCL=1;
zongjine=0;licheng=0;dengdai=0;
danjia1=read_data(1);danjia2=read_data(2);danjia3=read_data(3);qibu=read_data(4);
aa=0;//數(shù)碼管動態(tài)掃描的定時器時基個數(shù)
bb=0;//判斷是否等待的時基個數(shù)
inter=0;
EA=1;//開總中斷
EX1=1;//開外部中斷1 IT1=1;//觸發(fā)方式下降沿
TMOD=0x01;TH0=(65536-1000)/256;TL0=(65536-1000)%256;ET0=1;//開定時器T0中斷
TR0=1;//開定時器T0
P3=0x08;P0=table[0];}
void jisuan(){ if(licheng>3)zongjine=qibu+(licheng-3)*danjia+dengdai*danjia3;//金額計算
else zongjine=qibu+dengdai*danjia3;//起步公里內(nèi)金額計算 }
void qiehuan(){ if(key1==0)//白天夜晚切換
{ delay(5);//鍵盤防抖
if(key1==0)qiehuantemp=!qiehuantemp;while(!key1);delay(5);while(!key1);} if(qiehuantemp==0)danjia=danjia2;if(qiehuantemp==1)danjia=danjia1;}
void main(){ init();qiehuantemp=1;key3num=0;while(1){ qiehuan();//切換白天夜晚單價
jisuan();//計算總金額
display(zongjine,licheng,danjia);keyscan();if(key0==0)//清零鍵
init();} }
void inter1()interrupt 2 //脈沖中斷 { delay(5);// if(exter==0)// { // IT1=1;inter++;if(inter==5){ inter=0;licheng++;} } // while(!exter);// delay(5);// while(!exter);// }
void timer0()interrupt 1 { TH0=(65536-1000)/256;TL0=(65536-1000)%256;aa++;bb++;temp1=licheng;//測試是否進入等待
if(bb==10000)//10s無反應(yīng)進入等待計費
{ bb=0;if(temp=temp&temp1)dengdai++;temp=licheng;} }
原來文件地址http://blog.sina.com.cn/s/blog_609003ef0100dt1o.html
存儲器可以不用