前言
在之前的教程中,我們成功搭建了開發(fā)環(huán)境,初步對開發(fā)板的GPIO口有了一定的了解,在本教程中,我們將帶領大家制作第一個工程,就是通過GPIO口來點亮一盞LED小燈!
一、LED簡介
LED 即發(fā)光二極管。它具有單向?qū)щ娦裕ㄟ^5mA 左右電流即可發(fā)光,電流越大,其亮度越強,但若電流過大,會燒毀二極管,一般我們控制在3 mA-20mA之間,通常我們會在LED 管腳上串聯(lián)一個電阻,目的就是為了限制通過發(fā)光二極管的電流不要太大,因此這些電阻又可以稱為“限流電阻”。當發(fā)光二極管發(fā)光時,測量它兩端電壓約為1.7V,這個電壓又叫做發(fā)光二極管的“導通壓降”。
下圖左右分別為直插式發(fā)光二極管和貼片式發(fā)光二極管實物圖。發(fā)光二極管正極又稱陽極,負極又稱陰極,電流只能從陽極流向陰極。直插式發(fā)光二極管長腳為陽極,短腳為陰極( 長正短負、大負小正 )。仔細觀察貼片式發(fā)光二極管正面的一端有彩色標記通常有標記的一端為陰極。
二、硬件設計
開發(fā)板上LED 模塊電路如下圖所示:
在前面我們介紹過如何查看原理圖,相同網(wǎng)絡標號表示它們是連接在一起的,該模塊獨立,可自由連接單片機IO 口,因此D1-D8 可連接到單片機的P20-P27口。圖中LED 采用 共陽接法 ,即所有LED 陽極管腳接電源VCC,陰極管腳通過一個470 歐的限流電阻接到P2 口上。根據(jù)前面LED 的介紹我們知道,要讓LED 發(fā)光即對應的陰極管腳應該為低電平,若為高電平則熄滅。
如果要想51 單片機控制LED,就必須通過單片機管腳在P2 口上輸出低電平。本教程所要實現(xiàn)的功能是:點亮D1 指示燈。
三、程序設計
#include< reg52.h > //頭文件
sbit LED1=P2^0; //將P2.0管腳定義為LED1
void main()
{
while(1)
{
LED1=0; //LED端口設置為低電平 即點亮LED燈
}
}
main.c 文件內(nèi)代碼非常少也很簡單,首先將51 單片機的頭文件包含進來,然后使用sbit 關鍵字來定義P2.0 管腳,定義好后即可使用LED1 來替代P2.0口的操作。主函數(shù)功能非常簡單,首先讓LED1 為低電平,即P2.0 口輸出為低電平,D1 指示燈即點亮,然后進入while 循環(huán),單片機此時一直在while 內(nèi)循環(huán)操作。當然該條語句也可以放在while 循環(huán)語句內(nèi),同樣會點亮D1 指示燈。在51 單片機程序開發(fā)中,main 函數(shù)內(nèi)通常都會有一個while 循環(huán),在循環(huán)體內(nèi)不斷執(zhí)行我們所要實現(xiàn)的功能。對于僅點亮LED,可以把控制語句放在while 之前來執(zhí)行。
至此,整個程序就編寫完成,我們編譯一下,如下圖所示:
可以看到?jīng)]有錯誤,也沒有警告。
從編譯信息可以看出,我們的代碼占用FLASH 大小為:19 字節(jié),所用的SRAM 大小為:9 個字節(jié)(9+0)。這里我們解釋一下,編譯結果里面的幾個數(shù)據(jù)的意義:
code:表示程序所占用FLASH 的大小。
data:數(shù)據(jù)儲存器內(nèi)部RAM 占用大小。
xdata:數(shù)據(jù)儲存器外部RAM 占用大小。
有了這個就可以知道你當前使用的flash 和sram 大小了。一定要注意的是程序的大小不是.hex 文件的大小,而是編譯后的code 和data 之和。
四、LED 閃爍實驗
如果要實現(xiàn)LED 閃爍,只需循環(huán)讓D1 指示燈先亮一會后熄滅。這里就有一個延時問題,如何來產(chǎn)生延時呢?我們知道單片機執(zhí)行每條代碼指令都是需要時間的,在前面介紹C 語言時講解過循環(huán)語句,因此只需編寫一個循環(huán)函數(shù),讓CPU 不干其它事,專門在那循環(huán)運行即可實現(xiàn)延時功能。依據(jù)人的肉眼余暉效應,延時時間不能太短,否則就無法觀察到LED 閃爍。
void delay_10us(u16 time_us)
{
while(time_us--);
}
上述代碼即為延時函數(shù),通過while 循環(huán)來實現(xiàn)。函數(shù)入口有一個形式參數(shù)ten_us,如果ten_us 等于1,則while 循環(huán)執(zhí)行一次,調(diào)用該函數(shù)延時時間大約10us,當然使用循環(huán)來實現(xiàn)延時,這種延時是不精確的,目前我們先得到個大概的時間即可。
細心的朋友可能會看到函數(shù)形參ten_us 是u16 類型的,這個似乎不是C 語言數(shù)據(jù)類型關鍵字,這是我們重定義的數(shù)據(jù)類型,如下:
typedef unsigned int u16;
typedef unsigned char u8;
使用關鍵字typedef 對系統(tǒng)默認數(shù)據(jù)類型unsigned int 和unsigned char重新命名,主要是方便我們代碼的書寫和變量類型的查看。u16 即代表該變量是16 位的無符號整型數(shù)據(jù),u8 代表該變量是8 位的無符號字符型數(shù)據(jù)。有了這個就知道參數(shù)的傳送范圍,不能超過形參定義的范圍。
下面看下main 函數(shù)代碼,如下:
void main()
{
while(1)
{
LED1=0; //點亮
delay_10us(50000); //延時大概450ms
LED1=1; //熄滅
delay_10us(50000);
}
}
main 函數(shù)內(nèi)實現(xiàn)功能很簡單,在while 循環(huán)內(nèi)不斷間隔一定時間點亮LED1和熄滅LED1,這樣即可實現(xiàn)D1 指示燈閃爍。細心的朋友可能會問,前面delay_10us 函數(shù)形參為1 時大約是10us,那現(xiàn)在實參傳輸50000,不應該是500ms嗎,為什么注釋寫的是450ms 呢?這里還得回到剛才話題,使用循環(huán)來延時只是獲得一個大概的時間,并不能精確,如需精確延時,后期我們會學習定時器。此處就不用糾結這個問題。
#include< reg52.h >
typedef unsigned int u16;
typedef unsigned char u8;
sbit LED1=P2^0;
void delay_10us(u16 time_us)
{
while(time_us--);
}
void main()
{
while(1)
{
LED1=0; //點亮
delay_10us(50000); //延時大概450ms
LED1=1; //熄滅
delay_10us(50000);
}
}
評論
查看更多