單片機(jī)教學(xué)課件第11章_第1頁
單片機(jī)教學(xué)課件第11章_第2頁
單片機(jī)教學(xué)課件第11章_第3頁
單片機(jī)教學(xué)課件第11章_第4頁
單片機(jī)教學(xué)課件第11章_第5頁
已閱讀5頁,還剩61頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

單片機(jī)原理及應(yīng)用

曲鳳娟,計(jì)算機(jī)應(yīng)用(10615)

課件郵箱:assemb@126.com,password

第11章單片機(jī)

C51程序設(shè)計(jì)C51語言概述在學(xué)會(huì)使用匯編語言后,學(xué)習(xí)C語言編程是一件比較容易的事。下面是一個(gè)簡單的例子:89S52的P1引腳上接8個(gè)發(fā)光二極管,我們的任務(wù)是讓接在P1引腳上的發(fā)光二極管按要求發(fā)光。

11.1簡單的C程序介紹例1-1:

讓接在P1.0引腳上的LED發(fā)光。

/**********************************/

單燈閃爍程序

/**********************************/

#include

“reg51.h”

sbit

P1_0=P1^0;

void

main()

{

P1_1=0;

}

這個(gè)C語言程序包含了哪些信息

1.“文件包含”處理所謂“文件包含”是指一個(gè)文件將另外一個(gè)文件的內(nèi)容全部包含進(jìn)來,所以這里的程序雖然只有4行,但C編譯器在處理的時(shí)候卻要處理幾十或幾百行。這里程序中包含REG51.h文件的目的是為了要使用P1這個(gè)符號(hào),即通知C編譯器,程序中所寫的P1是指80C51單片機(jī)的P1端口而不是其它變量。reg51.h文件包含以下內(nèi)容:/*-----------------------------------------REG51.H

Header

file

for

generic

80C51

and

80C31

microcontroller.

Copyright

(c)

1988-2001

Keil

Elektronik

GmbH

and

Keil

Software,

Inc.

All

rights

reserved.

--------------------------------------------*/

/*

BYTE

Register

*/

sfr

P0

=

0x80;

sfr

P1

=

0x90;

sfr

P2

=

0xA0;

sfr

P3

=

0xB0;

sfr

PSW

=

0xD0;

sfr

ACC

=

0xE0;

sfr

B

=

0xF0;

sfr

SP

=

0x81;

sfr

DPL

=

0x82;

sfr

DPH

=

0x83;

sfr

PCON

=

0x87;

sfr

TCON

=

0x88;

sfr

TMOD

=

0x89;

sfr

TL0

=

0x8A;

sfr

TL1

=

0x8B;

sfr

TH0

=

0x8C;

sfr

TH1

=

0x8D;

sfr

IE

=

0xA8;

sfr

IP

=

0xB8;sfr

SCON

=

0x98;

sfr

SBUF

=

0x99;

/*

BIT

Register

*/

/*

PSW

*/

sbit

CY

=

0xD7;

sbit

AC

=

0xD6;

sbit

F0

=

0xD5;

sbit

RS1

=

0xD4;

sbit

RS0

=

0xD3;

sbit

OV

=

0xD2;

sbit

P

=

0xD0;

/*

TCON

*/

sbit

TF1

=

0x8F;

sbit

TR1

=

0x8E;

sbit

TF0

=

0x8D;

sbit

TR0

=

0x8C;

sbit

IE1

=

0x8B;

sbit

IT1

=

0x8A;

sbit

IE0

=

0x89;

sbit

IT0

=

0x88;

/*

IE

*/

sbit

EA

=

0xAF;

sbit

ES

=

0xAC;

sbit

ET1

=

0xAB;

sbit

EX1

=

0xAA;

sbit

ET0

=

0xA9;

sbit

EX0

=

0xA8;

/*

IP

*/

sbit

PS

=

0xBC;

sbit

PT1

=

0xBB;

sbit

PX1

=

0xBA;

sbit

PT0

=

0xB9;

sbit

PX0

=

0xB8;

/*

P3

*/

sbit

RD

=

0xB7;

sbit

WR

=

0xB6;

sbit

T1

=

0xB5;

sbit

T0

=

0xB4;

sbit

INT1

=

0xB3;

sbit

INT0

=

0xB2;

sbit

TXD

=

0xB1;

sbit

RXD

=

0xB0;

/*

SCON

*/

sbit

SM0

=

0x9F;

sbit

SM1

=

0x9E;

sbit

SM2

=

0x9D;

sbit

REN

=

0x9C;

sbit

TB8

=

0x9B;

sbit

RB8

=

0x9A;

sbit

TI

=

0x99;

sbit

RI

=

0x98;

注意:sfr

P1

=

0x90;

這樣的一行(上文中用黑體表示),即定義P1與地址0x90對(duì)應(yīng),P1口的地址就是0x90(0x90是C語言中十六進(jìn)制數(shù)的寫法,相當(dāng)于匯編語言中寫90H)。

sfr是標(biāo)準(zhǔn)C語言的關(guān)鍵字,而是Keil為能直接訪問80C51中的SFR而提供了一個(gè)新的關(guān)鍵詞,其用法是:

sfrt

變量名=地址值。2.符號(hào)P1_0來表示P1.0引腳

在C語言里,如果直接寫P1.0,C編譯器并不能識(shí)別,而且P1.0也不是一個(gè)合法的C語言變量名,所以得給它另起一個(gè)名字,這里起的名為P1_0,可是P1_0是不是就是P1.0呢?你這么認(rèn)為,C編譯器可不這么認(rèn)為,所以必須給它們建立聯(lián)系,這里使用了Keil

C的關(guān)鍵字sbit來定義,sbit的用法有三種:

第一種方法:sbit

位變量名=地址值

第二種方法:sbit

位變量名=SFR名稱^變量位地址值

第三種方法:sbit

位變量名=SFR地址值^變量位地址值

如定義PSW中的OV可以用以下三種方法:sbit

OV=0xd2

(1)說明:0xd2是OV的位地址值

sbit

OV=PSW^2

(2)說明:其中PSW必須先用sfr定義好

sbit

OV=0xD0^2

(3)說明:0xD0就是PSW的地址值

因此這里用sfr

P1_0=P1^0;就是定義用符號(hào)P1_0來表示P1.0引腳,如果你愿意也可以起P10一類的名字,只要下面程序中也隨之更改就行了。3.main稱為“主函數(shù)”。

每一個(gè)C語言程序有且只有一個(gè)主函數(shù),函數(shù)后面一定有一對(duì)大括號(hào)“{}”,在大括號(hào)里面書寫其它程序。

從上面的分析我們了解了部分C語言的特性,下面再看一個(gè)稍復(fù)雜一點(diǎn)的例子。例1-2

讓接在P1.0引腳上的LED閃爍發(fā)光

/*********************************單燈閃爍程序

**********************************/

#include

"reg51.h"

#define

uchar

unsigned

char

#define

uint

unsigned

int

sbit

P10=P1^0;

/*延時(shí)程序由Delay參數(shù)確定延遲時(shí)間*/

void

mDelay(unsigned

int

Delay)

{

unsigned

int

i;

for(;Delay>0;Delay--)

{

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

{;}

}

}void

main(){

for(;;)

{

P10=!P10;

//取反P1.0引腳

mDelay(1000);

}

}程序分析:程序第二行是“P1_0=!P1_0;”,在P1_0前有一個(gè)符號(hào)“!”,符號(hào)“!”是C語言的一個(gè)運(yùn)算符,就像數(shù)學(xué)中的“+”、“-”一樣,是一種運(yùn)算任號(hào),意義是“取反”,即將該符號(hào)后面的那個(gè)變量的值取反。

注意:

取反運(yùn)算只是對(duì)變量的值而言的,并不會(huì)自動(dòng)改變變量本身??梢哉J(rèn)為C編譯器在處理“!P1_0”時(shí),將P1_0的值給了一個(gè)臨時(shí)變量,然后對(duì)這個(gè)臨時(shí)變量取反,而不是直接對(duì)P1_0取反,団此取反完畢后還要使用賦值符號(hào)(“=”)將取反后的值再賦給P1_0,這樣,如果原來P1.0是低電平(LED亮),那么取反后,P1.0就是高電平(LED滅),反之,如果P1.0是高電平,取反后,P1.0就是低電平,這條指令被反復(fù)地執(zhí)行,接在P1.0上燈就會(huì)不斷“亮”、“滅”。

for(;;),這行程序連同其后的一對(duì)大括號(hào)“{}”構(gòu)成了一個(gè)無限循環(huán)語句,該大括號(hào)內(nèi)的語句會(huì)被反復(fù)執(zhí)行。

第三行程序是:“mDelay(1000);”,這行程序的用途是延時(shí)1s時(shí)間。這里mDelay(1000)并不是由Keil

C提供的庫函數(shù)。在下面的程序中有void

mDelay(…)一段,如果你的程序中沒有這么一段程序行,那就不能使用mDelay(1000)了。

mDelay后面有一個(gè)小括號(hào),小括號(hào)里有數(shù)據(jù)(1000),這個(gè)1000被稱之“參數(shù)”,用它可以在一定范圍內(nèi)調(diào)整延時(shí)時(shí)間的長短,這里用1000來要求延時(shí)時(shí)間為1000毫秒。C語言的一些特點(diǎn)1、C程序是由函數(shù)構(gòu)成的,一個(gè)C源程序至少包括一個(gè)函數(shù),一個(gè)C源程序有且只有一個(gè)名為main()的函數(shù),也可能包含其它函數(shù),因此,函數(shù)是C程序的基本單位。主程序通過直接書寫語句和調(diào)用其它函數(shù)來實(shí)現(xiàn)有關(guān)功能,這些其它函數(shù)可以是由C語言本身提供給我們的,這樣的函數(shù)稱之為庫函數(shù),也可以是用戶自己編寫的,這樣的函數(shù)稱之為用戶自定義函數(shù)。那么庫函數(shù)和用戶自定義函數(shù)有什么區(qū)別呢?簡單地說,任何使用Keil

C語言的人,都可以直接調(diào)用C的庫函數(shù)而不需要為這個(gè)函數(shù)寫任何代碼,只需要包含具有該函數(shù)說明的相應(yīng)的頭文件即可;而自定義函數(shù)則是完全個(gè)性化的,是用戶根據(jù)自己需要而編寫的。Keil

C提供了100多個(gè)庫函數(shù)供我們直接使用。2、一個(gè)函數(shù)由兩部份組成:(1)函數(shù)的首部、即函數(shù)的第一行。包括函數(shù)名、函數(shù)類型、函數(shù)屬性、函數(shù)參數(shù)(形參)名、參數(shù)類型。

例如:void

mDelay

(unsigned

int

DelayTime)

一個(gè)函數(shù)名后面必須跟一對(duì)圓括號(hào),即便沒有任何參數(shù)也是如此。

(2)函數(shù)體,即函數(shù)首部下面的大括號(hào)“{}”內(nèi)的部份。如果一個(gè)函數(shù)內(nèi)有多個(gè)大括號(hào),則最外層的一對(duì)“{}”為函數(shù)體的范圍。

函數(shù)體一般包括:

聲明部份:在這部份中定義所用到的變量,

執(zhí)行部份:由若干個(gè)語句組成。

C51的一般格式如下:類型

函數(shù)名(參數(shù)表)參數(shù)說明;{

數(shù)據(jù)說明部分;執(zhí)行語句部分;}在某此情況下也可以沒有聲明部份,甚至即沒有聲明部份,也沒有執(zhí)行部份,如:

void

mDelay()

{}

這是一個(gè)空函數(shù),什么也不干,但它是合法的。

通過上述的幾個(gè)例子,可以得出一些結(jié)論:

在編寫程序時(shí),可以利用空函數(shù),比如主程序需要調(diào)用一個(gè)延時(shí)函數(shù),可具體延時(shí)多少,怎么個(gè)延時(shí)法,暫時(shí)還不清楚,我們可以主程序的框架結(jié)構(gòu)弄清,先編譯通過,把架子搭起來再說,至于里面的細(xì)節(jié),可以在以后慢慢地填,這時(shí)利用空函數(shù),先寫這么一個(gè)函數(shù),這樣在主程序中就可以調(diào)用它了。

3、一個(gè)C語言程序,總是從main函數(shù)開始執(zhí)行的,而不管物理位置上這個(gè)main()放在什么地方。

4、主程序中的mDelay如果寫成mdelay就會(huì)編譯出錯(cuò),即C語言區(qū)分大小寫,這一點(diǎn)往往讓初學(xué)者非常困惑,尤其是學(xué)過一門其它語言的人,有人喜歡,有人不喜歡,但不管怎樣,你得遵守這一規(guī)定。

5、C語言書寫的格式自由,可以在一行寫多個(gè)語句,也可以把一個(gè)語句寫在多行。沒有行號(hào)(但可以有標(biāo)號(hào)),書寫的縮進(jìn)沒有要求。但是建議讀者自己按一定的規(guī)范來寫,可以給自己帶來方便。

6、每個(gè)語句和資料定義的最后必須有一個(gè)分號(hào),分號(hào)是C語句的必要組成部份。

7、可以用/*…..*/的形式為C程序的任何一部份作注釋。

Keil

C也支持C++風(fēng)格的注釋,就是用“//”引導(dǎo)的后面的語句是注釋,例:P1_0=!P1_0;

//取反P1.0

這種風(fēng)格的注釋,只對(duì)本行有效,所以不會(huì)出現(xiàn)上面的問題,而且書寫比較方便,所以在只需要一行注釋的時(shí)候,我們往往采用這種格式。但要注意,只有Keil

C支持這種格式,早期的Franklin

C以及PC機(jī)上用的TC都不支持這種格式的注釋,用上這種注釋,編譯時(shí)通不過,會(huì)報(bào)告編譯錯(cuò)誤。

11.2C51的數(shù)據(jù)結(jié)構(gòu)C51的常量與變量

其值不能改變的量稱為常量。常量可以有不同的數(shù)據(jù)類型。如0,1,2,-3為整型常量;4.6,-1.23等為實(shí)型常量;’a’、‘、’為字符型常量。可以用一個(gè)標(biāo)識(shí)符號(hào)代表一個(gè)常量。在程序運(yùn)行中,其值可以改變的量稱為變量。一個(gè)變量主要由兩部分構(gòu)成:一個(gè)是變量名,一個(gè)是變量值。每個(gè)變量都有一個(gè)變量名,在內(nèi)存中占據(jù)一定的存儲(chǔ)單元(地址),并在該內(nèi)存單元中存放該變量的值。

#defineCONST60main(){intvar,res;var=20;res=var*CONSTprintf(“res=%d\n”,res);}程序運(yùn)行結(jié)果:res=1200在程序開頭#defineCONST60這一行定義了一個(gè)符號(hào)常量CONST,其值為60。這樣在后面的程序中,凡是出現(xiàn)CONST的地方,都代表常量60。

常量變量11.3C51的運(yùn)算符和表達(dá)式1.賦值運(yùn)算符和表達(dá)式變量=表達(dá)式;例如:tmp=9; /*將常數(shù)9賦給變量tmp*/i=j(luò)=8; /*將常數(shù)8同時(shí)賦給變量i和j*/C51提供了10種復(fù)合運(yùn)算符:+=、-=、*=、/=、%=、<<=、>>=、&=、^=、!=。

2.算術(shù)運(yùn)算符和算術(shù)表達(dá)式C51有+、-、*、/、%五種運(yùn)算符3.關(guān)系運(yùn)算符

4.邏輯運(yùn)算符C語言中有3種邏輯運(yùn)算符:(1)邏輯非(?。?(2)邏輯與(&&) (3)邏輯或(||) 5.逗號(hào)運(yùn)算符在C51語言中,逗號(hào)“,”是一個(gè)特殊的運(yùn)算符,可以用它將兩個(gè)(或多個(gè))表達(dá)式連接起來,稱為逗號(hào)表達(dá)式。6.條件運(yùn)算符表達(dá)式“?:”是C51中唯一的三目運(yùn)算符,要求有3個(gè)運(yùn)算對(duì)象,它將三個(gè)表達(dá)式連接構(gòu)成一個(gè)條件表達(dá)式。7.自增和自減運(yùn)算符C51語言中,除了基本的加、減、乘、除運(yùn)算符之外,還提供一種特殊的運(yùn)算符:“++”自增運(yùn)算符;“--”自減運(yùn)算符。8.指針和地址運(yùn)算符指針在C51語言中指示變量的地址,另外,還可以定義一個(gè)指向某個(gè)變量的指針變量。為了表示指針變量和它所指向的變量地址之間的關(guān)系,C51語言提供了兩個(gè)專門的運(yùn)算符:取內(nèi)容(﹡)和取地址(&)。9.位運(yùn)算符位運(yùn)算符的作用是按位對(duì)變量進(jìn)行運(yùn)算,并不改變參與運(yùn)算的變量的值。

10.強(qiáng)制類型轉(zhuǎn)換運(yùn)算符強(qiáng)制類型轉(zhuǎn)換運(yùn)算符的作用是將表達(dá)式或變量的類型強(qiáng)制轉(zhuǎn)換成所指定的類型。在C51程序中進(jìn)行算術(shù)運(yùn)算時(shí),編譯器自動(dòng)處理數(shù)據(jù)類型轉(zhuǎn)換。當(dāng)自動(dòng)類型轉(zhuǎn)換不能實(shí)現(xiàn)目的時(shí),可以使用強(qiáng)制類型轉(zhuǎn)換。強(qiáng)制類型轉(zhuǎn)換的一般格式為:(類型名)(表達(dá)式)例如: (double)a /*將a轉(zhuǎn)換成double類型*/(int)(x+y) /*將x+y的值轉(zhuǎn)換成整型*/11.3.2運(yùn)算符的優(yōu)先級(jí)和結(jié)合性在表達(dá)式中,不同運(yùn)算符連接的對(duì)象的運(yùn)算順序不完全按照表達(dá)式中書寫的先后順序進(jìn)行的,各運(yùn)算符參與運(yùn)算的先后順序不僅要遵守運(yùn)算符優(yōu)先級(jí)別的規(guī)定,還要受運(yùn)算符結(jié)合性的制約。

11.4C51的存儲(chǔ)結(jié)構(gòu)11.4.1存儲(chǔ)區(qū)域8051單片機(jī)有4個(gè)存儲(chǔ)空間:片內(nèi)程序存儲(chǔ)空間,片外程序存儲(chǔ)空間,片內(nèi)數(shù)據(jù)存儲(chǔ)空間和片外數(shù)據(jù)存儲(chǔ)空間。11.4.2存儲(chǔ)模式1.Small模式2.緊湊模式(Compact)模式3.Large模式4.混合存儲(chǔ)模式11.5C51的基本程序結(jié)構(gòu)1.If語句

(1)If(條件表達(dá)式)

{動(dòng)作}

如果條件表達(dá)式的值為真(非零的數(shù)),則執(zhí)行{}內(nèi)的動(dòng)作,如果條件表達(dá)式為假,則略過

該動(dòng)作繼續(xù)往下執(zhí)行。

(2)If(條件表達(dá)式)

{動(dòng)作1}

else

{動(dòng)作2}

如果條件表達(dá)式的值為真(非零的數(shù)),則執(zhí)行動(dòng)作1,(則略過else)如果條件表達(dá)式為假,則執(zhí)行動(dòng)作2。

(3)If(條件表達(dá)式1)

{

溫馨提示

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

評(píng)論

0/150

提交評(píng)論