|
第一個實驗:keil軟件使用與點亮人生的第一只發(fā)光二極管
本實驗教程的 pdf完整版下載及配套的的仿真工程文件和源碼下載地址:http://www.zg4o1577.cn/bbs/dpj-85401-1.html
1.001.jpg (23.15 KB, 下載次數(shù): 162)
下載附件
2017-5-20 17:27 上傳
本章詳細介紹單片機程序常用編譯軟件 Keil 的用法,用一個完整的 C51 程序來操作發(fā)光二極管的點亮與熄滅,然后調用 C51 庫函數(shù)來方 便地實現(xiàn)流水燈,從這一章開始我們將手把手地講解單片機 C 語言編 程。認真學好本章,對于初學者來說將會是一個非常好的開頭。
用實操點亮一只燈程序來學會使用編程軟件 keil 的基本功能。
最終目標:點亮下圖 D8 發(fā)光二極管。
1 電路走線如下:
1.002.jpg (57.33 KB, 下載次數(shù): 171)
下載附件
2017-5-20 17:27 上傳
2 元件特性 發(fā)光二極管的原理
1.003.jpg (4.3 KB, 下載次數(shù): 162)
下載附件
2017-5-20 17:27 上傳
正極這邊為高電平,負極為低電平,發(fā)光二極管就行,兩邊為高電平, 發(fā)光二極管就不亮。
3 程序流程:把 P1.1~P1.7 置高電平,P1.0 置低電平即可。
4 程序的書寫與調試。 我們要書寫程序,需要一個 keil 軟件。
Keil 的操作步驟。 詳細操作步驟:
1.004.jpg (16.07 KB, 下載次數(shù): 160)
下載附件
2017-5-20 17:27 上傳
從圖片中不難看出,我們寫的程序(子項目)都是圍繞總項目轉的, 然后從總項目輸出我們想要的單片機程序。
第一步:新建總項目(打開軟件跟著做,熟悉一下)
當我們安裝好 Keil Uvision 3 編程軟件后,就點 projec(t 項目)——new
prouect(新項目)來新建項目。
1.005.jpg (35.35 KB, 下載次數(shù): 153)
下載附件
2017-5-20 17:27 上傳
點擊完 new project 后,會有如下對話框。
1.006.jpg (22.51 KB, 下載次數(shù): 157)
下載附件
2017-5-20 17:27 上傳
從上面不難看出,我們新建的單片機程序項目后綴名字是 uv2,而且
當 uv2 項目產(chǎn)生的時候,會自動附帶很多其它 uv2 需要的文件,為了 防止我們產(chǎn)生瀏覽混亂,這個時候我們就需要“新建一個文件夾”, 把 uv2 存在里面,那么附帶的文件也會自己存進去這個文件夾里面去 方便我們?yōu)g覽和操作了。
1.007.jpg (33.48 KB, 下載次數(shù): 175)
下載附件
2017-5-20 17:27 上傳
我命名字為“點亮一只燈”,并且雙擊進入這個文件夾里面。
1.008.jpg (26.56 KB, 下載次數(shù): 138)
下載附件
2017-5-20 17:27 上傳
1.009.jpg (27.39 KB, 下載次數(shù): 158)
下載附件
2017-5-20 17:27 上傳
CPU 選擇是找到 Atmel 并點擊其它+號。
1.010.jpg (32.4 KB, 下載次數(shù): 164)
下載附件
2017-5-20 17:27 上傳
往下拉,找到 AT89C52(選擇 51 類型的單片機)
1.011.jpg (31.94 KB, 下載次數(shù): 160)
下載附件
2017-5-20 17:27 上傳
選擇后,點確定按鈕。
1.012.jpg (40.14 KB, 下載次數(shù): 151)
下載附件
2017-5-20 17:27 上傳
是否復制 51 標準代碼,這個暫時沒有什么用,點否就可以。
1.013.jpg (13.58 KB, 下載次數(shù): 152)
下載附件
2017-5-20 17:27 上傳
這個時候,我們才創(chuàng)建好總項目,從一開始的圖片我們看到,還需要
為總項目“添加子項目”。
下面圖片指針頭指的是,點亮一盞燈的總項目,通過上面的操作,已 經(jīng)創(chuàng)建完成。
1.014.jpg (29.37 KB, 下載次數(shù): 142)
下載附件
2017-5-20 17:27 上傳
第二步:為總項目添加子項目
為總項目添加子項目之前,我們需要新建一個文件(程序編輯窗口), 點擊軟件 file 下面那個文本圖標 create a newfile(創(chuàng)建一個新的文件)
1.015.jpg (23.12 KB, 下載次數(shù): 163)
下載附件
2017-5-20 17:27 上傳
得到如下圖的程序編輯窗口,在這里面編寫單片機的程序。
1.016.jpg (30.43 KB, 下載次數(shù): 196)
下載附件
2017-5-20 17:27 上傳
現(xiàn)在我們需要的是點亮一只燈的程序。
1.017.jpg (33.25 KB, 下載次數(shù): 139)
下載附件
2017-5-20 17:27 上傳
#include Main() { P1=0xfe; } 寫好后,我們還不知道子項目里的程序有沒有錯,現(xiàn)在我們需要把這 個子項目添加到“點亮一只燈.uv2”的總項目里,去讓軟件查錯,方 便我們修正,輸出我們想要的單片機代碼去讓單片機工作,那需要如 何做呢?
很顯然,當我們新建一個子項目編輯窗口時(子項目),軟件是沒有
把這個子項目存到總項目當中的,而是需要我們人手添加進去。
操作方法是:先保存,然后再把這個子項目添加到總項目去。
先保存。
需要點擊如下圖的圖標 save the active document(保存活動文檔),就 是保存當前編輯中的程序編輯窗口(子項目)。
1.018.jpg (32.86 KB, 下載次數(shù): 157)
下載附件
2017-5-20 17:27 上傳
或許有些朋友很聰明,看到窗口上的*號就知道還沒有保存的文件。
默認保存在我們創(chuàng)建的“點亮一只燈”文件夾當中,還有重要的一點
是,記得文件名后綴必須是“.c”,第二次:文件名后綴必須是“.c” 第三次:文件名后綴必須是“.c”,重要是事情說三遍,這樣后面的 操作就會萬無一失了。
1.019.jpg (30.62 KB, 下載次數(shù): 156)
下載附件
2017-5-20 17:27 上傳
保存后,某些字母是有顏色的,這個就是保存好的象征,如下圖所示:
1.020.jpg (31.85 KB, 下載次數(shù): 157)
下載附件
2017-5-20 17:27 上傳
保存后,現(xiàn)在我們需要把子項目添加到總項目當中。
1.021.jpg (35.76 KB, 下載次數(shù): 145)
下載附件
2017-5-20 17:27 上傳
鼠標右擊“source group1”選擇”add file to group ’source group1 ’”(添
加文件到組,根源組 1)
1.022.jpg (50.2 KB, 下載次數(shù): 172)
下載附件
2017-5-20 17:27 上傳
默認打開的就是“點亮一只燈”文件夾下面的“點亮一點燈”的 C 語
言程序(就是我們剛剛保存的.c 文件) 然后點窗口上的 add(添加),
1.023.jpg (23.46 KB, 下載次數(shù): 160)
下載附件
2017-5-20 17:27 上傳
Source group1 下有了“點亮一只燈”的 C 語言程序
1.024.jpg (30.04 KB, 下載次數(shù): 161)
下載附件
2017-5-20 17:27 上傳
添加成功后,就退出上面那個添加窗口。
添加子項目到總項目后,我們還不知道我們寫的程序有沒有錯,現(xiàn)在
1.025.jpg (43.57 KB, 下載次數(shù): 149)
下載附件
2017-5-20 17:27 上傳
要做的是,讓軟件查錯,那要如何做呢? 如下圖所示。
如果總項目只有一個子項目的時候(就像點亮一只燈.c),我們就點 built target,如果有二個或以上的子項目,就點 built all target files, 就兩個按鈕就是這樣用,這就為什么叫總項目和子項目的原因,因為 總項目中可以包含多個子項目的。
來看看點擊后的效果。
這里只有一個子項目,只點 build target 就行。
1.026.jpg (38.84 KB, 下載次數(shù): 148)
下載附件
2017-5-20 17:27 上傳
1.027.jpg (48.86 KB, 下載次數(shù): 146)
下載附件
2017-5-20 17:27 上傳
從上圖可以看到,build 完后,我們看到是 0 error (0 錯誤),0 warning
(0 警告)。
如果我們把 P1=0xff;,后面這個“;”分號去掉,看看是怎么樣。
1.028.jpg (55.32 KB, 下載次數(shù): 134)
下載附件
2017-5-20 17:27 上傳
很明顯,它出來了一句,syntax error near (} 語法錯誤在花括號附近),
target not created(目標沒創(chuàng)建)。
雙擊 syntax error near }這條語句時,光標就會出來在附近,讓你改錯。
1.029.jpg (61.5 KB, 下載次數(shù): 141)
下載附件
2017-5-20 17:27 上傳
現(xiàn)在我們把分號加上后,它編譯沒有錯誤,證明程序可以運用,但是
軟件還沒有輸出單片機運行需要的代碼。
1.030.jpg (33.28 KB, 下載次數(shù): 150)
下載附件
2017-5-20 17:27 上傳
第三步:輸出單片機運行需要的代碼
鼠標右擊“target”點“options for target ‘target 1’”(選項對于目標 1)
1.031.jpg (42.96 KB, 下載次數(shù): 140)
下載附件
2017-5-20 17:27 上傳
點第三列的 output “輸出”按鈕,然后把 create hex file“創(chuàng)建 16 進
制文件”勾上后,點確定。
1.032.jpg (37.99 KB, 下載次數(shù): 127)
下載附件
2017-5-20 17:27 上傳
再點 built target
1.033.jpg (16.52 KB, 下載次數(shù): 124)
下載附件
2017-5-20 17:27 上傳
這樣在編譯沒有錯誤成功后,它就會產(chǎn)生一個 hex 文件(單片機需要 的代碼),我們就可以用這個 hex 文件讓我們的單片機工作啦!
它在什么位置?就在我們新建的“點亮一只燈”的文件夾里面。
1.034.jpg (22.49 KB, 下載次數(shù): 142)
下載附件
2017-5-20 17:27 上傳
需要用的時候,我們需要到這個文件夾找出來,這樣我們 P1.0 口的 發(fā)光二極管就可以點亮了。
1.035.jpg (38.74 KB, 下載次數(shù): 135)
下載附件
2017-5-20 17:27 上傳
查找方法:
如果你是用仿真軟件。 先雙擊 89C52
1.036.jpg (46.57 KB, 下載次數(shù): 136)
下載附件
2017-5-20 17:27 上傳
再點擊 program file 到點亮一盞燈文件夾里面,把點亮一只燈.hex 文 件,找出來就行。(如下圖)
1.037.jpg (40.3 KB, 下載次數(shù): 158)
下載附件
2017-5-20 17:27 上傳
找出來后,再點右上角的 OK 就可以了。
你可以復制下面程序去編程軟件,熟悉上面的功能,如果想要靠自己 記憶去寫,也可以嘗試一下。
#include
main()
{ P1=0xff; }
程序講解:
#include 包含這個頭文件,頭文件上面我們講解,就是為
單片機里面的地址命名字,方便我們直接用名字使用(每個程序的開 頭肯定有頭文件的)
main()
{
}
Main()這個是主函數(shù)入口,程序在花括號{ }里面執(zhí)行,之于 main 旁邊 的括號是什么東西,我們以后用到再講解,現(xiàn)在明白它是固定格式 main(),mian 括號就行。
P1=0xfe;
P1=1111 1110,把 P1.0 位置低電平,點亮 D8 發(fā)光二極管。
需要注意的是,這里的 P1 不可隨意寫,P 是大寫,若寫成 p,編譯程 序時將報錯,因為編譯器并不認識 p1,它只認識 P1,這是因為我們 在頭文件中定義的是“sfr P1= 0x90;”。 P1=0xfe 后面的分號“;”也不要漏掉,不然程序會報錯, 這些也是大多初學者編寫第一個程序時常犯的錯誤,希望大家留意一 下。
注釋問題。
知識點:C 語言中注釋的寫法
在 C 語言中,注釋有兩種寫法:
(1)// 兩個斜扛后面跟著的為注釋語句。這種寫法只能注釋一行, 當換行時,又必須在新行上重新寫兩個斜扛。
(2)/*…*/ 斜扛與星號結合使用,這種寫法可以注釋任意行,即斜 扛星號與星號斜扛之間的所有文字都作為注釋。
下圖是第二種。
1.038.jpg (25.15 KB, 下載次數(shù): 145)
下載附件
2017-5-20 17:27 上傳
所有注釋都不參與程序編譯,編譯器在編譯過程會自動刪去注釋,注
釋的目的是為了我們讀程序方便,一般在編寫較大的程序時,分段加 入注釋,這樣當我們回過頭來再次讀程序時,因為有了注釋,其代碼 的意義便一目了然了。若無注釋,我們不得不特別費力地將程序 重新閱讀一遍方可知道代碼含義。養(yǎng)成良好的書寫代碼格式的習慣, 經(jīng)常為自己編寫的代碼加入注釋,以后定能方便許多。
練習:
把 P1.1~P1.7 口逐個點亮。
把 P1.0~P1.3 點亮,其它四個不亮。
while語句 通過上面一節(jié)的學習,想必大家已經(jīng)對點亮實驗板上的任意發(fā)光二極 管非常熟悉了,但是,先不要高興得太早,上面的程序并不完善,任 何一個程序都要有頭有尾才對,而上面我們寫的程序似乎只有頭而無 尾。我們分析一下看,當程序運行時,首先進入主函數(shù),順序執(zhí)行里 面的所有語句,因為主函數(shù)中只有一條語句,當執(zhí)行完這條語句后, 該執(zhí)行什么了?
因為我們沒有給單片機明確指示下一步該做什么,所以單片機在運行 時就很有可能會出錯。
根據(jù)經(jīng)驗,當 Keil 編譯器遇到這種情況時,它會自動從主函數(shù)開始處 重新執(zhí)行語句,所以單片機在運行上面兩個程序時,實際上是在不斷 地重復點亮發(fā)光二極管的操作,而我們的意圖是讓單片機點亮二極管 后就結束,也就是讓程序停止在某處,這樣一個有頭有尾的程序才完
整。
那么如何讓程序停止在某處呢?我們用 while 語句就可以實現(xiàn)。 知識點:while()語句的應用
格式:
while(表達式)
{
內部語句(內部可為空)
}
特點:先判斷表達式是真還是假,再執(zhí)行或者不執(zhí)行內部語句。 在 C 語言的判斷條件中,1 或以上為真,0 為假。 判斷原則:若表達式不是 0,即不是 while(0)這樣的形式。這樣說就 是 while(1),while(2),while(3 或以上),即為真,那么執(zhí)行 while 花括 號的內部語句,如果是 while(0)即為假,跳過while,不執(zhí)行 while 花 括號的內部語句。
while 有兩種形式:
1 如果語句只有一條。 直接用表達式+執(zhí)行語句+分號結束就行。 如:
While(1) 表達式。
P1=0xfe; 執(zhí)行語句+分號。
While(1)是表達式,用來判斷是真是假。 因為這里是真,所以語句就無限循環(huán)于 P1=0xfe,后面再加上一個分 號表示這是一條結束。
1.039.jpg (8.4 KB, 下載次數(shù): 134)
下載附件
2017-5-20 17:27 上傳
2 如果有兩條以上表達式。 如:
While(1) P1=0xfe; P1=0xfa;
它也只是無限循環(huán)于 P1=0xfe 這條語句,而不往下執(zhí)行 P1=0xfa,這
樣的程序格式顯然是滿足不了多少功能,沒有什么意義的,那我們要 怎么寫才能讓 while 執(zhí)行多些語句呢?
從上面可以觀察到,我們還有花括號可用。 是的,
while(1)
{
}
“While(1)+花括號”就可以實現(xiàn)我們想要的功能。
While(1)
{ P1=0xfe; P1=0xfa; }
這樣就可以執(zhí)行完 P1=0xfe,又繼續(xù)執(zhí)行 P1=0xfa,如果后面還有語句
就會接著一條條繼續(xù)執(zhí)行,直到 } 的這個結尾,繼續(xù)又重新開始到
{ 這個開始繼續(xù)執(zhí)行,無限循環(huán)。
1.040.jpg (8.57 KB, 下載次數(shù): 131)
下載附件
2017-5-20 17:27 上傳
現(xiàn)在我們可以了解到,while 有無限循環(huán)執(zhí)行它內部語句的用法,如
果只有一條語句,直接在這條語句加分號就行,如果有兩條語句或以 上就需要加{}花括號。
如果 while(0) P1=0xfe; P1=0xfa;
因為現(xiàn)在 while 為假,所以它不會執(zhí)行 P1=0xfe,而往下執(zhí)行 P1=0xfa, 因為 P1=0xfa;是不屬于 while 的內部語句。
花括號原理也是一樣。
while(0)
{ P1=0xfe; P1=0xfa; } P1=0x0f;
不執(zhí)行 while 花括號里面的語句,執(zhí)行 P1=0x0f;
通過這些認識 我們來編寫一個完整的點亮第一個發(fā)光二極管的程序。 #include //52 系列單片機頭文件
void main() //主函數(shù)
(
P1=0xfe;
while(1);
)
這里的 main 前面多了一個 void,void 有空的意思,在 main 前面加上
void 這個東西,實際意義并不大,只是讓程序具體點,你直接用 main()
也可以。
然后到 P1=0xfe,再停止在 while(1);這里,while 里面,如果有一條語 句就執(zhí)行完這個語句,停止到分號,如果沒有語句就直接在分號這里 無限循環(huán),相當于停止標記,所以以后一看到 while(1);,就知道是停 止標記了。
知識點:for語句 格式:
for(表達式 1;表達式 2;表達式 3)
{
內部語句
}
例子:
for(i=0;i<3;i++)
{ P1=0xfe; }
語句解說:
1.041.jpg (16.58 KB, 下載次數(shù): 134)
下載附件
2017-5-20 17:27 上傳
執(zhí)行過程:
1.042.jpg (27.71 KB, 下載次數(shù): 133)
下載附件
2017-5-20 17:27 上傳
上圖文字說明:
1 判斷:判斷 i 是否少于 3。
2 執(zhí)行:執(zhí)行 for 內部語句。
3 i++:i 自加 1。
從上面圖片可以看到 第一輪: 第 1 步:初始化 i=0(i 賦值等于 0)。 第 2 步:判斷 i 是否少于 3。 第 3 步:現(xiàn)在 i=0 是少于 3,就執(zhí)行 for 花括號的內部語句一次。
第 4 步:當執(zhí)行完一次內部語句后,i++(i++的意思就是 i 自己加 1)。
第二輪:
第 5 步:因為上面 i 從 0 加了一次,現(xiàn)在 i=1。 第 6 步:判斷 i 是否少于 3。 第 7 步:現(xiàn)在 i=1 是少于 3,就執(zhí)行 for 花括號的內部語句一次。
第 8 步:當執(zhí)行完一次內部語句后,i++(i++的意思就是 i 自己加 1)。
第三輪:
第 9 步:因為上面 i 從 1 加了一次,現(xiàn)在 i=2。 第 10 步:判斷 i 是否少于 3。 第 11 步:現(xiàn)在 i=1 是少于 3,就執(zhí)行 for 花括號的內部語句一次。 第 12 步:當執(zhí)行完一次內部語句后,i++(i++的意思就是 i 自己加 1)。
第四輪:
第 13 步:因為上面 i 從 2 加了一次,現(xiàn)在 i=3。 第 14 步:判斷 i 是否少于 3。 第 15 步:現(xiàn)在 i=3 不少于 3,就不執(zhí)行 for 內部語句了,退出 for 語 句繼續(xù)往下面執(zhí)行。
1.043.jpg (15.18 KB, 下載次數(shù): 123)
下載附件
2017-5-20 17:27 上傳
要點:
1 當 for 初始化完一次后,就沒有它的事了。
2 因為 i 初始化是 0,從第 0 次開始執(zhí)行,就算 i<3 也是執(zhí)行 3 次(第
0 次,第 1 次,第 2 次,共三次)
3 i++是 i 自加 1 的意思。
如果上面的理解。 那么
for(i=3;i>0;i--)
{ P1=0xfe; }
也是一樣的原理,這里是 i 首先等于 3,如果 i>0,就執(zhí)行內部語句, 然后 i--,這里是 i 自減 1 次。這個也是共執(zhí)行 3 次,執(zhí)行完后就退出 for 語句
通過以上步驟,這個 for 語句就執(zhí)行完了,單片機在執(zhí)行這個 for
語句的時候是需要時間的,上面 i 的初值較小,所以執(zhí)行的步數(shù)就少,
當我們給 i 賦的初值越大,它執(zhí)行所需的時間就越長,因此我們就可
以利用單片機執(zhí)行這個 for 語句的時間來作為一個簡單延時語句。
很多初學者容易犯的錯誤是,想用 for 語句寫一個延時比較長的語句, 那么他可能會這樣寫:
unsigned char i;(unsigned char 無符號字符型,這是是定義 i 為無 符號字符型,數(shù)值范圍是 0~255)
for(i=0;i<3000;i--)
{
;
}
但是結果卻發(fā)現(xiàn)這樣寫并不能達到延長時間的效果,因為在這里 i 是 一個字符型變量,它的最大值為 255,當你給它賦一個比最大值都大 的數(shù)時,這里 i 賦值是 3000,程序自然就出錯誤了。
因此我們尤其要注意,每次給變量賦初值時,都要首先考慮變量類型, 然后根據(jù)變量類型賦一個合理的值,我們所指的變量類型,就是字符
型(8 位),和整型(16 位),等,而且這兩個在 51 單片機最常用,
理解這兩個,其它的都已收入囊中。
如果我們想用 for 語句做一個秒的延時,我們該怎么寫呢? 秒是我們日常用的時間單位,如果單片機也用秒的時間來一句句執(zhí)行 程序語句,這樣就非常沒有效率,還不如直接用人手操作,我們創(chuàng)造 出單片機代替人手的根本原因,就是讓它自動化,而且快速。
那單片機到底有多快?
我們用 s(秒),單片機用的時間是 us(微秒) 而且
1s=1000ms=1000000us
1 秒=1000 毫秒=1 百萬微秒。 很明顯,單片機用的時間是我們的時間的 1 百萬倍。
如果我們知道單片機執(zhí)行一條語句需要多少時間,就可以用 for 語句 編寫出一個一秒的延時程序了。
我們來看看執(zhí)行一個分號需要多少時間。因為晶振是決定時間的,我 們單片機常用的是 11.0592M,想計算準確的時間,先在軟件里面設 置一下。
1.044.jpg (37.26 KB, 下載次數(shù): 108)
下載附件
2017-5-20 17:27 上傳
右擊 target,點 option for target ,點 target,在 xtal 窗口輸入“11.0592”,
后點確定。
然后通過 keil 軟件——start/stop debug 可以監(jiān)測到程序執(zhí)行流程,進 入 debug(調試)后(看下圖),按鍵盤F10 或者 F11 一步步執(zhí)行, F10 是跨越式執(zhí)行,F(xiàn)11 是細節(jié)語句執(zhí)行,說的多不如動手試一試, 就會明白很多了。
1.045.jpg (28.62 KB, 下載次數(shù): 102)
下載附件
2017-5-20 17:27 上傳
來看看執(zhí)行分號之前的時間。
1.046.jpg (32.58 KB, 下載次數(shù): 114)
下載附件
2017-5-20 17:27 上傳
從上圖可以看到,執(zhí)行一個分號之前的時間是,0.00044162 s(左邊 的 sec 那里看到),0.00044162 s=0.00044162s*100 萬=441.62us(小數(shù) 點向右移六位就行)
執(zhí)行一次分號后的時間。
1.047.jpg (31.25 KB, 下載次數(shù): 115)
下載附件
2017-5-20 17:27 上傳
從 上 圖 可 以 看 到, 執(zhí) 行 完 一 次 分號 之 后 的 時 間 是: 0.00044596
s=445.96us
分號之前的時間=441.62us 分號之后的時間=445.96us 分號用的時間=445.96us - 441.62us=4.34us。 所以執(zhí)行一次分號的時間是 4.34 微秒。
從我們上面圖片程序可以看到。
For(j=0;j<230;j++)
{
;
}
為什么是執(zhí)行 230 次分號呢?
因為 230*4.34us(一次分號的時間)= 998.2us=0.9982ms 約等于 1ms,
(因為 1s=1000ms,1ms=1000us,牢記這個時間關系)
現(xiàn)在我們知道。
For(j=0;j<230;j++)
{
;
}
這個 for 語法是執(zhí)行了 1ms(1 毫秒)的時間,但是這還沒有達到我 們想要的 1S 的時間,或許有些朋友很聰明可以想出,把這個 1ms 執(zhí) 行多 1000 次不就是 1S 的時間了?
好家伙,現(xiàn)在動手。
for(i=0;i<1000;i++)
{
For(j=0;j<230;j++)
{
;
}
}
1.048.jpg (21.66 KB, 下載次數(shù): 103)
下載附件
2017-5-20 17:27 上傳
很明顯,C 語言是可以用于內嵌語句執(zhí)行的,從上面圖片不難看到, 執(zhí)行完 230 次分號后(花 1ms),還要重復執(zhí)行 1000 次 1ms 就是 1s 了。
一盞燈的一秒亮與滅
目標:一盞燈的一秒亮與滅
1 電路流程圖:
2 元件特性 發(fā)光二極管的原理
正極這邊為高電平,負極為低電平,發(fā)光二極管就行,兩邊為高電平, 發(fā)光二極管就不亮。 。
3 程序流程的概括
1.049.jpg (19.32 KB, 下載次數(shù): 109)
下載附件
2017-5-20 17:27 上傳
從上面圖片可以看到,讓一只燈亮滅的原理還是比如容易的,首先是 點亮一只燈,然后一秒延時,再滅燈,再一秒延時,再回到點亮一只 燈這樣無限循環(huán)的重復。
來看看程序。
#include //頭文件
#define uchar unsigned char //把 unsigned char 命名字為 uchar
#define uint unsigned int //把 unsigned int 命名字為 uchar
uint i; //整型 i 變量
uchar j; //字符型 j 變量
sbit led=P1^0; //把 P1 的第 0 個位命名字為 led
main() //主函數(shù)入口
{
while(1) //無限循環(huán)入口
{
led=0; //點亮 P1.0
for(i=0;i<1000;i++) //延時 1 秒
{
for(j=0;j<230;j++)
{
;
}
}
led=1; 滅燈
for(i=0;i<1000;i++) 延時一秒
{
for(j=0;j<230;j++)
{
;
}
}
}
}
看看這前面部分是什么東西
#include //頭文件
#define uchar unsigned char //把 unsigned char 命名字為 uchar
#define uint unsigned int //把 unsigned int 命名字為 uchar uint i; //整型 i 變量 uchar j; //字符型 j 變量
sbit led=P1^0; //把 P1 的第 0 個位命名字為 led
#include //頭文件 頭文件每個程序開頭肯定有的。
#define 也很好理解的,也是作命名字用,因為當引入頭文件 reg52
后,單片機也只是知道什么是 unsigned char,unsigned int 等。
而我們覺得太長不好寫,就有了#define uchar unsigned char ,把 unsigned char(無符號字符型)命名字為uchar,#define uint unsigned int 也是同樣的道理,uint(無符號整型)
1.050.jpg (10.83 KB, 下載次數(shù): 105)
下載附件
2017-5-20 17:27 上傳
還記得我們上面學過的 8 位,16 位嗎?8 個位的二進制最大的數(shù)是十 進制 255,當超過 255 后,它就又會回歸到 0重新開始,而我們的 uchar 就是用于表明是 8 個位的水杯(最大十進制數(shù)是 255)。
而 uint 是 16 位的水杯,最大的十進制數(shù)可以表達到 65535,6 萬多。
那么現(xiàn)在 uint i,和 uchar j 現(xiàn)在明白了麼?
uint i,聲明一個 16 位的變量 i,方便程序內用。I 的數(shù)值范圍在 0~65535
內都可以。
uchar j,聲明一個 8 位的變量 j,方便程序內用。J 的數(shù)值范圍在 0~255
內都可以。
聲明完后,I, j 這些變量位置哪里來?當你定義好,單片機 RAM(動 態(tài)存儲器)自動分配的,這不用你操心。
從上面程序你可以看到 I, j 在哪里用嗎? 延時程序 for(i=0;i<1000;i++) 延時一秒
{
for(j=0;j<230;j++) 延時 1 毫秒
{
;
}
}
很明顯,j 少于 255,所以用 uchar 就行,i>255<6 萬用 uint
sbit led=P1^0; 也很好理解的,聲名特殊功能寄存器的位,把 P1.0 這 個位命名字為 led,現(xiàn)在看到^這個符號了吧?很常用。
命名字方式,我們學過四種。 特殊功能寄存器的位命名:sbit 特殊功能寄存器 8 位地址命名:sfr P1=0x90; 特殊功能寄存器 16 位地址命名:sfr16 TC=0x91;(連續(xù)用 0x91,0x92 這兩個地址,只聲名第一個地址就可以)Define:把什么名字命什么名字(多數(shù)用于英文字母的定義,方便我 們記憶運用)
再看看我們程序編寫時常用的四種(牢記)。
1 特殊功能寄存器位命名:sbit
2 Define:把什么名字命什么名字(多數(shù)用于英文字母的定義,方便 我們記憶運用)
3 Uchar 字符型。
4 Uint 整型。
如何區(qū)分特殊功能寄存器和普通寄存器?原理很簡單的,當你這個寄 存器是特殊功能的,比如 P1(廠家告訴你這個寄存器有什么用,就
是特殊功能),如果定義它的位來運用,就用 sbit(特殊功能寄存器
位命名)。
如果廠家沒有告訴你這個寄存器具體有什么用,就是普通寄存器,比 如 uchar i, uint j,等等,當你聲明好后,單片機會自動分配寄存器的, 如果你想用普通的位,直接用 bit 就行,如 bit flag,為 flag 這個名字 定義為位功能,這個時候 flag 也是只能在 0~1,這兩個數(shù)內變化,現(xiàn) 在稍微了解就行,以后用就的時候你就明白了。
再來看看程序,和我們的流程圖是一模一樣。
1.051.jpg (28.44 KB, 下載次數(shù): 102)
下載附件
2017-5-20 17:27 上傳
從上面圖片我們發(fā)現(xiàn),延時程序是一模一樣的,那我們有沒有方法把
同樣的代碼放在別處,需要的時候才調用出來,這樣就可以減少很多 代碼重寫,不用浪費那么多單片機內部資源。
有兩種方式: 第一種是在主程序(main)上面書寫。 第二種是在主程序(main)下面書寫。
來看看第一種,在主程序上面書寫。
1.052.jpg (37.92 KB, 下載次數(shù): 91)
下載附件
2017-5-20 17:27 上傳
從上面圖片可以看到,當定義好頭文件后和其它相應的名字后,子程 序就可以開始書寫了。
延時子程序講解
void del_ms(uint k) // 延時子程序
{
for(i=0;i<k;i++)[ size][="" align]
{
for(j=0;j<230;j++)
{
;
}
}
}
Void 是空的意思,相當于從這個子程序中,沒有東西(數(shù)值)返回的 意思吧,現(xiàn)在不理解,你可以暫時忽略它,直接書寫就行,以后你見 到有東西(數(shù)值)返回的,對比一下,就一目了然了。 del_ms(uint k)
del_ms 是子程序名字, del 是我們把英文單詞 delay(延時)的縮寫, 加_符號,再加 ms(毫秒),這樣從字面上就可以直接理解到是延時 1
毫秒的子程序,其實這個子程序名字你可以自己定義的,以后慢慢你
就懂。
叫做 ms 的原因是現(xiàn)在我們沒有像上面那樣直接賦值 1000 次的一毫 秒延時,而是把這個 1000 變成可變的數(shù)字,如下圖所示的 uint k:
1.053.jpg (11.2 KB, 下載次數(shù): 130)
下載附件
2017-5-20 17:27 上傳
可以看到,現(xiàn)在我們上面的 1000 改變成可變的變量整型 k,uint(無符 號整型)可在 0~65535 之間隨意賦值,定義完后,k 就可以在 0~65535 隨意賦值。
如果是少于 255 的話,用無符號字符型(uchar)就行,這里大于 255, 就用了整型,而且這個 k,只能在延時子程序花括號范圍內使用,就 是
del_ms(uint k)
{
K 在這里隨意使用,在這范圍外使用是無效的。
}
你在主程序(main)內定義,就是主程序(main)花括號內可以使用,其 它范圍無效,如果你是一開頭就定義了,子程序和主程序都可以使用。
就是下面的 uint i 和 ichar j 可以在子程序和主程序的花括號里隨意使 用,理解沒?
1.054.jpg (24.7 KB, 下載次數(shù): 142)
下載附件
2017-5-20 17:27 上傳
回歸正傳。
1.055.jpg (21.46 KB, 下載次數(shù): 123)
下載附件
2017-5-20 17:27 上傳
del_ms 這名字在英文或符號之間(不是中文就行,因為這軟件不懂
中文),你可以隨你懂的命名字,比如你不太懂英文,直接寫 yan_shi
也行,只要做到一看這名字就知道是什么樣的子程序就行。
延時子程序調用方法,在主程序內調用。
1.056.jpg (19.46 KB, 下載次數(shù): 123)
下載附件
2017-5-20 17:27 上傳
del_ms(多少數(shù)字你定義);
記得后面不要漏了分號,這樣做只要是告訴軟件,你已經(jīng)寫完一條語 句,不然的話,程序會出錯。
第二種:子程序在主程序下面寫。
1.057.jpg (37.45 KB, 下載次數(shù): 123)
下載附件
2017-5-20 17:27 上傳
這種方式除了位置不同和加多一句“告訴單片機主程序”下面有子程
序外,其它一樣,如果你在主程序下面寫子程序而沒有首先告訴單片 機,程序編譯中會出錯的,你可以自己試試,試過就知道了。
詳細請打開編程軟件和仿真軟件瀏覽效果。
本實驗配套的的仿真工程文件和源碼下載地址: http://www.zg4o1577.cn/bbs/dpj-85401-1.html
|
|