《單片機(jī)C語言應(yīng)用技術(shù)》課件-第6章_第1頁
《單片機(jī)C語言應(yīng)用技術(shù)》課件-第6章_第2頁
《單片機(jī)C語言應(yīng)用技術(shù)》課件-第6章_第3頁
《單片機(jī)C語言應(yīng)用技術(shù)》課件-第6章_第4頁
《單片機(jī)C語言應(yīng)用技術(shù)》課件-第6章_第5頁
已閱讀5頁,還剩137頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

模塊6串行口通信技術(shù)任務(wù)11單片機(jī)之間雙機(jī)通信任務(wù)12單片機(jī)和PC之間一對一通信任務(wù)13基于I2C串行總線的多點溫度測量習(xí)題6單片機(jī)廣泛應(yīng)用于工業(yè)控制領(lǐng)域,通過串行通信不但可以實現(xiàn)將單片機(jī)的數(shù)據(jù)傳輸?shù)接嬎銠C(jī)端,而且也能實現(xiàn)計算機(jī)對單片機(jī)的控制。由于其所需電纜線少,接線簡單,所以在遠(yuǎn)距離傳輸中得到了廣泛的運用。本模塊從開發(fā)單片機(jī)之間雙機(jī)通信的應(yīng)用程序入手,介紹51單片機(jī)的串行口內(nèi)部結(jié)構(gòu)及其使用方法,然后介紹常用的I2C總線及其應(yīng)用。任務(wù)11單片機(jī)之間雙機(jī)通信在兩個51單片機(jī)之間,通過其串行口實現(xiàn)雙方的數(shù)據(jù)交換在實踐中是很常見的,硬件實現(xiàn)方便,軟件編程也很簡單。

1.任務(wù)目的了解51系列單片機(jī)串行口的結(jié)構(gòu),掌握其使用方法。

2.任務(wù)要求

發(fā)送方向接收方發(fā)送數(shù)據(jù),接收方接收數(shù)據(jù)并通過8個LED發(fā)光二極管以二進(jìn)制形式顯示出來。

3.硬件電路硬件連接時,將雙方的RXD(P3.0)和TXD(P3.1)交叉互連即可,如圖6.1所示。實際上,本任務(wù)僅涉及單向通信,所以只需將發(fā)送方的TXD連接至接收方的RXD即可。圖6.1雙機(jī)通信硬件連接圖

4.程序設(shè)計軟件編程分為接收方和發(fā)送方。發(fā)送方程序如下:

#include<reg51.h>

//下面定義將發(fā)送給接收方的數(shù)據(jù)

unsignedcharcode

num[]={0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F};

voiddelay(intms);

voidmain()

{

unsignedchari;

TMOD=0x20; //?TMOD=00100000B,定時器T1工作于方式2

SCON=0x40; //?SCON=01000000B,串口工作方式1

PCON=0x00; //?PCON=00000000B,波特率9600

TH1=0xfd; //根據(jù)規(guī)定給定時器T1賦初值

TL1=0xfd; //根據(jù)規(guī)定給定時器T1賦初值

TR1=1; //啟動定時器T1

while(1)

{

for(i=0;i<8;i++)

{ SBUF=num[i]; //發(fā)送數(shù)據(jù)i while(TI==0){} //等待數(shù)據(jù)發(fā)送完畢

TI=0; //準(zhǔn)備下一次發(fā)送

delay(400);

}

}

}

voiddelay(intms)

{

inti,j;

for(i=0;i<ms;i++)

for(j=0;j<120;j++);

}在編寫軟件之前,應(yīng)該確定雙方通信的波特率。對于51系列的雙機(jī)通信,典型的應(yīng)用是采用11.0592MHz的芯片,波特率設(shè)定為9600b/s。在程序里面,根據(jù)波特率首先設(shè)定定時器的初始值,然后設(shè)定串行口的工作模式。小提示通信雙方的波特率和串口的工作方式應(yīng)設(shè)定一致。主程序中,for循環(huán)體一次發(fā)送一個字節(jié)的數(shù)據(jù),整個for循環(huán)發(fā)送8個字節(jié)的預(yù)定義數(shù)據(jù)。程序里面串口采用的是查詢方式,通過語句while(TI==0){}查詢TI的狀態(tài),可以了解數(shù)據(jù)是否發(fā)送完成。TI為0時,數(shù)據(jù)未發(fā)送完成;TI為1時,發(fā)送結(jié)束。為了能夠再次發(fā)送,可通過語句TI=0;將串口設(shè)定為空載狀態(tài)。接收方程序如下:

#include<reg51.h>

voidmain(void)

{

TMOD=0x20; //定時器T1工作于方式2

SCON=0x50; //?SCON=01010000B,串口工作方式1,允許接收(REN=1)

PCON=0x00; //?PCON=00000000B,波特率9600

TH1=0xfd; //根據(jù)規(guī)定給定時器T1賦初值

TL1=0xfd; //根據(jù)規(guī)定給定時器T1賦初值

TR1=1; //啟動定時器T1

while(1)

{

while(RI==0){}//等待,直至一次數(shù)據(jù)接收完畢(RI=1) RI=0; //為了接收下一幀數(shù)據(jù),需將RI清0

P0=SBUF; //將接收緩沖器中的數(shù)據(jù)通過P0口顯示出來

}

}同發(fā)送方一樣,接收方采用的也是查詢方式,通過語句while(RI==0){}查詢RI的狀態(tài),可以了解是否接收到了數(shù)據(jù)。RI為0時,未收到數(shù)據(jù);RI為1時,收到數(shù)據(jù)。為了能夠再次接收數(shù)據(jù),可通過語句RI=0;將串口設(shè)定為空載狀態(tài)。小提示發(fā)送方采用查詢方式,接收方?jīng)]必要也一定采用查詢方式。通信雙方可任意采用查詢或中斷方式,但是波特率和串口的工作方式應(yīng)設(shè)定一致。查詢或中斷方式只是對串口的使用者(這里就是發(fā)送和接收方程序)而言的,不會影響到具體的通信過程。接收方也可以采用中斷方式,代碼如下所示:

#include<reg51.h> //包含單片機(jī)寄存器的頭文件

voidmain(void)

{TMOD=0x20; //定時器T1工作于方式2

SCON=0x50; //?SCON=01010000B,串口工作方式1,允許接收(REN=1)

PCON=0x00; //?PCON=00000000B,波特率9600

TH1=0xfd; //根據(jù)規(guī)定給定時器T1賦初值

TL1=0xfd; //根據(jù)規(guī)定給定時器T1賦初值

TR1=1; //啟動定時器T1

EA=1; //開總中斷允許位

ES=1; //開串行中斷允許位

while(1);

}

//定義串行中斷處理程序

voidcom()interrupt4

{ if(RI==1) //如果有數(shù)據(jù)到來

{

P0=SBUF;

RI=0;

}

}相比查詢方式,初始化時通過語句EA=1和ES=1開放了相應(yīng)的中斷控制位。主程序執(zhí)行語句while(1)進(jìn)入無限循環(huán),此循環(huán)不做任何實質(zhì)工作,僅僅是為了不讓程序跑飛。主要的處理工作在串行中斷處理程序中完成,每當(dāng)接收完一幀數(shù)據(jù),就會進(jìn)入串行中斷處理程序。因為發(fā)送、接收共享同一個中斷,所以在串行中斷處理程序中要判斷是接收中斷還是發(fā)送中斷,這是通過語句if(RI==1)來實現(xiàn)的。當(dāng)然,由于我們的程序不會通過串口發(fā)送數(shù)據(jù),因此在串行中斷處理程序中即使不做判斷也不會有任何問題。6.1串行通信基礎(chǔ)6.1.1串行通信與并行通信通信方式有兩種:一種是并行通信;另一種是串行通信。并行通信是指多位數(shù)據(jù)同時通過多根數(shù)據(jù)線傳送,如圖6.2所示。其優(yōu)點是傳送速度快;缺點是數(shù)據(jù)有多少位,就需要用多少根傳送線。并行通信適用于近距離通信。串行通信是指數(shù)據(jù)通過一根數(shù)據(jù)線,一位一位地傳送,如圖6.3所示。其優(yōu)點是只需一對傳輸線;缺點是傳輸速度慢。串行通信適用于遠(yuǎn)距離通信。圖6.28位并行通信圖6.3串行通信6.1.2串行通信的制式圖串行通信裝置的設(shè)置不同,通信線路的連接不同,它們的通信能力也是不同的,按數(shù)據(jù)的傳送方向可分為單工、半雙工、全雙工通信方式。在串行通信中,把通信接口只能發(fā)送或接收的單向傳送叫單工傳送;而把數(shù)據(jù)在甲乙兩機(jī)之間的雙向傳遞,稱之為雙工傳送。在雙工傳送方式中又分為半雙工傳送和全雙工傳送。半雙工傳送是指兩機(jī)之間不能同時進(jìn)行發(fā)送和接收,任一時刻只能發(fā)或者只能收信息。

(1)單工傳送方式:單工方式下,只允許數(shù)據(jù)向一個方向傳送,它只需一條通信線和一條地線。

(2)半雙工傳送方式:也只需要一條通信線和一條地線,允許數(shù)據(jù)雙向傳送,但分時進(jìn)行。

(3)全雙工傳送方式:允許雙方同時進(jìn)行數(shù)據(jù)的接收和發(fā)送。接收和發(fā)送需采用兩條不同的通信線和一條地線。串行通信幾種方式的示意圖如圖6.4所示。6.4串行通信方式示意圖6.1.3異步通信和同步通信串行通信可使數(shù)據(jù)一位一位地按先后順序在一根傳輸線上傳送。串行通信的方式有異步通信和同步通信兩種。在異步通信中,一次通信傳輸一幀數(shù)據(jù),一幀數(shù)據(jù)包含8到11個二進(jìn)制位,通常一次傳輸一個字節(jié)數(shù)據(jù)。異步通信對硬件的要求較低,通信雙方的時鐘不必嚴(yán)格同步(在一定的時間范圍以內(nèi)),因而實現(xiàn)起來較為簡單,其缺點是效率較低。同步通信要求由時鐘來實現(xiàn)發(fā)送端與接收端之間的同步,故硬件較復(fù)雜,但是效率較高。小提示

51系列單片機(jī)支持全雙工的異步串行通信,不支持同步通信。

1.異步通信(AsynchronousCommunication)在異步通信中,每個數(shù)據(jù)都是以特定的幀形式傳送,數(shù)據(jù)在通信線上一位一位地串行傳送。每一幀按先后順序由以下幾部分組成:

(1)起始位:表示傳送一個數(shù)據(jù)的開始,用低電平表示,占一位。

(2)數(shù)據(jù)位:要傳送的數(shù)據(jù)的具體內(nèi)容,典型的數(shù)據(jù)位數(shù)是7或8位,一般為7位(ASCII碼),數(shù)據(jù)從低位開始傳送。

(3)奇偶校驗位:為了保證數(shù)據(jù)傳輸?shù)恼_性,在數(shù)據(jù)位之后緊跟一位奇偶校驗位,該位可用于有限差錯檢測,微機(jī)在通信時雙方約定一致的奇偶校驗方式。

(4)停止位:表示發(fā)送一個數(shù)據(jù)的結(jié)束,用高電平表示,占一位、一位半或兩位。這里的一位對應(yīng)于一定的發(fā)送時間,故有半位。由以上可知,一幀數(shù)據(jù)可由10位、10.5位或11位組成。在發(fā)送的間隙,即線路空閑時,線路處于邏輯“1”狀態(tài),我們稱邏輯“1”為傳號(MARK),稱邏輯“0”為空號(SPACE)。在異步通信中,數(shù)據(jù)以如圖6.5所示的格式一個接一個地傳送。圖6.5異步通信中數(shù)據(jù)傳送的格式

2.同步通信(SynchronousCommunication)在異步通信中,每個數(shù)據(jù)都包含起始位和停止位,它們占用了傳送的時間,當(dāng)數(shù)據(jù)量較大時,這一點更為突出。所以,在傳輸大量數(shù)據(jù)時通常采用同步通信方式來傳送數(shù)據(jù)。同步通信依靠同步字符在每個數(shù)據(jù)塊傳送開始時使收發(fā)雙方同步。同步字符可由用戶選定的某個特殊的8位二進(jìn)制代碼來表示,收發(fā)雙方必須使用相同的同步字符,當(dāng)線路空閑時不斷發(fā)送同步字符。同步通信中數(shù)據(jù)傳送的格式如圖6.6所示。同步通信要求有準(zhǔn)確的時鐘來保證發(fā)送端和接收端的嚴(yán)格同步,所以硬件成本較高。實際應(yīng)用中,異步通信常用于少量數(shù)據(jù)的傳送且傳送速度要求較低的場合;同步通信常用于大量數(shù)據(jù)的傳送且傳送速度要求較快的場合。圖6.6同步通信中數(shù)據(jù)傳送的格式

3.波特率以上兩種傳輸方式中,一幀信息中每一位的傳送時間(位寬)是一定的,用Td表示。Td的倒數(shù)稱為波特率。波特率是串行通信中的一個重要概念,只有當(dāng)通信雙方采用相同的波特率時,通信才不會發(fā)生混亂。波特率表示每秒傳送的位數(shù),單位為b/s。例如,當(dāng)采用8位數(shù)據(jù)的異步串行通信(這時每個字符加上起始位和停止位,一共為10位),且每秒發(fā)送100個字符時,波特率為:10位/字符?×?100字符/秒?=?1000位/秒,傳送時間Td?=?1/1000s=1?ms。串行通信常用的標(biāo)準(zhǔn)波特率在RS-232C標(biāo)準(zhǔn)中已有規(guī)定,如波特率為600?b/s、1200?b/s、2400?b/s、4800?b/s、9600??b/s、19?200?b/s等。應(yīng)根據(jù)數(shù)據(jù)量的大小、線路質(zhì)量的好壞等因素綜合選擇合適的波特率。比特率也是數(shù)據(jù)傳輸速率的測量單位,但它與波特率并不完全等同。波特率是指每秒傳輸?shù)挠行?shù)據(jù)的位數(shù),而比特率則是指在傳輸介質(zhì)上每秒實際傳輸?shù)奈粩?shù)。所以比特率可以大于或等于波特率。比如每秒傳輸100個數(shù)據(jù)位,則波特率為100?b/s。如果將數(shù)據(jù)發(fā)送到傳輸介質(zhì)時是一個脈沖發(fā)送一位數(shù)據(jù),則比特率也為100?b/s,但若將數(shù)據(jù)發(fā)送到傳輸介質(zhì)時是n個脈沖發(fā)送一位數(shù)據(jù),則比特率為100n,比波特率大。6.1.4串行通信的校驗異步通信時可能會出現(xiàn)幀格式錯、超時錯等傳輸錯誤。在具有串行口的單片機(jī)的開發(fā)中,應(yīng)考慮在通信過程中對數(shù)據(jù)差錯進(jìn)行校驗,因為差錯校驗是保證準(zhǔn)確無誤通信的關(guān)鍵。常用差錯校驗方法有奇偶校驗、和校驗及循環(huán)冗余碼校驗。

1.奇偶校驗在發(fā)送數(shù)據(jù)時,數(shù)據(jù)位尾隨的一位數(shù)據(jù)為奇偶校驗位(1或0)。當(dāng)設(shè)置為奇校驗時,數(shù)據(jù)中1的個數(shù)與校驗位1的個數(shù)之和應(yīng)為奇數(shù);當(dāng)設(shè)置為偶校驗時,數(shù)據(jù)中1的個數(shù)與校驗位中1的個數(shù)之和應(yīng)為偶數(shù)。接收時,接收方應(yīng)具有與發(fā)送方一致的差錯檢驗設(shè)置,當(dāng)接收一個字符時,對1的個數(shù)進(jìn)行校驗,若二者不一致,則說明數(shù)據(jù)傳送出現(xiàn)了差錯。奇偶校驗是按字符校驗,數(shù)據(jù)傳輸速度將受到影響。這種特點使得它一般只用于異步串行通信中。

2.和校驗發(fā)送方將所發(fā)送的數(shù)據(jù)塊求和(字節(jié)數(shù)求和),并產(chǎn)生一個字節(jié)的校驗字符(校驗和)附加到數(shù)據(jù)塊末尾。接收方接收數(shù)據(jù)時也是先對數(shù)據(jù)塊求和,將所得結(jié)果與發(fā)送方的校驗和進(jìn)行比較,相符則無差錯,否則即出現(xiàn)了差錯。這種和校驗的特點是無法檢驗出字節(jié)位序的錯誤。

3.循環(huán)冗余碼校驗這種校驗是對一個數(shù)據(jù)塊校驗一次。例如對磁盤信息的訪問、ROM或RAM存儲區(qū)的完整性等的檢驗。這種方法廣泛應(yīng)用于串行通信方式。6.2MCS-51的串行接口6.2.1MCS-51串行口的結(jié)構(gòu)

MCS-51單片機(jī)的串行接口主要由兩個物理上獨立的串行數(shù)據(jù)(接收、發(fā)送)緩沖器SBUF、發(fā)送控制器、接收控制器、輸入移位寄存器和輸出控制門組成,如圖6.7所示。發(fā)送數(shù)據(jù)緩沖器SBUF只能寫入、不能讀出。接收數(shù)據(jù)緩沖器只能讀出、不能寫入。兩個緩沖器共用一個單元地址99H,是不可位尋址的特殊功能寄存器,在編程應(yīng)用中就如同使用一個寄存器SBUF一樣。在接收緩沖器之前還有輸入移位寄存器,從而構(gòu)成了串行接收的雙緩沖結(jié)構(gòu),以避免在數(shù)據(jù)接收過程中出現(xiàn)幀重疊錯誤。與接收數(shù)據(jù)情況不同,發(fā)送數(shù)據(jù)時,由于CPU是主動的,不會發(fā)生幀重疊錯誤,因此發(fā)送電路不需要雙緩沖結(jié)構(gòu)。圖6.7串行接口電路的組成

1.串行口控制寄存器SCON

SCON的字節(jié)地址為98H,可位尋址。SCON格式為

(1)串行口工作方式選擇位SM0、SM1:此二位用于控制串行口的工作方式(其功能說明詳見串行口工作方式部分)。

(2)多機(jī)通信控制位SM2:允許方式2和方式3進(jìn)行多機(jī)通信的控制位。在方式2或方式3中,如SM2=1,接收到第9位數(shù)據(jù)(RB8)為0時,不啟動接收中斷標(biāo)志RI(RI=0)。在方式1時,如SM2?=?1,只有在接收到有效停止位時才啟動RI,若沒有接收到有效停止位,則RI清零。在方式0中,SM2應(yīng)為0。

(3)允許串行接收控制位REN:由軟件置位時允許接收,由軟件清零時禁止接收。

(4)?TB8:在方式2或方式3中所要發(fā)送的第九位數(shù)據(jù),需要時由軟件置位或復(fù)位。

(5)?RB8:在方式2或方式3中所要接收的第九位數(shù)據(jù)。在方式1中,若SM2=0,則RB8是接收到的停止位。在方式0中,不使用RB8。

(6)發(fā)送中斷標(biāo)志位TI:由片內(nèi)硬件在方式0串行發(fā)送到第八位結(jié)束時置位,或在其他方式串行發(fā)送停止位的開始時置位。必須由軟件清零。

(7)接收中斷標(biāo)志位RI:由片內(nèi)硬件在方式0串行接收到第八位結(jié)束時置位,或在其他方式串行接收到停止位的中間狀態(tài)時置位。必須由軟件清零。SCON的所有位復(fù)位時被清零。

2.電源控制寄存器PCON

PCON主要是為CHMOS型單片機(jī)的電源控制而設(shè)置的專用寄存器,其字節(jié)地址為87H,沒有位尋址功能。PCON格式如下(在CHMOS型單片機(jī)中,除SMOD位外,其他位均為虛設(shè)的):

SMOD是波特率加倍控制位。當(dāng)SMOD=1時,使波特率加倍。系統(tǒng)復(fù)位時,SMOD=0,所以如需使波特率加倍,則需用指令MOVPCON,#80H使SMOD為1。若不需加倍,則可以不初始化PCON。6.2.2串行口的工作方式串行口的工作方式由SM0和SM1定義,其編碼及工作方式的功能說明如表6.1所示。

1.方式0串行接口的工作方式0為移位寄存器輸入/輸出方式,可外接移位寄存器,以擴(kuò)展I/O口,也可外接同步輸入/輸出設(shè)備。在方式0中,串行口作為輸出,當(dāng)一個數(shù)據(jù)輸入串行口發(fā)送緩沖器SBUF時,串行口即將8位數(shù)據(jù)以fosc/12的波特率從RXD引腳輸出(從低位到高位),發(fā)送完中斷標(biāo)志TI置1。串行口作為輸入時,RXD為數(shù)據(jù)輸入端,TXD為同步信號輸出端,接收器也以fosc/12的波特率采樣RXD引腳輸入的數(shù)據(jù)信息,當(dāng)接收器接收到8位數(shù)據(jù)時中斷標(biāo)志位RI置1。表6.1串行口工作方式功能說明

【例6.1】單片機(jī)串行口工作在方式0下,利用串口控制8個LED燈的循環(huán)顯示。基本連線如圖6.8所示。電路中采用74HC164芯片(串行輸入并行輸出移位寄存器,雙列直插14引腳),串行口的數(shù)據(jù)通過RXD引腳加到74HC164的輸入端,移位時鐘通過TXD引腳加到74HC164的時鐘端,并用89C52的P1.0控制74HC164的選通端,當(dāng)P1.0?=?1時,選通74HC164芯片,接收串行輸入數(shù)據(jù)且并行輸出控制LED發(fā)光二極管的顯示。圖6.8串行口方式0的應(yīng)用程序如下:

#include<reg51.h>

#include<intrins.h>

sbitP10=P1^0;

voiddelay(intms);

voidmain()

{ unsignedcharled;

SCON=0;/*串行口方式0工作*/

ES=0;/*禁止串行中斷*/

P10=1;/*選通74HC164?*/

led=0xfe;

while(1)

{ SBUF=led; /*串行輸出*/ led=_crol_(led,1); while(!TI){} /*等待數(shù)據(jù)傳送完畢*/ TI=0; /*清發(fā)送完成標(biāo)志*/ delay(400);

}

}

voiddelay(intms)

{

inti,j;

for(i=0;i<ms;i++) for(j=0;j<120;j++);

}小知識

74HC164是一款高速CMOS器件,引腳兼容低功耗肖特基TTL(LSTTL)系列。74HC164遵循JEDEC標(biāo)準(zhǔn)no.7A。

74HC164是帶有串行數(shù)據(jù)輸入和并行輸出的8位邊沿觸發(fā)移位寄存器。數(shù)據(jù)通過兩個輸入端(DSA和DSB)中的任一個串行輸入。當(dāng)其中一端作為數(shù)據(jù)輸入時,另一端可作為高有效使能端。兩輸入端必須連接在一起,或者把未使用的端口綁定為高。在時鐘脈沖(CP)的每個上升沿,數(shù)據(jù)將向右移動一位,并輸入至Q0。Q0是兩個數(shù)據(jù)輸入端(DSA和DSB)進(jìn)行邏輯與運算后的結(jié)果,在時鐘脈沖上升沿來臨之前存在一段就緒時間。如果74HC164的主復(fù)位(CR)輸入為低電平,則所有其他輸入將被忽略,并且異步清零寄存器強(qiáng)制所有輸出為低電平。

2.方式1方式1時,串行口為波特率可變的8位異步通信接口。當(dāng)串行口以方式1輸出時,數(shù)據(jù)位由TXD端輸出,發(fā)送一幀信息為10位:一位啟始位(0),八位數(shù)據(jù)位(先低位)和一個停止位(1)。CPU執(zhí)行一條數(shù)據(jù)寫入發(fā)送緩沖器SBUF的指令,就啟動發(fā)送器發(fā)送。當(dāng)發(fā)送完數(shù)據(jù)后,中斷標(biāo)志位TI置1。當(dāng)串行口以方式1輸入時,以16倍于波特率的速率采樣RXD狀態(tài),當(dāng)采樣到RXD引腳1到0的跳變時啟動接收器。接收的值是三次采樣中至少相同兩次的值,以保證可靠無誤。當(dāng)檢測到啟始位有效時,開始接收一幀的其余信息。一幀信息也是10位:一位啟始位(0),八位數(shù)據(jù)位(先低位),一位停止位(1)。當(dāng)RI=0,且停止位為1或SM2=0時,停止位進(jìn)入RB8,且置位中斷標(biāo)志RI。若這兩個條件不滿足,信息將丟失。因此,中斷標(biāo)志必須由用戶的中斷服務(wù)程序(或查詢程序)清0。通常情況下串行口為方式1時,SM2置為0。方式1的波特率為

3.方式2當(dāng)串行口工作于方式2時,串行口定義為9位異步通信接口。當(dāng)方式2用作輸出時,發(fā)送數(shù)據(jù)由TXD端輸出,發(fā)送一幀信息為11位:一位啟始位(0),八位數(shù)據(jù)位(先低位),一位可程控為1或0的第九位數(shù)據(jù)位,一位停止位(1)。附加的第九位數(shù)據(jù)即SCON中的TB8位,可由軟件置位或清零,它可以作為多機(jī)通信中的地址、數(shù)據(jù)標(biāo)志位,也可以作為數(shù)據(jù)的奇偶校驗位。當(dāng)方式2用作輸入時,數(shù)據(jù)由RXD端輸入,接收11位信息:一位啟始位(0),八位數(shù)據(jù)位,一位附加的第九數(shù)據(jù)位,一位停止位(1)。當(dāng)接收器采樣到RXD端從1到0的跳變,同時斷定起始位有效后,便開始接收一幀信息。當(dāng)接收器接收到第九位數(shù)據(jù)后,若滿足條件RI=0,且SM2=0或接收到的第九位數(shù)據(jù)為1,則接收到的數(shù)據(jù)送入SBUF(接收緩沖器),第九位數(shù)據(jù)送入RB8,并置位RI。若條件不滿足,接收的信息將丟失。方式2的波特率為

4.方式3當(dāng)串行口工作于方式3時,串行口定義為波特率可變的9位異步通信接口。除了波特率外,方式3與方式2相同,其波特率由下式?jīng)Q定:定時器T1作波特率使用時,通常選用自動裝載的工作方式2。在實際使用時,總是先確定波特率,然后根據(jù)波特率計算T1的計數(shù)值,并對計數(shù)值求補(bǔ)(256-計數(shù)值),最后再進(jìn)行T1的初始化。所以例如,晶振頻率為6MHz、波特率為1200,則定時器T1的計數(shù)值為

13的補(bǔ)數(shù)為11110011B=F3H,初始化程序如下:

TMOD=0x20;

TH1=0xf3;

TL1=0xf3;由于定時器T1的初始值只能為整數(shù),這樣就不可避免要產(chǎn)生波特率誤差。為了降低誤差,一般采用晶振頻率為11.0592MHz的晶振。另外在雙機(jī)或多機(jī)通信中,波特率的選擇也不是任意的,有一系列離散的值可供選擇。為了保證通信的可靠性,通常波特率的相對誤差不能超過2.5%。表6.2給出了常用波特率及相應(yīng)的振蕩頻率fosc和定時器T1的狀態(tài),表6.3給出了不同振蕩頻率時定時器TH1所產(chǎn)生的波特率,表6.4給出了波特率及其誤差。表6.2常用的波特率值表6.3不同振蕩頻率時的波特率表6.4波特率及其誤差小提示通信之前雙方應(yīng)該商定一個通信速率,這樣才能正確同步。波特率和比特率是衡量通信速率的兩個單位。波特率是指數(shù)據(jù)信號對載波的調(diào)制速率,它用單位時間內(nèi)載波調(diào)制狀態(tài)改變的次數(shù)來表示。比特率指的是每秒傳送的二進(jìn)制數(shù)的位數(shù),其單位為b/s。51系列上波特率與比特率相同。

51串口在四種工作模式下有不同的波特率計算方法。在選擇波特率的時候需要考慮兩點:首先,系統(tǒng)需要的通信速率。這要根據(jù)系統(tǒng)的運作特點來確定通信的頻率范圍。然后考慮通信時鐘誤差。使用同一晶振頻率在選擇不同的通信速率時,通信時鐘誤差會有很大差別。為了通信的穩(wěn)定,我們應(yīng)該盡量選擇時鐘誤差最小的頻率進(jìn)行通信。通常如果硬件允許,我們可以選擇較高的通信速率。典型的,如果單片機(jī)的晶振頻率為11.0592MHz,我們可以選擇9600b/s。經(jīng)過四舍五入,波特率的結(jié)果會有微小誤差。通常,在異步通信時,允許誤差為5%。使用11.0592MHz晶振可以獲得精確的波特率。任務(wù)12單片機(jī)和PC之間一對一通信隨著計算機(jī)技術(shù)尤其是單片微型機(jī)技術(shù)的發(fā)展,人們已越來越多地采用單片機(jī)來對一些工業(yè)控制系統(tǒng)中如溫度、流量和壓力等參數(shù)進(jìn)行檢測和控制。PC機(jī)具有強(qiáng)大的監(jiān)控和管理功能,而單片機(jī)則具有快速及靈活的控制特點,通過PC機(jī)的RS-232串行接口與外部設(shè)備進(jìn)行通信,是許多測控系統(tǒng)中常用的一種通信解決方案。

1.任務(wù)目的了解51系列單片機(jī)與PC之間通過串行口通信的方法。

2.任務(wù)要求

從單片機(jī)連續(xù)向PC機(jī)發(fā)送字符數(shù)據(jù)。

3.硬件電路單片機(jī)通過MAX232連接至PC機(jī)的串行口,如圖6.9所示。圖6.9單片機(jī)連接RS232C的接口電路

4.程序設(shè)計單片機(jī)與PC機(jī)之間通過串口通信的過程與單片機(jī)與單片機(jī)之間的通信過程是類似的。一般而言,通信的雙方應(yīng)制定通信協(xié)議以保證正確的交換數(shù)據(jù)。小提示通信協(xié)議是通信雙方在通信前的約定,包括要交換的數(shù)據(jù)格式以及通信的過程(先交換什么數(shù)據(jù),后交換什么數(shù)據(jù)等)。通信實際上就是通信雙方交換數(shù)據(jù)的過程,為了雙方能夠相互理解,雙方應(yīng)該事先制定通信數(shù)據(jù)的格式以及數(shù)據(jù)交換的順序等。下面是單片機(jī)一方的程序。

#include<reg51.h>

voiddelay(intms)

{

inti,j;

for(i=0;i<ms;i++)

for(j=0;j<120;j++);

}//發(fā)送函數(shù)。參數(shù)為待發(fā)送的字符串voidsend(unsignedchar*s){ while(*s!='\0') { SBUF=*s++; while(TI==0); //采用查詢方式發(fā)送數(shù)據(jù)

TI=0; }}voidmain(){ unsignedcharletters[3],c; letters[2]='\0'; letters[1]=''; SCON=0x40; TMOD=0x20;

PCON=0x00;

TH1=0xfd; TL1=0xfd; TI=0; TR1=1; delay(50); send("receivingdatafrommcs-8051...\r\n"); //發(fā)送消息至串行口 send("------------------------------\r\n"); delay(50); while(1) //循環(huán)發(fā)送消息

{ for(c='A';c<='Z';c++) //依次發(fā)送大寫字母

{ letters[0]=c; send(letters); delay(50); } send("\r\n------------------------------\r\n"); }}程序循環(huán)發(fā)送大寫字母到串行口。程序中定義了字符數(shù)組letters,大小為3字節(jié),用于發(fā)送單個字母:第一個元素是要發(fā)送的字母,后跟一個空格,第三個元素是字符串結(jié)束標(biāo)記。

5.程序調(diào)試

為了調(diào)試程序,可在下載程序后,將單片機(jī)連接至PC機(jī)的串行口,打開PC機(jī)的串口調(diào)試工具(一個免費的串口調(diào)試工具,可到網(wǎng)上下載),設(shè)置好串口參數(shù)(波特率9600b/s,8位數(shù)據(jù),1位停止位)后,打開單片機(jī),就可以在串口調(diào)試工具中看到來自單片機(jī)的消息。也可以脫離硬件環(huán)境,直接在Proteus里面仿真調(diào)試。這要求PC機(jī)上有2個可用的串行口,一個用于Proteus仿真使用,另外一個用于PC機(jī)的串口調(diào)試工具,連接這2個串行口,就可以仿真調(diào)試了。現(xiàn)在的PC機(jī)一般沒有這2個串口,這時可以通過虛擬串口軟件(例如VirtualSerialPortDriver)在PC機(jī)上虛擬出多個串口進(jìn)行調(diào)試。6.3單片機(jī)和PC之間的串行通信在串行通信時,要求通信雙方都采用一個標(biāo)準(zhǔn)接口,使不同的設(shè)備可以方便地連接起來進(jìn)行通信。RS-232-C接口(又稱EIARS-232-C)是目前最常用的一種串行通信接口。6.3.1RS-232C串行通信總線標(biāo)準(zhǔn)

RS-232一共有3個版本:RS-232A、RS-232B、RS-232C。RS-232C是現(xiàn)在最常使用的串行接口標(biāo)準(zhǔn),現(xiàn)在常用的PC上的串口COM都采用RS-232C接口。RC-2329針接口如圖6.10所示,接口信號定義如表6.5所示。圖6.10RS-232C9針接口表6.5PC常用的RS-232C接口信號定義(9針)

1.?RS-232C電氣標(biāo)準(zhǔn)

RS-232C采用負(fù)邏輯,要求高、低兩信號有較大幅度。其電平標(biāo)準(zhǔn)如下:作為驅(qū)動輸出時,邏輯0為?+5?V~+15V,邏輯1為?-5?V~-15V;作為驅(qū)動輸入時,邏輯0為大于?+3V,邏輯1為小于?-3V。通常采用?+10V作為邏輯0,-10V作為邏輯1??梢娖湓肼暼菹掭^大,抗干擾能力較強(qiáng)。

2.?PC機(jī)與RS-232C的連接

RS-232C最大通信距離是15m,最大傳輸速率為19.2kb/s。使用RS-232C連接系統(tǒng)時,當(dāng)通信距離小于15m時,可以直接利用電纜進(jìn)行連接,如圖6.11所示。圖6.11PC與外設(shè)的RS-232直接連接當(dāng)通信距離大于15m時,就必須使用調(diào)制解調(diào)器(modem)進(jìn)行連接了,其連接圖如圖6.12所示。應(yīng)該注意的是,當(dāng)PC與終端以RS-232C標(biāo)準(zhǔn)直接連接時,PC與終端的“發(fā)送數(shù)據(jù)線”和“接收數(shù)據(jù)線”應(yīng)該交叉連接,以完成雙方的數(shù)據(jù)交換。PC與終端的“數(shù)據(jù)終端就緒”和“數(shù)據(jù)設(shè)備就緒”兩線也要交叉連接,以完成數(shù)據(jù)傳輸前的設(shè)備是否準(zhǔn)備好檢測。在實際應(yīng)用中,當(dāng)要求不高時,經(jīng)常使用一種最簡單的三線制連接,即直接連接兩條數(shù)據(jù)線和一條共地線。簡單的三線制RS-232電路連接方法如圖6.13所示。圖6.12PC與終端的遠(yuǎn)程RC-232C連接圖6.13簡單的三線制RS-232電路連接6.3.2單片機(jī)和PC的串行通信接口微機(jī)中的信號電平是TTL電平,即2.4?V~5V為高電平“1”,0~0.4V為低電平“0”。通常RS-232C總線的邏輯“0”用?+10V表示,邏輯“1”用-10V表示,與TTL以高低電平表示邏輯狀態(tài)的規(guī)定不同。因此,為了能夠與計算機(jī)接口或終端的TTL器件連接,必須在RS-232C與TTL電路之間進(jìn)行電平和邏輯關(guān)系的變換。實現(xiàn)這種變換的方法既可用分立元件,也可用集成電路芯片。目前MC1488、75188等芯片可實現(xiàn)TTL~RS-232C的電平轉(zhuǎn)換;MCI489、75189等芯片可實現(xiàn)RS-232C~TTL的電平轉(zhuǎn)換。

RS-232收發(fā)器MAX232只需要?+5V單電源即可同時實現(xiàn)TTL電平與RS-232C電平的雙向轉(zhuǎn)換。單片機(jī)應(yīng)用中廣泛使用MAX232轉(zhuǎn)換電平后與RS-232連接。

1.MAX232簡介

MAX232是一種雙組驅(qū)動器/接收器,片內(nèi)含有一個電容性電壓發(fā)生器,以便在單5V電源供電時提供EIA/TIA-232-E電平。每個接收器將EIA/TIA-232-E電平輸入轉(zhuǎn)換為5VTTL/CMOS電平,這些接收器具有1.3V的典型門限值及0.5V的典型遲滯,而且可以接收±30V的輸入。每個驅(qū)動器將TTL/CMOS輸入電平轉(zhuǎn)換為EIA/TIA-232-E電平。MAX232的工作溫度范圍為0℃~70℃,MAX232I的工作溫度范圍為?-40℃~85℃。其工作特點如下:

(1)單5V電源工作;

(2)?LinBiCMOSTM工藝技術(shù);

(3)兩個驅(qū)動器及兩個接收器;

(4)?±30?V輸入電平;

(5)低電源電流,典型值是8mA;

(6)符合甚至優(yōu)于ANSI標(biāo)準(zhǔn)EIA/TIA-232-E及ITU推薦標(biāo)準(zhǔn)V.28;

(7)?ESD保護(hù)大于MIL-STD-883(方法3015)標(biāo)準(zhǔn)的2000V。

2.?MAX232引腳及功能

MAX232的引腳如圖6.14所示。第一部分是電源電路,由1、2、3、4、5、6腳和4只電容構(gòu)成,功能是產(chǎn)生+12V和-12V兩個電源,提供給RS-232串口電平。第二部分是數(shù)據(jù)轉(zhuǎn)換通道,由7、8、9、10、11、12、13、14腳構(gòu)成兩個數(shù)據(jù)通道,其中13腳(R1IN)、12腳(R1OUT)、11腳(T1IN)、14腳(T1OUT)為第一數(shù)據(jù)通道;8腳(R2IN)、9腳(R2OUT)、10腳(T2IN)、7腳(T2OUT)為第二數(shù)據(jù)通道。TTL/CMOS數(shù)據(jù)從T1IN、T2IN輸入轉(zhuǎn)換成RS-232數(shù)據(jù)從T1OUT、T2OUT送到電腦DB9插頭;DB9插頭的RS-232數(shù)據(jù)從R1IN、R2IN輸入轉(zhuǎn)換成TTL/CMOS數(shù)據(jù)后從R1OUT、R2OUT輸出。第三部分是供電部分。由15腳GND、16腳VCC(+5V)構(gòu)成。圖6.14MAX232引腳排列

3.?MAX232典型工作電路

MAX232的典型工作電路如圖6.15所示,利用它進(jìn)行電平轉(zhuǎn)換,可以實現(xiàn)單片機(jī)和PC機(jī)的串行通信。圖6.15MAX232典型工作電路任務(wù)13基于I2C串行總線的多點溫度測量

I2C總線(InterIntegratedCircuitBUS,內(nèi)部集成電路總線)是一種由PHILIPS公司開發(fā)的兩線式串行總線,用于連接微控制器及其外圍設(shè)備。I2C總線產(chǎn)生于20世紀(jì)80年代,最初為音頻和視頻設(shè)備開發(fā),如今主要在服務(wù)器管理中使用,其中包括單個組件狀態(tài)的通信。例如,管理員可對各個組件進(jìn)行查詢,以管理系統(tǒng)的配置或掌握組件的功能狀態(tài),如電源和系統(tǒng)風(fēng)扇;可隨時監(jiān)控內(nèi)存、硬盤、網(wǎng)絡(luò)、系統(tǒng)溫度等多個參數(shù),增加了系統(tǒng)的安全性,方便了管理。

1.任務(wù)目的了解51系列單片機(jī)模擬I2C總線接口與I2C總線設(shè)備通信的方法。

2.任務(wù)要求

利用單片機(jī)連接2片DS1621(溫度傳感器),實時采集多點的溫度并通過LCD顯示出來。

3.硬件電路

MCS-51系列單片機(jī)本身沒有I2C接口電路,可以通過軟件來模擬I2C接口。比如使用2個并行引腳(本任務(wù)使用P2.6和P2.7)連接到SDL和SCL總線。本任務(wù)采用2片DS1621采集溫度,將第一片地址連接成000(A2A1A0均接低電平),將第二片地址連接成001(A2A1接低電平,A0接高電平)。溫度采集的結(jié)果通過LCD顯示出來。LCD的數(shù)據(jù)線連接至MCU的P3口。電路圖如圖6.16所示。圖6.16多點測溫的電路圖

4.程序設(shè)計軟件分為多個文件,包含幾個芯片的驅(qū)動程序和主程序。下面是I2C的驅(qū)動,包含兩個文件,一個頭文件,一個代碼文件。小提示將程序按其邏輯劃分為多個模塊是分解軟件復(fù)雜性的一個有效的辦法,這樣可以使軟件結(jié)構(gòu)看起來更清晰,且容易維護(hù)。

(1)?iic.h頭文件。

#ifndef IIC_h

#define IIC_h

#include<reg51.h>

sbitSda=P2^6; //?P2.6腳連接至SDA線

sbitScl=P2^7; //?P2.7腳連接至SCL線

voidIIC_Recieve(unsignedcharslave,unsignedcharbytes[],unsignedcharlen);

voidIIC_Send(unsignedcharslave,unsignedcharbytes[],unsignedcharlen);

#endif

(2)?iic.c代碼文件。

#include<intrins.h>

#include"iic.h"

staticunsignedcharbdatabyte;

sbitLsb=byte^0;

sbitMsb=byte^7;

staticvoidStart()

{

Sda=1;

Scl=1;

_nop_(); //此處的延時應(yīng)該滿足I2C總線的時序要求,依據(jù)不同的機(jī)器,

Sda=0; //可能需要增加空指令個數(shù)

_nop_();

}staticvoidStop(){

Sda=0;

Scl=1;

_nop_();

Sda=1; }//發(fā)送一字節(jié)函數(shù)staticvoidSendByte(unsignedcharn){

unsignedchari;

byte=n;

for(i=0;i<8;i++){

Scl=0;

_nop_();

_nop_();

Sda=Msb;

byte<<=1;

_nop_();

_nop_();

Scl=1;

_nop_();

_nop_();

Scl=0;}

Sda=1;

Scl=1;

_nop_();

_nop_();

Scl=0;

_nop_();

_nop_(); }//接收一字節(jié)函數(shù)。參數(shù)end表示是否是接收一批數(shù)據(jù)的最后一個字節(jié)staticunsignedcharRecvByte(unsignedcharend)

{ unsignedchari,rcv; for(i=0;i<8;i++) { Sda=1; Scl=1; _nop_(); Lsb=Sda;

if(i<7) byte<<=1; _nop_(); Scl=0; _nop_(); }

if(end) Sda=1; else Sda=0; Scl=1; _nop_(); Scl=0; Sda=1; _nop_(); rcv=byte; returnrcv;

}

//接收數(shù)據(jù)函數(shù)

voidIIC_Recieve(unsignedcharslave,unsignedcharbytes[],unsignedcharlen)

{

unsignedchari;

Start();

SendByte(slave|1);

for(i=0;i<len;i++)

bytes[i]=RecvByte(i==len-1?1:0);

Stop();

}

//發(fā)送數(shù)據(jù)函數(shù)

voidIIC_Send(unsignedcharslave,unsignedcharbytes[],unsignedcharlen)

{

unsignedchari;

Start();

SendByte(slave);

for(i=0;i<len;i++)

SendByte(bytes[i]);

Stop();

}

MCS-51通過軟件方式模擬I2C總線時序,因此必須滿足I2C總線的時序要求。I2C驅(qū)動對外主要提供2個接口函數(shù)。發(fā)送數(shù)據(jù)函數(shù)和接收數(shù)據(jù)函數(shù)。發(fā)送數(shù)據(jù)函數(shù)IIC_Send有3個參數(shù),分別是從設(shè)備地址、發(fā)送數(shù)據(jù)的緩沖區(qū)和待發(fā)送數(shù)據(jù)的大小,以字節(jié)為單位。接收數(shù)據(jù)函數(shù)IIC_Receive也有3個參數(shù),分別是從設(shè)備地址、接收數(shù)據(jù)的緩沖區(qū)和待接收數(shù)據(jù)的大小,以字節(jié)為單位。

Ds1621的驅(qū)動程序使用了I2C的驅(qū)動,下面是Ds1621的驅(qū)動程序。

(3)?Ds1621.h頭文件。

#ifndef Ds1621_h

#define Ds1621_h

floatDs1621_GetTemperature();

voidDs1621_SetTemperatureLimit(unsignedcharhigh,unsignedcharlow);

voidDs1621_WriteConfig(unsignedcharc);

voidDs1621_SetDeviceAddress(unsignedcharaddr);

#endif

(4)?Ds1621.c代碼文件。

#include"utility.h"

#include"iic.h"

staticbitpoint;

staticunsignedcharaddress; //保存設(shè)備的地址

staticunsignedcharcommand[]= //定義DS1621的命令字

{

0xac,0x00,0xee,0xa1,0x00,0x00,0xa2,0x00,0x00,0xaa,0x22

};

staticunsignedcharrecvbytes[2]; //存放接收Ds1621的溫度數(shù)據(jù)

//設(shè)置Ds1621的溫度上下界

voidDs1621_SetTemperatureLimit(unsignedcharhigh,unsignedcharlow)

{

command[4]=high;

command[5] =0;

command[7]=low;

command[8]=0;

IIC_Send(address,&command[3],3);

Util_DelayMs(10);

IIC_Send(address,&command[6],3);

}

staticvoidStartConversion()

{

IIC_Send(address,&command[2],1);

Util_DelayMs(750);

}

staticvoidStopConversion()

{

IIC_Send(address,&command[10],1);

Util_DelayMs(750);

}

staticvoidReadTemp()

{

StartConversion();

IIC_Send(address,&command[9],1);

IIC_Recieve(address,recvbytes,2);

StopConversion();

}

voidDs1621_WriteConfig(unsignedcharc)

{

command[1]=c;

IIC_Send(address,command,2);

}

//設(shè)定設(shè)備地址??梢詮?到7,共8種地址

voidDs1621_SetDeviceAddress(unsignedcharaddr)

{

address=addr<<1|0x90;

}

//讀取Ds1621溫度值

floatDs1621_GetTemperature()

{

floattemp;

ReadTemp();

point=recvbytes[1]>>7;

if(recvbytes[0]>200)

{

recvbytes[0]=255-recvbytes[0];

temp=recvbytes[0];

temp=-temp-0.5;

if(!point) temp-=0.5;

}

else

{

temp=recvbytes[0];

if(point) temp+=0.5;

}

returntemp;

}下面是LCD的驅(qū)動。

(5)?LCD1602.H頭文件。

#ifndefLCD1602_H

#defineLCD1602_H

#include<reg51.h>

sbitLcdRs =P1^0;

sbitLcdRw =P1^1;

sbitLcdEn=P1^2;

#defineDBPortP3

voidLcd1602_Initialize();

voidLcd1602_Write(unsignedcharx,unsignedchary,unsignedcharstring[]);

#endif

(6)?LCD1602.c代碼文件。

#include<intrins.h>

#include"Lcd1602.h"

#defineLCD_COMMAND 0

#defineLCD_DATA 1

#defineLCD_CLEAR_SCREEN 0x01

#defineLCD_NO_CURSOR 0x00

#defineLCD_NO_MOVE 0x00

#defineLCD_SHOW 0x04

#defineLCD_AC_UP 0x02

staticvoidwrite(bitstyle,unsignedcharbyte)

{

LcdEn=0;

LcdRs=style;

LcdRw=0; _nop_();

DBPort=byte; _nop_();

LcdEn=1; _nop_();

LcdEn=0; _nop_();

LcdRs=0;

LcdRw=1; _nop_();

LcdEn=1; _nop_();

while(DBPort&0x80)

LcdEn=0;

}

voidLcd1602_Initialize()

{

LcdEn=0;

write(LCD_COMMAND,0x38); //?8位數(shù)據(jù)端口,2行顯示,5*7點陣

write(LCD_COMMAND,0x38);

write(LCD_COMMAND,0x08|LCD_SHOW|LCD_NO_CURSOR);

write(LCD_COMMAND,LCD_CLEAR_SCREEN); //清屏

write(LCD_COMMAND,0x04|LCD_AC_UP|LCD_NO_MOVE);//AC遞增,畫面不動

}

voidLcd1602_Write(unsignedcharx,unsignedchary,unsignedcharstring[])

{

write(LCD_COMMAND,0x80|(y==0?x:x-0x40));

while(*string!='\0')

{ write(LCD_DATA,*string); string++;

}

}

LCD1602為16列2行的顯示方式。使用LCD的時候,首先調(diào)用Lcd1602_Initialize初始化LCD,由函數(shù)Lcd1602_Write向LCD發(fā)送要顯示的字符。參數(shù)x為橫坐標(biāo),取值范圍為0~15;參數(shù)y為縱坐標(biāo),取值為0或1;第3個參數(shù)string是要顯示的字符串。

Utility模塊提供了應(yīng)用程序要使用到的幾個輔助函數(shù),一個是延時函數(shù),另外一個函數(shù)用于將浮點數(shù)轉(zhuǎn)換成字符串。

(7)?Utility.h頭文件。

#ifndef Utility_h

#define Utility_h

voidUtil_DelayMs(intms);

unsignedcharUtil_IntToString(intn,unsignedchars[]);

unsignedcharUtil_FloatToString(floatf,unsignedchard,unsignedchars[]);

#endif

(8)?Utility.c代碼文件

voidUtil_DelayMs(intms)

{ inti,j; for(i=0;i<ms;i++) for(j=0;j<120;j++);

}

unsignedcharUtil_IntToString(intn,unsignedchars[])

{ unsignedchari=0; unsignedintw=10000;

If(n==0)s[i++]='0'; while(w>n)

{ w/=10; } while(w>0) { s[i++]=n/w+'0'; n%=w; w/=10;

} s[i]='\0'; returni;

}

//參數(shù)d是要顯示的精度(小數(shù)點后保留的位數(shù))

unsignedcharUtil_FloatToString(floatf,unsignedchard,unsignedchars[])

{ unsignedchari=0; unsignedintn; if(f<0)

{ s[i++]='-'; f=-f; } n=f; i+=Util_IntToString(n,&s[i]);

f-=n; s[i++]='.'; while(f>0&&d>0)

{

n=f*=10; s[i++]=n+'0'; f-=n; d--;

} if(s[i-1]=='.')i--; s[i]='\0'; returni;

}最后是程序的主函數(shù)。主函數(shù)首先初始化硬件,包括LCD1602以及兩個DS1621,隨后進(jìn)入無限循環(huán),在循環(huán)里依次讀取兩個溫度芯片采集的溫度值,并以適當(dāng)?shù)姆绞皆贚CD中顯示出來。

(9)主程序文件。

#include"lcd1602.h"

#include"utility.h"

#include"ds1621.h"

voidmain()

{ unsignedchars[10],i,a[2]; //數(shù)組s存放顯示的字符串,a存放DS1621的地址,

a[1]=‘\0’; //用于顯示

Lcd1602_Initialize(); Lcd1602_Write(1,0,"thtemp(c):"); for(i=0;i<2;++i) //初始化2個DS1621 { Ds1621_SetDeviceAddress(i); Ds1621_WriteConfig(0x03); Ds1621_SetTemperatureLimit(40,35); }

while(1)

{ for(i=0;i<2;++i)//循環(huán)依次顯示2個DS1621采集的溫度

{

DS1621_SetDeviceAddress(i); //設(shè)置DS1621的地址取到DS1621的溫度,轉(zhuǎn)換成字符串,保留小數(shù)點后2位,并顯示出來

Util_FloatToString(DS1621_GetTemperature(),2,s);

a[0]=i+'1'; //顯示DS1621的地址

Lcd1602_Write(0,0,a);

Lcd1602_Write(0,1,""); //擦去前面顯示的溫度

Lcd1602_Write(0,1,s); //顯示當(dāng)前讀取的DS1621的溫度值

Util_DelayMs(1000); }

}

}6.4I2C串行通信

I2C總線最主要的優(yōu)點是其簡單性和有效性。由于接口直接接在組件之上,因此I2C總線占用的空間非常小,減少了電路板的空間和芯片管腳的數(shù)量,降低了互連成本。總線的長度可長達(dá)25英尺,并且能夠以10kb/s的最大傳輸速率支持40個組件。I2C總線的另一個優(yōu)點是,它支持多主控(multimastering),其中任何能夠進(jìn)行發(fā)送和接收的設(shè)備都可以成為主總線。一個主控能夠控制信號的傳輸和時鐘頻率。當(dāng)然,在任何時間點上只能有一個主控。6.4.1I2C串行通信的原理

1.總線的構(gòu)成及信號類型

I2C總線是由數(shù)據(jù)線SDA和時鐘SCL構(gòu)成的串行總線,可發(fā)送和接收數(shù)據(jù),其構(gòu)成如圖6.17所示。數(shù)據(jù)可在CPU與被控IC之間、IC與IC之間進(jìn)行雙向傳送,最高傳送速率為100kb/s。各種被控電路均并聯(lián)在這條總線上,但就像電話機(jī)一樣只有撥通各自的號碼才能工作。所以,每個電路和模塊都有唯一的地址,在信息的傳輸過程中,I2C總線上并接的每一個模塊電路既是主控器(或被控器),又是發(fā)送器(或接收器),這取決于它所要完成的功能。CPU發(fā)出的控制信號分為地址碼和控制量兩部分:地址碼用來選址,即接通需要控制的電路,確定控制的種類;控制量用來決定該調(diào)整的類別(如對比度、亮度等)及需要調(diào)整的量。這樣,各控制電路雖然掛在同一條總線上,卻彼此獨立,互不相關(guān)。圖6.17I2C總線構(gòu)成

I2C總線通過上拉電阻接正電源,如圖6.18所示。當(dāng)總線空閑時,兩根線均為高電平。連到總線上的任一器件輸出的低電平,都將使總線的信號變低,即各器件的SDA及SCL都是線“與”關(guān)系。

I2C總線在傳送數(shù)據(jù)的過程中共有三種類型信號:開始信號、結(jié)束信號和應(yīng)答信號。開始信號:SCL為高電平時,SDA由高電平向低電平跳變,開始傳送數(shù)據(jù)。結(jié)束信號:SCL為低電平時,SDA由低電平向高電平跳變,結(jié)束傳送數(shù)據(jù)。圖6.18I2C總線連接正電源應(yīng)答信號:接收數(shù)據(jù)的IC在接收到8?bit數(shù)據(jù)后,向發(fā)送數(shù)據(jù)的IC發(fā)出特定的低電平脈沖,表示已收到數(shù)據(jù)。CPU向受控單元發(fā)出一個信號后,等待受控單元發(fā)出一個應(yīng)答信號,CPU接收到應(yīng)答信號后,根據(jù)實際情況作出是否繼續(xù)傳遞信號的判斷。若未收到應(yīng)答信號,可判斷受控單元出現(xiàn)了故障。

2.?I2C總線的數(shù)據(jù)傳送

I2C總線進(jìn)行數(shù)據(jù)傳送時,時鐘信號為高電平期間,數(shù)據(jù)線上的數(shù)據(jù)必須保持穩(wěn)定,只有在時鐘線上的信號為低電平期間,數(shù)據(jù)線上的高電平或低電平狀態(tài)才允許變化,如圖6.19所示。圖6.19I2C總線信號與數(shù)據(jù)的電平關(guān)系

SCL線為高電平期間,SDA線由高電平向低電平的變化表示起始信號;SCL線為高電平期間,SDA線由低電平向高電平的變化表示終止信號,如圖6.20所示。起始和終止信號都是由主機(jī)發(fā)出的,在起始信號產(chǎn)生后,總線就處于被占用的狀態(tài);在終止信號產(chǎn)生后,總線就處于空閑狀態(tài)。連接到I2C總線上的器件,若具有I2C總線的硬件接口,則很容易檢測到起始和終止信號。接收器件收到一個完整的數(shù)據(jù)字節(jié)后,有可能需要完成一些其他工作,如處理內(nèi)部中斷服務(wù)等,可能無法立刻接收下一個字節(jié),這時接收器件可以將SCL線拉成低電平,從而使主機(jī)處于等待狀態(tài)。直到接收器件準(zhǔn)備好接收下一個字節(jié)時,再釋放SCL線使之成為高電平,從而使數(shù)據(jù)傳送可以繼續(xù)進(jìn)行。圖6.20I2C總線的起始信號與終止信號

3.數(shù)據(jù)傳送格式

1)字節(jié)傳送與應(yīng)答每一個字節(jié)必須保證是8位長度。數(shù)據(jù)傳送時,先傳送最高位(MSB),每一個被傳送的字節(jié)后面都必須跟隨一位應(yīng)答位(即一幀共有9位)。傳送一字節(jié)時序如圖6.21所示。由于某種原因從機(jī)不對主機(jī)尋址信號應(yīng)答時(如從機(jī)正在進(jìn)行實時性的處理工作而無法接收總線上的數(shù)據(jù)),它必須將數(shù)據(jù)線置于高電平,而由主機(jī)產(chǎn)生一個終止信號以結(jié)束總線的數(shù)據(jù)傳送。圖6.21傳送一字節(jié)時序如果從機(jī)對主機(jī)進(jìn)行了應(yīng)答,但在數(shù)據(jù)傳送一段時間后無法繼續(xù)接收更多的數(shù)據(jù),那么從機(jī)可以通過對無法接收的第一個數(shù)據(jù)字節(jié)的“非應(yīng)答”來通知主機(jī),主機(jī)將發(fā)出終止信號以結(jié)束數(shù)據(jù)的繼續(xù)傳送。主機(jī)接收數(shù)據(jù)時,在收到最后一個數(shù)據(jù)字節(jié)后,必須向從機(jī)發(fā)出一個結(jié)束傳送的信號。這個信號是由對從機(jī)的“非應(yīng)答”來實現(xiàn)的。然后,從機(jī)釋放SDA線,以允許主機(jī)產(chǎn)生終止信號。

2)數(shù)據(jù)幀格式

I2C總線上傳送的數(shù)據(jù)信號是廣義的,既包括地址信號,又包括真正的數(shù)據(jù)信號。在起始信號后必須傳

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論