0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

基于STC8A8K64S4A12開發(fā)板的GPIO點燈實驗

CHANBAEK ? 來源:百家號電子友人號 ? 作者:百家號電子友人號 ? 2023-11-15 16:52 ? 次閱讀

前言

最近空閑時間比較多,準備說說STC8A8K64S4A12開發(fā)板。 實驗做起來——先從GPIO點燈開始。

一、硬件電路原理

1.開發(fā)板指示燈硬件電路

LED(Light Emitting Diode)是發(fā)光二極管的簡稱,在很多設(shè)備上常用它來做為一種簡單的人機接口,如網(wǎng)卡、路由器等通過LED向用戶指示設(shè)備的不同工作狀態(tài)。所以,我們習(xí)慣把這種用于指示狀態(tài)的LED稱為LED指示燈
STC8A8K64S4A12開發(fā)板上設(shè)計了4個LED指示燈,我們可以通過編程驅(qū)動LED指示燈點亮、熄滅、閃爍,從而達到狀態(tài)指示的目的,LED指示燈驅(qū)動電路如下圖所示。

圖1:LED指示燈驅(qū)動電路

LED指示燈驅(qū)動電路是一個很常見、簡單的電路,同時它也是一個典型的單元電路,對于初學(xué)者來說,類似常用的典型電路必須要掌握,不但要知其然、還要知其所以然。
接下來,我們來分析一下這個簡單的LED指示燈驅(qū)動電路。
LED驅(qū)動電路設(shè)計的時候,要考慮兩個方面:控制方式和限流電阻的選取。

2.控制方式

LED指示燈控制方式分為高電平有效和低電平有效兩種,高電平有效是單片機GPIO輸出高電平時點亮LED,低電平有效是單片機GPIO輸出低電平時點亮LED。

2.1.低電平有效的控制方式

LED控制-低電平有效原理

低電平有效控制方式中,當(dāng)單片機的GPIO輸出低電平(邏輯0)的時候,LED和電阻R上的壓降等于(VCC-VCCIO = 3.3V),這時候,因為存在壓降,同時,這個電路是閉合回路,這就達到了電流產(chǎn)生的兩個要素,LED上會有電流流過,LED被點亮。
當(dāng)單片機的GPIO輸出高電平(邏輯1)的時候,LED和電阻R上的壓降等于(VCC-VCCIO = 0V),這時候,因為LED上沒有壓降,當(dāng)然不會有電流流過,所以LED熄滅。

2.2.高電平有效的控制方式

圖3:LED控制-高電平有效原理

高電平有效控制方式中,由單片機的GPIO輸出電流驅(qū)動LED,當(dāng)單片機的GPIO輸出高電平(邏輯1)的時候,LED上存在壓降,因為電路是閉合回路,所以會有電流流過,這時LED被點亮,但要注意,單片機的GPIO要能提供足夠的輸出電流,否則,電流過小,會導(dǎo)致LED亮度很弱。
當(dāng)單片機的GPIO輸出低電平(邏輯0)的時候,LED和電阻R上的壓降等于0V,這時候,LED上沒有電流流過,LED熄滅。

2.3.選擇哪種方式來控制LED

絕大多數(shù)情況下,我們會選擇使用低電平有效的控制方式,如艾克姆科技STC8A8K64S4A12開發(fā)板中的LED指示燈就是低電平有效。這樣設(shè)計指示燈驅(qū)動電路的好處是:

① 單片機GPIO口低電平時的灌入電流一般比高電平時的拉電流要大,能提供足夠的電流驅(qū)動LED。
② 單片機上電或復(fù)位啟動時,GPIO口一般都是高阻輸入,用低電平有效的控制方式可以確保LED在上電或復(fù)位啟動時處于熄滅狀態(tài)。

3.LED限流電阻的選取

3.1.限流電阻的計算

圖4:LED限流電阻計算

由上圖可以看出,LED限流電阻的計算公式如下:

其中,VCC=3.3V,VF是LED的正向壓降,LED的數(shù)據(jù)手冊都會給出正向電流為2mA時測試的VF的范圍,下圖是一款0805 LED的實物圖和參數(shù)。在參數(shù)表中可以看到正向電流為2mA時VF最小值是2.5V,典型值是2.7V,最大值是3.6V。

圖5:封裝0805的LED

圖6:0805 LED參數(shù)圖

計算時VF的值可以用典型值來進行估算,對于電流,需要根據(jù)經(jīng)驗值和對LED亮度的要求相結(jié)合來確定,一般經(jīng)驗值是(1~5)mA,不過要注意,只要亮度符合自己的要求,電流低于1mA也沒有任何問題。
電流為1mA時限流電阻值計算如下:

3.2.限流電阻的選擇

根據(jù)上一節(jié)對限流電阻計算公式的描述及對選擇的封裝0805的指示燈參數(shù)的了解,計算出供電3.3V電流1mA時的限流電阻理論值是600Ω,供電5V電流1mA時的限流電阻理論值是2.3KΩ,為保證供電為3.3V時指示燈夠亮但同時5V供電指示燈又不宜過亮,選擇一個比較常見的阻值2K作為限流電阻。
還有一點需要強調(diào)的是,不同顏色的指示燈在即使同一亮度時所需的限流電阻不一定是相同的。這也是為什么有些產(chǎn)品的面板上有不同顏色的指示燈,各指示燈所使用的限流電阻不一樣的原因。

4.STC8A8K64S4A12系列單片機GPIO口

STC8A8K64S4A12系列單片機GPIO口數(shù)量取決于芯片引腳的個數(shù),芯片引腳個數(shù)和芯片封裝密切相關(guān)。正常情況下,GPIO口數(shù)量是所選擇單片機引腳個數(shù)減去5,因為單片機需要2個引腳作為供電引腳(電源正VCC、電源負GND),ADC外設(shè)會占用3個引腳(電源正ADC_Avcc、電源負ADC_Agnd、參考電壓AVref)。

4.1.芯片封裝

封裝,Package,是把集成電路裝配為芯片最終產(chǎn)品的過程,簡單地說,就是把Foundry生產(chǎn)出來的集成電路裸片(Die)放在一塊起到承載作用的基板上,把管腳引出來,然后固定包裝成為一個整體。
STC8A8K64S4A12系列有多種封裝,廠家批量常見的芯片封裝是:LQFP44、LQFP48和LQFP64S。

4.2.GPIO口工作模式

STC8A8K64S4A12系列單片機所有GPIO口均有4種工作模式:準雙向口/弱上拉(標準8051輸出口模式)、推挽輸出/強上拉、高阻輸入(電流既不能流入也不能流出)、開漏輸出。下面針對內(nèi)部結(jié)構(gòu)圖進行分析。
■ 準雙向口/弱上拉模式:

圖7:GPIO準雙向口/弱上拉模式內(nèi)部框圖

1)準雙向口(弱上拉) 輸出類型可用作輸出和輸入功能而不需要重新配置端口輸出狀態(tài)。這是因為準雙向口有3個上拉晶體管可適應(yīng)輸入輸出不同的需要。
2)手冊中有這樣一句話:準雙向口(弱上拉)在讀外部狀態(tài)前,要先鎖存為‘1’,才可讀到外部正確的狀態(tài)。下圖分別就鎖存數(shù)據(jù)為‘1’和‘0’時進行了分析。

圖8:GPIO準雙向口/弱上拉模式內(nèi)部框圖分析

3)由上圖分析可知,準雙向口(弱上拉)在讀外部狀態(tài)前,如果鎖存為‘0’,則GPIO引腳狀態(tài)被固定,無法讀到外部正確的狀態(tài)。

■ 推挽輸出/強上拉模式:

圖9:GPIO推挽輸出/強上拉模式內(nèi)部框圖

1)強推挽輸出配置的下拉結(jié)構(gòu)與開漏輸出以及準雙向口的下拉結(jié)構(gòu)相同,但當(dāng)鎖存器為1時可提供持續(xù)的強上拉。所以,推挽輸出一般用于需要更大驅(qū)動電流的情況。
2)在控制LED時,如果采用的是高電平有效的控制方式,則控制LED的單片機GPIO口必須配置成推挽輸出/強上拉模式方可。
■ 高阻輸入模式:

圖10:GPIO高阻輸入模式內(nèi)部框圖

1)因帶有一個施密特觸發(fā)輸入以及一個干擾抑制電路,GPIO配置為高阻輸入時,電流既不能流入也不能流出GPIO口。
2)在很多STC相關(guān)的文檔中有說的高阻態(tài)即是GPIO口被設(shè)置了高阻輸入模式。
■ 開漏輸出模式:

圖11:GPIO開漏輸出模式內(nèi)部框圖

1)開漏模式既可以讀外部狀態(tài)也可以對外輸出高電平或低電平。
2)如果要正確讀外部狀態(tài)或需要對外輸出高電平時,需外加上拉電阻。

二、軟件編寫

1.GPIO寄存器匯集

STC8A8K64S4A12系列單片機提供了40個用于操作GPIO的寄存器,如下表所示:

表2:

2.寄存器解析

首先普及一個常用知識點:為什么說STC8A8K64S4A12系列單片機是8位單片機呢?這個8位指的是什么?
一般來說某個單片機或微處理器是幾位,指的是“機器字長”。每個單片機或微處理器最基本的功能是算術(shù)邏輯運算,而算術(shù)邏輯運算的主要部件是“算術(shù)邏輯單元(ALU)”。機器字長即是指ALU的數(shù)據(jù)位寬,也就是指令能直接處理的二進制位數(shù)。
通常單片機或微處理器的寄存器的位寬等于ALU的位寬,所以一般可通過識別單片機或微處理器寄存器的位寬來確定該單片機或微處理器是多少位的。我們所接觸的STC的單片機,其寄存器都是8位的,所以STC的單片機都是8位的單片機。以后學(xué)習(xí)STM32F103系列的微處理器,其寄存器是32位的,所以會說STM32F103系列微處理器是32位的。

2.1.端口數(shù)據(jù)寄存器

下圖是對端口數(shù)據(jù)寄存器P0、P1、P2、P3、P4、P5、P6、P7的描述,端口數(shù)據(jù)寄存器各位代表對應(yīng)端口的IO口,比如,P7端口數(shù)據(jù)寄存器B0位代表P7.0口,B7位代表P7.7口。

圖12:端口數(shù)據(jù)寄存器

2.2.端口配置寄存器

端口配置寄存器PnM1和PnM0都是8位的寄存器,PnM1和PnM0寄存器必須組合使用才能正確地配置IO口工作模式。
STC8A8K64S4A12系列單片機所有GPIO口均有4種工作模式:準雙向口/弱上拉(標準8051輸出口模式)、推挽輸出/強上拉、高阻輸入(電流既不能流入也不能流出)、開漏輸出。每個GPIO口工作模式由PnM1和PnM0寄存器中的相應(yīng)位控制。如下圖。

圖13:GPIO端口配置

3.GPIO驅(qū)動LED實驗(寄存器版本)

3.1.頭文件引用和路徑設(shè)置

■ 需要宏定義部分及引用的頭文件
因為在“main.c”文件中使用了STC8的頭文件“STC8.H”,所以需要引用下面的頭文件。在頭文件“STC8.H”中需要確定主時鐘取值,所以宏定義主時鐘值。

1.#define  uint16   unsigned int    
2.#define  uint8    unsigned char    

在程序設(shè)計中會用到定義變量的類型,為了定義變量方便,將較為復(fù)雜的“unsigned int”和“unsigned char ”進行了宏定義。

#define  uint16   unsigned int    
#define  uint8    unsigned char   

這樣,再定義變量時可直接使用“uint16”和“uint8”來取代“unsigned int”和“unsigned char ”即可。

■ 需要包含的頭文件路徑
本例需要包含的頭文件路徑如下表:

MDK中點擊魔術(shù)棒,打開工程配置窗口,按照下圖所示添加頭文件包含路徑。

圖14:添加頭文件包含路徑

3.2.編寫代碼

首先介紹下毫秒級的延時函數(shù)。控制指示燈亮和滅需要中間有足夠的間隔時間,這個間隔一般通過延時函數(shù)實現(xiàn)。微秒級的延時時間很難控制,這和主頻大小及其精度有密切關(guān)系。但毫秒級的延時還是可以控制的,下面給出在11.0592MHZ下的毫秒延時函數(shù),僅供參考。

代碼清單:毫秒延時函數(shù)

1./************************************** 
2.功能描述:延時函數(shù) 
3.入口參數(shù):uint16 x ,該值為1時,延時1ms 
4.返回值:無 
5.***************************************/  
6.void delay_ms(uint16 x)   
7.{    
8.    uint16 j,i;     
9.    for(j=0;j

在對端口數(shù)據(jù)寄存器介紹時我們簡單介紹過控制單片機GPIO的過程。需要再說明的地方是關(guān)于兩個關(guān)鍵字“sfr”和“sbit”。
sfr是Keil C51為能直接訪問51內(nèi)核單片機中的SFR而提供了一個關(guān)鍵詞,其用法是:
1)sfrt 變量名=地址值。
sbit是定義特殊功能寄存器的位變量。其用法有三種:
1)sbit 位變量名=地址值。
2)sbit 位變量名=SFR名稱^變量位地址值。
3)sbit 位變量名=SFR地址值^變量位地址值。

程序清單:頭文件“STC8.H”定義P0端口部分

1.sfr P7          =   0Xf8;    
2.sbit P70        =   P7^0;  
3.sbit P71        =   P7^1;  
4.sbit P72        =   P7^2;  
5.sbit P73        =   P7^3;  
6.sbit P74        =   P7^4;  
7.sbit P75        =   P7^5;  
8.sbit P76        =   P7^6;  
9.sbit P77        =   P7^7; 
}  

然后,在主函數(shù)中先對P7.2口進行模式配置,針對P7.2口是被配置了準雙向口,后主循環(huán)中將用戶指示燈D3點亮,延時200ms,再熄滅,再延時200ms的過程,這樣可觀察到指示燈D3不停閃爍的現(xiàn)象。

代碼清單:主函數(shù)

1.int main()  
2.{  
3.    P7M1 &= 0xFB;    P7M0 &= 0xFB;    //設(shè)置P7.2為準雙向口  
4.    // P7M1 &= 0xFB;  P7M0 |= 0x04;      //設(shè)置P7.2為推挽輸出
5.    // P7M1 |= 0x04;  P7M0 &= 0xFB;      //設(shè)置P7.2為高阻輸入  
6.    //  P7M1 |= 0x04;  P7M0 |= 0x04;    //設(shè)置P7.2為開漏輸出  
7.      
8.  while(1)  
9.  {  
10.        P72=0;        //控制P7.2端口輸出低電平,點亮用戶指示燈D3  
11.        delay_ms(200);  
12.        P72=1;        //控制P7.2端口輸出高電平,熄滅用戶指示燈D3  
13.        delay_ms(200);  
14.    }  
15.} 

4.GPIO驅(qū)動LED實驗(庫函數(shù)版本)

4.1.工程需要用到的c文件

本例需要用到的c文件如下表所示,工程需要添加下表中的c文件。

該GPIO.c是STC官方提供的有關(guān)GPIO配置的函數(shù)庫。

4.2.頭文件引用和路徑設(shè)置

■ 需要引用的頭文件
因為在“main.c”文件中使用了GPIO相關(guān)的庫,所以需要引用下面的頭文件。

1.#include    "GPIO.h"  

■ 需要包含的頭文件路徑
本例需要包含的頭文件路徑如下表:

MDK中點擊魔術(shù)棒,打開工程配置窗口,按照下圖所示添加頭文件包含路徑。

圖15:添加頭文件包含路徑

4.3.編寫代碼

首先在GPIO口初始化函數(shù)中調(diào)用庫函數(shù)GPIO_Inilize完成P7.2口的工作模式配置,即配置P7.2為準雙向口。

代碼清單:GPIO口初始化函數(shù)

1./************************************** 
2.功能描述:GPIO口初始化 
3.入口參數(shù):無 
4.返回值:無 
5.***************************************/  
6.void    GPIO_config(void)  
7.{  
8.    GPIO_InitTypeDef  GPIO_InitStructure;  
9.   
10.    //設(shè)置P7.2口工作模式  
11.    GPIO_InitStructure.Mode=GPIO_PullUp;      //配置P7.2口為準雙向口  
12.      //GPIO_InitStructure.Mode=GPIO_OUT_PP;    //配置P7.2口為推挽輸出(強上拉)  
13.      //GPIO_InitStructure.GPIO_HighZ;          //配置P7.2口為高阻輸入  
14.      //GPIO_InitStructure.Mode=GPIO_OUT_OD;    //配置P7.2口為開漏輸出  
15.    GPIO_InitStructure.Pin=GPIO_Pin_2;  
16.    GPIO_Inilize(GPIO_P7,&GPIO_InitStructure);  
17.   
18.}  

打開庫函數(shù)GPIO_Inilize后會發(fā)現(xiàn),配置P7.2口實際最終操作還是P0M0和P0M1寄存器。代碼如下。

程序清單:頭文件“GPIO.c”定義GPIO初始化庫函數(shù)

1.//========================================================================  
2.// 函數(shù): uint8    GPIO_Inilize(uint8 GPIO, GPIO_InitTypeDef *GPIOx)  
3.// 描述: 初始化IO口.  
4.// 參數(shù): GPIOx: 結(jié)構(gòu)參數(shù),請參考gpio.h里的定義.  
5.// 返回: 成功返回0, 空操作返回1,錯誤返回2.  
6.//========================================================================  
7.uint8   GPIO_Inilize(uint8 GPIO, GPIO_InitTypeDef *GPIOx)  
8.{  
9.    if(GPIO > GPIO_P7)               return 1;   //空操作  
10.    if(GPIOx->Mode > GPIO_OUT_PP) return 2;   //錯誤  
11.  
12.    if(GPIO == GPIO_P0)  
13.    {  
14.        if(GPIOx->Mode == GPIO_PullUp)       P0M1 &= ~GPIOx->Pin, P0M0 &= ~GPIOx->Pin;  //上拉準雙向口  
15.        if(GPIOx->Mode == GPIO_HighZ)          P0M1 |=  GPIOx->Pin,   P0M0 &= ~GPIOx->Pin;  //浮空輸入  
16.        if(GPIOx->Mode == GPIO_OUT_OD)       P0M1 |=  GPIOx->Pin, P0M0 |=  GPIOx->Pin;  //開漏輸出  
17.        if(GPIOx->Mode == GPIO_OUT_PP)       P0M1 &= ~GPIOx->Pin, P0M0 |=  GPIOx->Pin;  //推挽輸出  
18.    }  
19.    if(GPIO == GPIO_P1)  
20.    {  
21.        if(GPIOx->Mode == GPIO_PullUp)       P1M1 &= ~GPIOx->Pin, P1M0 &= ~GPIOx->Pin;  //上拉準雙向口  
22.        if(GPIOx->Mode == GPIO_HighZ)          P1M1 |=  GPIOx->Pin,   P1M0 &= ~GPIOx->Pin;  //浮空輸入  
23.        if(GPIOx->Mode == GPIO_OUT_OD)       P1M1 |=  GPIOx->Pin, P1M0 |=  GPIOx->Pin;  //開漏輸出  
24.        if(GPIOx->Mode == GPIO_OUT_PP)       P1M1 &= ~GPIOx->Pin, P1M0 |=  GPIOx->Pin;  //推挽輸出  
25.    }  
26.    if(GPIO == GPIO_P2)  
27.    {  
28.        if(GPIOx->Mode == GPIO_PullUp)       P2M1 &= ~GPIOx->Pin, P2M0 &= ~GPIOx->Pin;  //上拉準雙向口  
29.        if(GPIOx->Mode == GPIO_HighZ)          P2M1 |=  GPIOx->Pin,   P2M0 &= ~GPIOx->Pin;  //浮空輸入  
30.        if(GPIOx->Mode == GPIO_OUT_OD)       P2M1 |=  GPIOx->Pin, P2M0 |=  GPIOx->Pin;  //開漏輸出  
31.        if(GPIOx->Mode == GPIO_OUT_PP)       P2M1 &= ~GPIOx->Pin, P2M0 |=  GPIOx->Pin;  //推挽輸出  
32.    }  
33.    if(GPIO == GPIO_P3)  
34.    {  
35.        if(GPIOx->Mode == GPIO_PullUp)       P3M1 &= ~GPIOx->Pin, P3M0 &= ~GPIOx->Pin;  //上拉準雙向口  
36.        if(GPIOx->Mode == GPIO_HighZ)          P3M1 |=  GPIOx->Pin,   P3M0 &= ~GPIOx->Pin;  //浮空輸入  
37.        if(GPIOx->Mode == GPIO_OUT_OD)       P3M1 |=  GPIOx->Pin, P3M0 |=  GPIOx->Pin;  //開漏輸出  
38.        if(GPIOx->Mode == GPIO_OUT_PP)       P3M1 &= ~GPIOx->Pin, P3M0 |=  GPIOx->Pin;  //推挽輸出  
39.    }  
40.    if(GPIO == GPIO_P4)  
41.    {  
42.        if(GPIOx->Mode == GPIO_PullUp)       P4M1 &= ~GPIOx->Pin, P4M0 &= ~GPIOx->Pin;  //上拉準雙向口  
43.        if(GPIOx->Mode == GPIO_HighZ)          P4M1 |=  GPIOx->Pin,   P4M0 &= ~GPIOx->Pin;  //浮空輸入  
44.        if(GPIOx->Mode == GPIO_OUT_OD)       P4M1 |=  GPIOx->Pin, P4M0 |=  GPIOx->Pin;  //開漏輸出  
45.        if(GPIOx->Mode == GPIO_OUT_PP)       P4M1 &= ~GPIOx->Pin, P4M0 |=  GPIOx->Pin;  //推挽輸出  
46.    }  
47.    if(GPIO == GPIO_P5)  
48.    {  
49.        if(GPIOx->Mode == GPIO_PullUp)       P5M1 &= ~GPIOx->Pin, P5M0 &= ~GPIOx->Pin;  //上拉準雙向口  
50.        if(GPIOx->Mode == GPIO_HighZ)          P5M1 |=  GPIOx->Pin,   P5M0 &= ~GPIOx->Pin;  //浮空輸入  
51.        if(GPIOx->Mode == GPIO_OUT_OD)       P5M1 |=  GPIOx->Pin, P5M0 |=  GPIOx->Pin;  //開漏輸出  
52.        if(GPIOx->Mode == GPIO_OUT_PP)       P5M1 &= ~GPIOx->Pin, P5M0 |=  GPIOx->Pin;  //推挽輸出  
53.    }  
54.    if(GPIO == GPIO_P6)  
55.    {  
56.        if(GPIOx->Mode == GPIO_PullUp)       P6M1 &= ~GPIOx->Pin, P6M0 &= ~GPIOx->Pin;  //上拉準雙向口  
57.        if(GPIOx->Mode == GPIO_HighZ)          P6M1 |=  GPIOx->Pin,   P6M0 &= ~GPIOx->Pin;  //浮空輸入  
58.        if(GPIOx->Mode == GPIO_OUT_OD)       P6M1 |=  GPIOx->Pin, P6M0 |=  GPIOx->Pin;  //開漏輸出  
59.        if(GPIOx->Mode == GPIO_OUT_PP)       P6M1 &= ~GPIOx->Pin, P6M0 |=  GPIOx->Pin;  //推挽輸出  
60.    }  
61.    if(GPIO == GPIO_P7)  
62.    {  
63.        if(GPIOx->Mode == GPIO_PullUp)       P7M1 &= ~GPIOx->Pin, P7M0 &= ~GPIOx->Pin;  //上拉準雙向口  
64.        if(GPIOx->Mode == GPIO_HighZ)          P7M1 |=  GPIOx->Pin,   P7M0 &= ~GPIOx->Pin;  //浮空輸入  
65.        if(GPIOx->Mode == GPIO_OUT_OD)       P7M1 |=  GPIOx->Pin, P7M0 |=  GPIOx->Pin;  //開漏輸出  
66.        if(GPIOx->Mode == GPIO_OUT_PP)       P7M1 &= ~GPIOx->Pin, P7M0 |=  GPIOx->Pin;  //推挽輸出  
67.    }  
68.    return 0;   //成功  
}  

然后,在主函數(shù)中先調(diào)用GPIO口初始化函數(shù),后主循環(huán)中將用戶指示燈D3點亮,延時500ms,再熄滅,再延時500ms的過程,這樣可觀察到指示燈D3不停閃爍的現(xiàn)象。

代碼清單:主函數(shù)

1.int main()  
2.{  
3.  GPIO_config();   //設(shè)置P7.2口為準雙向口  
4.      
5.  while(1)  
6.  {  
7.        P72=0;        //控制P7.2端口輸出低電平,點亮用戶指示燈D3  
8.        delay_ms(500);  
9.        P72=1;        //控制P7.2端口輸出高電平,熄滅用戶指示燈D3  
10.        delay_ms(500);  
11.    }  
12.} 

5.流水燈實驗(單個c文件)

5.1.頭文件引用和路徑設(shè)置

本實驗需要用到的頭文件以及添加頭文件包含路徑的方法請參考“實驗2-1-1:GPIO驅(qū)動LED(寄存器版本)”部分。
在程序設(shè)計中重新定義了P2寄存器的位變量P26和P27及P7寄存器的位變量P71和P72,這是為了控制GPIO口比較鮮明地知道其用途。

1./********************************************* 
2.引腳別名定義 
3.**********************************************/           
4.sbit LED_D1=P2^6;     //用戶指示燈D1用IO口P26    
5.sbit LED_D2=P2^7;     //用戶指示燈D2用IO口P27    
6.sbit LED_D3=P7^2;     //用戶指示燈D3用IO口P72    
sbit LED_D4=P7^1;     //用戶指示燈D4用IO口P71   

須知,語句“LED_D1=0; ”和語句“P26=0;” 效果是完全一樣的;語句“LED_D1=1; ”和語句“P26=1;” 效果也是完全一樣的。

5.2.編寫代碼

首先編寫一個函數(shù),該函數(shù)會控制4個用戶LED分別依次點亮,代碼如下。

程序清單:流水燈點亮函數(shù)

1./************************************************************************* 
2.功能描述:流水燈 
3.入口參數(shù):無 
4.返回值:無 
5. ************************************************************************/  
6.void LED_Blink(void)  
7.{  
8.      LED_D1=0;        //點亮用戶指示燈D1  
9.      LED_D2=1;        //熄滅用戶指示燈D2  
10.      LED_D3=1;        //熄滅用戶指示燈D3  
11.      LED_D4=1;        //熄滅用戶指示燈D4  
12.      delay_ms(300);  
13.      LED_D1=1;        //熄滅用戶指示燈D1  
14.      LED_D2=0;        //點亮用戶指示燈D2  
15.      LED_D3=1;        //熄滅用戶指示燈D3  
16.      LED_D4=1;        //熄滅用戶指示燈D4  
17.      delay_ms(300);  
18.      LED_D1=1;        //熄滅用戶指示燈D1  
19.      LED_D2=1;        //熄滅用戶指示燈D2  
20.      LED_D3=0;        //點亮用戶指示燈D3  
21.      LED_D4=1;        //熄滅用戶指示燈D4  
22.      delay_ms(300);  
23.      LED_D1=1;        //熄滅用戶指示燈D1  
24.      LED_D2=1;        //熄滅用戶指示燈D2  
25.      LED_D3=1;        //熄滅用戶指示燈D3  
26.      LED_D4=0;        //點亮用戶指示燈D4  
27.      delay_ms(300);  
28.      LED_D1=1;        //熄滅用戶指示燈D1  
29.      LED_D2=1;        //熄滅用戶指示燈D2  
30.      LED_D3=1;        //熄滅用戶指示燈D3  
31.      LED_D4=1;        //熄滅用戶指示燈D4  
32.      delay_ms(300);  
33.}  

然后,在主函數(shù)中先對P2.6、P2.7、P7.1、P7.2口進行模式配置,后主循環(huán)中調(diào)用流水燈函數(shù),這樣可觀察到指示燈D1、D2、D3、D4被流水點亮。

代碼清單:主函數(shù)

1.int main(void)  
2.{  
3.    P2M1 &= 0x3F;   P2M0 &= 0x3F;     //設(shè)置P2.6~P2.7為準雙向口  
4.    //P2M1 &= 0x3F; P2M0 |= 0xC0;   //設(shè)置P2.6~P2.7為推挽輸出  
5.  //P2M1 |= 0xC0;   P2M0 &= 0x3F;   //設(shè)置P2.6~P2.7為高阻輸入  
6.  //P2M1 |= 0xC0;   P2M0 |= 0xC0;   //設(shè)置P2.6~P2.7為開漏輸出  
7.    P7M1 &= 0xF9;   P7M0 &= 0xF9;     //設(shè)置P7.1~P7.2為準雙向口  
8.    //P7M1 &= 0xF9; P7M0 |= 0x06;   //設(shè)置P7.1~P7.2為推挽輸出  
9.  //P7M1 |= 0x06;   P7M0 &= 0xF9;   //設(shè)置P7.1~P7.2為高阻輸入  
10.  //P7M1 |= 0x06;   P7M0 |= 0x06;   //設(shè)置P7.1~P7.2為開漏輸出  
11.      
12.  while(1)  
13.  {  
14.        LED_Blink();      //指示燈流水點亮  
15.    }  
16.}  

6.流水燈實驗(多個c文件)

6.1.工程需要用到的c文件

本例需要用到的c文件如下表所示,工程需要添加下表中的c文件。

6.2.頭文件引用和路徑設(shè)置

■ 需要引用的頭文件
因為在“main.c”文件中使用了控制led的函數(shù)和延時函數(shù)(延時函數(shù)沒有在main.c中定義),所以需要引用下面的頭文件。

1.#include    "led.h"  
2.#include "delay.h" 

■ 需要包含的頭文件路徑
本例需要包含的頭文件路徑如下表:

MDK中點擊魔術(shù)棒,打開工程配置窗口,添加頭文件包含路徑。

6.3.編寫代碼

首先在delay.c文件中編寫兩個延時函數(shù)delay_ms和Delay10us,delay_ms函數(shù)是毫秒延時,Delay10us函數(shù)是10微秒延時,代碼如下。

程序清單:延時函數(shù)

1./************************************** 
2.功能描述:延時函數(shù) 
3.入口參數(shù):uint16 x ,該值為1時,延時1ms 
4.返回值:無 
5.***************************************/  
6.void delay_ms(uint16 x)   
7.{    
8.    uint16 j,i;     
9.    for(j=0;j

程序清單:延時函數(shù)

1./******************************************************************* 
2.功能描述:延時函數(shù),延時約10us,在11.0592MHZ下 
3.入口參數(shù):無 
4.返回值:無 
5.********************************************************************/  
6.void Delay10us(void)          
7.{  
8.    uint8 i;  
9.    _nop_();  
10.    i = 33;  
11.    while (--i);  
12.}  

該delay_ms函數(shù)會在delay.h頭文件中被聲明,這樣可以被外部調(diào)用。如下。

1.extern void delay_ms(uint16 x);  
extern void Delay10us(void);  

然后在led.c文件中封裝和4個LED有關(guān)的所有基本操作函數(shù)。如下表所示的5個函數(shù)。

LED基本操作函數(shù)程序清單如下:

程序清單:點亮一個指定的LED

1. /************************************************************************** 
2.功能描述:點亮一個指定的指示燈(D1、D2、D3、D4) 
3.入口參數(shù):uint8 led_idx  (可取值LED_1、LED_2、LED_3、LED_4) 
4.返回值:無 
5. *************************************************************************/  
6.void led_on(uint8 led_idx)  
7.{  
8.  switch(led_idx)  
9.    {  
10.        case LED_1:  
11.      LED_D1=0;        //控制P2.6端口輸出低電平,點亮用戶指示燈D1  
12.          break;          
13.        case LED_2:  
14.      LED_D2=0;        //控制P2.7端口輸出低電平,點亮用戶指示燈D2  
15.          break;  
16.        case LED_3:  
17.      LED_D3=0;        //控制P7.2端口輸出低電平,點亮用戶指示燈D3  
18.          break;          
19.        case LED_4:  
20.      LED_D4=0;        //控制P7.1端口輸出低電平,點亮用戶指示燈D4  
21.          break;  
22.        default:  
23.          break;  
24.  }  
25.}  

程序清單:熄滅一個指定的LED

1./************************************************************************** 
2.功能描述:熄滅一個指定的指示燈(D1、D2、D3、D4) 
3.入口參數(shù):uint8 led_idx  (可取值LED_1、LED_2、LED_3、LED_4) 
4.返回值:無 
5. *************************************************************************/  
6.void led_off(uint8 led_idx)  
7.{  
8.  switch(led_idx)  
9.    {  
10.        case LED_1:  
11.      LED_D1=1;        //控制P2.6端口輸出高電平,熄滅用戶指示燈D1  
12.          break;          
13.        case LED_2:  
14.      LED_D2=1;        //控制P2.7端口輸出高電平,熄滅用戶指示燈D2  
15.          break;  
16.        case LED_3:  
17.      LED_D3=1;        //控制P7.2端口輸出高電平,熄滅用戶指示燈D3  
18.          break;          
19.        case LED_4:  
20.      LED_D4=1;        //控制P7.1端口輸出高電平,熄滅用戶指示燈D4  
21.          break;  
22.        default:  
23.          break;  
24.  }  
25.}  

程序清單:翻轉(zhuǎn)一個指定的LED的狀態(tài)

1./************************************************************************** 
2.功能描述:翻轉(zhuǎn)一個指定的指示燈(D1、D2、D3、D4) 
3.入口參數(shù):uint8 led_idx  (可取值LED_1、LED_2、LED_3、LED_4) 
4.返回值:無 
5.*************************************************************************/  
6.void led_toggle(uint8 led_idx)  
7.{  
8.  switch(led_idx)  
9.    {  
10.        case LED_1:  
11.      LED_D1=~LED_D1;      //控制P2.6端口輸出不同于上一次的電平,翻轉(zhuǎn)用戶指示燈D1  
12.          break;          
13.        case LED_2:  
14.      LED_D2=~LED_D2;    //控制P2.7端口輸出不同于上一次的電平,翻轉(zhuǎn)用戶指示燈D2  
15.          break;  
16.        case LED_3:  
17.      LED_D3=~LED_D3;      //控制P7.2端口輸出不同于上一次的電平,翻轉(zhuǎn)用戶指示燈D3  
18.          break;          
19.        case LED_4:  
20.      LED_D4=~LED_D4;    //控制P7.1端口輸出不同于上一次的電平,翻轉(zhuǎn)用戶指示燈D4  
21.          break;  
22.        default:  
23.          break;  
24.  }  
25.}  

程序清單:同時點亮開發(fā)板上的4個指示燈

1./************************************************************************** 
2.功能描述:點亮開發(fā)板上的4個指示燈(D1、D2、D3、D4) 
3.入口參數(shù):無 
4.返回值:無 
5. *************************************************************************/  
6.void leds_on(void)  
7.{  
8.      LED_D1=0;        //控制P2.6端口輸出低電平,點亮用戶指示燈D1  
9.      LED_D2=0;        //控制P2.7端口輸出低電平,點亮用戶指示燈D2  
10.      LED_D3=0;        //控制P7.2端口輸出低電平,點亮用戶指示燈D3  
11.      LED_D4=0;        //控制P7.1端口輸出低電平,點亮用戶指示燈D4  
12.}  

程序清單:同時熄滅開發(fā)板上的4個LED

1./************************************************************************** 
2.功能描述:熄滅開發(fā)板上的4個指示燈(D1、D2、D3、D4) 
3.入口參數(shù):無 
4.返回值:無 
5. *************************************************************************/  
6.void leds_off(void)  
7.{  
8.      LED_D1=1;        //控制P2.6端口輸出高電平,熄滅用戶指示燈D1  
9.      LED_D2=1;        //控制P2.7端口輸出高電平,熄滅用戶指示燈D2  
10.      LED_D3=1;        //控制P7.2端口輸出高電平,熄滅用戶指示燈D3  
11.      LED_D4=1;        //控制P7.1端口輸出高電平,熄滅用戶指示燈D4  
12.} 

在led.c文件中還編寫了一個流水燈點亮的函數(shù)LED_Blink,該函數(shù)調(diào)用LED的基本函數(shù)實現(xiàn)流水點亮4個用戶指示燈的目的。代碼如下。

程序清單:流水燈點亮函數(shù)

1./************************************************************************** 
2.功能描述:流水燈 
3.入口參數(shù):無 
4.返回值:無 
5. *************************************************************************/  
6.void LED_Blink(void)  
7.{  
8.        leds_off();           //熄滅所有用戶指示燈  
9.        led_on(LED_1);        //點亮用戶指示燈D1  
10.        delay_ms(300);  
11.        leds_off();           //熄滅所有用戶指示燈  
12.        led_on(LED_2);        //點亮用戶指示燈D2  
13.        delay_ms(300);  
14.        leds_off();           //熄滅所有用戶指示燈  
15.        led_on(LED_3);        //點亮用戶指示燈D3  
16.        delay_ms(300);  
17.        leds_off();           //熄滅所有用戶指示燈  
18.        led_on(LED_4);        //點亮用戶指示燈D4  
19.        delay_ms(300);  
20.        leds_off();           //熄滅所有用戶指示燈  
21.        delay_ms(300);  
}  

在led.h頭文件中會聲明可供外部調(diào)用的函數(shù),LED_Blink函數(shù)便是其中之一。如下。

1.extern void led_on(uint8 led_idx);  
2.extern void led_off(uint8 led_idx);  
3.extern void led_toggle(uint8 led_idx);  
4.extern void leds_on(void);  
5.extern void leds_off(void);  
6.extern void LED_Blink(void);  

最后,在主函數(shù)中先對P2.6、P2.7、P7.1、P7.2口進行模式配置,后主循環(huán)中調(diào)用流水燈函數(shù),這樣可觀察到指示燈D1、D2、D3、D4被流水點亮。

代碼清單:主函數(shù)

1.int main(void)  
2.{  
3.    P2M1 &= 0x3F;   P2M0 &= 0x3F;     //設(shè)置P2.6~P2.7為準雙向口  
4.    //P2M1 &= 0x3F; P2M0 |= 0xC0;   //設(shè)置P2.6~P2.7為推挽輸出  
5.  //P2M1 |= 0xC0;   P2M0 &= 0x3F;   //設(shè)置P2.6~P2.7為高阻輸入  
6.  //P2M1 |= 0xC0;   P2M0 |= 0xC0;   //設(shè)置P2.6~P2.7為開漏輸出  
7.    P7M1 &= 0xF9;   P7M0 &= 0xF9;     //設(shè)置P7.1~P7.2為準雙向口  
8.    //P7M1 &= 0xF9; P7M0 |= 0x06;   //設(shè)置P7.1~P7.2為推挽輸出  
9.  //P7M1 |= 0x06;   P7M0 &= 0xF9;   //設(shè)置P7.1~P7.2為高阻輸入  
10.  //P7M1 |= 0x06;   P7M0 |= 0x06;   //設(shè)置P7.1~P7.2為開漏輸出  
11.  
12.  while(1)  
13.  {  
14.      LED_Blink();    //指示燈流水點亮  
15.    }  
16.} 

好啦!以上就是今天要講的內(nèi)容,當(dāng)然期間也咨詢了艾克姆科技的技術(shù)人員幫忙搞定的,希望對你有所幫助!

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • led
    led
    +關(guān)注

    關(guān)注

    240

    文章

    23062

    瀏覽量

    657037
  • 指示燈
    +關(guān)注

    關(guān)注

    3

    文章

    414

    瀏覽量

    28220
  • 開發(fā)板
    +關(guān)注

    關(guān)注

    25

    文章

    4895

    瀏覽量

    97055
  • 硬件電路
    +關(guān)注

    關(guān)注

    39

    文章

    239

    瀏覽量

    29182
  • GPIO
    +關(guān)注

    關(guān)注

    16

    文章

    1188

    瀏覽量

    51832
收藏 人收藏

    評論

    相關(guān)推薦

    STC8A8K64S4A12系列單片機DAC數(shù)模轉(zhuǎn)換器講解

      今天介紹下STC8A8K64S4A12系列單片機DAC數(shù)模轉(zhuǎn)換原理及RC積分電路原理,掌握掌握STC8A8K64S4A12系列單片機實現(xiàn)DAC功能的硬件和軟件設(shè)計。
    的頭像 發(fā)表于 11-17 16:38 ?2390次閱讀
    <b class='flag-5'>STC8A8K64S4A12</b>系列單片機DAC數(shù)模轉(zhuǎn)換器講解

    請問哪位朋友有火龍電子FD51D_8STC8A8K64S4A12開發(fā)板)的資料呢?

    請問哪位朋友有火龍電子FD51D_8STC8A8K64S4A12開發(fā)板)的資料呢?如果方便的話請發(fā)郵箱252868106@qq.com非常感謝!
    發(fā)表于 12-19 13:03

    STC8A8K64S4A12串口通信

    宏晶 的51單片機STC8A8K64S4A12想用r422的串口通信方式,誰能發(fā)個原理圖,r422芯片是TI的65HVD33。
    發(fā)表于 03-09 15:48

    STC8A8K64S4A12開發(fā)板學(xué)習(xí)資料

    STC8A8K64S4A12教學(xué),板載資源豐富。具體參考下圖: 此開發(fā)板將單片機STC8A8K64S4A12所有的外設(shè)資源都詮釋到,關(guān)聯(lián)到相應(yīng)的模塊電路或接口上。
    發(fā)表于 01-06 10:25

    淺析STC8A8K64S4A12開發(fā)板

    版權(quán)聲明:本文為博主原創(chuàng)文章,轉(zhuǎn)載請附上原文出處鏈接。文章目錄前言一、STC8A8K64S4A12系列單片機介紹二、STC8A8K64S4A12開發(fā)板概述三、STC8A8K64S4A12
    發(fā)表于 07-19 09:24

    如何去實現(xiàn)一種基于STC8A8K64S4A12開發(fā)板GPIO按鍵設(shè)計

    如何去實現(xiàn)一種基于STC8A8K64S4A12開發(fā)板GPIO按鍵設(shè)計?如何對基于STC8A8K64S4A12開發(fā)板
    發(fā)表于 08-19 07:24

    STC8A8K64S4A12靜態(tài)數(shù)碼管驅(qū)動的方法是什么

    STC8A8K64S4A12靜態(tài)數(shù)碼管驅(qū)動的方法是什么
    發(fā)表于 02-09 06:11

    基于STC8A8K64S4A12智能車設(shè)計資料分享

    智能車進階版文章目錄基于STC8A8K64S4A12智能車設(shè)計一、板載外設(shè)二、功能三、實物:四、代碼五、PCB和元件六、焊接基于STC8A8K64S4A12智能車設(shè)計一、板載外設(shè)1.1 紅外接收頭
    發(fā)表于 02-16 06:43

    STC8A8K64S4A12的命名規(guī)則是什么

    STC8A8K64S4A12的命名規(guī)則STC8 -- STC8系列A -- 子系列中的A子系列8K
    發(fā)表于 02-18 07:32

    STC8A8K64S4A12迷你開發(fā)板電路原理圖免費下載

    本文檔的主要內(nèi)容詳細介紹的是STC8A8K64S4A12迷你開發(fā)板電路原理圖免費下載。
    發(fā)表于 06-27 08:00 ?159次下載
    <b class='flag-5'>STC8A8K64S4A12</b>迷你<b class='flag-5'>開發(fā)板</b>電路原理圖免費下載

    使用STC8A8K64S4A12單片機掉電喚醒定時器應(yīng)用的實例

    本文檔的主要內(nèi)容詳細介紹的是使用STC8A8K64S4A12單片機掉電喚醒定時器應(yīng)用的實例。
    發(fā)表于 01-28 08:00 ?24次下載
    使用<b class='flag-5'>STC8A8K64S4A12</b>單片機掉電喚醒定時器應(yīng)用的實例

    STC8A8K64S4A12開發(fā)板】—聊聊單片機中斷原理

    版權(quán)聲明:本文為博主原創(chuàng)文章,轉(zhuǎn)載請附上原文出處鏈接。文章目錄前言一、關(guān)于中斷的一些概念二、STC8A8K64S4A12系列的中斷請求源三、關(guān)于中斷的一些概念STC8A8K64S4A12系列的中斷
    發(fā)表于 11-10 20:50 ?13次下載
    【<b class='flag-5'>STC8A8K64S4A12</b><b class='flag-5'>開發(fā)板</b>】—聊聊單片機中斷原理

    基于STC8A8K64S4A12單片機硬件IIC_光照強度檢測

    基于STC8A8K64S4A12單片機硬件IIC_光照強度檢測
    發(fā)表于 11-14 15:21 ?20次下載
    基于<b class='flag-5'>STC8A8K64S4A12</b>單片機硬件IIC_光照強度檢測

    STC8A8K64S4A12的命名規(guī)則

    STC8A8K64S4A12的命名規(guī)則STC8 -- STC8系列A -- 子系列中的A子系列8K
    發(fā)表于 12-23 19:11 ?24次下載
    <b class='flag-5'>STC8A8K64S4A12</b>的命名規(guī)則

    基于STC8A8K64S4A12制作一個示波器

    摘要:此示波器的主控是STC8A8K64S4A12,是在B站老劉示波器基礎(chǔ)上的升級版,擴展了測量負電壓的功能,更新了UI設(shè)計,屏幕升級為1.3寸OLED屏。
    的頭像 發(fā)表于 02-06 11:48 ?2582次閱讀