51單片機C語言程序100例

 

目錄git

目錄................................................................................................................................1數組

函數的使用和熟悉********************************/.......................................4函數

實例3:用單片機控制第一個燈亮.............................................................................4ui

實例4:用單片機控制一個燈閃爍:認識單片機的工做頻率.................................4spa

實例5:將P1口狀態分別送入P0P2P3口:認識I/O口的引腳功能............5設計

實例6:使用P3口流水點亮8LED.......................................................................5指針

實例7:經過對P3口地址的操做流水點亮8LED...............................................6code

實例8:用不一樣數據類型控制燈閃爍時間.................................................................7接口

實例9:用P0口、P1口分別顯示加法和減法運算結果.........................................8字符串

實例10:用P0P1口顯示乘法運算結果................................................................9

實例11:用P1P0口顯示除法運算結果................................................................9

實例12:用自增運算控制P08LED流水花樣..............................................10

實例13:用P0口顯示邏輯""運算結果...............................................................10

實例14:用P0口顯示條件運算結果.......................................................................11

實例15:用P0口顯示按位"異或"運算結果...........................................................11

實例16:用P0顯示左移運算結果...........................................................................11

實例17"萬能邏輯電路"實驗.................................................................................11

實例18:用右移運算流水點亮P18LED.......................................................12

實例19:用if語句控制P08LED的流水方向..............................................13

實例20:用swtich語句的控制P08LED的點亮狀態..................................13

實例21:用for語句控制蜂鳴器鳴笛次數..............................................................14

實例22:用while語句控制LED...............................................................................16

實例23:用do-while語句控制P08LED流水點亮......................................16

實例24:用字符型數組控制P08LED流水點亮..........................................17

實例25P0口顯示字符串常量.........................................................................18

實例26:用P0口顯示指針運算結果......................................................................19

實例27:用指針數組控制P08LED流水點亮..............................................19

實例28:用數組的指針控制P08LED流水點亮........................................20

實例29:用P0P1口顯示整型函數返回值........................................................21

實例30:用有參函數控制P08LED流水速度..............................................22

實例31:用數組做函數參數控制流水花樣.............................................................23

實例32:用指針做函數參數控制P08LED流水點亮..................................23

實例33:用函數型指針控制P1口燈花樣...............................................................25

實例34:用指針數組做爲函數的參數顯示多個字符串.........................................26

實例35:字符函數ctype.h應用舉例.......................................................................27

實例36:內部函數intrins.h應用舉例.....................................................................27

實例37:標準函數stdlib.h應用舉例.......................................................................28

實例38:字符串函數string.h應用舉例..................................................................29

實例39:宏定義應用舉例2......................................................................................29

1/192


實例40:宏定義應用舉例2......................................................................................30

實例41:宏定義應用舉例3......................................................................................30

 

中斷、定時器************************************************   .........31

實例42:用定時器T0查詢方式P28位控制LED閃爍....................................31

實例43:用定時器T1查詢方式控制單片機發出1KHz音頻.................................31

實例44:將計數器T0計數的結果送P18LED顯示....................................32

實例45:用定時器T0的中斷控制1LED閃爍...................................................33

實例46:用定時器T0的中斷實現長時間定時.......................................................34

實例47:用定時器T1中斷控制兩個LED以不一樣週期閃爍...................................34

實例48:用計數器T1的中斷控制蜂鳴器發出1KHz音頻.....................................36

實例49:用定時器T0的中斷實現"渴望"主題曲的播放.......................................36

實例50-1:輸出50個矩形脈衝...............................................................................39

實例50-2:計數器T0統計外部脈衝數...................................................................40

實例51-2:定時器T0的模式2測量正脈衝寬度...................................................40

實例52:用定時器T0控制輸出高低寬度不一樣的矩形波.......................................41

實例53:用外中斷0的中斷方式進行數據採集.....................................................42

實例54-1:輸出負脈寬爲200微秒的方波.............................................................43

實例54-2:測量負脈衝寬度.....................................................................................43

實例55:方式0控制流水燈循環點亮.....................................................................44

實例56-1:數據發送程序.........................................................................................45

實例56-2:數據接收程序.........................................................................................47

實例57-1:數據發送程序.........................................................................................47

實例57-2:數據接收程序.........................................................................................49

實例58:單片機向PC發送數據..............................................................................50

實例59:單片機接收PC發出的數據......................................................................51

 

*********************************數碼管顯示       ...............................52

實例60:用LED數碼顯示數字5..............................................................................52

實例61:用LED數碼顯示器循環顯示數字0~9......................................................52

實例62:用數碼管慢速動態掃描顯示數字"1234".................................................53

實例63:用LED數碼顯示器僞靜態顯示數字1234...............................................54

實例64:用數碼管顯示動態檢測結果.....................................................................54

實例65:數碼秒錶設計.............................................................................................56

實例66:數碼時鐘設計.............................................................................................58

實例67:用LED數碼管顯示計數器T0的計數值...................................................62

實例68:靜態顯示數字「59」...................................................................................63

*****************************鍵盤控制


2


/


192


*****************************************************/...........................63

實例69:無軟件消抖的獨立式鍵盤輸入實驗.........................................................64

實例70:軟件消抖的獨立式鍵盤輸入實驗.............................................................64

實例71CPU控制的獨立式鍵盤掃描實驗.............................................................65

實例72:定時器中斷控制的獨立式鍵盤掃描實驗.................................................68

實例73:獨立式鍵盤控制的4級變速流水燈.........................................................71

實例74:獨立式鍵盤的按鍵功能擴展:"以一當四".............................................73

實例75:獨立式鍵盤調時的數碼時鐘實驗.............................................................75

實例76:獨立式鍵盤控制步進電機實驗.................................................................79

實例77:矩陣式鍵盤按鍵值的數碼管顯示實驗.....................................................82

//實例78:矩陣式鍵盤按鍵音..................................................................................85

實例79:簡易電子琴.................................................................................................86

實例80:矩陣式鍵盤實現的電子密碼鎖.................................................................92

*********************************************************************

*****液晶顯示LCD*********液晶顯示LCD*****液晶顯示LCD*************

***********************************************************/...............95

實例81:用LCD顯示字符'A'....................................................................................96

實例82:用LCD循環右移顯示"WelcometoChina"...............................................99

實例83:用LCD顯示適時檢測結果......................................................................102

實例84:液晶時鐘設計...........................................................................................106

 

******************************************一些芯片的使用*****24c02   ........DS18B20   X5045   ADC0832   DAC0832   DS1302

紅外遙控**********************************************/......................112

 

實例85:將數據"0x0f"寫入AT24C02再讀出送P1口顯示..................................112

實例86:將按鍵次數寫入AT24C02,再讀出並用1602LCD顯示.......................117

實例87:對I2C總線上掛接多個AT24C02的讀寫操做.......................................124

實例88:基於AT24C02的多機通訊   讀取程序..................................................129

實例88:基於AT24C02的多機通訊寫入程序....................................................133

實例90DS18B20溫度檢測及其液晶顯示...........................................................144

實例91:將數據"0xaa"寫入X5045再讀出送P1口顯示......................................153

實例92:將流水燈控制碼寫入X5045並讀出送P1口顯示................................157

實例93:對SPI總線上掛接多個X5045的讀寫操做............................................161

實例94:基於ADC0832的數字電壓表..................................................................165

實例95:用DAC0832產生鋸齒波電壓..................................................................171

實例96:用P1口顯示紅外遙控器的按鍵值.........................................................171

實例97:用紅外遙控器控制繼電器.......................................................................174

實例98:基於DS1302的日曆時鐘........................................................................177

實例99:單片機數據發送程序...............................................................................185

實例100:電機轉速錶設計.....................................................................................186

模擬霍爾脈衝............................................................................................................192


 


3


/


192


 

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

函數的使用和熟悉***************

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


 

//實例3:用單片機控制第一個燈亮

#include<reg51.h>   //包含51單片機寄存器定義的頭文件

voidmain(void)

{

P1=0xfe;//P1=11111110B,即P1.0輸出低電平

}


 


//


4


//實例4:用單片機控制一個燈閃爍:認識單片機的工做頻率

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

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

函數功能:延時一段時間

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

voiddelay(void)          //兩個void意思分別爲無需返回值,沒有參數傳遞

{

unsignedinti;         //定義無符號整數,最大取值範圍65535

for(i=0;i<20000;i++)   //20000次空循環

;                  //什麼也不作,等待一個機器週期

}

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

函數功能:主函數C語言規定必須有也只能有1個主函數)

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

voidmain(void)

{

while(1)       //無限循環

{

P1=0xfe;   //P1=11111110BP1.0輸出低電平

delay();   //延時一段時間

P1=0xff;   //P1=11111111BP1.0輸出高電平

delay();  //延時一段時間

}

}

4/192


 


//


5


P1


P0


P2


P3


I/O


//實例5:將

#include<reg51.h>


P1口狀態分別送入P0P2P3口:認識I/O

的引腳功能

//包含單片機寄存器的頭文件


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

函數功能:主函數C語言規定必須有也只能有1個主函數)

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

voidmain(void)

{

while(1)          //無限循環

{

P1=0xff;   //P1=11111111B,熄滅LED

P0=P1;     //  P1口狀態送入P0

P2=P1;         //  P1口狀態送入P2

P3=P1;     //  P1口狀態送入P3

}

}


 

//實例6:使用P3口流水點亮8LED

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

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

函數功能:延時一段時間

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

voiddelay(void)

{

unsignedchari,j;

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

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

;

}

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

函數功能:主函數

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

voidmain(void)

{

5/192


while(1)

{


P3=0xfe;

delay();

P3=0xfd;

delay();

P3=0xfb;

delay();

P3=0xf7;

delay();

P3=0xef;


//第一個燈亮

//調用延時函數

//第二個燈亮

//調用延時函數

//第三個燈亮

//調用延時函數

//第四個燈亮

//調用延時函數

//第五個燈亮


 


delay();


//調用延時函數


P3=0xdf;

delay();

P3=0xbf;


//第六個燈亮

//調用延時函數

//第七個燈亮


delay();


//調用延時函數


 


P3=0x7f;


//第八個燈亮


}


}


delay();


//調用延時函數


 

//實例7:經過對P3口地址的操做流水點亮8LED

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

sfrx=0xb0;    //P3口在存儲器中的地址是b0H經過sfr可定義8051內核單片

//的全部內部8位特殊功能寄存器,對地址x的操做也就是對P1口的

操做

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

函數功能:延時一段時間

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

voiddelay(void)

{

unsignedchari,j;

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

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

;    //利用循環等待若干機器週期,從而延時一段時間

}

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

函數功能:主函數

6/192


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

voidmain(void)

{

while(1)

{

x=0xfe;   //第一個燈亮

delay();  //調用延時函數

x=0xfd;  //第二個燈亮

delay();  //調用延時函數

x=0xfb;  //第三個燈亮

delay();  //調用延時函數

x=0xf7;  //第四個燈亮

delay();  //調用延時函數

x=0xef;   //第五個燈亮

delay();  //調用延時函數

x=0xdf;   //第六個燈亮

delay();  //調用延時函數

x=0xbf;   //第七個燈亮

delay();  //調用延時函數

x=0x7f;   //第八個燈亮

delay();  //調用延時函數

}

}


 

//實例8:用不一樣數據類型控制燈閃爍時間

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

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

函數功能:用整形數據延時一段時間

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

voidint_delay(void)//延時一段較長的時間

{

unsignedintm;     //定義無符號整形變量,雙字節數據,值域爲0~65535

for(m=0;m<36000;m++)

;            //空操做

}

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

函數功能:用字符型數據延時一段時間

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

7/192


voidchar_delay(void)//延時一段較短的時間

{

unsignedchari,j;    //定義無符號字符型變量,單字節數據,值域0~255

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

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

;         //空操做

}

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

函數功能:主函數

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

voidmain(void)

{

unsignedchari;

while(1)

{

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

{

P1=0xfe;      //P1.0口的燈點亮

int_delay();//延時一段較長的時間

P1=0xff;      //熄滅

int_delay();//延時一段較長的時間

}

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

{

P1=0xef;      //P1.4口的燈點亮

char_delay();//延時一段較長的時間

P1=0xff;      //熄滅

char_delay();//延時一段較長的時間

}

}

}


 


//實例9:用P0口、P1

#include<reg51.h>

voidmain(void)

{

unsignedcharm,n;


口分別顯示加法和減法運算結果


m=43;


//即十進制數2x16+11=43

8/


192


n=60;

P1=m+n;


//即十進制數3x16+12=60

//P1=103=01100111B,結果P1.3P1.4P1.7


口的燈被點亮


}


P0=n-m;


//P0=17=00010001B,結果P0.0P0.4的燈被熄滅


 

//實例10:用P0P1口顯示乘法運算結果

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

voidmain(void)

{

unsignedcharm,n;

unsignedints;

m=64;

n=71;

s=m*n;         //s=64*71=4544,須要16位二進制數表示,高8位送P1口,低

8位送P0

//因爲4544=17*256+192=H3*16*16*16+H2*16*16+H1*16+H0

//兩邊同除以256,可得17+192/256=H3*16+H2+  H1*16+H0

/256

//所以,高816進制數H3*16+H2必然等於17,即4544

除以256的商

//816進制數H1*16+H0必然等於192,即4544除以

256的餘數

P1=s/256;      //8位送P1P1=17=11H=00010001B,P1.0P1.4口滅

其他亮

P0=s%256;      //8位送P0,P3=192=c0H=11000000B,P3.1,P3.6,P3.7

滅,其他亮

}


 

//實例11:用P1P0口顯示除法運算結果

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

voidmain(void)

{

P1=36/5;            //求整數

P0=((36%5)*10)/5;//求小數

while(1)

9/192


}


;


//無限循環防止程序「跑飛」


 

//實例12:用自增運算控制P08LED流水花樣

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

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

函數功能:延時一段時間

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

voiddelay(void)

{

unsignedinti;

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

;

}

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

函數功能 :主函數

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

voidmain(void)

{

unsignedchari;

for(i=0;i<255;i++)   //注意i的值不能超過255

{

P0=i;    //i的值送P0

delay();//調用延時函數

}

}


 

//實例13:用P0口顯示邏輯""運算結果

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

voidmain(void)

{

P0=(4>0)&&(9>0xab);//將邏輯運算結果送P0

while(1)

;    //設置無限循環,防止程序「跑飛」

}

110/192


 


//


14


P0


//實例14:用P0口顯示條件運算結果

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

voidmain(void)

{

P0=(8>4)?8:4;//將條件運算結果送P0口,P0=8=00001000B

while(1)

;    //設置無限循環,防止程序「跑飛」

}


 

//實例15:用P0口顯示按位"異或"運算結果

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

voidmain(void)

{

P0=0xa2^0x3c;//將條件運算結果送P0口,P0=8=00001000B

while(1)

;    //設置無限循環,防止程序「跑飛」

}


 


//


16


P0


//實例16:用P0顯示左移運算結果

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

voidmain(void)

{

P0=0x3b<<2;//將左移運算結果送P0口,P0=11101100B=0xec

while(1)

;    //無限循環,防止程序「跑飛」

}


 


#include<reg51.h>

sbitF=P1^4;


//實例17"萬能邏輯電路"實驗

//包含單片機寄存器的頭文件

//F位定義爲P1.4

111/192


sbitX=P1^5;

sbitY=P1^6;

sbitZ=P1^7;

voidmain(void)

{

while(1)

{


//X位定義爲

//Y位定義爲

//Z位定義爲


P1.5

P1.6

P1.7


}


}


F=((~X)&Y)|Z;//將邏輯運算結果賦給F

;


 

//實例18:用右移運算流水點亮P18LED

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

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

函數功能:延時一段時間

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

voiddelay(void)

{

unsignedintn;

for(n=0;n<30000;n++)

;

}

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

函數功能:主函數

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

voidmain(void)

{

unsignedchari;

while(1)

{

P1=0xff;

delay();

for(i=0;i<8;i++)//設置循環次數爲8

{

P1=P1>>1;    //每次循環P1的各二進位右移1位,高位補0

delay();    //調用延時函數

}

}

}

112/192


 


//


19


iff


P0


8


LED


//實例19:用iff語句控制P08LED的流水方向

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

sbitS1=P1^4;      //S1位定義爲P1.4

sbitS2=P1^5;      //S2位定義爲P1.5

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

函數功能:主函數

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

voidmain(void)

{

while(1)

{

if(S1==0)   //若是按鍵S1按下

P0=0x0f;  //P0口高四位LED點亮

if(S2==0)   //若是按鍵S2按下

P0=0xf0;  //P0口低四位LED點亮

}

}


 

//實例20:用swtich語句的控制P08LED的點亮狀態

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

sbitS1=P1^4;      //S1位定義爲P1.4

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

函數功能:延時一段時間

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

voiddelay(void)

{

unsignedintn;

for(n=0;n<10000;n++)

;

}

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

函數功能:主函數

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

voidmain(void)

{

unsignedchari;

113/192


i=0;

while(1)

{


//i初始化爲0


if(S1==0)

{

delay();


//若是S1鍵按下

//延時一段時間


 


}


if(S1==0)//若是再次檢測到S1鍵按下

i++;    //i自增1

if(i==9)  //若是i=9,從新將其置爲1

i=1;


}


switch(i)

}


{

}


//使用多分支選擇語句

case1:P0=0xfe;   //第一個LED

break;

case2:P0=0xfd;   //第二個LED

break;

case3:P0=0xfb;    //第三個LED

break;

case4:P0=0xf7;    //第四個LED

break;

case5:P0=0xef;    //第五個LED

break;

case6:P0=0xdf;    //第六個LED

break;

case7:P0=0xbf;    //第七個LED

break;

case8:P0=0x7f;    //第八個LED

break;

default:   //缺省值,關閉全部LED

P0=0xff;


 


//


21


for


//實例21:用for語句控制蜂鳴器鳴笛次數

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

sbitsound=P3^7;   //sound位定義爲P3.7

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

函數功能:延時造成1600Hz音頻

114/192


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

voiddelay1600(void)

{

unsignedcharn;

for(n=0;n<100;n++)

;

}

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

函數功能:延時造成800Hz音頻

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

voiddelay800(void)

{

unsignedcharn;

for(n=0;n<200;n++)

;

}

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

函數功能:主函數

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

voidmain(void)

{

unsignedinti;

while(1)

{

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

{

sound=0;  //P3.7輸出低電平

delay1600();

sound=1;  //P3.7輸出高電平

delay1600();

}

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

{

sound=0;  //P3.7輸出低電平

delay800();

sound=1;  //P3.7輸出高電平

delay800();

}

}

}


 


115


/


192


 

//實例22:用whille語句控制LED


 


#include<reg51.h>


//包含單片機寄存器的頭文件


 

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

函數功能:延時約60ms(3*100*200=60000μs)

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

voiddelay60ms(void)

{

unsignedcharm,n;

for(m=0;m<100;m++)

for(n=0;n<200;n++)

;

}

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

函數功能:主函數

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

voidmain(void)

{

unsignedchari;

while(1)    //無限循環

{

i=0;    //i初始化爲0

while(i<0xff)    //i小於0xff255)時執行循環體

{

P0=i;          //iP0口顯示

delay60ms();//延時

i++;           //i自增1

}

}

}


 

//實例23:用do-whiile語句控制P08LED流水點亮

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

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

函數功能:延時約60ms(3*100*200=60000μs)

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

voiddelay60ms(void)

{

116/192


}


unsignedcharm,n;

for(m=0;m<100;m++)

for(n=0;n<200;n++)

;


 

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

函數功能:主函數

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

voidmain(void)

{

do

{

P0=0xfe;      //第一個LED

delay60ms();

P0=0xfd;      //第二個LED

delay60ms();

P0=0xfb;      //第三個LED

delay60ms();

P0=0xf7;      //第四個LED

delay60ms();

P0=0xef;      //第五個LED

delay60ms();

P0=0xdf;      //第六個LED

delay60ms();

delay60ms();

P0=0xbf;      //第七個LED

delay60ms();

P0=0x7f;      //第八個LED

delay60ms();

}while(1);      //無限循環,使8LED循環流水點亮

}


 

//實例24:用字符型數組控制P08LED流水點亮

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

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

函數功能:延時約60ms(3*100*200=60000μs)

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

voiddelay60ms(void)

{

unsignedcharm,n;

for(m=0;m<100;m++)

117/192


}


for(n=0;n<200;n++)

;


 

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

函數功能:主函數

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

voidmain(void)

{

unsignedchari;

unsignedcharcodeTab[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//定義無符

號字符型數組

while(1)

{

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

{

P0=Tab[i];//依次引用數組元素,並將其送P0口顯示

delay60ms();//調用延時函數

}

}

}


 


//


25


P0


//實例25


P0口顯示字符串常量


 


#include<reg51.h>


//包含單片機寄存器的頭文件


 

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

函數功能:延時約150ms(3*200*250=150000μs=150ms

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

voiddelay150ms(void)

{

unsignedcharm,n;

for(m=0;m<200;m++)

for(n=0;n<250;n++)

;

}

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

函數功能:主函數

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

voidmain(void)

{

unsignedcharstr[]={"Now,Temperatureis:"};   //將字符串賦給字符型所有元素

賦值

unsignedchari;

118/192


while(1)

{

i=0;


//i初始化爲0,從第一個元素開始顯示


}


}


while(str[i]!='\0')//只要沒有顯示到結束標誌'\0'

{

P0=str[i];      //將第i個字符送到P0口顯示

delay150ms();   //調用150ms延時函數

i++;             //指向下一個待顯字符

}


 


//實例26:用P0

#include<reg51.h>

voidmain(void)

{


口顯示指針運算結果


unsignedchar*p1,*p2;


//定義無符號字符型指針變量p1,p2


 


unsignedchari,j;


//定義無符號字符型數據


i=25;

j=15;

p1=&i;

p2=&j;


//i賦初值25

//使指針變量指向i

//使指針變量指向j


,對指針初始化

,對指針初始化


 


P0=*p1+*p2;


//*p1+*p2至關於i+j,因此P0=25+15=40=0x28


}


//P0=00101000B,結果P0.3P0.5引腳LED熄滅,其他點亮

while(1)

;             //無限循環,防止程序「跑飛」


 


//


27


P0


8


LED


//實例27:用指針數組控制P08LED流水點亮

#include<reg51.h>

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

函數功能:延時約150ms(3*200*250=150000μs=150ms

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

voiddelay150ms(void)

{

unsignedcharm,n;

for(m=0;m<200;m++)

119/192


}


for(n=0;n<250;n++)

;


 

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

函數功能:主函數

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

voidmain(void)

{

unsignedcharcodeTab[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};

unsignedchar*p[]={&Tab[0],&Tab[1],&Tab[2],&Tab[3],&Tab[4],&Tab[5],

&Tab[6],&Tab[7]};

unsignedchari;      //定義無符號字符型數據

while(1)

{

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

{

P0=*p[i];

delay150ms();

}

}

}


 


//


28


P0


8


LED


//實例28:用數組的指針控制P0

#include<reg51.h>


8


LED流水點亮


 

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

函數功能:延時約150ms(3*200*250=150000μs=150ms

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

voiddelay150ms(void)

{

unsignedcharm,n;

for(m=0;m<200;m++)

for(n=0;n<250;n++)

;

}

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

函數功能:主函數

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

voidmain(void)

{

220/192


}


unsignedchari;

unsignedcharTab[]={0xFF,0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,

0x7F,0xBF,0xDF,0xEF,0xF7,0xFB,0xFD,0xFE,

0xFE,0xFC,0xFB,0xF0,0xE0,0xC0,0x80,0x00,

0xE7,0xDB,0xBD,0x7E,0x3C,0x18,0x00,0x81,

0xC3,0xE7,0x7E,0xBD,0xDB,0xE7,0xBD,0xDB};

//流水燈控制碼

unsignedchar*p;    //定義無符號字符型指針

p=Tab;                 //將數組首地址存入指針p

while(1)

{

for(i=0;i<32;i++)//32個流水燈控制碼

{

P0=*(p+i);      //*p+i)的值等於a[i]

delay150ms();   //調用150ms延時函數

}

}


 


//


29


P0


P1


//實例29:用P0

#include<reg51.h>


P1口顯示整型函數返回值


 

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

函數功能:計算兩個無符號整數的和

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

unsignedintsum(inta,intb)

{

unsignedints;

s=a+b;

return(s);

}

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

函數功能:主函數

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

voidmain(void)

{

unsignedz;

z=sum(2008,2009);

P1=z/256;        //取得z的高8

P0=z%256;     //取得z的低8

while(1)

;

221/192


}


 

//實例30:用有參函數控制P08LED流水速度

#include<reg51.h>

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

函數功能:延時一段時間

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

voiddelay(unsignedcharx)

{

unsignedcharm,n;

for(m=0;m<x;m++)

for(n=0;n<200;n++)

;

}

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

函數功能:主函數

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

voidmain(void)

{

unsignedchari;

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

//流水燈控制碼

while(1)

{

//快速流水點亮LED

for(i=0;i<8;i++)//8個流水燈控制碼

{

P0=Tab[i];

delay(100);   //延時約60ms,(3*100*200=60000μs

}

//慢速流水點亮LED

for(i=0;i<8;i++)//8個流水燈控制碼

{

P0=Tab[i];

delay(250);   //延時約150ms,(3*250*200=150000μs

}

}

}


 


222


/


192


//


31


//實例31:用數組做函數參數控制流水花樣

#include<reg51.h>

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

函數功能:延時約150ms

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

voiddelay(void)

{

unsignedcharm,n;

for(m=0;m<200;m++)

for(n=0;n<250;n++)

;

}

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

函數功能:流水點亮P08LED

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

voidled_flow(unsignedchara[8])

{

unsignedchari;

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

{

P0=a[i];

delay();

}

}


 

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

函數功能:主函數

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

voidmain(void)

{

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

//流水燈控制碼

led_flow(Tab);

}


 


//


32


P0


8


LED


//實例32:用指針做函數參數控制P08LED流水點亮

#include<reg51.h>

223/192


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

函數功能:延時約150ms

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

voiddelay(void)

{

unsignedcharm,n;

for(m=0;m<200;m++)

for(n=0;n<250;n++)

;

}

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

函數功能:流水點亮P08LED

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

voidled_flow(unsignedchar*p)//形參爲無符號字符型指針

{

unsignedchari;

while(1)

{

i=0;   //i置爲0,指向數組第一個元素

while(*(p+i)!='\0')//只要沒有指向數組的結束標誌

{

P0=*(p+i);//  取的指針所指變量(數組元素)的值,送P0

delay();   //調用延時函數

i++;    //指向下一個數組元素

}

}

}


 

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

函數功能:主函數

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

voidmain(void)

{

unsigned  charcodeTab[]={0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F,

0x7F,0xBF,0xDF,0xEF,0xF7,0xFB,0xFD,0xFE,

0xFF,0xFE,0xFC,0xFB,0xF0,0xE0,0xC0,0x80,

0x00,0xE7,0xDB,0xBD,0x7E,0xFF,0xFF,0x3C,

0x18,0x0,0x81,0xC3,0xE7,0xFF,

0xFF,0x7E};

//流水燈控制碼

unsignedchar*pointer;

224/192


}


pointer=Tab;

led_flow(pointer);


 


//


33


P1


//實例33:用函數型指針控制P1口燈花樣

#include<reg51.h>    //包含51單片機寄存器定義的頭文件

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

//流水燈控制碼,該數組被定義爲全局變量

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

函數功能:延時約150ms

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

voiddelay(void)

{

unsignedcharm,n;

for(m=0;m<200;m++)

for(n=0;n<250;n++)

;

}

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

函數功能:流水燈左移

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

voidled_flow(void)

{

unsignedchari;

for(i=0;i<8;i++)   //8位控制碼

{

P0=Tab[i];

delay();

}

}

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

函數功能:主函數

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

voidmain(void)

{

void(*p)(void);//定義函數型指針,所指函數無參數,無返回值

p=led_flow;   //將函數的入口地址賦給函數型指針p

while(1)

225/192


}


(*p)();


//經過函數的指針p調用函數led_flow()


 


//


34


//實例34:用指針數組做爲函數的參數顯示多個字符串

#include<reg51.h>    //包含51單片機寄存器定義的頭文件

unsignedcharcodestr1[]="TemperatureistestedbyDS18B20";//C語言中,字符串

是做爲字符數組來處理的

unsignedcharcodestr2[]="Nowtemperatureis:";     //因此,字符串的名字就是

字符串的首地址

unsignedcharcodestr3[]="TheSystermisdesignedbyZhangSan";

unsignedcharcodestr4[]="Thedateis2008-9-30";

unsignedchar*p[]={str1,str2,str3,str4};//定義p[4]爲指向4個字符串的字符型指

針數組

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

函數功能:延時約150ms

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

voiddelay(void)

{

unsignedcharm,n;

for(m=0;m<200;m++)

for(n=0;n<250;n++)

;

}

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

函數功能:流水點亮P08LED

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

voidled_display(unsignedchar*x[])   //形參必須爲指針數組

{

unsignedchari,j;

for(i=0;i<4;i++)//4個字符串要顯示

{

j=0;  //指向待顯字符串的第0號元素

while(*(x[i]+j)!='\0')//只要第i個字符串的第j號元素不是結束標誌

{

P0=*(x[i]+j);//取得該元素值送到P0口顯示

delay();  //調用延時函數

j++;   //指向下一個元素

}

}

}

226/192


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

函數功能:主函數

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

voidmain(void)

{

unsignedchari;

while(1)

{

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

led_display(p);//將指針數組名做實際參數傳遞

}

}


 

//實例35:字符函數ctype.h應用舉例

#include<reg51.h>    //包含51單片機寄存器定義的頭文件

#include<ctype.h>

voidmain(void)

{

while(1)

{

P3=isalpha('_')?0xf0:0x0f;//條件運算,若'_'是英文字母,P3=0xf0

}

}


 

//實例36:內部函數intrins..h應用舉例

#include<reg51.h>    //包含51單片機寄存器定義的頭文件

#include<intrins.h>    //包含函數isalpha()聲明的頭文件

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

函數功能:延時約150ms

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

voiddelay(void)

{

unsignedcharm,n;

for(m=0;m<200;m++)

for(n=0;n<250;n++)

;

}

227/192


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

函數功能:主函數

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

voidmain(void)

{

P3=0xfe;  //P3=11111110B

while(1)

{

P3=_crol_(P3,1);//P3的二進制位循環左移1位後再賦給P3

delay();  //調用延時函數

}

}


 


//


37


stdlib.h


//實例37:標準函數stdliib.h應用舉例

#include<reg51.h>    //包含51單片機寄存器定義的頭文件

#include<stdlib.h>    //包含函數isalpha()聲明的頭文件

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

函數功能:延時約150ms

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

voiddelay(void)

{

unsignedcharm,n;

for(m=0;m<200;m++)

for(n=0;n<250;n++)

;

}

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

函數功能:主函數

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

voidmain(void)

{

unsignedchari;

while(1)

{

for(i=0;i<10;i++)//產生10個隨機數

{

P3=rand()/160;//將產生的隨機數縮小160倍後送P3顯示

delay();

}

}

228/192


}


 

//實例38:字符串函數striing.h應用舉例

#include<reg51.h>    //包含51單片機寄存器定義的頭文件

#include<string.h>    //包含函數isalpha()聲明的頭文件

voidmain(void)

{

unsignedcharstr1[]="Now,Thetemperatureis:";

unsignedcharstr2[]="Now,Thetemperatureis36Centgrade:";

unsignedchari;

i=strcmp(str1,str2);//比較兩個字符串,並將結果存入i

if(i==0)//str1=str2

P3=0x00;

else

if(i<0)    //str1<str2

P3=0xf0;

else    //str1>str2

P3=0x0f;

while(1)

;    //防止程序「跑飛」

}


 


//


39


2


#include<reg51.h>


//實例39:宏定義應用舉例2

//包含51單片機寄存器定義的頭文件


#defineF(a,b)(a)+(a)*(b)/256+(b)

voidmain(void)

{

unsignedchari,j,k;

i=40;

j=30;

k=20;


//帶參數的宏定義,ab爲形參


}


P3=F(i,j+k);

while(1)

;


//ij+k分別爲實參,宏展開時,實參將替代宏定義中的形

229/192


 

//實例40:宏定義應用舉例2


 

#include<AT89X51.h>

#include<ctype.h>

voidmain(void)

{

P3_0=0;  //P3.0引腳置低電平,LED點亮

P3_1=0;  //P3.0引腳置低電平,LED點亮

P3_2=0;  //P3.0引腳置低電平,LED點亮

P3_3=0;  //P3.0引腳置低電平,LED點亮

P3_4=1;  //P3.4引腳置高電平,LED熄滅

P3_5=1;  //P3.5引腳置高電平,LED熄滅

P3_6=1;  //P3.7引腳置高電平,LED熄滅

P3_7=1;  //P3.7引腳置高電平,LED熄滅

while(1)

;

}


 

//實例41:宏定義應用舉例3


 


#include<reg51.h>

#defineMAX100

voidmain(void)

{

#ifMAX>80

P3=0xf0;

#else

P3=0x0f;

#endif

}


//包含51單片機寄存器定義的頭文件

//MAX宏定義爲字符串100

//若是字符串100大於80

//P3口低四位LED點亮

//不然,P3口高四位LED點亮

//結束本次編譯


 


330


/


192


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

*********中斷、定時器********斷、定時器************

*********中斷、定時器*********中斷、定時************

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


 

//實例42:用定時器T0查詢方式P28位控制LED閃爍

#include<reg51.h>          //   包含51單片機寄存器定義的頭文件

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

函數功能:主函數

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

voidmain(void)

{

//EA=1;                      //開總中斷

//   ET0=1;                     //定時器T0中斷容許

TMOD=0x01;               //使用定時器T0的模式1

TH0=(65536-46083)/256;   //定時器T0的高8位賦初值

TL0=(65536-46083)%256;   //定時器T0的高8位賦初值

TR0=1;                   //啓動定時器T0

TF0=0;

P2=0xff;

while(1)//無限循環等待查詢

{

while(TF0==0)

;

TF0=0;

P2=~P2;

TH0=(65536-46083)/256;   //定時器T0的高8位賦初值

TL0=(65536-46083)%256;   //定時器T0的高8位賦初值

}

}


 

//實例43:用定時器T1查詢方式控制單片機發出1KHz音頻

#include<reg51.h>          //   包含51單片機寄存器定義的頭文件

sbitsound=P3^7;    //sound位定義爲P3.7引腳

331/192


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

函數功能:主函數

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

voidmain(void)

{

//EA=1;                      //開總中斷

//   ET0=1;                     //定時器T0中斷容許

TMOD=0x10;               //使用定時器T1的模式1

TH1=(65536-921)/256;   //定時器T1的高8位賦初值

TL1=(65536-921)%256;   //定時器T1的高8位賦初值

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

TF1=0;

while(1)//無限循環等待查詢

{

while(TF1==0)

;

TF1=0;

sound=~sound;   //P3.7引腳輸出電平取反

TH1=(65536-921)/256;   //定時器T0的高8位賦初值

TL1=(65536-921)%256;   //定時器T0的高8位賦初值

}

}


 


//


44


T0


P1


8


LED


//實例44:將計數器T0計數的結果送P18LED顯示

#include<reg51.h>          //   包含51單片機寄存器定義的頭文件

sbitS=P3^4;    //S位定義爲P3.4引腳

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

函數功能:主函數

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

voidmain(void)

{

//EA=1;                      //開總中斷

//   ET0=1;                     //定時器T0中斷容許

TMOD=0x02;               //使用定時器T0的模式2

TH0=256-156;   //定時器T0的高8位賦初值

TL0=256-156;   //定時器T0的高8位賦初值

TR0=1;                   //啓動定時器T0

while(1)//無限循環等待查詢

{

while(TF0==0)   //若是未計滿就等待

332/192


{


if(S==0)


//按鍵S按下接地,電平爲0


}


}


}

TF0=0;


P1=TL0;//計數器TL01後送P1口顯示

//計數器溢出後,將TF00


 

//實例45:用定時器T0的中斷控制1LED閃爍

#include<reg51.h>   //   包含51單片機寄存器定義的頭文件

sbitD1=P2^0;   //D1位定義爲P2.0引腳

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

函數功能:主函數

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

voidmain(void)

{

EA=1;                      //開總中斷

ET0=1;                     //定時器T0中斷容許

TMOD=0x01;                //使用定時器T0的模式2

TH0=(65536-46083)/256;//定時器T0的高8位賦初值

TL0=(65536-46083)%256;//定時器T0的高8位賦初值

TR0=1;                     //啓動定時器T0

while(1)//無限循環等待中斷

;

}

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

函數功能:定時器T0的中斷服務程序

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

voidTime0(void)interrupt1using0//interrupt」聲明函數爲中斷服務函數

//其後的1爲定時器T0的中斷編號;0表示使用第0組工做

寄存器

{

D1=~D1;  //按位取反操做,將P2.0引腳輸出電平取反

TH0=(65536-46083)/256;//定時器T0的高8位從新賦初值

TL0=(65536-46083)%256;//定時器T0的高8位從新賦初值

}


 


333


/


192


//


46


T0


//實例46:用定時器T0的中斷實現長時間定時

#include<reg51.h>   //   包含51單片機寄存器定義的頭文件

sbitD1=P2^0;   //D1位定義爲P2.0引腳

unsignedcharCountor;//設置全局變量,儲存定時器T0中斷次數

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

函數功能:主函數

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

voidmain(void)

{

EA=1;                      //開總中斷

ET0=1;                     //定時器T0中斷容許

TMOD=0x01;                //使用定時器T0的模式2

TH0=(65536-46083)/256;//定時器T0的高8位賦初值

TL0=(65536-46083)%256;//定時器T0的高8位賦初值

TR0=1;                     //啓動定時器T0

Countor=0;               //0開始累計中斷次數

while(1)//無限循環等待中斷

;

}

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

函數功能:定時器T0的中斷服務程序

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

voidTime0(void)interrupt1using0//interrupt」聲明函數爲中斷服務函數

//其後的1爲定時器T0的中斷編號;0表示使用第0組工做

寄存器

{

Countor++;    //中斷次數自加1

if(Countor==20)   //若累計滿20次,即計時滿1s

{

D1=~D1;      //按位取反操做,將P2.0引腳輸出電平取反

Countor=0;  //Countor0,從新從0開始計數

}

TH0=(65536-46083)/256;//定時器T0的高8位從新賦初值

TL0=(65536-46083)%256;//定時器T0的高8位從新賦初值

}


 

//實例47:用定時器T1中斷控制兩個LED以不一樣週期閃爍

#include<reg51.h>   //   包含51單片機寄存器定義的頭文件

sbitD1=P2^0;   //D1位定義爲P2.0引腳

334/192


sbitD2=P2^1;


//D2位定義爲P2.1引腳


 

unsignedcharCountor1;//設置全局變量,儲存定時器T1中斷次數

unsignedcharCountor2;//設置全局變量,儲存定時器T1中斷次數

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

函數功能:主函數

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

voidmain(void)

{

EA=1;                      //開總中斷

ET1=1;                     //定時器T1中斷容許

TMOD=0x10;                //使用定時器T1的模式1

TH1=(65536-46083)/256;//定時器T1的高8位賦初值

TL1=(65536-46083)%256;//定時器T1的高8位賦初值

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

Countor1=0;               //0開始累計中斷次數

Countor2=0;               //0開始累計中斷次數

while(1)//無限循環等待中斷

;

}

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

函數功能:定時器T1的中斷服務程序

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

voidTime1(void)interrupt3using0//interrupt」聲明函數爲中斷服務函數

//其後的3爲定時器T1的中斷編號;0表示使用第0組工做

寄存器

{

Countor1++;    //Countor1自加1

Countor2++;    //Countor2自加1

if(Countor1==2)   //若累計滿2次,即計時滿100ms

{

D1=~D1;      //按位取反操做,將P2.0引腳輸出電平取反

Countor1=0;   //Countor10,從新從0開始計數

}

if(Countor2==8)   //若累計滿8次,即計時滿400ms

{

D2=~D2;      //按位取反操做,將P2.1引腳輸出電平取反

Countor2=0;   //Countor10,從新從0開始計數

}

TH1=(65536-46083)/256;//定時器T1的高8位從新賦初值

TL1=(65536-46083)%256;//定時器T1的高8位從新賦初值

}


 


335


/


192


//


48


T1


1KHz


//實例48:用計數器T1的中斷控制蜂鳴器發出1KHz音頻

#include<reg51.h>   //   包含51單片機寄存器定義的頭文件

sbitsound=P3^7;   //sound位定義爲P3.7引腳

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

函數功能:主函數

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

voidmain(void)

{

EA=1;                      //開總中斷

ET1=1;                     //定時器T1中斷容許

TMOD=0x10;                //TMOD=0001000B,使用定時器T1的模式1

TH1=(65536-921)/256;    //定時器T1的高8位賦初值

TL1=(65536-921)%256;   //定時器T1的高8位賦初值

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

while(1)//無限循環等待中斷

;

}

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

函數功能:定時器T1的中斷服務程序

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

voidTime1(void)interrupt3using0//interrupt」聲明函數爲中斷服務函數

{

sound=~sound;

TH1=(65536-921)/256;    //定時器T1的高8位從新賦初值

TL1=(65536-921)%256;   //定時器T1的高8位從新賦初值

}


 


//


49


T0


"


"


//實例49:用定時器T0的中斷實現"渴望"主題曲的播放

#include<reg51.h>    //包含51單片機寄存器定義的頭文件

sbitsound=P3^7;     //sound位定義爲P3.7

unsignedintC;      //儲存定時器的定時常數

//如下是C調低音的音頻宏定義

#definel_dao262    //將「l_dao」宏定義爲低音「1」的頻率262Hz

#definel_re286     //將「l_re」宏定義爲低音「2」的頻率286Hz

#definel_mi311     //將「l_mi」宏定義爲低音「3」的頻率311Hz

#definel_fa349     //將「l_fa」宏定義爲低音「4」的頻率349Hz

#definel_sao392    //將「l_sao」宏定義爲低音「5」的頻率392Hz

#definel_la440     //將「l_a」宏定義爲低音「6」的頻率440Hz

#definel_xi494     //將「l_xi」宏定義爲低音「7」的頻率494Hz

336/192


//如下是C調中音的音頻宏定義

#definedao523      //將「dao」宏定義爲中音「1」的頻率523Hz

#definere587       //將「re」宏定義爲中音「2」的頻率587Hz

#definemi659       //將「mi」宏定義爲中音「3」的頻率659Hz

#definefa698       //將「fa」宏定義爲中音「4」的頻率698Hz

#definesao784      //將「sao」宏定義爲中音「5」的頻率784Hz

#definela880       //將「la」宏定義爲中音「6」的頻率880Hz

#definexi987       //將「xi」宏定義爲中音「7」的頻率523H

//如下是C調高音的音頻宏定義

#defineh_dao1046      //將「h_dao」宏定義爲高音「1」的頻率1046Hz

#defineh_re1174       //將「h_re」宏定義爲高音「2」的頻率1174Hz

#defineh_mi1318       //將「h_mi」宏定義爲高音「3」的頻率1318Hz

#defineh_fa1396      //將「h_fa」宏定義爲高音「4」的頻率1396Hz

#defineh_sao1567     //將「h_sao」宏定義爲高音「5」的頻率1567Hz

#defineh_la1760      //將「h_la」宏定義爲高音「6」的頻率1760Hz

#defineh_xi1975      //將「h_xi」宏定義爲高音「7」的頻率1975Hz

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

函數功能:1個延時單位,延時200ms

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

voiddelay()

{

unsignedchari,j;

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

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

;

}

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

函數功能:主函數

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

voidmain(void)

{

unsignedchari,j;

//如下是《渴望》片頭曲的一段簡譜

unsigned  intcodef[]={re,mi,re,dao,l_la,dao,l_la,    //每行對應一小節音符

l_sao,l_mi,l_sao,l_la,dao,

l_la,dao,sao,la,mi,sao,

re,

mi,re,mi,sao,mi,

l_sao,l_mi,l_sao,l_la,dao,

l_la,l_la,dao,l_la,l_sao,l_re,l_mi,

l_sao,

re,re,sao,la,sao,

fa,mi,sao,mi,

la,sao,mi,re,mi,l_la,dao,

337/192


//如下是簡譜中每一個音符的節拍


re,

mi,re,mi,sao,mi,

l_sao,l_mi,l_sao,l_la,dao,

l_la,dao,re,l_la,dao,re,mi,

re,

l_la,dao,re,l_la,dao,re,mi,

re,

0xff};//0xff做爲音符的結束標誌


//"4"對應4個延時單位,"2"對應2個延時單位,"1"對應1個延時單位

unsignedcharcodeJP[]={4,1,1,4,1,1,2,

2,2,2,2,8,

4,2,3,1,2,2,

10,

4,2,2,4,4,

2,2,2,2,4,

2,2,2,2,2,2,2,

10,

4,4,4,2,2,

4,2,4,4,

4,2,2,2,2,2,2,

10,

4,2,2,4,4,

2,2,2,2,6,

4,2,2,4,1,1,4,

10,

4,2,2,4,1,1,4,

10

};

EA=1;           //開總中斷

ET0=1;          //定時器T0中斷容許

TMOD=0x00;     //  使用定時器T0的模式113位計數器)

while(1)         //無限循環

{

i=0;   //從第1個音符f[0]開始播放

while(f[i]!=0xff)               //只要沒有讀到結束標誌就繼續播放

{

C=460830/f[i];

TH0=(8192-C)/32;    //可證實這是13位計數器TH08位的賦

初值方法

TL0=(8192-C)%32;    //可證實這是13位計數器TL05位的賦初

值方法

TR0=1;                //啓動定時器T0

338/192


}


}


}


for(j=0;j<JP[i];j++)

delay();

TR0=0;

i++;


//控制節拍數

//延時1個節拍單位

//關閉定時器T0

//播放下一個音符


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

函數功能:定時器T0的中斷服務子程序,使P3.7引腳輸出音頻的方波

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

voidTime0(void)interrupt1using1

{

sound=!sound;       //P3.7引腳輸出電平取反,造成方波

TH0=(8192-C)/32;    //可證實這是13位計數器TH08位的賦初值方法

TL0=(8192-C)%32;    //可證實這是13位計數器TL05位的賦初值方法

}


 


//


50-1


50


#include<reg51.h>


//實例50-1:輸出50個矩形脈衝

//包含51單片機寄存器定義的頭文件


sbitu=P1^4;


//u位定義爲P1.4


 

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

函數功能:延時約30ms(3*100*100=30000μs=30m

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

voiddelay30ms(void)

{

unsignedcharm,n;

for(m=0;m<100;m++)

for(n=0;n<100;n++)

;

}

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

函數功能:主函數

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

voidmain(void)

{

unsignedchari;

u=1;    //初始化輸出高電平

for(i=0;i<50;i++)//輸出50個矩形脈衝

{

339/192


}


}


u=1;

delay30ms();

u=0;

delay30ms();

while(1)

;//無限循環,防止程序「跑飛」


 

//實例50-2:計數器T0統計外部脈衝數

#include<reg51.h>    //包含51單片機寄存器定義的頭文件

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

函數功能:主函數

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

voidmain(void)

{

TMOD=0x06;     //TMOD=00000110B,使用計數器T0的模式2

EA=1;           //開總中斷

ET0=0;          //不使用定時器T0的中斷

TR0=1;          //啓動T0

TH0=0;         //計數器T08位賦初值

TL0=0;         //計數器T08位賦初值

while(1)  //無限循環,不停地將TL0計數結果送P1

P1=TL0;

}


 

//實例51-2:定時器T0的模式2測量正脈衝寬度

#include<reg51.h>    //包含51單片機寄存器定義的頭文件

sbitui=P3^2;   //ui位定義爲P3.0INT0)引腳,表示輸入電壓

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

函數功能:主函數

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

voidmain(void)

{

TMOD=0x0a;    //TMOD=00001010B,使用定時器T0的模式2GATE1

EA=1;           //開總中斷

440/192


ET0=0;

TR0=1;

TH0=0;

TL0=0;

while(1)

{

while(ui==0)

;

TL0=0;


//不使用定時器T0的中斷

//啓動T0

//計數器T08位賦初值

//計數器T08位賦初值

//無限循環,不停地將TL0計數結果送P1

//INT0爲低電平,T0不能啓動

//INT0爲高電平,啓動T0計時,因此將TL00


 


}


}


while(ui==1)//INT0高電平期間,等待,計時

;

P1=TL0;    //將計時結果送P1口顯示


 


//


52


T0


//實例52:用定時器T0控制輸出高低寬度不一樣的矩形波

#include<reg51.h>    //包含51單片機寄存器定義的頭文件

sbitu=P3^0;       //u位定義爲P3.0,從該引腳輸出矩形脈衝

unsignedcharCountor;   //設置全局變量,儲存負跳變累計數

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

函數功能:延時約30ms(3*100*100=30000μs=30ms)

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

voiddelay30ms(void)

{

unsignedcharm,n;

for(m=0;m<100;m++)

for(n=0;n<100;n++)

;

}

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

函數功能:主函數

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

voidmain(void)

{

unsignedchari;

EA=1;   //開放總中斷

EX0=1;  //容許使用外中斷

IT0=1;  //選擇負跳變來觸發外中斷

Countor=0;

441/192


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

{

u=1;

delay30ms();

u=0;

delay30ms();

}

while(1)


//輸出100個負跳變


}


;//無限循環,


防止程序跑飛


 

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

函數功能:外中斷T0的中斷服務程序

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

voidint0(void)interrupt0using0//外中斷0的中斷編號爲0

{

Countor++;

P1=Countor;

}


 


//


53


0


//實例53:用外中斷0的中斷方式進行數據採集

#include<reg51.h>    //包含51單片機寄存器定義的頭文件

sbitS=P3^2;       //S位定義爲P3.2

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

函數功能:主函數

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

voidmain(void)

{

EA=1;   //開放總中斷

EX0=1;  //容許使用外中斷

IT0=1;  //選擇負跳變來觸發外中斷

P1=0xff;

while(1)

;//無限循環,防止程序跑飛

}

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

函數功能:外中斷T0的中斷服務程序

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

voidint0(void)interrupt0using0//外中斷0的中斷編號爲0

{

442/192


}


P1=~P1;


//每產生一次中斷請求,P1取反一次。


 

//實例54-1:輸出負脈寬爲200微秒的方波

#include<reg51.h>    //包含51單片機寄存器定義的頭文件

sbitu=P1^4;     //u位定義爲P1.4

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

函數功能:主函數

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

voidmain(void)

{

TMOD=0x02;               //TMOD=00000010B,使用定時器T0的模式2

EA=1;                        //開總中斷

ET0=1;                      //定時器T0中斷容許

TH0=256-200;    //定時器T0的高8位賦初值

TL0=256-200;   //定時器T0的高8位賦初值

TR0=1;                     //啓動定時器T0

while(1)                   //無限循環,等待中斷

;

}

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

函數功能:定時器T0的中斷服務程序

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

voidTime0(void)interrupt1using0//"interrupt"聲明函數爲中斷服務函數

{

u=~u;  //P1.4引腳輸出電平取反,產生方波

}


 


//


54-2


#include<reg51.h>


//實例54-2:測量負脈衝寬度

//包含51單片機寄存器定義的頭文件


sbitu=P3^2;


//u位定義爲P3.2


 

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

函數功能:主函數

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

443/192


voidmain(void)

{

TMOD=0x02;


//TMOD=00000010B,使用定時器T0的模式2


EA=1;

EX0=1;

IT0=1;

ET0=1;

TH0=0;

TL0=0;

TR0=0;


//開放總中斷

//容許使用外中斷

//選擇負跳變來觸發外中斷

//容許定時器T0中斷

//定時器T0賦初值0

//定時器T0賦初值0

//先關閉T0


 


}


while(1)

;//無限循環,


不停檢測輸入負脈衝寬度


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

函數功能:外中斷0的中斷服務程序

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

voidint0(void)interrupt0using0//外中斷0的中斷編號爲0

{

TR0=1;   //外中斷一到來,即啓動T0計時

TL0=0;  //0開始計時

while(u==0)   //低電平時,等待T0計時

;

P1=TL0;//將結果送P1口顯示

TR0=0;  //關閉T0

}


 

//實例55:方式0控制流水燈循環點亮

#include<reg51.h>    //包含51單片機寄存器定義的頭文件

#include<intrins.h>//包含函數_nop_()定義的頭文件

unsignedcharcodeTab[]={0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F};//流水燈控

制碼,該數組被定義爲全局變量

sbitP17=P1^7;

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

函數功能:延時約150ms

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

voiddelay(void)

{

unsignedcharm,n;

for(m=0;m<200;m++)

444/192


}


for(n=0;n<250;n++)

;


 

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

函數功能:發送一個字節的數據

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

voidSend(unsignedchardat)

{

P17=0;     //P1.7引腳輸出清0信號,對74LS1640

_nop_();   //延時一個機器週期

_nop_();  //延時一個機器週期,保證清0完成

P17=1;    //結束對74LS164的清0

SBUF=dat;  //將數據寫入發送緩衝器,啓動發送

while(TI==0)   //若沒有發送完畢,等待

;

TI=0;   //發送完畢,TI被置「1」,需將其清0

}

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

函數功能:主函數

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

voidmain(void)

{

unsignedchari;

SCON=0x00;  //SCON=00000000B,使串行口工做於方式0

while(1)

{

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

{

Send(Tab[i]);   //發送數據

delay();         //延時

}

}

}


 


#include<reg51.h>


//實例56-1:數據發送程序

//包含單片機寄存器的頭文件


 

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

//流水燈控制碼,該數組被定義爲全局變量

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

445/192


函數功能:向PC發送一個字節數據

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

voidSend(unsignedchardat)

{

SBUF=dat;

while(TI==0)

;

TI=0;

}

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

函數功能:延時約150ms

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

voiddelay(void)

{

unsignedcharm,n;

for(m=0;m<200;m++)

for(n=0;n<250;n++)

;

}

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

函數功能:主函數

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

voidmain(void)

{

unsignedchari;

TMOD=0x20;  //TMOD=00100000B,定時器T1工做於方式2

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

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

TH1=0xfd;   //根據規定給定時器T1賦初值

TL1=0xfd;   //根據規定給定時器T1賦初值

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

while(1)

{

for(i=0;i<8;i++)    //模擬檢測數據

{

Send(Tab[i]);          //發送數據i

delay();   //50ms發送一次檢測數據

}

}

}


 


446


/


192


//


56-2


#include<reg51.h>


//實例56-2:數據接收程序

//包含單片機寄存器的頭文件


 

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

函數功能:接收一個字節數據

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

unsignedcharReceive(void)

{

unsignedchardat;

while(RI==0)   //只要接收中斷標誌位RI沒有被置「1

;      //等待,直至接收完畢(RI=1

RI=0;      //爲了接收下一幀數據,需將RI0

dat=SBUF;  //將接收緩衝器中的數據存於dat

returndat;

}

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

函數功能:主函數

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

voidmain(void)

{

TMOD=0x20;  //定時器T1工做於方式2

SCON=0x50;  //SCON=01010000B,串口工做方式1,容許接收(REN=1

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

TH1=0xfd;  //根據規定給定時器T1賦初值

TL1=0xfd;  //根據規定給定時器T1賦初值

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

REN=1;    //容許接收

while(1)

{

P1=Receive();//將接收到的數據送P1口顯示

}

}


 


//


57-1


#include<reg51.h>

sbitp=PSW^0;


//實例57-1:數據發送程序

//包含單片機寄存器的頭文件


 

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

//流水燈控制碼,該數組被定義爲全局變量

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

447/192


函數功能:向PC發送一個字節數據

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

voidSend(unsignedchardat)

{

ACC=dat;

TB8=p;

SBUF=dat;

while(TI==0)

;

TI=0;

}

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

函數功能:延時約150ms

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

voiddelay(void)

{

unsignedcharm,n;

for(m=0;m<200;m++)

for(n=0;n<250;n++)

;

}

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

函數功能:主函數

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

voidmain(void)

{

unsignedchari;

TMOD=0x20;  //TMOD=00100000B,定時器T1工做於方式2

SCON=0xc0;  //SCON=11000000B,串口工做方式3,

//SM20,不使用多機通訊,TB80

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

TH1=0xfd;     //根據規定給定時器T1賦初值

TL1=0xfd;     //根據規定給定時器T1賦初值

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

while(1)

{

for(i=0;i<8;i++)    //模擬檢測數據

{

Send(Tab[i]);          //發送數據i

delay();   //50ms發送一次檢測數據

}

}

}


 


448


/


192


 


//


57-2


#include<reg51.h>

sbitp=PSW^0;


//實例57-2:數據接收程序

//包含單片機寄存器的頭文件


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

函數功能:接收一個字節數據

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

unsignedcharReceive(void)

{

unsignedchardat;

while(RI==0)     //只要接收中斷標誌位RI沒有被置"1"

;        //等待,直至接收完畢(RI=1

RI=0;      //爲了接收下一幀數據,需將RI0

ACC=SBUF;  //將接收緩衝器中的數據存於dat

if(RB8==p)

{

dat=ACC;

returndat;

}

}

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

函數功能:主函數

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

voidmain(void)

{

TMOD=0x20;  //定時器T1工做於方式2

SCON=0xd0;  //SCON=11010000B,串口工做方式1,容許接收(REN=1

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

TH1=0xfd;     //根據規定給定時器T1賦初值

TL1=0xfd;     //根據規定給定時器T1賦初值

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

REN=1;       //容許接收

while(1)

{

P1=Receive();//將接收到的數據送P1口顯示

}

}


 


449


/


192


//


58


PC


#include<reg51.h>


//實例58:單片機向PC發送數據

//包含單片機寄存器的頭文件


 

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

//流水燈控制碼,該數組被定義爲全局變量

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

函數功能:向PC發送一個字節數據

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

voidSend(unsignedchardat)

{

SBUF=dat;

while(TI==0)

;

TI=0;

}

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

函數功能:延時約150ms

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

voiddelay(void)

{

unsignedcharm,n;

for(m=0;m<200;m++)

for(n=0;n<250;n++)

;

}

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

函數功能:主函數

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

voidmain(void)

{

unsignedchari;

TMOD=0x20;  //TMOD=00100000B,定時器T1工做於方式2

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

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

TH1=0xfd;     //根據規定給定時器T1賦初值

TL1=0xfd;     //根據規定給定時器T1賦初值

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

while(1)

{

for(i=0;i<8;i++)    //模擬檢測數據

{

Send(Tab[i]);          //發送數據i

delay();   //150ms發送一次數據

}

550/192


}


}


 


//


59


PC


//實例59:單片機接收PC發出的數據

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

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

函數功能:接收一個字節數據

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

unsignedcharReceive(void)

{

unsignedchardat;

while(RI==0)   //只要接收中斷標誌位RI沒有被置「1

;      //等待,直至接收完畢(RI=1

RI=0;      //爲了接收下一幀數據,需將RI0

dat=SBUF;  //將接收緩衝器中的數據存於dat

returndat;

}

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

函數功能:主函數

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

voidmain(void)

{

TMOD=0x20;  //定時器T1工做於方式2

SCON=0x50;  //SCON=01010000B,串口工做方式1,容許接收(REN=1

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

TH1=0xfd;  //根據規定給定時器T1賦初值

TL1=0xfd;  //根據規定給定時器T1賦初值

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

REN=1;    //容許接收

while(1)

{

P1=Receive();//將接收到的數據送P1口顯示

}

}


 


551


/


192


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

*********數碼管顯示*****數碼管顯示********************

數碼管顯示****************數碼管顯示

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


 


#include<reg51.h>

voidmain(void)

{


//實例60:用LED數碼顯示數字5

//   包含51單片機寄存器定義的頭文件


}


P2=0xfe;

P0=0x92;


//P2.0引腳輸出低電平,數碼顯示器接通電源準備點亮

//P0口輸出數字"5"的段碼92H


 


//


61


LED


0~9


//實例61:用LED數碼顯示器循環顯示數字0~9

#include<reg51.h>     //  包含51單片機寄存器定義的頭文件

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

函數功能:延時函數,延時一段時間

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

voiddelay(void)

{

unsignedchari,j;

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

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

;

}

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

函數功能:主函數

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

voidmain(void)

{

unsignedchari;


 


552


/


192


unsignedcharcode

Tab[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};

//數碼管顯示09的段碼錶,程序運行中當數組值不發生變化

時,

//前面加關鍵字code,能夠大大節約單片機的存儲空間

P2=0xfe;   //P2.0引腳輸出低電平,數碼顯示器DS0接通電源工做

while(1)   //無限循環

{

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

{

P0=Tab[i];  //P0口輸出數字的段碼92H

delay();   //調用延時函數

}

}

}


 

//實例62:用數碼管慢速動態掃描顯示數字"1234"

#include<reg51.h>          //   包含51單片機寄存器定義的頭文件

voiddelay(void)          //延時函數,延時一段時間

{

unsignedchari,j;

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

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

;

}

voidmain(void)

{

while(1)    //無限循環

{

P2=0xfe;   //P2.0引腳輸出低電平,DS0點亮

P0=0xf9;  //數字1的段碼

delay();

P2=0xfd;   //P2.1引腳輸出低電平,DS1點亮

P0=0xa4;  //數字2的段碼

delay();

P2=0xfb;   //P2.2引腳輸出低電平,DS2點亮

P0=0xb0;  //數字3的段碼

delay();

P2=0xf7;   //P2.3引腳輸出低電平,DS3點亮

P0=0x99;  //數字4的段碼

553/192


}


}


delay();

P2=0xff;


 


//


63


LED


1234


//實例63:用LED數碼顯示器僞靜態顯示數字1234

#include<reg51.h>              //   包含51單片機寄存器定義的頭文件

voiddelay(void)          //延時函數,延時約0.6毫秒

{

unsignedchari;

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

;

}

voidmain(void)

{

while(1)    //無限循環

{

P2=0xfe;   //P2.0引腳輸出低電平,DS0點亮

P0=0xf9;  //數字1的段碼

delay();

P2=0xfd;   //P2.1引腳輸出低電平,DS1點亮

P0=0xa4;  //數字2的段碼

delay();

P2=0xfb;   //P2.2引腳輸出低電平,DS2點亮

P0=0xb0;  //數字3的段碼

delay();

P2=0xf7;   //P2.3引腳輸出低電平,DS3點亮

P0=0x99;  //數字4的段碼

delay();

P2=0xff;

}

}


 

//實例64:用數碼管顯示動態檢測結果

#include<reg51.h>     //  包含51單片機寄存器定義的頭文件

554/192


#include<stdlib.h>

unsignedchari;

unsignedintx;


//包含隨機函數rand()的定義文件

//記錄中斷次數

//隨機檢測的數據


 

unsignedcharcodeTab[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};

//數碼管顯示09的段碼錶

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

***

函數功能:快速動態掃描延時,延時約0.9毫秒

*********************************************************************

***/

voiddelay(void)

{

unsignedinti;

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

;

}

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

***

函數功能:4位數的數碼顯示器顯示

入口參數:k

出口參數:無

*********************************************************************

***/

voiddisplay(unsignedintk)

{

P2=0xfe;   //P2=11111110BP2.0引腳輸出低電平,數碼顯示器DS0

通電源

P0=Tab[k/1000];          //顯示千位

delay();

P2=0xfd;   //P2=11111101BP2.1引腳輸出低電平,數碼顯示器DS1接通

電源

P0=Tab[(k%1000)/100];            //顯示百位

delay();

P2=0xfb;   //P2=11111011BP2.2引腳輸出低電平,數碼顯示器DS2接通

電源

P0=Tab[(k%100)/10];   //顯示十位

delay();

P2=0xf7;   //P2=11110111BP2.3引腳輸出低電平,數碼顯示器DS3

通電源

P0=Tab[k%10];//顯示個位

delay();

P2=0xff;  //關閉全部顯示器

555/192


}

voidmain(void)

{


//主函數


TMOD=0x01;

TH0=(65536-46083)/256;

1.085微秒=50000微秒=50毫秒

TL0=(65536-46083)%256;

EA=1;

ET0=1;

TR0=1;

while(1)

{


//使用定時器T0

//將定時器計時時間設定爲46083×

//開啓總中斷

//定時器T0中斷容許

//啓動定時器T0開始運行


}


}


display(x);


//調用檢測結果的顯示程序


 

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

函數功能:定時器T0的中斷服務程序

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

voidTime0(void)interrupt1using1

{

TR0=0;    //關閉定時器T0

i++;          //每來一次中斷,i自加1

if(i==20)   //20次中斷,即1秒鐘進行一次檢測結果採樣

{

x=rand()/10;      //隨機產生一個從032767的整數,再將其除以10

得到一個隨機4位數,模擬檢測結果

i=0;                //i0,從新統計中斷次數

}

TH0=(65536-46083)/256;    //從新給計數器T0賦初值

TL0=(65536-46083)%256;

TR0=1;     //啓動定時器T0

}


 


//


65


#include<reg51.h>


//


//實例65:數碼秒錶設計

包含51單片機寄存器定義的頭文件

556/192


unsignedcharcodeTab[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};

//數碼管顯示09的段碼錶

unsignedcharint_time;          //記錄中斷次數

unsignedcharsecond;          //儲存秒

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

***

函數功能:快速動態掃描延時,延時約0.6毫秒

*********************************************************************

***/

voiddelay(void)

{

unsignedchari;

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

;

}

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

***

函數功能:顯示秒

入口參數:k

出口參數:無

*********************************************************************

***/

voidDisplaySecond(unsignedchark)

{

P2=0xfb;          //P2.6引腳輸出低電平,DS6點亮

P0=Tab[k/10];            //顯示十位

delay();

P2=0xf7;         //P2.7引腳輸出低電平,DS7點亮

P0=Tab[k%10];           //顯示個位

delay();

P2=0xff;      //關閉全部數碼管


 


}


voidmain(void)

{

TMOD=0x01;


//主函數


//使用定時器T0



TH0=(65536-46083)/256;


//將定時器計時時間設定爲46083×1.085


//=50000微秒=50毫秒

TL0=(65536-46083)%256;


557


/


192


EA=1;

ET0=1;

TR0=1;

int_time=0;

second=0;

while(1)

{


//開啓總中斷

//定時器T0中斷容許

//啓動定時器T0開始運行

//中斷次數初始化

//秒初始化


}


}


DisplaySecond(second);


//調用秒的顯示子程序


 

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

//函數功能:定時器T0的中斷服務程序

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

voidinterserve(void)interrupt1using1

{

TR0=0;    //關閉定時器T0

int_time++;          //每來一次中斷,中斷次數int_time自加1

if(int_time==20)    //20次中斷,1秒鐘進行一次檢測結果採樣

{

int_time=0;     //中斷次數清0

second++;     //秒加1

if(second==60)

second=0;//秒等於60就返回0

}

TH0=(65536-46083)/256;    //從新給計數器T0賦初值

TL0=(65536-46083)%256;

TR0=1;     //啓動定時器T0

}


 


#include<reg51.h>


//實例66:數碼時鐘設計

//   包含51單片機寄存器定義的頭文件


 

unsignedcharTab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};

//control  shape

unsignedcharport[8]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};

unsignedcharint_time;//中斷次數計數變量

unsignedcharsecond;     //秒計數變量

unsignedcharminute;     //分鐘計數變量

unsignedcharhour;      //小時計數變量

/////////////////////////////////////////////////////

558/192


 


voiddelay(void)

{

unsignedcharj;

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

;

}


//延時函數,延時約0.6ms


 

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

函數功能:顯示秒的子程序

入口參數:s

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

voidDisplaySecond(unsignedchars)

{

P2=0xbf;          //P2.6引腳輸出低電平,DS6點亮

P0=Tab[s/10];            //顯示十位

delay();

P2=0x7f;         //P2.7引腳輸出低電平,DS7點亮

P0=Tab[s%10];           //顯示個位

delay();

P2=0xff;      //關閉全部數碼管

}

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

函數功能:顯示分鐘的子程序

入口參數:m

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

voidDisplayMinute(unsignedcharm)

{

P2=0xf7;   //P2.3引腳輸出低電平,DS3點亮

P0=Tab[m/10];//顯示個位

delay();

P2=0xef;   //P2.4引腳輸出低電平,DS4點亮

P0=Tab[m%10];

delay();

P2=0xdf;   //P2.5引腳輸出低電平,DS5點亮

P0=0xbf;   //分隔符「-」的段碼

delay();

P2=0xff;   //關閉全部數碼管


 


559


/


192


}

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

函數功能:顯示小時的子程序

入口參數:h

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

voidDisplayHour(unsignedcharh)

{

P2=0xfe;          //P2.0引腳輸出低電平,DS0點亮

P0=Tab[h/10];            //顯示十位

delay();

P2=0xfd;         //P2.1引腳輸出低電平,DS1點亮

P0=Tab[h%10];     //顯示個位

delay();

P2=0xfb;      //P2.2引腳輸出低電平,DS2點亮

P0=0xbf;      //分隔符「-」的段碼

delay();

P2=0xff;      //關閉全部數碼管

}

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

函數功能:主函數

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

voidmain(void)

{

TMOD=0x01;                //使用定時器T0

EA=1;                      //開中斷總容許

ET0=1;                     //容許T0中斷

TH0=(65536-46083)/256;   //定時器高八位賦初值

TL0=(65536-46083)%256;   //定時器低八位賦初值

TR0=1;

int_time=0;     //中斷計數變量初始化

second=0;       //秒計數變量初始化

minute=0;      //分鐘計數變量初始化

hour=0;         //小時計數變量初始化

while(1)

{

DisplaySecond(second);     //調用秒顯示子程序

delay();

DisplayMinute(minute);    //調用分鐘顯示子程序

660/192


}


}


delay();

DisplayHour(hour);

delay();


 

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

函數功能:定時器T0的中斷服務子程序

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

voidinterserve(void)interrupt1using1   //usingTime0

{

int_time++;

if(int_time==20)

{

int_time=0;     //中斷計數變量清0

second++;       //秒計數變量加1

}

if(second==60)

{

second=0;     //若是秒計滿60,將秒計數變量清0

minute++;     //分鐘計數變量加1

}

if(minute==60)

{

minute=0;     //若是分鐘計滿60,將分鐘計數變量

0

hour++;       //小時計數變量加1

}

if(hour==24)

{

hour=0;    //若是小時計滿24,將小時計數變量

0

}

TH0=(65536-46083)/256;    //定時器從新賦初值

TL0=(65536-46083)%256;


 

}


 


661


/


192


//


67


LED


T0


//實例67:用LED數碼管顯示計數器T0的計數值

#include<reg51.h>    //包含51單片機寄存器定義的頭文件

sbitS=P3^2;  //S位定義爲P3.2引腳

unsignedcharTab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};

碼錶

unsignedcharx;


//


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

函數功能:延時約0.6ms

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

voiddelay(void)

{

unsignedcharj;

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

;

}

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

函數功能:顯示計數次數的子程序

入口參數:x

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

voidDisplay(unsignedcharx)

{

P2=0xf7;          //P2.6引腳輸出低電平,DS6點亮

P0=Tab[x/10];    //顯示十位

delay();

P2=0xfb;       //P2.7引腳輸出低電平,DS7點亮

P0=Tab[x%10];   //顯示個位

delay();

}

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

函數功能:主函數

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

voidmain(void)

{

EA=1;   //開放總中斷

EX0=1;  //容許使用外中斷

IT0=1;  //選擇負跳變來觸發外中斷

x=0;

while(1)

Display(x);

662/192


 

}

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

函數功能:外中斷T0的中斷服務程序

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

voidint0(void)interrupt0using0//外中斷0的中斷編號爲0

{

x++;

if(x==100)

x=0;

}


 


//


68


59


#include<reg51.h>


//實例68:靜態顯示數字「59

//包含51單片機寄存器定義的頭文件


 

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

函數功能:主函數

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

voidmain(void)

{

P0=0x92;   //將數字5的段碼送P0

P1=0x90;      //將數字9的段碼送P1

while(1)   //無限循環,防止程序跑飛

;

}


 

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

**************鍵盤控制*********鍵盤控制***************

***************鍵盤控制*********鍵盤控制*******************             **********

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


 


663


/


192


//


69


//實例69:無軟件消抖的獨立式鍵盤輸入實驗

#include<reg51.h>     //  包含51單片機寄存器定義的頭文件

sbitS1=P1^4;          //S1位定義爲P1.4引腳

sbitLED0=P3^0;         //LED0位定義爲P3.0引腳

voidmain(void)   //主函數

{

LED0=0;         //P3.0引腳輸出低電平

while(1)

{

if(S1==0)   //P1.4引腳輸出低電平,按鍵S1被按下

LED0=!LED0;   //P3.0引腳取反

}

}


 

//實例70:軟件消抖的獨立式鍵盤輸入實驗

#include<reg51.h>     //  包含51單片機寄存器定義的頭文件

sbitS1=P1^4;          //S1位定義爲P1.4引腳

sbitLED0=P3^0;         //LED0位定義爲P3.0引腳

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

函數功能:延時約30ms

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

voiddelay(void)

{

unsignedchari,j;

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

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

;

}

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

函數功能:主函數

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

voidmain(void)   //主函數

{

LED0=0;         //P3.0引腳輸出低電平

while(1)

{

if(S1==0)   //P1.4引腳輸出低電平,按鍵S1被按下

{

664/192


}


}


}


delay();//延時一段時間再次檢測

if(S1==0)   //按鍵S1的確被按下

LED0=!LED0;   //P3.0引腳取反


 

//實例71CPU控制的獨立式鍵盤掃描實驗

#include<reg51.h>     //包含51單片機寄存器定義的頭文件

sbitS1=P1^4;          //S1位定義爲P1.4引腳

sbitS2=P1^5;          //S2位定義爲P1.5引腳

sbitS3=P1^6;          //S3位定義爲P1.6引腳

sbitS4=P1^7;          //S4位定義爲P1.7引腳

unsignedcharkeyval;   //儲存按鍵值

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

函數功能:流水燈延時

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

voidled_delay(void)

{

unsignedchari,j;

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

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

;

}

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

函數功能:軟件消抖延時

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

voiddelay30ms(void)

{

unsignedchari,j;

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

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

;

}

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

函數功能:正向流水點亮LED

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

voidforward(void)

{

665/192


}


P3=0xfe;

led_delay();

P3=0xfd;

led_delay();

P3=0xfb;

led_delay();

P3=0xf7;

led_delay();

P3=0xef;

led_delay();

P3=0xdf;

led_delay();

P3=0xbf;

led_delay();

P3=0x7f;

led_delay();

P3=0xff;

P3=0xfe;

led_delay();


//第一個燈亮

//第二個燈亮

//第三個燈亮

//第四個燈亮

//第五個燈亮

//第六個燈亮

//第七個燈亮

//第八個燈亮

//第一個燈亮


 

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

函數功能:反向流水點亮LED

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

voidbackward(void)

{

P3=0x7f;            //第八個燈亮

led_delay();

P3=0xbf;            //第七個燈亮

led_delay();

P3=0xdf;            //第六個燈亮

led_delay();

P3=0xef;            //第五個燈亮

led_delay();

P3=0xf7;            //第四個燈亮

led_delay();

P3=0xfb;            //第三個燈亮

led_delay();

P3=0xfd;           //第二個燈亮

led_delay();

P3=0xfe;           //第一個燈亮

led_delay();

}

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

666/192


函數功能:關閉全部LED

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

voidstop(void)

{

P3=0xff;

}

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

函數功能:閃爍點亮LED

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

voidflash(void)

{

P3=0xff;

led_delay();

P3=0x00;

led_delay();

}

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

函數功能:鍵盤掃描子程序

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

voidkey_scan(void)

{

if((P1&0xf0)!=0xf0)           //第一次檢測到有鍵按下

{

delay30ms();    //延時20ms再去檢測

if(S1==0)        //按鍵S1被按下

keyval=1;

if(S2==0)        //按鍵S2被按下

keyval=2;

if(S3==0)        //按鍵S3被按下

keyval=3;

if(S4==0)        //按鍵S4被按下

keyval=4;

}

}

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

函數功能:主函數

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

voidmain(void)   //主函數

{

keyval=0;                 //按鍵值初始化爲0,什麼也不作

while(1)

{

key_scan();

667/192


}


}


switch(keyval)

{

case1:forward();

break;

case2:backward();

break;

case3:stop();

break;

case4:flash();

break;

}


 


//


72


//實例72:定時器中斷控制的獨立式鍵盤掃描實驗

#include<reg51.h>     //包含51單片機寄存器定義的頭文件

sbitS1=P1^4;          //S1位定義爲P1.4引腳

sbitS2=P1^5;          //S2位定義爲P1.5引腳

sbitS3=P1^6;          //S3位定義爲P1.6引腳

sbitS4=P1^7;          //S4位定義爲P1.7引腳

unsignedcharkeyval;   //儲存按鍵值

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

函數功能:流水燈延時

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

voidled_delay(void)

{

unsignedchari,j;

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

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

;

}

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

函數功能:軟件消抖延時

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

voiddelay20ms(void)

{

unsignedchari,j;

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

668/192


}


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

;


 

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

函數功能:正向流水點亮LED

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

voidforward(void)

{

P3=0xfe;           //第一個燈亮

led_delay();

P3=0xfd;           //第二個燈亮

led_delay();

P3=0xfb;            //第三個燈亮

led_delay();

P3=0xf7;            //第四個燈亮

led_delay();

P3=0xef;            //第五個燈亮

led_delay();

P3=0xdf;            //第六個燈亮

led_delay();

P3=0xbf;            //第七個燈亮

led_delay();

P3=0x7f;            //第八個燈亮

led_delay();

P3=0xff;

P3=0xfe;           //第一個燈亮

led_delay();

}

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

函數功能:反向流水點亮LED

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

voidbackward(void)

{

P3=0x7f;            //第八個燈亮

led_delay();

P3=0xbf;            //第七個燈亮

led_delay();

P3=0xdf;            //第六個燈亮

led_delay();

P3=0xef;            //第五個燈亮

led_delay();

P3=0xf7;            //第四個燈亮

led_delay();

P3=0xfb;            //第三個燈亮

669/192


}


led_delay();

P3=0xfd;

led_delay();

P3=0xfe;

led_delay();


//第二個燈亮

//第一個燈亮


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

函數功能:關閉全部LED

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

voidstop(void)

{

P3=0xff;     //關閉8LED

}

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

函數功能:閃爍點亮LED

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

voidflash(void)

{

P3=0xff;        //關閉8LED

led_delay();

P3=0x00;       //點亮8LED

led_delay();

}


 

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

函數功能:主函數

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

voidmain(void)   //主函數

{

TMOD=0x01;        //使用定時器T0的模式1

EA=1;              //開總中斷

ET0=1;            //定時器T0中斷容許

TR0=1;            //啓動定時器T0

TH0=(65536-1000)/256;     //定時器T0賦初值,每計數200次(217微秒)發

送一次中斷請求

TL0=(65536-1000)%256;     //定時器T0賦初值

keyval=0;                 //按鍵值初始化爲0,什麼也不作

while(1)

{

switch(keyval)

{

case1:forward();

770/192


}


}


}


break;

case2:backward();

break;

case3:stop();

break;

case4:flash();

break;


 

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

函數功能:定時器T0的中斷服務子程序

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

voidTime0_serve(void)interrupt1using1

{

if((P1&0xf0)!=0xf0)           //第一次檢測到有鍵按下

{

delay20ms();    //延時20ms再去檢測

if(S1==0)        //按鍵S1被按下

keyval=1;

if(S2==0)        //按鍵S2被按下

keyval=2;

if(S3==0)        //按鍵S3被按下

keyval=3;

if(S4==0)        //按鍵S4被按下

keyval=4;

}

TH0=(65536-1000)/256;

TL0=(65536-1000)%256;

}


 


//


73


4


//實例73:獨立式鍵盤控制的4級變速流水燈

#include<reg51.h>          //   包含51單片機寄存器定義的頭文件

unsignedcharspeed;     //儲存流水燈的流動速度

sbitS1=P1^4;            //位定義S1P1.4

sbitS2=P1^5;            //位定義S2P1.5

sbitS3=P1^6;            //位定義S3P1.6

sbitS4=P1^7;            //位定義S4P1.7

771/192


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

函數功能:延時20ms的子程序

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

voiddelay20ms(void)     //3*i*j+2*i=3*100*60+2*100=20000μs=20ms;

{

unsignedchari,j;

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

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

;

}

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

函數功能:延時可調子程序

入口參數:x

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

voiddelay(unsignedcharx)

{

unsignedchark;

for(k=0;k<x;k++)

delay20ms();

}

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

函數功能:主函數

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

voidmain(void)

{

TMOD=0x02;      //使用定時器T0的模式2

EA=1;            //開總中斷

ET0=1;           //定時器T0中斷容許

TR0=1;           //定時器T0開始運行

TH0=256-200;    //定時器T0賦初值,200微妙來1次中斷請求

TL0=256-200;

speed=3;          //默認流水燈流水點亮延時20ms×3=60ms

while(1)

{

P3=0xfe;           //第一個燈亮

delay(speed);     //調用延時可調子程序

P3=0xfd;           //第二個燈亮

delay(speed);

P3=0xfb;            //第三個燈亮

delay(speed);

P3=0xf7;            //第四個燈亮

delay(speed);

P3=0xef;            //第五個燈亮

delay(speed);

772/192


}


}


P3=0xdf;

delay(speed);

P3=0xbf;

delay(speed);

P3=0x7f;

delay(speed);

P3=0xff;


//第六個燈亮

//第七個燈亮

//第八個燈亮


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

函數功能:定時器T0的中斷服務子程序,進行鍵盤掃描

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

voidintersev(void)interrupt1using1

{

TR0=0;               //關閉定時器T0/

P1=0xff;              //P1口的均置高電平"1"

if((P1&0xf0)!=0xf0)     //若是有鍵按下

{

delay20ms();         //延時20ms,軟件消抖

if((P1&0xf0)!=0xf0)   //確實有鍵按下

{

if(S1==0)         //若是是按鍵S1按下

speed=5;   //流水燈流水點亮延時20ms×5=100ms

if(S2==0)        //若是是按鍵S2按下

speed=10;   //流水燈流水點亮延時20ms×10=200ms

if(S3==0)        //若是是按鍵S3按下

speed=25;  //流水燈流水點亮延時20ms×25=500ms

if(S4==0)        //若是是按鍵S4按下

speed=50;  //流水燈流水點亮延時20ms×50=1000ms

}

}

TR0=1;                  //啓動定時器T0

}


 

//實例74:獨立式鍵盤的按鍵功能擴展:"以一當四"

#include<reg51.h>          //   包含51單片機寄存器定義的頭文件

unsignedcharID;     //儲存流水燈的流動速度

sbitS1=P1^4;            //位定義S1P1.4

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

773/192


函數功能:延時子程序

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

voiddelay(void)     //由於僅對一個按鍵掃描,因此延時時間較長約200ms

{

unsignedchari,j;

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

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

;

}


 

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

函數功能:主函數

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

voidmain(void)

{

TMOD=0x02;      //使用定時器T0的模式2

EA=1;            //開總中斷

ET0=1;           //定時器T0中斷容許

TR0=1;           //定時器T0開始運行

TH0=256-200;    //定時器T0賦初值,每200微妙來1次中斷請求

TL0=256-200;

ID=0;

while(1)

{

switch(ID)

{

case0:P3=0xfe;

break;

case1:P3=0xfd;

break;

case2:P3=0xfb;

break;

case3:P3=0xf7;

break;

}

}

}

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

函數功能:定時器T0的中斷服務子程序,進行鍵盤掃描

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

voidintersev(void)interrupt1using1

{

774/192


TR0=0;

P1=0xff;

if(S1==0)

{


//關閉定時器T0

//若是是按鍵S1按下


}


delay();

if(S1==0)

ID=ID+1;


//延時20ms,軟件消抖

//若是是按鍵S1按下


 


}


if(ID==4)

ID=0;

TR0=1;


//啓動定時器T0


 


//


75


//實例75:獨立式鍵盤調時的數碼時鐘實驗

#include<reg51.h>     //  包含51單片機寄存器定義的頭文件

unsignedcharcodeTab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};

//數字0~9的段碼

unsignedcharint_time;//中斷次數計數變量

unsignedcharsecond;     //秒計數變量

unsignedcharminute;     //分鐘計數變量

unsignedcharhour;      //小時計數變量

sbitS1=P1^4;            //S1位定義爲P1.4

sbitS2=P1^5;            //S2位定義爲P1.5

sbitS3=P1^6;            //S3位定義爲P1.6

sbitS4=P1^7;            //S4位定義爲P1.7

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

函數功能:數碼管掃描延時

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

voiddelay(void)

{

unsignedcharj;

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

;

}

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

函數功能:鍵盤掃描延時

775/192


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

voiddelay60ms(void)

{

unsignedchari,j;

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

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

;

}

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

函數功能:顯示秒

入口參數:s

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

voidDisplaySecond(unsignedchars)

{

P2=0xbf;          //P2.6引腳輸出低電平,DS6點亮

P0=Tab[s/10];            //顯示十位

delay();

P2=0x7f;         //P2.7引腳輸出低電平,DS7點亮

P0=Tab[s%10];           //顯示個位

delay();

P2=0xff;      //關閉全部數碼管

}

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

函數功能:顯示分鐘

入口參數:m

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

voidDisplayMinute(unsignedcharm)

{

P2=0xf7;   //P2.3引腳輸出低電平,DS3點亮

P0=Tab[m/10];//顯示個位

delay();

P2=0xef;   //P2.4引腳輸出低電平,DS4點亮

P0=Tab[m%10];

delay();

P2=0xdf;   //P2.5引腳輸出低電平,DS5點亮

P0=0xbf;   //分隔符「-」的段碼

delay();

P2=0xff;   //關閉全部數碼管

}

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

776/192


函數功能:顯示小時的子程序

入口參數:h

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

voidDisplayHour(unsignedcharh)

{

P2=0xfe;          //P2.0引腳輸出低電平,DS0點亮

P0=Tab[h/10];            //顯示十位

delay();

P2=0xfd;         //P2.1引腳輸出低電平,DS1點亮

P0=Tab[h%10];     //顯示個位

delay();

P2=0xfb;      //P2.2引腳輸出低電平,DS2點亮

P0=0xbf;      //分隔符「-」的段碼

delay();

P2=0xff;      //關閉全部數碼管

}

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

函數功能:鍵盤掃描

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

voidkey_scan(void)

{

P1=0xf0;   //P1口高4位置高電平「1

if((P1&0xf0)!=0xf0)           //有鍵按下

{

delay60ms();           //延時60ms再檢測

if((P1&0xf0)!=0xf0)           //確實有鍵按下

{

if(S1==0)        //若是是S1鍵按下

second++;   //秒加1

if(S2==0)        //若是是S2鍵按下

minute++;     //分鐘加1

if(S3==0)      //若是是S3鍵按下

hour++;       //小時加1

if(S4==0)      //若是是S4鍵按下

{

second=0;   //秒清0

minute=0;   //分鐘清0

hour=0;      //小時清0

}

}

}

777/192


}

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

函數功能:主函數

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

voidmain(void)

{

TMOD=0x01;                //使用定時器T0

EA=1;                      //開中斷總容許

ET0=1;                     //容許T0中斷

TH0=(65536-46083)/256;   //定時器高八位賦初值

TL0=(65536-46083)%256;   //定時器低八位賦初值

TR0=1;                     //啓動定時器T0

int_time=0;     //中斷計數變量初始化

second=0;       //秒計數變量初始化

minute=0;      //分鐘計數變量初始化

hour=0;         //小時計數變量初始化

while(1)

{

DisplaySecond(second);     //調用秒顯示子程序

DisplayMinute(minute);    //調用分鐘顯示子程序

DisplayHour(hour);         //調用小時顯示子程序

}

}

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

函數功能:定時器T0的中斷服務子程序

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

voidinterserve(void)interrupt1using1   //usingTime0

{

TR0=0;                     //關閉定時器T0

int_time++;             //中斷次數加1

if(int_time==20)     //若是中斷次數滿20

{

int_time=0;     //中斷計數變量清0

second++;       //秒計數變量加1

}

if(second==60)        //若是秒計滿60

{

second=0;     //若是秒計滿60,將秒計數變量清0

778/192


}


minute++;


//分鐘計數變量加1


if(minute==60)

{

minute=0;

hour++;

}

if(hour==24)

{

hour=0;

}

key_scan();


//若是分鐘計滿60

//若是分鐘計滿60,將分鐘計數變量清0

//小時計數變量加1

//若是小時計滿24

//若是小時計滿24,將小時計數變量清0

//執行鍵盤掃描


}


TH0=(65536-46083)/256;

TL0=(65536-46083)%256;

TR0=1;


//定時器T0高四位賦值

//定時器T0低四位賦值

//啓動定時器T0


 


//


76


//實例76:獨立式鍵盤控制步進電機實驗

#include<reg51.h>         //包含51單片機寄存器定義的頭文件

sbitS1=P1^4;             //S1位定義爲P1.4引腳

sbitS2=P1^5;             //S2位定義爲P1.5引腳

sbitS3=P1^6;             //S3位定義爲P1.6引腳

unsignedcharkeyval;    //儲存按鍵值

unsignedcharID;         //儲存功能標號

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

函數功能:軟件消抖延時(約50ms

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

voiddelay(void)

{

unsignedchari,j;

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

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

;

}

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

函數功能:步進電機轉動延時,延時越長,轉速越慢

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

voidmotor_delay(void)

{

779/192


}


unsignedinti;

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

;


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

函數功能:步進電機正轉

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

voidforward()

{

P0=0xfc;             //P0口低四位脈衝1100

motor_delay();

P0=0xf6;             //P0口低四位脈衝0110

motor_delay();

P0=0xf3;             //P0口低四位脈衝0011

motor_delay();

P0=0xf9;            //P0口低四位脈衝1001

motor_delay();

}

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

函數功能:步進電機反轉

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

voidbackward()

{

P0=0xfc;               //P0口低四位脈衝1100

motor_delay();

P0=0xf9;             //P0口低四位脈衝1001

motor_delay();

P0=0xf3;             //P0口低四位脈衝0011

motor_delay();

P0=0xf6;             //P0口低四位脈衝0110

motor_delay();

}

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

函數功能:步進電機停轉

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

voidstop(void)

{

P0=0xff;            //中止輸出脈衝

}

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

函數功能:主函數

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

voidmain(void)

{

880/192


TMOD=0x01;

EA=1;

ET0=1;

TR0=1;

TH0=(65536-500)/256;

送一次中斷請求

TL0=(65536-500)%256;

keyval=0;

ID=0;

while(1)

{

switch(keyval)

{


//使用定時器T0的模式1

//開總中斷

//定時器T0中斷容許

//啓動定時器T0

//定時器T0賦初值,每計數200次(217微秒)發

//定時器T0賦初值

//按鍵值初始化爲0,什麼也不作

//根據按鍵值keyval選擇待執行的功能


}


}


}


case1:forward();

break;

case2:backward();

break;

case3:stop();

break;


//按鍵S1按下,正轉

//按鍵S2按下,反轉

//按鍵S3按下,停轉


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

函數功能:定時器T0的中斷服務子程序

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

voidTime0_serve(void)interrupt1using1

{

TR0=0;                            //關閉定時器T0

if((P1&0xf0)!=0xf0)            //第一次檢測到有鍵按下

{

delay();                 //延時一段時間再去檢測

if((P1&0xf0)!=0xf0)    //確實有鍵按下

{

if(S1==0)          //按鍵S1被按下

keyval=1;

if(S2==0)          //按鍵S2被按下

keyval=2;

if(S3==0)          //按鍵S3被按下

keyval=3;

}

}

TH0=(65536-200)/256;           //定時器T0的高8位賦初值

TL0=(65536-200)%256;           //定時器T0的低8位賦初值

TR0=1;                            //啓動定時器T0

881/192


}


 

//實例77:矩陣式鍵盤按鍵值的數碼管顯示實驗

#include<reg51.h>    //包含51單片機寄存器定義的頭文件

sbitP14=P1^4;       //P14位定義爲P1.4引腳

sbitP15=P1^5;       //P15位定義爲P1.5引腳

sbitP16=P1^6;       //P16位定義爲P1.6引腳

sbitP17=P1^7;       //P17位定義爲P1.7引腳

unsignedcharcodeTab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};

//數字0~9的段碼

unsignedcharkeyval;     //定義變量儲存按鍵值

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

函數功能:數碼管動態掃描延時

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

voidled_delay(void)

{

unsignedcharj;

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

;

}

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

函數功能:按鍵值的數碼管顯示子程序

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

voiddisplay(unsignedchark)

{

P2=0xbf;               //點亮數碼管DS6

P0=Tab[k/10];         //顯示十位

led_delay();          //動態掃描延時

P2=0x7f;               //點亮數碼管DS7

P0=Tab[k%10];         //顯示個位

led_delay();         //動態掃描延時

}

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

函數功能:軟件延時子程序

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

voiddelay20ms(void)

{

unsignedchari,j;

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

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

882/192


}


;


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

函數功能:主函數

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

voidmain(void)

{

EA=1;                      //開總中斷

ET0=1;                    //定時器T0中斷容許

TMOD=0x01;               //使用定時器T0的模式1

TH0=(65536-500)/256;   //定時器T0的高8位賦初值

TL0=(65536-500)%256;   //定時器T0的高8位賦初值

TR0=1;                   //啓動定時器T0

keyval=0x00;            //按鍵值初始化爲0

while(1)                   //無限循環

{

display(keyval);    //調用按鍵值的數碼管顯示子程序

}

}

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

函數功能:定時器0的中斷服務子程序,進行鍵盤掃描,判斷鍵位

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

voidtime0_interserve(void)interrupt1using1     //定時器T0的中斷編號爲1

使用第一組寄存器

{

TR0=0;                      //關閉定時器T0

P1=0xf0;                     //全部行線置爲低電平「0」,全部列線置爲高

電平「1

if((P1&0xf0)!=0xf0)        //列線中有一位爲低電平「0」,說明有鍵按下

delay20ms();              //延時一段時間、軟件消抖

if((P1&0xf0)!=0xf0)        //確實有鍵按下

{

P1=0xfe;                //第一行置爲低電平「0」(P1.0輸出低電平

0」)

if(P14==0)              //若是檢測到接P1.4引腳的列線爲低電平「0

keyval=1;               //可判斷是S1鍵被按下

if(P15==0)                //若是檢測到接P1.5引腳的列線爲低電平

0

keyval=2;               //可判斷是S2鍵被按下

if(P16==0)                //若是檢測到接P1.6引腳的列線爲低電平

0

keyval=3;               //可判斷是S3鍵被按下

883/192


0

0」)

0

0

0

0」)

0」)


if(P17==0)

keyval=4;

P1=0xfd;

if(P14==0)

keyval=5;

if(P15==0)

keyval=6;

if(P16==0)

keyval=7;

if(P17==0)

keyval=8;

P1=0xfb;

if(P14==0)

keyval=9;

if(P15==0)

keyval=10;

if(P16==0)

keyval=11;

if(P17==0)

keyval=12;

P1=0xf7;

if(P14==0)

keyval=13;

if(P15==0)

keyval=14;

if(P16==0)

keyval=15;

if(P17==0)

keyval=16;


//若是檢測到接P1.7引腳的列線爲低電平

//可判斷是S4鍵被按下

//第二行置爲低電平「0」(P1.1輸出低電平

//若是檢測到接P1.4引腳的列線爲低電平「0

//可判斷是S5鍵被按下

//若是檢測到接P1.5引腳的列線爲低電平

//可判斷是S6鍵被按下

//若是檢測到接P1.6引腳的列線爲低電平

//可判斷是S7鍵被按下

//若是檢測到接P1.7引腳的列線爲低電平

//可判斷是S8鍵被按下

//第三行置爲低電平「0」(P1.2輸出低電平

//若是檢測到接P1.4引腳的列線爲低電平「0

//可判斷是S9鍵被按下

//若是檢測到接P1.5引腳的列線爲低電平「0

//可判斷是S10鍵被按下

//若是檢測到接P1.6引腳的列線爲低電平「0

//可判斷是S11鍵被按下

//若是檢測到接P1.7引腳的列線爲低電平「0

//可判斷是S12鍵被按下

//第四行置爲低電平「0」(P1.3輸出低電平

//若是檢測到接P1.4引腳的列線爲低電平「0

//可判斷是S13鍵被按下

//若是檢測到接P1.5引腳的列線爲低電平「0

//可判斷是S14鍵被按下

//若是檢測到接P1.6引腳的列線爲低電平「0

//可判斷是S15鍵被按下

//若是檢測到接P1.7引腳的列線爲低電平「0

//可判斷是S16鍵被按下


 


}


}

TR0=1;

TH0=(65536-500)/256;

TL0=(65536-500)%256;


//開啓定時器T0

//定時器T0的高8位賦初值

//定時器T0的高8位賦初值

884/192


 


#include<reg51.h>

sbitsound=P3^7;


//實例78:矩陣式鍵盤按鍵音

//包含51單片機寄存器定義的頭文件

//sound位定義爲P3.7


 

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

函數功能:蜂鳴器發聲延時約120ms

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

voiddelay_sound(void)

{

unsignedchari;

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

;

}

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

函數功能:軟件延時子程序約20ms

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

voiddelay20ms(void)

{

unsignedchari,j;

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

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

;

}

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

函數功能:主函數

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

voidmain(void)

{

EA=1;                      //開總中斷

ET0=1;                     //定時器T0中斷容許

TMOD=0x01;                //使用定時器T0的模式1

TH0=(65536-500)/256;    //定時器T0的高8位賦初值

TL0=(65536-500)%256;    //定時器T0的高8位賦初值

TR0=1;                     //啓動定時器T0

while(1)                  //無限循環,等待鍵盤按下

;

}

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

885/192


函數功能:定時器0的中斷服務子程序,進行鍵盤掃描,判斷鍵位

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

voidtime0_interserve(void)interrupt1using1     //定時器T0的中斷編號爲1

使用第一組寄存器

{

unsignedchari;

TR0=0;                       //關閉定時器T0

P1=0xf0;                     //全部行線置爲低電平「0」,全部列線置爲高

電平「1

if((P1&0xf0)!=0xf0)        //列線中有一位爲低電平「0」,說明有鍵按下

delay20ms();              //延時一段時間、軟件消抖

if((P1&0xf0)!=0xf0)        //確實有鍵按下

{

for(i=0;i<200;i++)   //P3.7引腳電平不斷取反輸出音頻

{

sound=0;

delay_sound();

sound=1;

delay_sound();

}

}

TR0=1;                        //開啓定時器T0

TH0=(65536-500)/256;        //定時器T0的高8位賦初值

TL0=(65536-500)%256;       //定時器T0的高8位賦初值

}


 


//


79


#include<reg51.h>

sbitP14=P1^4;

sbitP15=P1^5;

sbitP16=P1^6;

sbitP17=P1^7;

unsignedcharkeyval;

sbitsound=P3^7;


//實例79:簡易電子琴

//包含51單片機寄存器定義的頭文件

//P14位定義爲P1.4引腳

//P15位定義爲P1.5引腳

//P16位定義爲P1.6引腳

//P17位定義爲P1.7引腳

//定義變量儲存按鍵值

//sound位定義爲P3.7


unsignedintC;

unsignedintf;


//全局變量,儲存定時器的定時常數

//全局變量,儲存音階的頻率


 

//如下是C調低音的音頻宏定義

#definel_dao262    //將「l_dao」宏定義爲低音「1」的頻率262Hz

886/192


#definel_re286

#definel_mi311

#definel_fa349

#definel_sao392

#definel_la440

#definel_xi494


//將「l_re」宏定義爲低音「2」的頻率286Hz

//將「l_mi」宏定義爲低音「3」的頻率311Hz

//將「l_fa」宏定義爲低音「4」的頻率349Hz

//將「l_sao」宏定義爲低音「5」的頻率392Hz

//將「l_a」宏定義爲低音「6」的頻率440Hz

//將「l_xi」宏定義爲低音「7」的頻率494Hz


 

//如下是C調中音的音頻宏定義

#definedao523      //將「dao」宏定義爲中音「1」的頻率523Hz

#definere587       //將「re」宏定義爲中音「2」的頻率587Hz

#definemi659       //將「mi」宏定義爲中音「3」的頻率659Hz

#definefa698       //將「fa」宏定義爲中音「4」的頻率698Hz

#definesao784      //將「sao」宏定義爲中音「5」的頻率784Hz

#definela880       //將「la」宏定義爲中音「6」的頻率880Hz

#definexi987       //將「xi」宏定義爲中音「7」的頻率53

//如下是C調高音的音頻宏定義

#defineh_dao1046      //將「h_dao」宏定義爲高音「1」的頻率1046Hz

#defineh_re1174       //將「h_re」宏定義爲高音「2」的頻率1174Hz

#defineh_mi1318       //將「h_mi」宏定義爲高音「3」的頻率1318Hz

#defineh_fa1396      //將「h_fa」宏定義爲高音「4」的頻率1396Hz

#defineh_sao1567     //將「h_sao」宏定義爲高音「5」的頻率1567Hz

#defineh_la1760      //將「h_la」宏定義爲高音「6」的頻率1760Hz

#defineh_xi1975      //將「h_xi」宏定義爲高音「7」的頻率1975Hz

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

函數功能:軟件延時子程序

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

voiddelay20ms(void)

{

unsignedchari,j;

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

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

;

}


 

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

函數功能:節拍的延時的基本單位,延時200ms

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

voiddelay()

{

unsignedchari,j;

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

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

887/192


}


;


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

函數功能:輸出音頻

入口參數:F

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

voidOutput_Sound(void)

{

C=(46083/f)*10;       //計算定時常數

TH0=(8192-C)/32;      //可證實這是13位計數器TH08位的賦初值方法

TL0=(8192-C)%32;      //可證實這是13位計數器TL05位的賦初值方法

TR0=1;                  //開定時T0

delay();                //延時200ms,播放音頻

TR0=0;                  //關閉定時器

sound=1;          //關閉蜂鳴器

keyval=0xff;        //播放按鍵音頻後,將按鍵值更改,中止播放

}

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

函數功能:主函數

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

voidmain(void)

{

EA=1;           //開總中斷

ET0=1;           //定時器T0中斷容許

ET1=1;          //定時器T1中斷容許

TR1=1;          //定時器T1啓動,開始鍵盤掃描

TMOD=0x10;     //分別使用定時器T1的模式1T0的模式0

TH1=(65536-500)/256;   //定時器T1的高8位賦初值

TL1=(65536-500)%256;   //定時器T1的高8位賦初值


 


while(1)

{

switch(keyval)

{


//無限循環


中音1的頻率賦給f

低音7的頻率賦給f


case1:f=dao;

Output_Sound();

break;

case2:f=l_xi;

Output_Sound();

break;


//若是第1個鍵按下,將

//轉去計算定時常數

//若是第2個鍵按下,將

//轉去計算定時常數


 


888


/


192


6的頻率賦給f

低音5的頻率賦給f


case3:f=l_la;

Output_Sound();

break;

case4:f=l_sao;


//若是第3個鍵按下,將低音

//轉去計算定時常數

//若是第4個鍵按下,將


 


將中音5的頻率賦給f

將中音4的頻率賦給f


Output_Sound();

break;

case5:f=sao;

Output_Sound();

break;

case6:f=fa;

Output_Sound();

break;


//轉去計算定時常數

//若是第5個鍵按下,

//轉去計算定時常數

//若是第6個鍵按下,

//轉去計算定時常數


3的頻率賦給f

中音2的頻率賦給f

高音2的頻率賦給f


case7:f=mi;

Output_Sound();

break;

case8:f=re;

Output_Sound();

break;

case9:f=h_re;

Output_Sound();

break;

case10:f=h_dao;


//若是第7個鍵按下,將中

//轉去計算定時常數

//若是第8個鍵按下,將

//轉去計算定時常數

//若是第9個鍵按下,將

//轉去計算定時常數

//若是第10個鍵按


 


下,將高音1的頻率賦給f


Output_Sound();

break;


//轉去計算定時常數


7的頻率賦給f

中音6的頻率賦給f

將高音6的頻率賦給f


case11:f=xi;

Output_Sound();

break;

case12:f=la;

Output_Sound();

break;

case13:f=h_la;

Output_Sound();

break;

889/192


//若是第11個鍵按下,將中

//轉去計算定時常數

//若是第12個鍵按下,將

//轉去計算定時常數

//若是第13個鍵按下,

//轉去計算定時常數


將高音5的頻率賦給f

4的頻率賦給f

將高音3的頻率賦給f

}

}

}


case14:f=h_sao;

Output_Sound();

break;

case15:f=h_fa;

Output_Sound();

break;

case16:f=h_mi;

Output_Sound();

break;


//若是第14個鍵按下

//轉去計算定時常數

//若是第15個鍵按下,將高

//轉去計算定時常數

//若是第16個鍵按下

//轉去計算定時常數


 

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

函數功能:定時器T0的中斷服務子程序,使P3.7引腳輸出音頻方波

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

voidTime0_serve(void)interrupt1using1

{

TH0=(8192-C)/32;      //可證實這是13位計數器TH08位的賦初值

方法

TL0=(8192-C)%32;      //可證實這是13位計數器TL05位的賦初值方

sound=!sound;          //P3.7引腳取反,輸出音頻方波

}

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

函數功能:定時器T1的中斷服務子程序,進行鍵盤掃描,判斷鍵位

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

voidtime1_serve(void)interrupt3using2     //定時器T1的中斷編號爲3,使用

2組寄存器

{

TR1=0;                      //關閉定時器T0

P1=0xf0;                     //全部行線置爲低電平「0」,全部列線置爲高

電平「1

if((P1&0xf0)!=0xf0)        //列線中有一位爲低電平「0」,說明有鍵按下

{

delay20ms();              //延時一段時間、軟件消抖

if((P1&0xf0)!=0xf0)        //確實有鍵按下

{


 


990


/


192


輸出低電平「0」)

爲低電平「0

線爲低電平「0

線爲低電平「0

線爲低電平「0

輸出低電平「0」)

低電平「0

線爲低電平「0

線爲低電平「0

線爲低電平「0

輸出低電平「0」)

電平「0

爲低電平「0

爲低電平「0

爲低電平「0


P1=0xfe;

if(P14==0)

keyval=1;

if(P15==0)

keyval=2;

if(P16==0)

keyval=3;

if(P17==0)

keyval=4;

P1=0xfd;

if(P14==0)

keyval=5;

if(P15==0)

keyval=6;

if(P16==0)

keyval=7;

if(P17==0)

keyval=8;

P1=0xfb;

if(P14==0)

keyval=9;

if(P15==0)

keyval=10;

if(P16==0)

keyval=11;

if(P17==0)

keyval=12;


991


/


//第一行置爲低電平「0」(P1.0

//若是檢測到接P1.4引腳的列線

//可判斷是S1鍵被按下

//若是檢測到接P1.5引腳的列

//可判斷是S2鍵被按下

//若是檢測到接P1.6引腳的列

//可判斷是S3鍵被按下

//若是檢測到接P1.7引腳的列

//可判斷是S4鍵被按下

//第二行置爲低電平「0」(P1.1

//若是檢測到接P1.4引腳的列線爲

//可判斷是S5鍵被按下

//若是檢測到接P1.5引腳的列

//可判斷是S6鍵被按下

//若是檢測到接P1.6引腳的列

//可判斷是S7鍵被按下

//若是檢測到接P1.7引腳的列

//可判斷是S8鍵被按下

//第三行置爲低電平「0」(P1.2

//若是檢測到接P1.4引腳的列線爲低

//可判斷是S9鍵被按下

//若是檢測到接P1.5引腳的列線

//可判斷是S10鍵被按下

//若是檢測到接P1.6引腳的列線

//可判斷是S11鍵被按下

//若是檢測到接P1.7引腳的列線

//可判斷是S12鍵被按下

192


 


輸出低電平「0」)

電平「0

爲低電平「0

爲低電平「0

爲低電平「0

}

}


P1=0xf7;

if(P14==0)

keyval=13;

if(P15==0)

keyval=14;

if(P16==0)

keyval=15;

if(P17==0)

keyval=16;


//第四行置爲低電平「0」(P1.3

//若是檢測到接P1.4引腳的列線爲低

//可判斷是S13鍵被按下

//若是檢測到接P1.5引腳的列線

//可判斷是S14鍵被按下

//若是檢測到接P1.6引腳的列線

//可判斷是S15鍵被按下

//若是檢測到接P1.7引腳的列線

//可判斷是S16鍵被按下


}


TR1=1;

TH1=(65536-500)/256;

TL1=(65536-500)%256;


//開啓定時器T1

//定時器T1的高8位賦初值

//定時器T1的高8位賦初值


 


//


80


//實例80:矩陣式鍵盤實現的電子密碼鎖

#include<reg51.h>    //包含51單片機寄存器定義的頭文件

sbitP14=P1^4;       //P14位定義爲P1.4引腳

sbitP15=P1^5;       //P15位定義爲P1.5引腳

sbitP16=P1^6;       //P16位定義爲P1.6引腳

sbitP17=P1^7;       //P17位定義爲P1.7引腳

sbitsound=P3^7;     //sound位定義爲P3.7

unsignedcharkeyval;     //儲存按鍵值

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

函數功能:延時輸出音頻

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

voiddelay(void)

{

unsignedchari;

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

;

}

992/192


 

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

函數功能:軟件延時子程序

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

voiddelay20ms(void)

{

unsignedchari,j;

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

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

;

}

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

函數功能:主函數

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

voidmain(void)

{

unsignedcharD[]={0,8,0,8,7,4,11};       //設定密碼

EA=1;                      //開總中斷

ET0=1;                     //定時器T0中斷容許

TMOD=0x01;               //使用定時器T0的模式1

TH0=(65536-500)/256;   //定時器T0的高8位賦初值

TL0=(65536-500)%256;   //定時器T0的高8位賦初值

TR0=1;                   //啓動定時器T0

keyval=0xff;            //按鍵值初始化

while(keyval!=D[0])    //第一位密碼輸入不正確,等待

;

while(keyval!=D[1])    //第二位密碼輸入不正確,等待

;

while(keyval!=D[2])    //第三位密碼輸入不正確,等待

;

while(keyval!=D[3])    //第四位密碼輸入不正確,等待

;

while(keyval!=D[4])    //第五位密碼輸入不正確,等待

;

while(keyval!=D[5])    //第六位密碼輸入不正確,等待

;

while(keyval!=D[6])   //沒有輸入「OK」,等待

;

P3=0xfe;             //P3.0引腳輸出低電平,點亮LED

}

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

函數功能:定時器0的中斷服務子程序,進行鍵盤掃描,判斷鍵位

993/192


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

voidtime0_interserve(void)interrupt1using1     //定時器T0的中斷編號爲1

使用第一組寄存器

{

unsignedchari;

TR0=0;                      //關閉定時器T0

P1=0xf0;                     //全部行線置爲低電平「0」,全部列線置爲高

電平「1

if((P1&0xf0)!=0xf0)        //列線中有一位爲低電平「0」,說明有鍵按下

delay20ms();              //延時一段時間、軟件消抖

if((P1&0xf0)!=0xf0)        //確實有鍵按下

{

P1=0xfe;                //第一行置爲低電平「0」(P1.0輸出低電平

0」)

if(P14==0)              //若是檢測到接P1.4引腳的列線爲低電平「0

keyval=1;               //可判斷是S1鍵被按下

if(P15==0)                //若是檢測到接P1.5引腳的列線爲低電平

0

keyval=2;               //可判斷是S2鍵被按下

if(P16==0)                //若是檢測到接P1.6引腳的列線爲低電平

0

keyval=3;               //可判斷是S3鍵被按下

if(P17==0)               //若是檢測到接P1.7引腳的列線爲低電平

0

keyval=4;             //可判斷是S4鍵被按下

P1=0xfd;                //第二行置爲低電平「0」(P1.1輸出低電平

0」)

if(P14==0)              //若是檢測到接P1.4引腳的列線爲低電平「0

keyval=5;               //可判斷是S5鍵被按下

if(P15==0)                //若是檢測到接P1.5引腳的列線爲低電平

0

keyval=6;               //可判斷是S6鍵被按下

if(P16==0)                //若是檢測到接P1.6引腳的列線爲低電平

0

keyval=7;               //可判斷是S7鍵被按下

if(P17==0)               //若是檢測到接P1.7引腳的列線爲低電平

0

keyval=8;             //可判斷是S8鍵被按下

P1=0xfb;                //第三行置爲低電平「0」(P1.2輸出低電平

0」)

if(P14==0)            //若是檢測到接P1.4引腳的列線爲低電平「0

keyval=9;            //可判斷是S9鍵被按下

994/192


if(P15==0)

keyval=0;

if(P16==0)

keyval=11;

if(P17==0)


//若是檢測到接P1.5引腳的列線爲低電平「0

//可判斷是S10鍵被按下

//若是檢測到接P1.6引腳的列線爲低電平「0

//可判斷是S11鍵被按下

//若是檢測到接P1.7引腳的列線爲低電平「0

keyval=12;          //可判斷是S12鍵被按下


 


輸出低電平「0」)

電平「0

爲低電平「0

爲低電平「0

爲低電平「0


P1=0xf7;

if(P14==0)

keyval=13;

if(P15==0)

keyval=14;

if(P16==0)

keyval=15;

if(P17==0)

keyval=16;


//第四行置爲低電平「0」(P1.3

//若是檢測到接P1.4引腳的列線爲低

//可判斷是S13鍵被按下

//若是檢測到接P1.5引腳的列線

//可判斷是S14鍵被按下

//若是檢測到接P1.6引腳的列線

//可判斷是S15鍵被按下

//若是檢測到接P1.7引腳的列線

//可判斷是S16鍵被按下


 


}


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

{

sound=0;

delay();

sound=1;

delay();

}


//P3.7引腳電平不斷取反輸出音頻


}


TR0=1;

TH0=(65536-500)/256;

TL0=(65536-500)%256;


//開啓定時器T0

//定時器T0的高8位賦初值

//定時器T0的高8位賦初值


 

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

******************液晶顯LCD*********液晶顯示LCDLCD*********              LCD

*****液晶顯示LCD********************液晶顯示LCD********************

LCD*********液晶顯示LCD*****液晶顯示LCD**********

995/192


*********************************************************

**/


 


#include<reg51.h>

#include<intrins.h>


//實例81:用LCD顯示字符''A'

//包含單片機寄存器的頭文件

//包含_nop_()函數定義的頭文件


sbitRS=P2^0;

sbitRW=P2^1;

sbitE=P2^2;

sbitBF=P0^7;


//寄存器選擇位,將RS位定義爲P2.0引腳

//讀寫選擇位,將RW位定義爲P2.1引腳

//使能信號位,將E位定義爲P2.2引腳

//忙碌標誌位,,將BF位定義爲P0.7引腳


 

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

函數功能:延時1ms

(3j+2)*i=(3×33+2)×10=1010(微秒),能夠認爲是1毫秒

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

voiddelay1ms()

{

unsignedchari,j;

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

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

;

}

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

函數功能:延時若干毫秒

入口參數:n

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

voiddelay(unsignedcharn)

{

unsignedchari;

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

delay1ms();

}

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

函數功能:判斷液晶模塊的忙碌狀態

返回值:resultresult=1,忙碌;result=0,不忙

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

unsignedcharBusyTest(void)

{

bitresult;

RS=0;         //根據規定,RS爲低電平,RW爲高電平時,能夠讀狀態

996/192


RW=1;

E=1;

_nop_();

_nop_();

_nop_();

_nop_();

result=BF;

E=0;


//E=1,才容許讀寫

//空操做

//空操做四個機器週期,給硬件反應時間

//將忙碌標誌電平賦給result


 


}


returnresult;


 

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

函數功能:將模式設置指令或顯示地址寫入液晶模塊

入口參數:dictate

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

voidWriteInstruction(unsignedchardictate)

{

while(BusyTest()==1);//若是忙就等待

RS=0;                      //根據規定,RSR/W同時爲低電平時,能夠寫

入指令

RW=0;

E=0;                       //E置低電平(根據表8-6,寫指令時,E爲高脈衝,

//  就是讓E01發生正跳變,因此應先置

"0"

_nop_();

_nop_();                //空操做兩個機器週期,給硬件反應時間

P0=dictate;               //將數據送入P0口,即寫入指令或地址

_nop_();

_nop_();

_nop_();

_nop_();                  //空操做四個機器週期,給硬件反應時間

E=1;                       //E置高電平

_nop_();

_nop_();

_nop_();

_nop_();                  //空操做四個機器週期,給硬件反應時間

E=0;                      //E由高電平跳變成低電平時,液晶模塊開始

執行命令

}

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

函數功能:指定字符顯示的實際地址

入口參數:x

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

voidWriteAddress(unsignedcharx)

{

997/192


}


WriteInstruction(x|0x80);//顯示位置的肯定方法規定爲"80H+地址碼x"


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

函數功能:將數據(字符的標準ASCII)寫入液晶模塊

入口參數:y(爲字符常量)

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

voidWriteData(unsignedchary)

{

while(BusyTest()==1);

RS=1;             //RS爲高電平,RW爲低電平時,能夠寫入數據

RW=0;

E=0;               //E置低電平(根據表8-6,寫指令時,E爲高脈衝,

//  就是讓E01發生正跳變,因此應先置"0"

P0=y;             //將數據送入P0口,即將數據寫入液晶模塊

_nop_();

_nop_();

_nop_();

_nop_();         //空操做四個機器週期,給硬件反應時間

E=1;            //E置高電平

_nop_();

_nop_();

_nop_();

_nop_();          //空操做四個機器週期,給硬件反應時間

E=0;               //E由高電平跳變成低電平時,液晶模塊開始執行命令

}

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

函數功能:對LCD的顯示模式進行初始化設置

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

voidLcdInitiate(void)

{

delay(15);                //延時15ms,首次寫指令時應給LCD一段較長的反

應時間

WriteInstruction(0x38);   //顯示模式設置:16×2顯示,5×7點陣,8位數據

接口

delay(5);   //延時5ms

WriteInstruction(0x38);

delay(5);

WriteInstruction(0x38);

delay(5);

WriteInstruction(0x0f);   //顯示模式設置:顯示開,有光標,光標閃爍

delay(5);

WriteInstruction(0x06);   //顯示模式設置:光標右移,字符不移

delay(5);

WriteInstruction(0x01);   //清屏幕指令,將之前的顯示內容清除

998/192


}


delay(5);


voidmain(void)

{

LcdInitiate();

WriteAddress(0x07);

WriteData('A');

}


//主函數

//調用LCD初始化函數

//將顯示地址指定爲第1行第8

//將字符常量'A'寫入液晶模塊

//字符的字形點陣讀出和顯示由液晶模塊自動完成


 

//實例82:用LCD循環右移顯示"WelcometoChiina"

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

#include<intrins.h>   //包含_nop_()函數定義的頭文件

sbitRS=P2^0;     //寄存器選擇位,將RS位定義爲P2.0引腳

sbitRW=P2^1;     //讀寫選擇位,將RW位定義爲P2.1引腳

sbitE=P2^2;      //使能信號位,將E位定義爲P2.2引腳

sbitBF=P0^7;     //忙碌標誌位,,將BF位定義爲P0.7引腳

unsignedcharcodestring[]={"WelcometoChina"};

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

函數功能:延時1ms

(3j+2)*i=(3×33+2)×10=1010(微秒),能夠認爲是1毫秒

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

voiddelay1ms()

{

unsignedchari,j;

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

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

;

}

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

函數功能:延時若干毫秒

入口參數:n

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

voiddelay(unsignedcharn)

{

unsignedchari;

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

delay1ms();

}

999/192


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

函數功能:判斷液晶模塊的忙碌狀態

返回值:resultresult=1,忙碌;result=0,不忙

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

unsignedcharBusyTest(void)

{

bitresult;

RS=0;         //根據規定,RS爲低電平,RW爲高電平時,能夠讀狀態

RW=1;

E=1;          //E=1,才容許讀寫

_nop_();   //空操做

_nop_();

_nop_();

_nop_();   //空操做四個機器週期,給硬件反應時間

result=BF;  //將忙碌標誌電平賦給result

E=0;

returnresult;

}

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

函數功能:將模式設置指令或顯示地址寫入液晶模塊

入口參數:dictate

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

voidWriteInstruction(unsignedchardictate)

{

while(BusyTest()==1);//若是忙就等待

RS=0;                      //根據規定,RSR/W同時爲低電平時,能夠寫

入指令

RW=0;

E=0;                       //E置低電平(根據表8-6,寫指令時,E爲高脈衝,

//  就是讓E01發生正跳變,因此應先置

"0"

_nop_();

_nop_();                //空操做兩個機器週期,給硬件反應時間

P0=dictate;               //將數據送入P0口,即寫入指令或地址

_nop_();

_nop_();

_nop_();

_nop_();                  //空操做四個機器週期,給硬件反應時間

E=1;                       //E置高電平

_nop_();

_nop_();

_nop_();

_nop_();                  //空操做四個機器週期,給硬件反應時間


 


100


/


192


E=0;

執行命令

}


//E由高電平跳變成低電平時,液晶模塊開始


 

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

函數功能:指定字符顯示的實際地址

入口參數:x

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

voidWriteAddress(unsignedcharx)

{

WriteInstruction(x|0x80);//顯示位置的肯定方法規定爲"80H+地址碼x"

}

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

函數功能:將數據(字符的標準ASCII)寫入液晶模塊

入口參數:y(爲字符常量)

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

voidWriteData(unsignedchary)

{

while(BusyTest()==1);

RS=1;             //RS爲高電平,RW爲低電平時,能夠寫入數據

RW=0;

E=0;               //E置低電平(根據表8-6,寫指令時,E爲高脈衝,

//  就是讓E01發生正跳變,因此應先置"0"

P0=y;             //將數據送入P0口,即將數據寫入液晶模塊

_nop_();

_nop_();

_nop_();

_nop_();         //空操做四個機器週期,給硬件反應時間

E=1;            //E置高電平

_nop_();

_nop_();

_nop_();

_nop_();          //空操做四個機器週期,給硬件反應時間

E=0;               //E由高電平跳變成低電平時,液晶模塊開始執行命令

}

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

函數功能:對LCD的顯示模式進行初始化設置

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

voidLcdInitiate(void)

{

delay(15);                //延時15ms,首次寫指令時應給LCD一段較長的反

應時間

WriteInstruction(0x38);   //顯示模式設置:16×2顯示,5×7點陣,8位數據

接口

delay(5);   //延時5ms

101/192


}


WriteInstruction(0x38);

delay(5);

WriteInstruction(0x38);

delay(5);

WriteInstruction(0x0f);

delay(5);

WriteInstruction(0x06);

delay(5);

WriteInstruction(0x01);

delay(5);


//顯示模式設置:顯示開,有光標,光標閃爍

//顯示模式設置:光標右移,字符不移

//清屏幕指令,將之前的顯示內容清除


voidmain(void)

{

unsignedchari;

LcdInitiate();

delay(10);

while(1)

{


//主函數

//調用LCD初始化函數


WriteInstruction(0x01);//清顯示:清屏幕指令

WriteAddress(0x00);   //設置顯示位置爲第一行的第5個字

i=0;

while(string[i]!='\0')

{                         //  顯示字符

WriteData(string[i]);

i++;

delay(150);

}

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

delay(250);

}


 

}


 


//


83


LCD


//實例83:用LCD顯示適時檢測結果

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

#include<stdlib.h>    //包含隨機函數rand()的定義文件

#include<intrins.h>   //包含_nop_()函數定義的頭文件

sbitRS=P2^0;     //寄存器選擇位,將RS位定義爲P2.0引腳

102/192


sbitRW=P2^1;

sbitE=P2^2;

sbitBF=P0^7;


//讀寫選擇位,將RW位定義爲P2.1引腳

//使能信號位,將E位定義爲P2.2引腳

//忙碌標誌位,,將BF位定義爲P0.7引腳


unsignedcharcodedigit[]={"0123456789"};//定義字符數組顯示數字

unsignedcharcodestring[]={"TestResult"};//定義字符數組顯示提示信息

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

函數功能:延時1ms

(3j+2)*i=(3×33+2)×10=1010(微秒),能夠認爲是1毫秒

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

voiddelay1ms()

{

unsignedchari,j;

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

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

;

}

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

函數功能:延時若干毫秒

入口參數:n

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

voiddelay(unsignedcharn)

{

unsignedchari;

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

delay1ms();

}

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

函數功能:判斷液晶模塊的忙碌狀態

返回值:resultresult=1,忙碌;result=0,不忙

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

unsignedcharBusyTest(void)

{

bitresult;

RS=0;         //根據規定,RS爲低電平,RW爲高電平時,能夠讀狀態

RW=1;

E=1;          //E=1,才容許讀寫

_nop_();   //空操做

_nop_();

_nop_();

_nop_();   //空操做四個機器週期,給硬件反應時間

result=BF;  //將忙碌標誌電平賦給result

E=0;           //E恢復低電平

returnresult;

}

103/192


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

函數功能:將模式設置指令或顯示地址寫入液晶模塊

入口參數:dictate

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

voidWriteInstruction(unsignedchardictate)

{

while(BusyTest()==1);//若是忙就等待

RS=0;                      //根據規定,RSR/W同時爲低電平時,能夠寫

入指令

RW=0;

E=0;                       //E置低電平(根據表8-6,寫指令時,E爲高脈衝,

//  就是讓E01發生正跳變,因此應先置

"0"

_nop_();

_nop_();                //空操做兩個機器週期,給硬件反應時間

P0=dictate;               //將數據送入P0口,即寫入指令或地址

_nop_();

_nop_();

_nop_();

_nop_();                  //空操做四個機器週期,給硬件反應時間

E=1;                       //E置高電平

_nop_();

_nop_();

_nop_();

_nop_();                  //空操做四個機器週期,給硬件反應時間

E=0;                      //E由高電平跳變成低電平時,液晶模塊開始

執行命令

}

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

函數功能:指定字符顯示的實際地址

入口參數:x

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

voidWriteAddress(unsignedcharx)

{

WriteInstruction(x|0x80);//顯示位置的肯定方法規定爲"80H+地址碼x"

}

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

函數功能:將數據(字符的標準ASCII)寫入液晶模塊

入口參數:y(爲字符常量)

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

voidWriteData(unsignedchary)

{

while(BusyTest()==1);

RS=1;             //RS爲高電平,RW爲低電平時,能夠寫入數據

104/192


}


RW=0;

E=0;

P0=y;

_nop_();

_nop_();

_nop_();

_nop_();

E=1;

_nop_();

_nop_();

_nop_();

_nop_();

E=0;


//E置低電平(根據表8-6,寫指令時,E爲高脈衝,

//  就是讓E01發生正跳變,因此應先置"0"

//將數據送入P0口,即將數據寫入液晶模塊

//空操做四個機器週期,給硬件反應時間

//E置高電平

//空操做四個機器週期,給硬件反應時間

//E由高電平跳變成低電平時,液晶模塊開始執行命令


 

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

函數功能:對LCD的顯示模式進行初始化設置

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

voidLcdInitiate(void)

{

delay(15);                //延時15ms,首次寫指令時應給LCD一段較長的反

應時間

WriteInstruction(0x38);   //顯示模式設置:16×2顯示,5×7點陣,8位數據

接口

delay(5);                  //延時5ms   ,給硬件一點反應時間

WriteInstruction(0x38);

delay(5);

WriteInstruction(0x38);//連續三次,確保初始化成功

delay(5);

WriteInstruction(0x0c);   //顯示模式設置:顯示開,無光標,光標不閃爍

delay(5);

WriteInstruction(0x06);   //顯示模式設置:光標右移,字符不移

delay(5);

WriteInstruction(0x01);   //清屏幕指令,將之前的顯示內容清除

delay(5);

}

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

函數功能:主函數

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

voidmain(void)

{

unsignedchari;    //定義變量i指向字符串數組元素

unsignedintx;     //定義變量,儲存檢測結果


 


105


/


192


unsignedcharD1,D2,D3,D4,D5;

萬位數字


//分別儲存採集的個位、十位、百位、千位和


LcdInitiate();

delay(10);

WriteAddress(0x02);

i=0;

while(string[i]!='\0')

{


//調用LCD初始化函數

//延時10ms,給硬件一點反應時間

//從第1行第3列開始顯示

//指向字符數組的第1個元素


 


}

while(1)

{


WriteData(string[i]);

i++;                //指向下字符數組一個元素

//無限循環


}


}


x=rand();

D1=x%10;

D2=(x%100)/10;

D3=(x%1000)/100;

D4=(x%10000)/1000;

D5=x/10000;

WriteAddress(0x45);

WriteData(digit[D5]);

WriteData(digit[D4]);

WriteData(digit[D3]);

WriteData(digit[D2]);

WriteData('.');

WriteData(digit[D1]);

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

delay(250);


//模擬數據採集

//計算個位數字

//計算十位數字

//計算百位數字

//計算千位數字

//計算萬位數字

//從第2行第6列開始顯示

//將萬位數字的字符常量寫入LCD

//將千位數字的字符常量寫入LCD

//將百位數字的字符常量寫入LCD

//將十位數字的字符常量寫入LCD

//將小數點的字符常量寫入LCD

//將個位數字的字符常量寫入LCD

//延時1s(每1s採集一次數據)

//延時250ms


 


#include<reg51.h>

#include<stdlib.h>

#include<intrins.h>


//實例84:液晶時鐘設計

//包含單片機寄存器的頭文件

//包含隨機函數rand()的定義文件

//包含_nop_()函數定義的頭文件


sbitRS=P2^0;

sbitRW=P2^1;

sbitE=P2^2;

sbitBF=P0^7;


//寄存器選擇位,將RS位定義爲P2.0引腳

//讀寫選擇位,將RW位定義爲P2.1引腳

//使能信號位,將E位定義爲P2.2引腳

//忙碌標誌位,,將BF位定義爲P0.7引腳


unsignedcharcodedigit[]={"0123456789"};//定義字符數組顯示數字

106/192


unsignedcharcodestring[]={"BeiJingTime"};//定義字符數組顯示提示信息

unsignedcharcount;    //定義變量統計中斷累計次數

unsignedchars,m,h;    //定義變量儲存秒、分鐘和小時

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

函數功能:延時1ms

(3j+2)*i=(3×33+2)×10=1010(微秒),能夠認爲是1毫秒

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

voiddelay1ms()

{

unsignedchari,j;

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

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

;

}

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

函數功能:延時若干毫秒

入口參數:n

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

voiddelay(unsignedcharn)

{

unsignedchari;

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

delay1ms();

}

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

函數功能:判斷液晶模塊的忙碌狀態

返回值:resultresult=1,忙碌;result=0,不忙

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

unsignedcharBusyTest(void)

{

bitresult;

RS=0;         //根據規定,RS爲低電平,RW爲高電平時,能夠讀狀態

RW=1;

E=1;          //E=1,才容許讀寫

_nop_();   //空操做

_nop_();

_nop_();

_nop_();   //空操做四個機器週期,給硬件反應時間

result=BF;  //將忙碌標誌電平賦給result

E=0;           //E恢復低電平

returnresult;

}

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

函數功能:將模式設置指令或顯示地址寫入液晶模塊

107/192


入口參數:dictate

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

voidWriteInstruction(unsignedchardictate)

{

while(BusyTest()==1);//若是忙就等待

RS=0;                      //根據規定,RSR/W同時爲低電平時,能夠寫

入指令

RW=0;

E=0;                       //E置低電平(根據表8-6,寫指令時,E爲高脈衝,

//  就是讓E01發生正跳變,因此應先置"0"

_nop_();

_nop_();                //空操做兩個機器週期,給硬件反應時間

P0=dictate;               //將數據送入P0口,即寫入指令或地址

_nop_();

_nop_();

_nop_();

_nop_();                  //空操做四個機器週期,給硬件反應時間

E=1;                       //E置高電平

_nop_();

_nop_();

_nop_();

_nop_();                  //空操做四個機器週期,給硬件反應時間

E=0;                      //E由高電平跳變成低電平時,液晶模塊開始

執行命令

}

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

函數功能:指定字符顯示的實際地址

入口參數:x

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

voidWriteAddress(unsignedcharx)

{

WriteInstruction(x|0x80);//顯示位置的肯定方法規定爲"80H+地址碼x"

}

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

函數功能:將數據(字符的標準ASCII)寫入液晶模塊

入口參數:y(爲字符常量)

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

voidWriteData(unsignedchary)

{

while(BusyTest()==1);

RS=1;             //RS爲高電平,RW爲低電平時,能夠寫入數據

RW=0;

E=0;               //E置低電平(根據表8-6,寫指令時,E爲高脈衝,

//  就是讓E01發生正跳變,因此應先置"0"

108/192


}


P0=y;

_nop_();

_nop_();

_nop_();

_nop_();

E=1;

_nop_();

_nop_();

_nop_();

_nop_();

E=0;


//將數據送入P0口,即將數據寫入液晶模塊

//空操做四個機器週期,給硬件反應時間

//E置高電平

//空操做四個機器週期,給硬件反應時間

//E由高電平跳變成低電平時,液晶模塊開始執行命令


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

函數功能:對LCD的顯示模式進行初始化設置

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

voidLcdInitiate(void)

{

delay(15);                //延時15ms,首次寫指令時應給LCD一段較長的反

應時間

WriteInstruction(0x38);   //顯示模式設置:16×2顯示,5×7點陣,8位數據

接口

delay(5);                  //延時5ms   ,給硬件一點反應時間

WriteInstruction(0x38);

delay(5);

WriteInstruction(0x38);//連續三次,確保初始化成功

delay(5);

WriteInstruction(0x0c);   //顯示模式設置:顯示開,無光標,光標不閃爍

delay(5);

WriteInstruction(0x06);   //顯示模式設置:光標右移,字符不移

delay(5);

WriteInstruction(0x01);   //清屏幕指令,將之前的顯示內容清除

delay(5);

}

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

**********

函數功能:顯示小時

*********************************************************************

*********/

voidDisplayHour()

{

unsignedchari,j;

i=h/10;                    //取整運算,求得十位數字

109/192


}


j=h%10;

WriteAddress(0x44);

WriteData(digit[i]);

WriteData(digit[j]);


//取餘運算,求得各位數字

//寫顯示地址,將十位數字顯示在第2行第5

//將十位數字的字符常量寫入LCD

//將個位數字的字符常量寫入LCD


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

**********

函數功能:顯示分鐘

*********************************************************************

*********/

voidDisplayMinute()

{

unsignedchari,j;

i=m/10;                   //取整運算,求得十位數字

j=m%10;                   //取餘運算,求得各位數字

WriteAddress(0x47);    //寫顯示地址,將十位數字顯示在第2行第8

WriteData(digit[i]);   //將十位數字的字符常量寫入LCD

WriteData(digit[j]);   //將個位數字的字符常量寫入LCD

}

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

**********

函數功能:顯示秒

*********************************************************************

*********/

voidDisplaySecond()

{

unsignedchari,j;

i=s/10;                   //取整運算,求得十位數字

j=s%10;                   //取餘運算,求得各位數字

WriteAddress(0x4a);    //寫顯示地址,將十位數字顯示在第2行第11

WriteData(digit[i]);   //將十位數字的字符常量寫入LCD

WriteData(digit[j]);   //將個位數字的字符常量寫入LCD

}

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

*

mainfunction

*********************************************************************

**/

110/192


voidmain(void)

{

unsignedchari;

LcdInitiate();

TMOD=0x01;


//調用LCD初始化函數

//使用定時器T0的模式1


 


TH0=(65536-46083)/256;

TL0=(65536-46083)%256;

EA=1;

ET0=1;

TR0=1;

count=0;

s=0;

m=0;

h=0;


//定時器T0的高8位設置初值

//定時器T0的低8位設置初值

//開總中斷

//定時器T0中斷容許

//啓動定時器T0

//中斷次數初始化爲0

//秒初始化爲0

//分鐘初始化爲0

//小時初始化爲0


 


WriteAddress(0x03);

i=0;

while(string[i]!='\0')

{


//寫地址,從第1行第4列開始顯示

//從字符數組的第1個元素開始顯示

//只要沒有顯示到字符串的結束標誌'\0',就繼續


}


WriteData(string[i]);//將第i個字符數組元素寫入LCD

i++;                     //指向下一個數組元素


WriteAddress(0x46);

WriteData(':');

WriteAddress(0x49);

WriteData(':');

while(1)

{

DisplayHour();

delay(5);


//寫地址,將第二個分號顯示在第2行第7

//將分號的字符常量寫入LCD

//寫地址,將第二個分號顯示在第2行第10

//將分號的字符常量寫入LCD

//無限循環

//顯示小時

//給硬件一點反應時間


}


}


DisplayMinute();

delay(5);

DisplaySecond();

delay(5);


//顯示分鐘

//給硬件一點反應時間

//顯示秒

//給硬件一點反應時間


 

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

函數功能:定時器T0的中斷服務函數

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

voidTime0(void)interrupt1using1//定時器T0的中斷編號爲1,使用第1組工

做寄存器

{

111/192


count++;


//每產生1次中斷,中斷累計次數加1


 


if(count==20)

{


//若是中斷次數計滿20


}


count=0;

s++;


//中斷累計次數清0

//秒加1


if(s==60)

{

s=0;

m++;

}

if(m==60)

{

m=0;

h++;

}

if(h==24)

{

h=0;

}


//若是計滿60

//秒清0

//分鐘加1

//若是計滿60

//分鐘清0

//小時加1

//若是計滿24小時

//小時清0


}


TH0=(65536-46083)/256;

TL0=(65536-46083)%256;


//定時器T08位從新賦初值

//定時器T08位從新賦初值


 

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

***********一些芯片的使用*****24c02    DS18B20

X5045  ADC0832   DAC0832   DS1302   紅外遙控

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


 


//


85


"0x0ff"


AT24C02


P1


//實例85:將數據"0x0ff"寫入AT24C02再讀出送P1口顯示

#include<reg51.h>          //   包含51單片機寄存器定義的頭文件

#include<intrins.h>        //包含_nop_()函數定義的頭文件

#defineOP_READ    0xa1        //  器件地址以及讀取操做,0xa1即爲10100001B

#defineOP_WRITE0xa0      //  器件地址以及寫入操做,0xa1即爲10100000B

sbitSDA=P3^4;            //將串行數據總線SDA位定義在爲P3.4引腳

sbitSCL=P3^3;           //將串行時鐘總線SDA位定義在爲P3.3引腳

112/192


 

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

函數功能:延時1ms

(3j+2)*i=(3×33+2)×10=1010(微秒),能夠認爲是1毫秒

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

voiddelay1ms()

{

unsignedchari,j;

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

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

;

}

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

函數功能:延時若干毫秒

入口參數:n

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

voiddelaynms(unsignedcharn)

{

unsignedchari;

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

delay1ms();

}

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

函數功能:開始數據傳送

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

voidstart()

//  開始位

{

SDA=1;     //SDA初始化爲高電平「1

SCL=1;     //開始數據傳送時,要求SCL爲高電平「1

_nop_();    //等待一個機器週期

_nop_();    //等待一個機器週期

_nop_();    //等待一個機器週期

_nop_();    //等待一個機器週期

SDA=0;     //SDA的降低沿被認爲是開始信號

_nop_();    //等待一個機器週期

_nop_();    //等待一個機器週期

_nop_();    //等待一個機器週期

_nop_();    //等待一個機器週期

SCL=0;     //SCL爲低電平時,SDA上數據才容許變化(即容許之後的數據傳

遞)

}

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

113/192


函數功能:結束數據傳送

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

voidstop()

//  中止位

{

SDA=0;      //SDA初始化爲低電平「0  _n

SCL=1;      //結束數據傳送時,要求SCL爲高電平「1

_nop_();      //等待一個機器週期

_nop_();      //等待一個機器週期

_nop_();      //等待一個機器週期

_nop_();      //等待一個機器週期

SDA=1;     //SDA的上升沿被認爲是結束信號

_nop_();      //等待一個機器週期

_nop_();      //等待一個機器週期

_nop_();      //等待一個機器週期

_nop_();      //等待一個機器週期

SDA=0;

SCL=0;

}

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

函數功能:從AT24Cxx讀取數據

出口參數:x

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

unsignedcharReadData()

//  AT24Cxx移入數據到MCU

{

unsignedchari;

unsignedcharx;    //儲存從AT24Cxx中讀出的數據

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

{

SCL=1;                   //SCL置爲高電平

x<<=1;                      //x中的各二進位向左移一位

x|=(unsignedchar)SDA;   //SDA上的數據經過按位「或「運算存入x

SCL=0;                             //SCL的降低沿讀出數據

}

return(x);                   //將讀取的數據返回

}

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

函數功能:向AT24Cxx的當前地址寫入數據

入口參數:y(儲存待寫入的數據)

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

//在調用此數據寫入函數前需首先調用開始函數start(),因此SCL=0

bitWriteCurrent(unsignedchary)

114/192


{


unsignedchari;

bitack_bit;

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

{

SDA=(bit)(y&0x80);


//


//儲存應答位

循環移入8個位

//經過按位「與」運算將最高位數據送到S

//由於傳送時高位在前,低位在


_nop_();

SCL=1;

_nop_();

_nop_();

SCL=0;

據所需的8個脈衝

y<<=1;

}

SDA=1;

釋放SDA線,


//


//等待一個機器週期

//SCL的上升沿將數據寫入AT24Cxx

//等待一個機器週期

//等待一個機器週期

//SCL從新置爲低電平,以在SCL線造成傳送數

//y中的各二進位向左移一位

發送設備(主機)應在時鐘脈衝的高電平期間(SCL=1)


 


_nop_();

_nop_();

SCL=1;

_nop_();

_nop_();

_nop_();

_nop_();


//以讓SDA線轉由接收設備(AT24Cxx)控制

//等待一個機器週期

//等待一個機器週期

//根據上述規定,SCL應爲高電平

//等待一個機器週期

//等待一個機器週期

//等待一個機器週期

//等待一個機器週期


ack_bit=SDA;//接受設備(AT24Cxx)SDA送低電平,表示已經接收到一個

字節

//若送高電平,表示沒有接收到,傳送異常

SCL=0;         //SCL爲低電平時,SDA上數據才容許變化(即容許之後的數據

傳遞)

return  ack_bit;         //  返回AT24Cxx應答位

}

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

函數功能:向AT24Cxx中的指定地址寫入數據

入口參數:add(儲存指定的地址);dat(儲存待寫入的數據)

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

voidWriteSet(unsignedcharadd,unsignedchardat)

//  在指定地址addr處寫入數據WriteCurrent

{

start();                  //開始數據傳遞

WriteCurrent(OP_WRITE);   //選擇要操做的AT24Cxx芯片,並告知要對其寫

入數據

115/192


}


WriteCurrent(add);

WriteCurrent(dat);

stop();

delaynms(4);


//寫入指定地址

//向當前地址(上面指定的地址)寫入數據

//中止數據傳遞

//1個字節的寫入週期爲1ms,最好延時1ms以上


 

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

函數功能:從AT24Cxx中的當前地址讀取數據

出口參數:x(儲存讀出的數據)

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

unsignedcharReadCurrent()

{

unsignedcharx;

start();                  //開始數據傳遞

WriteCurrent(OP_READ);    //選擇要操做的AT24Cxx芯片,並告知要讀其數

x=ReadData();           //將讀取的數據存入x

stop();                   //中止數據傳遞

returnx;                 //返回讀取的數據

}

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

函數功能:從AT24Cxx中的指定地址讀取數據

入口參數:set_addr

出口參數:x

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

unsignedcharReadSet(unsignedcharset_addr)

//  在指定地址讀取

{

start();                           //開始數據傳遞

WriteCurrent(OP_WRITE);         //選擇要操做的AT24Cxx芯片,並告知要對

其寫入數據

WriteCurrent(set_addr);         //寫入指定地址

return(ReadCurrent());          //從指定地址讀出數據並返回

}

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

函數功能:主函數

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

main(void)

{

SDA=1;             //SDA=1,SCL=1,使主從設備處於空閒狀態

SCL=1;

WriteSet(0x36,0x0f);    //在指定地址「0x36」中寫入數據「0x0f

P1=ReadSet(0x36);       //從指定地址「0x36中讀取數據並送P1口顯示

}


 


116


/


192


 

//實例86:將按鍵次數寫入AT24C02,再讀出並用1602LCD

顯示

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

#include<intrins.h>      //包含_nop_()函數定義的頭文件

sbitRS=P2^0;              //寄存器選擇位,將RS位定義爲P2.0引腳

sbitRW=P2^1;              //讀寫選擇位,將RW位定義爲P2.1引腳

sbitE=P2^2;               //使能信號位,將E位定義爲P2.2引腳

sbitBF=P0^7;              //忙碌標誌位,,將BF位定義爲P0.7引腳

sbitS=P1^4;               //S位定義爲P1.4引腳

#defineOP_READ    0xa1    //  器件地址以及讀取操做,0xa1即爲10100001B

#defineOP_WRITE0xa0  //  器件地址以及寫入操做,0xa1即爲10100000B

sbitSDA=P3^4;            //將串行數據總線SDA位定義在爲P3.4引腳

sbitSCL=P3^3;            //將串行時鐘總線SDA位定義在爲P3.3引腳

unsignedcharcodedigit[]={"0123456789"};//定義字符數組顯示數字

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

函數功能:延時1ms

(3j+2)*i=(3×33+2)×10=1010(微秒),能夠認爲是1毫秒

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

voiddelay1ms()

{

unsignedchari,j;

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

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

;

}

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

函數功能:延時若干毫秒

入口參數:n

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

voiddelaynms(unsignedcharn)

{

unsignedchari;

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

delay1ms();

}

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

***********

如下是對液晶模塊的操做程序

117/192


*********************************************************************

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

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

函數功能:判斷液晶模塊的忙碌狀態

返回值:resultresult=1,忙碌;result=0,不忙

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

unsignedcharBusyTest(void)

{

bitresult;

RS=0;         //根據規定,RS爲低電平,RW爲高電平時,能夠讀狀態

RW=1;

E=1;          //E=1,才容許讀寫

_nop_();   //空操做

_nop_();

_nop_();

_nop_();   //空操做四個機器週期,給硬件反應時間

result=BF;  //將忙碌標誌電平賦給result

E=0;           //E恢復低電平

returnresult;

}

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

函數功能:將模式設置指令或顯示地址寫入液晶模塊

入口參數:dictate

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

voidWriteInstruction(unsignedchardictate)

{

while(BusyTest()==1);    //若是忙就等待

RS=0;                      //根據規定,RSR/W同時爲低電平時,能夠寫

入指令

RW=0;

E=0;                       //E置低電平(根據表8-6,寫指令時,E爲高脈衝,

//  就是讓E01發生正跳變,因此應先置

"0"

_nop_();

_nop_();                  //空操做兩個機器週期,給硬件反應時間

P0=dictate;               //將數據送入P0口,即寫入指令或地址

_nop_();

_nop_();

_nop_();

_nop_();                  //空操做四個機器週期,給硬件反應時間

E=1;                       //E置高電平

_nop_();

_nop_();

_nop_();

118/192


_nop_();

E=0;

執行命令

}


//空操做四個機器週期,給硬件反應時間

//E由高電平跳變成低電平時,液晶模塊開始


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

函數功能:指定字符顯示的實際地址

入口參數:x

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

voidWriteAddress(unsignedcharx)

{

WriteInstruction(x|0x80);//顯示位置的肯定方法規定爲"80H+地址碼x"

}

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

函數功能:將數據(字符的標準ASCII)寫入液晶模塊

入口參數:y(爲字符常量)

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

voidWriteData(unsignedchary)

{

while(BusyTest()==1);

RS=1;             //RS爲高電平,RW爲低電平時,能夠寫入數據

RW=0;

E=0;               //E置低電平(根據表8-6,寫指令時,E爲高脈衝,

//  就是讓E01發生正跳變,因此應先置"0"

P0=y;             //將數據送入P0口,即將數據寫入液晶模塊

_nop_();

_nop_();

_nop_();

_nop_();         //空操做四個機器週期,給硬件反應時間

E=1;            //E置高電平

_nop_();

_nop_();

_nop_();

_nop_();          //空操做四個機器週期,給硬件反應時間

E=0;               //E由高電平跳變成低電平時,液晶模塊開始執行命令

}

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

函數功能:對LCD的顯示模式進行初始化設置

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

voidLcdInitiate(void)

{

delaynms(15);                  //延時15ms,首次寫指令時應給LCD一段較

長的反應時間

WriteInstruction(0x38);      //顯示模式設置:16×2顯示,5×7點陣,8

數據接口

119/192


delaynms(5);

WriteInstruction(0x38);

delaynms(5);


//延時5ms


,給硬件一點反應時間


}


WriteInstruction(0x38);

delaynms(5);

WriteInstruction(0x0c);

delaynms(5);

WriteInstruction(0x06);

delaynms(5);

WriteInstruction(0x01);

delaynms(5);


//連續三次,確保初始化成功

//顯示模式設置:顯示開,無光標,光標不閃爍

//顯示模式設置:光標右移,字符不移

//清屏幕指令,將之前的顯示內容清除


 

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

函數功能:顯示小時

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

voidDisplay(unsignedcharx)

{

unsignedchari,j;

i=x/10;                      //取整運算,求得十位數字

j=x%10;                      //取餘運算,求得各位數字

WriteAddress(0x44);       //寫顯示地址,將十位數字顯示在第2行第5

WriteData(digit[i]);      //將十位數字的字符常量寫入LCD

WriteData(digit[j]);      //將個位數字的字符常量寫入LCD

}

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

***********

如下是對AT24C02的讀寫操做程序

*********************************************************************

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

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

函數功能:開始數據傳送

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

voidstart()

//  開始位

{

SDA=1;     //SDA初始化爲高電平「1

SCL=1;     //開始數據傳送時,要求SCL爲高電平「1

_nop_();    //等待一個機器週期

_nop_();    //等待一個機器週期

SDA=0;     //SDA的降低沿被認爲是開始信號

_nop_();    //等待一個機器週期

_nop_();    //等待一個機器週期

120/192


_nop_();

_nop_();

SCL=0;

遞)

}


//等待一個機器週期

//等待一個機器週期

//SCL爲低電平時,SDA上數據才容許變化(即容許之後的數據傳


 

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

函數功能:結束數據傳送

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

voidstop()

//  中止位

{

SDA=0;      //SDA初始化爲低電平「0

_nop_();      //等待一個機器週期

_nop_();      //等待一個機器週期

SCL=1;      //結束數據傳送時,要求SCL爲高電平「1

_nop_();      //等待一個機器週期

_nop_();      //等待一個機器週期

_nop_();      //等待一個機器週期

_nop_();      //等待一個機器週期

SDA=1;     //SDA的上升沿被認爲是結束信號

}

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

函數功能:從AT24Cxx讀取數據

出口參數:x

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

unsignedcharReadData()

//  AT24Cxx移入數據到MCU

{

unsignedchari;

unsignedcharx;    //儲存從AT24Cxx中讀出的數據

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

{

SCL=1;                   //SCL置爲高電平

x<<=1;                      //x中的各二進位向左移一位

x|=(unsignedchar)SDA;   //SDA上的數據經過按位「或「運算存入x

SCL=0;                             //SCL的降低沿讀出數據

}

return(x);                   //將讀取的數據返回

}

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

函數功能:向AT24Cxx的當前地址寫入數據

入口參數:y(儲存待寫入的數據)

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

121/192


//在調用此數據寫入函數前需首先調用開始函數start(),因此SCL=0

bitWriteCurrent(unsignedchary)

{

unsignedchari;

bitack_bit;                  //儲存應答位

for(i=0;i<8;i++)        //  循環移入8個位

{

SDA=(bit)(y&0x80);    //經過按位「與」運算將最高位數據送到S

//由於傳送時高位在前,低位在

_nop_();               //等待一個機器週期

SCL=1;               //SCL的上升沿將數據寫入AT24Cxx

_nop_();               //等待一個機器週期

_nop_();                //等待一個機器週期

SCL=0;               //SCL從新置爲低電平,以在SCL線造成傳送數

據所需的8個脈衝

y<<=1;              //y中的各二進位向左移一位

}

SDA=1;           //  發送設備(主機)應在時鐘脈衝的高電平期間(SCL=1)

釋放SDA線,

//以讓SDA線轉由接收設備(AT24Cxx)控制

_nop_();          //等待一個機器週期

_nop_();          //等待一個機器週期

SCL=1;         //根據上述規定,SCL應爲高電平

_nop_();         //等待一個機器週期

_nop_();         //等待一個機器週期

_nop_();         //等待一個機器週期

_nop_();         //等待一個機器週期

ack_bit=SDA;//接受設備(AT24Cxx)SDA送低電平,表示已經接收到一個

字節

//若送高電平,表示沒有接收到,傳送異常

SCL=0;         //SCL爲低電平時,SDA上數據才容許變化(即容許之後的數據

傳遞)

return  ack_bit;         //  返回AT24Cxx應答位

}

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

函數功能:向AT24Cxx中的指定地址寫入數據

入口參數:add(儲存指定的地址);dat(儲存待寫入的數據)

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

voidWriteSet(unsignedcharadd,unsignedchardat)

//  在指定地址addr處寫入數據WriteCurrent

{

start();                  //開始數據傳遞

122/192


WriteCurrent(OP_WRITE);

入數據

WriteCurrent(add);

WriteCurrent(dat);


//選擇要操做的AT24Cxx芯片,並告知要對其寫

//寫入指定地址

//向當前地址(上面指定的地址)寫入數據


 


}


stop();

delaynms(4);


//中止數據傳遞

//1個字節的寫入週期爲1ms,


最好延時1ms以上


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

函數功能:從AT24Cxx中的當前地址讀取數據

出口參數:x(儲存讀出的數據)

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

unsignedcharReadCurrent()

{

unsignedcharx;

start();                  //開始數據傳遞

WriteCurrent(OP_READ);    //選擇要操做的AT24Cxx芯片,並告知要讀其數

x=ReadData();           //將讀取的數據存入x

stop();                   //中止數據傳遞

returnx;                 //返回讀取的數據

}

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

函數功能:從AT24Cxx中的指定地址讀取數據

入口參數:set_add

出口參數:x

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

unsignedcharReadSet(unsignedcharset_add)

//  在指定地址讀取

{

start();                           //開始數據傳遞

WriteCurrent(OP_WRITE);         //選擇要操做的AT24Cxx芯片,並告知要對

其寫入數據

WriteCurrent(set_add);         //寫入指定地址

return(ReadCurrent());          //從指定地址讀出數據並返回

}

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

*

函數功能:主函數

*********************************************************************

**/

voidmain(void)

{

unsignedcharsum;     //儲存計數值

unsignedcharx;       //儲存從AT24C02讀出的值

123/192


LcdInitiate();

sum=0;

while(1)

{

if(S==0)

{


//調用LCD初始化函數

//將計數值初始化爲0

//無限循環

//若是該鍵被按下


delaynms(80);

if(S==0)

sum++;

if(sum==99)

sum=0;

}


//軟件消抖,延時80ms

//確實該鍵被按下

//計件值加1

//若是計滿99

//0,從新開始計數


}


}


WriteSet(0x01,sum);//將計件值寫入AT24C02中的指定地址"0x01"

x=ReadSet(0x01);     //AT24C02中讀出計件值

Display(x);         //將計件值用1602LCD顯示


 


//


87


I2C


AT24C02


//實例87:對I2C總線上掛接多個AT24C02的讀寫操做

#include<reg51.h>           //   包含51單片機寄存器定義的頭文件

#include<intrins.h>         //包含_nop_()函數定義的頭文件

#defineOP_READ1  0xa1        //  器件1地址以及讀取操做,0xa1即爲1010

0001B

#defineOP_WRITE10xa0     //  器件1地址以及寫入操做,0xa1即爲10100000B

#defineOP_READ2  0xaf     //  器件2地址以及讀取操做,0xa1即爲10101111B

#defineOP_WRITE20xae     //  器件2地址以及寫入操做,0xa1即爲10101110B

sbitSDA=P3^4;                //將串行數據總線SDA位定義在爲P3.4引腳

sbitSCL=P3^3;                //將串行時鐘總線SDA位定義在爲P3.3引腳

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

函數功能:延時1ms

(3j+2)*i=(3×33+2)×10=1010(微秒),能夠認爲是1毫秒

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

voiddelay1ms()

{

unsignedchari,j;

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

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

;

}

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

124/192


函數功能:延時若干毫秒

入口參數:n

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

voiddelaynms(unsignedcharn)

{

unsignedchari;

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

delay1ms();

}

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

函數功能:開始數據傳送

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

voidstart()

//  開始位

{

SDA=1;     //SDA初始化爲高電平「1

SCL=1;     //開始數據傳送時,要求SCL爲高電平「1

_nop_();    //等待一個機器週期

_nop_();    //等待一個機器週期

SDA=0;     //SDA的降低沿被認爲是開始信號

_nop_();    //等待一個機器週期

_nop_();    //等待一個機器週期

_nop_();    //等待一個機器週期

_nop_();    //等待一個機器週期

SCL=0;     //SCL爲低電平時,SDA上數據才容許變化(即容許之後的數據傳

遞)

_nop_();    //等待一個機器週期

}

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

函數功能:結束數據傳送

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

voidstop()

//  中止位

{

SDA=0;      //SDA初始化爲低電平「0

_nop_();      //等待一個機器週期

_nop_();      //等待一個機器週期

SCL=1;      //結束數據傳送時,要求SCL爲高電平「1

_nop_();      //等待一個機器週期

_nop_();      //等待一個機器週期

_nop_();      //等待一個機器週期

_nop_();      //等待一個機器週期

_nop_();      //等待一個機器週期

_nop_();      //等待一個機器週期

125/192


}


SDA=1;


//SDA的上升沿被認爲是結束信號


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

函數功能:從AT24Cxx讀取數據

出口參數:x

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

unsignedcharReadData()

//  AT24Cxx移入數據到MCU

{

unsignedchari;

unsignedcharx;             //儲存從AT24Cxx中讀出的數據

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

{

SCL=1;                   //SCL置爲高電平

x<<=1;                      //x中的各二進位向左移一位

x|=(unsignedchar)SDA;   //SDA上的數據經過按位「或「運算存入x

SCL=0;                  //SCL的降低沿讀出數據

}

return(x);                   //將讀取的數據返回

}

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

函數功能:向AT24Cxx的當前地址寫入數據

入口參數:y(儲存待寫入的數據)

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

//在調用此數據寫入函數前需首先調用開始函數start(),因此SCL=0

bitWriteCurrent(unsignedchary)

{

unsignedchari;

bitack_bit;                  //儲存應答位

for(i=0;i<8;i++)        //  循環移入8個位

{

SDA=(bit)(y&0x80);    //經過按位「與」運算將最高位數據送到S

//由於傳送時高位在前,低位在後

_nop_();                 //等待一個機器週期

SCL=1;                 //SCL的上升沿將數據寫入AT24Cxx

_nop_();                 //等待一個機器週期

_nop_();                  //等待一個機器週期

SCL=0;                 //SCL從新置爲低電平,以在SCL線造成傳送

數據所需的8個脈衝

y<<=1;                 //y中的各二進位向左移一位

}


 


126


/


192


SDA=1;

釋放SDA線,


//


發送設備(主機)應在時鐘脈衝的高電平期間(SCL=1)


_nop_();

_nop_();

SCL=1;

_nop_();

_nop_();

_nop_();

_nop_();


//以讓SDA線轉由接收設備(AT24Cxx)控制

//等待一個機器週期

//等待一個機器週期

//根據上述規定,SCL應爲高電平

//等待一個機器週期

//等待一個機器週期

//等待一個機器週期

//等待一個機器週期


ack_bit=SDA;//接受設備(AT24Cxx)SDA送低電平,表示已經接收到一個

字節

//若送高電平,表示沒有接收到,傳送異常

SCL=0;         //SCL爲低電平時,SDA上數據才容許變化(即容許之後的數據

傳遞)

return  ack_bit;//返回AT24Cxx應答位

}

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

函數功能:向第一個AT24Cxx中的指定地址寫入數據

入口參數:add(儲存指定的地址);dat(儲存待寫入的數據)

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

voidWriteSet1(unsignedcharadd,unsignedchardat)

//  在指定地址addr處寫入數據WriteCurrent

{

start();                      //開始數據傳遞

WriteCurrent(OP_WRITE1);   //選擇要操做的第一個AT24Cxx芯片,並告知要

對其寫入數據

WriteCurrent(add);          //寫入指定地址

WriteCurrent(dat);          //向當前地址(上面指定的地址)寫入數據

stop();                       //中止數據傳遞

delaynms(4);                  //1個字節的寫入週期爲1ms,最好延時1ms

}

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

函數功能:向第二個AT24Cxx中的指定地址寫入數據

入口參數:add(儲存指定的地址);dat(儲存待寫入的數據)

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

voidWriteSet2(unsignedcharadd,unsignedchardat)

//  在指定地址addr處寫入數據WriteCurrent

{

start();                      //開始數據傳遞

WriteCurrent(OP_WRITE2);   //選擇要操做的AT24Cxx芯片,並告知要對其寫

入數據

WriteCurrent(add);          //寫入指定地址

127/192


}


WriteCurrent(dat);

stop();

delaynms(4);


//向當前地址(上面指定的地址)寫入數據

//中止數據傳遞

//1個字節的寫入週期爲1ms,最好延時1ms


 

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

函數功能:從第一個AT24Cxx中的當前地址讀取數據

出口參數:x(儲存讀出的數據)

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

unsignedcharReadCurrent1()

{

unsignedcharx;

start();                       //開始數據傳遞

WriteCurrent(OP_READ1);    //選擇要操做的第一個AT24Cxx芯片,並告知要

讀其數據

x=ReadData();                //將讀取的數據存入x

stop();                       //中止數據傳遞

returnx;                     //返回讀取的數據

}

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

函數功能:從第二個AT24Cxx中的當前地址讀取數據

出口參數:x(儲存讀出的數據)

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

unsignedcharReadCurrent2()

{

unsignedcharx;

start();                       //開始數據傳遞

WriteCurrent(OP_READ2);     //選擇要操做的第二個AT24Cxx芯片,並告知

要讀其數據

x=ReadData();                 //將讀取的數據存入x

stop();                        //中止數據傳遞

returnx;                      //返回讀取的數據

}

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

函數功能:從第一個AT24Cxx中的指定地址讀取數據

入口參數:set_addr

出口參數:x

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

unsignedcharReadSet1(unsignedcharset_addr)

//  在指定地址讀取

{

start();                           //開始數據傳遞


 


128


/


192


WriteCurrent(OP_WRITE1);

告知要對其寫入數據

WriteCurrent(set_addr);

return(ReadCurrent1());

並返回

}


//選擇要操做的第一個AT24Cxx芯片,並

//寫入指定地址

//從第一個AT24Cxx芯片指定地址讀出數據


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

函數功能:從第二個AT24Cxx中的指定地址讀取數據

入口參數:set_addr

出口參數:x

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

unsignedcharReadSet2(unsignedcharset_addr)

//  在指定地址讀取

{

start();                            //開始數據傳遞

WriteCurrent(OP_WRITE2);         //選擇要操做的第二個AT24Cxx芯片,並

告知要對其寫入數據

WriteCurrent(set_addr);          //寫入指定地址

return(ReadCurrent2());          //從第二個AT24Cxx芯片指定地址讀出數據

並返回

}

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

函數功能:主函數

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

main(void)

{

unsignedcharx;

SDA=1;             //SDA=1,SCL=1,使主從設備處於空閒狀態

SCL=1;

WriteSet1(0x36,0xaa);    //將數據"0xaa"寫入第一個AT24C02的指定地址

"0x36"

x=ReadSet1(0x36);         //從第二個AT24C02中的指定地址"0x36"讀出數據

WriteSet2(0x48,x);       //將讀出的數據寫入第二個AT24C02的指定地址

"0x48"?

P1=ReadSet2(0x48);       //將從第二個AT24C02的指定地址讀出的數據送

P1口顯示驗證

}


 


//


88


AT24C02


//實例88:基於AT24C02的多機通訊


讀取程序


 


#include<reg51.h>


//


包含51單片機寄存器定義的頭文件

129/192


#include<intrins.h>

#defineOP_READ

0001B


0xa1


//包含_nop_()函數定義的頭文件

//  器件1地址以及讀取操做,0xa1即爲1010


#define


OP_WRITE0xa0


//


器件1地址以及寫入操做,0xa1即爲10100000B


 


sbitSDA=P3^4;

sbitSCL=P3^3;

sbitflag=P3^0;


//將串行數據總線SDA位定義在爲P3.4引腳

//將串行時鐘總線SDA位定義在爲P3.3引腳


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

函數功能:延時1ms

(3j+2)*i=(3×33+2)×10=1010(微秒),能夠認爲是1毫秒

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

voiddelay1ms()

{

unsignedchari,j;

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

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

;

}

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

函數功能:延時若干毫秒

入口參數:n

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

voiddelaynms(unsignedcharn)

{

unsignedchari;

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

delay1ms();

}

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

函數功能:開始數據傳送

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

voidstart()

//  開始位

{

SDA=1;     //SDA初始化爲高電平「1

SCL=1;     //開始數據傳送時,要求SCL爲高電平「1

_nop_();    //等待一個機器週期

_nop_();    //等待一個機器週期

SDA=0;     //SDA的降低沿被認爲是開始信號

_nop_();    //等待一個機器週期

_nop_();    //等待一個機器週期

_nop_();    //等待一個機器週期

_nop_();    //等待一個機器週期


 


130


/


192


SCL=0;

遞)

_nop_();

}


//SCL爲低電平時,SDA上數據才容許變化(即容許之後的數據傳

//等待一個機器週期


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

函數功能:結束數據傳送

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

voidstop()

//  中止位

{

SDA=0;      //SDA初始化爲低電平「0

_nop_();      //等待一個機器週期

_nop_();      //等待一個機器週期

SCL=1;      //結束數據傳送時,要求SCL爲高電平「1

_nop_();      //等待一個機器週期

_nop_();      //等待一個機器週期

_nop_();      //等待一個機器週期

_nop_();      //等待一個機器週期

SDA=1;     //SDA的上升沿被認爲是結束信號

_nop_();      //等待一個機器週期

_nop_();      //等待一個機器週期

}

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

函數功能:從AT24Cxx讀取數據

出口參數:x

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

unsignedcharReadData()

//  AT24Cxx移入數據到MCU

{

unsignedchari;

unsignedcharx;             //儲存從AT24Cxx中讀出的數據

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

{

SCL=1;                   //SCL置爲高電平

x<<=1;                      //x中的各二進位向左移一位

x|=(unsignedchar)SDA;   //SDA上的數據經過按位「或「運算存入x

SCL=0;                  //SCL的降低沿讀出數據

}

return(x);                   //將讀取的數據返回

}

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

函數功能:向AT24Cxx的當前地址寫入數據

入口參數:y(儲存待寫入的數據)

131/192


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

//在調用此數據寫入函數前需首先調用開始函數start(),因此SCL=0

bitWriteCurrent(unsignedchary)

{

unsignedchari;

bitack_bit;                  //儲存應答位

for(i=0;i<8;i++)        //  循環移入8個位

{

SDA=(bit)(y&0x80);    //經過按位「與」運算將最高位數據送到S

//由於傳送時高位在前,低位在後

_nop_();                 //等待一個機器週期

SCL=1;                 //SCL的上升沿將數據寫入AT24Cxx

_nop_();                 //等待一個機器週期

_nop_();                  //等待一個機器週期

SCL=0;                 //SCL從新置爲低電平,以在SCL線造成傳送

數據所需的8個脈衝

y<<=1;                 //y中的各二進位向左移一位

}

SDA=1;           //  發送設備(主機)應在時鐘脈衝的高電平期間(SCL=1)

釋放SDA線,

//以讓SDA線轉由接收設備(AT24Cxx)控制

_nop_();          //等待一個機器週期

_nop_();          //等待一個機器週期

SCL=1;         //根據上述規定,SCL應爲高電平

_nop_();         //等待一個機器週期

_nop_();         //等待一個機器週期

_nop_();         //等待一個機器週期

_nop_();         //等待一個機器週期

ack_bit=SDA;//接受設備(AT24Cxx)SDA送低電平,表示已經接收到一個

字節

//若送高電平,表示沒有接收到,傳送異常

SCL=0;         //SCL爲低電平時,SDA上數據才容許變化(即容許之後的數據

傳遞)

return  ack_bit;//返回AT24Cxx應答位

}

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

函數功能:從第一個AT24Cxx中的當前地址讀取數據

出口參數:x(儲存讀出的數據)

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

unsignedcharReadCurrent()

{

unsignedcharx;

132/192


}


start();

WriteCurrent(OP_READ);

x=ReadData();

stop();

returnx;


//開始數據傳遞

//選擇要操做的AT24Cxx芯片,並告知要讀其數

//將讀取的數據存入x

//中止數據傳遞

//返回讀取的數據


 

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

函數功能:從AT24Cxx中的指定地址讀取數據

入口參數:set_addr

出口參數:x

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

unsignedcharReadSet(unsignedcharset_addr)

//  在指定地址讀取

{

start();                           //開始數據傳遞

WriteCurrent(OP_WRITE);         //選擇要操做的AT24Cxx芯片,並告知要對

其寫入數據

WriteCurrent(set_addr);         //寫入指定地址

return(ReadCurrent());          //從第一個AT24Cxx芯片指定地址讀出數據並

返回

}

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

函數功能:主函數

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

main(void)

{

SDA=1;             //SDA=1,SCL=1,使主從設備處於空閒狀態

SCL=1;

while(1)

{

while(flag==1)

;

P1=ReadSet(0x36);         //從第二個AT24C02中的指定地址"0x36"讀出數

delaynms(90);

}

}


 


//


88


AT24C02


//實例88:基於AT24C02的多機通訊

133/192


寫入程序


#include<reg51.h>


//


包含51單片機寄存器定義的頭文件


 


#include<intrins.h>

#defineOP_READ

0001B


0xa1


//包含_nop_()函數定義的頭文件

//  器件1地址以及讀取操做,0xa1即爲1010


#define


OP_WRITE0xa0


//


器件1地址以及寫入操做,0xa1即爲10100000B


sbitSDA=P3^4;

sbitSCL=P3^3;

sbitflag=P3^0;


//將串行數據總線SDA位定義在爲P3.4引腳

//將串行時鐘總線SDA位定義在爲P3.3引腳


 

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

函數功能:延時1ms

(3j+2)*i=(3×33+2)×10=1010(微秒),能夠認爲是1毫秒

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

voiddelay1ms()

{

unsignedchari,j;

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

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

;

}

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

函數功能:延時若干毫秒

入口參數:n

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

voiddelaynms(unsignedcharn)

{

unsignedchari;

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

delay1ms();

}

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

函數功能:開始數據傳送

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

voidstart()

//  開始位

{

SDA=1;     //SDA初始化爲高電平「1

SCL=1;     //開始數據傳送時,要求SCL爲高電平「1

_nop_();    //等待一個機器週期

_nop_();    //等待一個機器週期

SDA=0;     //SDA的降低沿被認爲是開始信號

_nop_();    //等待一個機器週期

_nop_();    //等待一個機器週期

_nop_();    //等待一個機器週期

_nop_();    //等待一個機器週期

134/192


SCL=0;

遞)

_nop_();

}


//SCL爲低電平時,SDA上數據才容許變化(即容許之後的數據傳

//等待一個機器週期


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

函數功能:結束數據傳送

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

voidstop()

//  中止位

{

SDA=0;      //SDA初始化爲低電平「0

_nop_();      //等待一個機器週期

_nop_();      //等待一個機器週期

SCL=1;      //結束數據傳送時,要求SCL爲高電平「1

_nop_();      //等待一個機器週期

_nop_();      //等待一個機器週期

_nop_();      //等待一個機器週期

_nop_();      //等待一個機器週期

SDA=1;     //SDA的上升沿被認爲是結束信號

_nop_();      //等待一個機器週期

_nop_();      //等待一個機器週期

_nop_();      //等待一個機器週期

_nop_();      //等待一個機器週期

}

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

函數功能:向AT24Cxx的當前地址寫入數據

入口參數:y(儲存待寫入的數據)

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

//在調用此數據寫入函數前需首先調用開始函數start(),因此SCL=0

bitWriteCurrent(unsignedchary)

{

unsignedchari;

bitack_bit;                  //儲存應答位

for(i=0;i<8;i++)        //  循環移入8個位

{

SDA=(bit)(y&0x80);    //經過按位「與」運算將最高位數據送到S

//由於傳送時高位在前,低位在後

_nop_();                 //等待一個機器週期

SCL=1;                 //SCL的上升沿將數據寫入AT24Cxx

_nop_();                 //等待一個機器週期

_nop_();                  //等待一個機器週期


 


135


/


192


SCL=0;

數據所需的8個脈衝

y<<=1;

}

SDA=1;

釋放SDA線,


//


//SCL從新置爲低電平,以在SCL線造成傳送

//y中的各二進位向左移一位

發送設備(主機)應在時鐘脈衝的高電平期間(SCL=1)


 


_nop_();

_nop_();

SCL=1;

_nop_();

_nop_();

_nop_();

_nop_();


//以讓SDA線轉由接收設備(AT24Cxx)控制

//等待一個機器週期

//等待一個機器週期

//根據上述規定,SCL應爲高電平

//等待一個機器週期

//等待一個機器週期

//等待一個機器週期

//等待一個機器週期


 

ack_bit=SDA;//接受設備(AT24Cxx)SDA送低電平,表示已經接收到一個

字節

//若送高電平,表示沒有接收到,傳送異常

SCL=0;         //SCL爲低電平時,SDA上數據才容許變化(即容許之後的數據

傳遞)

return  ack_bit;//返回AT24Cxx應答位

}

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

函數功能:向AT24Cxx中的指定地址寫入數據

入口參數:add(儲存指定的地址);dat(儲存待寫入的數據)

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

voidWriteSet(unsignedcharadd,unsignedchardat)

//  在指定地址addr處寫入數據WriteCurrent

{

start();                      //開始數據傳遞

WriteCurrent(OP_WRITE);   //選擇要操做的第一個AT24Cxx芯片,並告知要

對其寫入數據

WriteCurrent(add);          //寫入指定地址

WriteCurrent(dat);          //向當前地址(上面指定的地址)寫入數據

stop();                       //中止數據傳遞

delaynms(4);                  //1個字節的寫入週期爲1ms,最好延時1ms

}

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

函數功能:主函數

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

main(void)

{

TMOD=0x01;

136/192


TH0=(65536-46083)/256;

TL0=(65536-46083)%256;

EA=1;

ET0=1;

TR0=1;

flag=1;

while(1)

{

while(flag==1)

{

WriteSet(0x36,0xf0);

"0x36"

delaynms(50);

}

while(flag==0)

;

}

}


//將數據"0xf0"寫入第一個AT24C02的指定地址

//延時50ms


 

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

函數功能:定時器T0的中斷函數,使P3.0引腳輸出100ms方波

***************

相關文章
相關標籤/搜索