目錄git
目錄................................................................................................................................1數組
函數的使用和熟悉********************************/.......................................4函數
實例3:用單片機控制第一個燈亮.............................................................................4ui
實例4:用單片機控制一個燈閃爍:認識單片機的工做頻率.................................4spa
實例5:將P1口狀態分別送入P0、P2、P3口:認識I/O口的引腳功能............5設計
實例6:使用P3口流水點亮8位LED.......................................................................5指針
實例7:經過對P3口地址的操做流水點亮8位LED...............................................6code
實例8:用不一樣數據類型控制燈閃爍時間.................................................................7接口
實例9:用P0口、P1口分別顯示加法和減法運算結果.........................................8字符串
實例10:用P0、P1口顯示乘法運算結果................................................................9
實例11:用P1、P0口顯示除法運算結果................................................................9
實例12:用自增運算控制P0口8位LED流水花樣..............................................10
實例13:用P0口顯示邏輯"與"運算結果...............................................................10
實例14:用P0口顯示條件運算結果.......................................................................11
實例15:用P0口顯示按位"異或"運算結果...........................................................11
實例16:用P0顯示左移運算結果...........................................................................11
實例17:"萬能邏輯電路"實驗.................................................................................11
實例18:用右移運算流水點亮P1口8位LED.......................................................12
實例19:用if語句控制P0口8位LED的流水方向..............................................13
實例20:用swtich語句的控制P0口8位LED的點亮狀態..................................13
實例21:用for語句控制蜂鳴器鳴笛次數..............................................................14
實例22:用while語句控制LED...............................................................................16
實例23:用do-while語句控制P0口8位LED流水點亮......................................16
實例24:用字符型數組控制P0口8位LED流水點亮..........................................17
實例25:用P0口顯示字符串常量.........................................................................18
實例26:用P0口顯示指針運算結果......................................................................19
實例27:用指針數組控制P0口8位LED流水點亮..............................................19
實例28:用數組的指針控制P0口8位LED流水點亮........................................20
實例29:用P0、P1口顯示整型函數返回值........................................................21
實例30:用有參函數控制P0口8位LED流水速度..............................................22
實例31:用數組做函數參數控制流水花樣.............................................................23
實例32:用指針做函數參數控制P0口8位LED流水點亮..................................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查詢方式P2口8位控制LED閃爍....................................31
實例43:用定時器T1查詢方式控制單片機發出1KHz音頻.................................31
實例44:將計數器T0計數的結果送P1口8位LED顯示....................................32
實例45:用定時器T0的中斷控制1位LED閃爍...................................................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
實例71:CPU控制的獨立式鍵盤掃描實驗.............................................................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
實例90:DS18B20溫度檢測及其液晶顯示...........................................................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=11111110B,P1.0輸出低電平
delay(); //延時一段時間
P1=0xff; //P1=11111111B,P1.0輸出高電平
delay(); //延時一段時間
}
}
4/192
//
5
P1
P0
P2
P3
I/O
//實例5:將
#include<reg51.h>
P1口狀態分別送入P0、P2、P3口:認識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口流水點亮8位LED
#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口地址的操做流水點亮8位LED
#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.3、P1.4、P1.7
口的燈被點亮
}
P0=n-m;
//P0=17=00010001B,結果P0.0、P0.4的燈被熄滅
//實例10:用P0、P1口顯示乘法運算結果
#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
//所以,高8位16進制數H3*16+H2必然等於17,即4544
除以256的商
//低8位16進制數H1*16+H0必然等於192,即4544除以
256的餘數
P1=s/256; //高8位送P1口,P1=17=11H=00010001B,P1.0和P1.4口滅,
其他亮
P0=s%256; //低8位送P0口,P3=192=c0H=11000000B,P3.1,P3.6,P3.7口
滅,其他亮
}
//實例11:用P1、P0口顯示除法運算結果
#include<reg51.h> //包含單片機寄存器的頭文件
voidmain(void)
{
P1=36/5; //求整數
P0=((36%5)*10)/5;//求小數
while(1)
9/192
}
;
//無限循環防止程序「跑飛」
//實例12:用自增運算控制P0口8位LED流水花樣
#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:用右移運算流水點亮P1口8位LED
#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語句控制P0口8位LED的流水方向
#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語句的控制P0口8位LED的點亮狀態
#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小於0xff(255)時執行循環體
{
P0=i; //將i送P0口顯示
delay60ms();//延時
i++; //i自增1
}
}
}
//實例23:用do-whiile語句控制P0口8位LED流水點亮
#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); //無限循環,使8位LED循環流水點亮
}
//實例24:用字符型數組控制P0口8位LED流水點亮
#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.3、P0.5引腳LED熄滅,其他點亮
while(1)
; //無限循環,防止程序「跑飛」
//
27
P0
8
LED
//實例27:用指針數組控制P0口8位LED流水點亮
#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:用有參函數控制P0口8位LED流水速度
#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++)
;
}
/*************************************************
函數功能:流水點亮P0口8位LED
*************************************************/
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:用指針做函數參數控制P0口8位LED流水點亮
#include<reg51.h>
223/192
/*************************************************
函數功能:延時約150ms
*************************************************/
voiddelay(void)
{
unsignedcharm,n;
for(m=0;m<200;m++)
for(n=0;n<250;n++)
;
}
/*************************************************
函數功能:流水點亮P0口8位LED
*************************************************/
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++)
;
}
/**************************************************************
函數功能:流水點亮P0口8位LED
**************************************************************/
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;
//帶參數的宏定義,a和b爲形參
參
}
P3=F(i,j+k);
while(1)
;
//i和j+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查詢方式P2口8位控制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計數的結果送P1口8位LED顯示
#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;//計數器TL0加1後送P1口顯示
//計數器溢出後,將TF0清0
//實例45:用定時器T0的中斷控制1位LED閃爍
#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; //將Countor清0,從新從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; //將Countor1清0,從新從0開始計數
}
if(Countor2==8) //若累計滿8次,即計時滿400ms
{
D2=~D2; //按位取反操做,將P2.1引腳輸出電平取反
Countor2=0; //將Countor1清0,從新從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的模式1(13位計數器)
while(1) //無限循環
{
i=0; //從第1個音符f[0]開始播放
while(f[i]!=0xff) //只要沒有讀到結束標誌就繼續播放
{
C=460830/f[i];
TH0=(8192-C)/32; //可證實這是13位計數器TH0高8位的賦
初值方法
TL0=(8192-C)%32; //可證實這是13位計數器TL0低5位的賦初
值方法
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位計數器TH0高8位的賦初值方法
TL0=(8192-C)%32; //可證實這是13位計數器TL0低5位的賦初值方法
}
//
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; //計數器T0高8位賦初值
TL0=0; //計數器T0低8位賦初值
while(1) //無限循環,不停地將TL0計數結果送P1口
P1=TL0;
}
//實例51-2:定時器T0的模式2測量正脈衝寬度
#include<reg51.h> //包含51單片機寄存器定義的頭文件
sbitui=P3^2; //將ui位定義爲P3.0(INT0)引腳,表示輸入電壓
/*******************************************
函數功能:主函數
******************************************/
voidmain(void)
{
TMOD=0x0a; //TMOD=00001010B,使用定時器T0的模式2,GATE置1
EA=1; //開總中斷
440/192
ET0=0;
TR0=1;
TH0=0;
TL0=0;
while(1)
{
while(ui==0)
;
TL0=0;
//不使用定時器T0的中斷
//啓動T0
//計數器T0高8位賦初值
//計數器T0低8位賦初值
//無限循環,不停地將TL0計數結果送P1口
//INT0爲低電平,T0不能啓動
//INT0爲高電平,啓動T0計時,因此將TL0清0
}
}
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信號,對74LS164清0
_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; //爲了接收下一幀數據,需將RI清0
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,
//SM2置0,不使用多機通訊,TB8置0
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; //爲了接收下一幀數據,需將RI清0
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; //爲了接收下一幀數據,需將RI清0
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};
//數碼管顯示0~9的段碼錶,程序運行中當數組值不發生變化
時,
//前面加關鍵字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};
//數碼管顯示0~9的段碼錶
/********************************************************************
***
函數功能:快速動態掃描延時,延時約0.9毫秒
*********************************************************************
***/
voiddelay(void)
{
unsignedinti;
for(i=0;i<300;i++)
;
}
/********************************************************************
***
函數功能:4位數的數碼顯示器顯示
入口參數:k
出口參數:無
*********************************************************************
***/
voiddisplay(unsignedintk)
{
P2=0xfe; //即P2=11111110B,P2.0引腳輸出低電平,數碼顯示器DS0接
通電源
P0=Tab[k/1000]; //顯示千位
delay();
P2=0xfd; //即P2=11111101B,P2.1引腳輸出低電平,數碼顯示器DS1接通
電源
P0=Tab[(k%1000)/100]; //顯示百位
delay();
P2=0xfb; //即P2=11111011B,P2.2引腳輸出低電平,數碼顯示器DS2接通
電源
P0=Tab[(k%100)/10]; //顯示十位
delay();
P2=0xf7; //即P2=11110111B,P2.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; //隨機產生一個從0到32767的整數,再將其除以10,
得到一個隨機4位數,模擬檢測結果
i=0; //將i清0,從新統計中斷次數
}
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};
//數碼管顯示0~9的段碼錶
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引腳取反
//實例71:CPU控制的獨立式鍵盤掃描實驗
#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; //關閉8個LED
}
/*************************************************
函數功能:閃爍點亮LED
**************************************************/
voidflash(void)
{
P3=0xff; //關閉8個LED
led_delay();
P3=0x00; //點亮8個LED
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; //位定義S1爲P1.4
sbitS2=P1^5; //位定義S2爲P1.5
sbitS3=P1^6; //位定義S3爲P1.6
sbitS4=P1^7; //位定義S4爲P1.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; //位定義S1爲P1.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位計數器TH0高8位的賦初值方法
TL0=(8192-C)%32; //可證實這是13位計數器TL0低5位的賦初值方法
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的模式1,T0的模式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位計數器TH0高8位的賦初值
方法
TL0=(8192-C)%32; //可證實這是13位計數器TL0低5位的賦初值方
法
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();
}
/*****************************************************
函數功能:判斷液晶模塊的忙碌狀態
返回值:result。result=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; //根據規定,RS和R/W同時爲低電平時,能夠寫
入指令
RW=0;
E=0; //E置低電平(根據表8-6,寫指令時,E爲高脈衝,
// 就是讓E從0到1發生正跳變,因此應先置
"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爲高脈衝,
// 就是讓E從0到1發生正跳變,因此應先置"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
/*****************************************************
函數功能:判斷液晶模塊的忙碌狀態
返回值:result。result=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; //根據規定,RS和R/W同時爲低電平時,能夠寫
入指令
RW=0;
E=0; //E置低電平(根據表8-6,寫指令時,E爲高脈衝,
// 就是讓E從0到1發生正跳變,因此應先置
"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爲高脈衝,
// 就是讓E從0到1發生正跳變,因此應先置"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();
}
/*****************************************************
函數功能:判斷液晶模塊的忙碌狀態
返回值:result。result=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; //根據規定,RS和R/W同時爲低電平時,能夠寫
入指令
RW=0;
E=0; //E置低電平(根據表8-6,寫指令時,E爲高脈衝,
// 就是讓E從0到1發生正跳變,因此應先置
"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爲高脈衝,
// 就是讓E從0到1發生正跳變,因此應先置"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();
}
/*****************************************************
函數功能:判斷液晶模塊的忙碌狀態
返回值:result。result=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; //根據規定,RS和R/W同時爲低電平時,能夠寫
入指令
RW=0;
E=0; //E置低電平(根據表8-6,寫指令時,E爲高脈衝,
// 就是讓E從0到1發生正跳變,因此應先置"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爲高脈衝,
// 就是讓E從0到1發生正跳變,因此應先置"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;
//定時器T0高8位從新賦初值
//定時器T0低8位從新賦初值
/********************************************************
***********一些芯片的使用*****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
*********************************************************************
***********/
/*****************************************************
函數功能:判斷液晶模塊的忙碌狀態
返回值:result。result=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; //根據規定,RS和R/W同時爲低電平時,能夠寫
入指令
RW=0;
E=0; //E置低電平(根據表8-6,寫指令時,E爲高脈衝,
// 就是讓E從0到1發生正跳變,因此應先置
"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爲高脈衝,
// 就是讓E從0到1發生正跳變,因此應先置"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方波
***************