吴忠躺衫网络科技有限公司

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

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

3天內不再提示

基于STC8A8K64S4A12開發板的GPIO點燈實驗

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

前言

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

一、硬件電路原理

1.開發板指示燈硬件電路

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

圖1:LED指示燈驅動電路

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

2.控制方式

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

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

LED控制-低電平有效原理

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

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

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

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

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

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

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

3.LED限流電阻的選取

3.1.限流電阻的計算

圖4:LED限流電阻計算

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

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

圖5:封裝0805的LED

圖6:0805 LED參數圖

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

3.2.限流電阻的選擇

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

4.STC8A8K64S4A12系列單片機GPIO口

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

4.1.芯片封裝

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

4.2.GPIO口工作模式

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

圖7:GPIO準雙向口/弱上拉模式內部框圖

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

圖8:GPIO準雙向口/弱上拉模式內部框圖分析

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

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

圖9:GPIO推挽輸出/強上拉模式內部框圖

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

圖10:GPIO高阻輸入模式內部框圖

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

圖11:GPIO開漏輸出模式內部框圖

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

二、軟件編寫

1.GPIO寄存器匯集

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

表2:

2.寄存器解析

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

2.1.端口數據寄存器

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

圖12:端口數據寄存器

2.2.端口配置寄存器

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

圖13:GPIO端口配置

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

3.1.頭文件引用和路徑設置

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

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

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

#define  uint16   unsigned int    
#define  uint8    unsigned char   

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

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

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

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

3.2.編寫代碼

首先介紹下毫秒級的延時函數??刂浦甘緹袅梁蜏缧枰虚g有足夠的間隔時間,這個間隔一般通過延時函數實現。微秒級的延時時間很難控制,這和主頻大小及其精度有密切關系。但毫秒級的延時還是可以控制的,下面給出在11.0592MHZ下的毫秒延時函數,僅供參考。

代碼清單:毫秒延時函數

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

在對端口數據寄存器介紹時我們簡單介紹過控制單片機GPIO的過程。需要再說明的地方是關于兩個關鍵字“sfr”和“sbit”。
sfr是Keil C51為能直接訪問51內核單片機中的SFR而提供了一個關鍵詞,其用法是:
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; 
}  

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

代碼清單:主函數

1.int main()  
2.{  
3.    P7M1 &= 0xFB;    P7M0 &= 0xFB;    //設置P7.2為準雙向口  
4.    // P7M1 &= 0xFB;  P7M0 |= 0x04;      //設置P7.2為推挽輸出
5.    // P7M1 |= 0x04;  P7M0 &= 0xFB;      //設置P7.2為高阻輸入  
6.    //  P7M1 |= 0x04;  P7M0 |= 0x04;    //設置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驅動LED實驗(庫函數版本)

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

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

該GPIO.c是STC官方提供的有關GPIO配置的函數庫。

4.2.頭文件引用和路徑設置

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

1.#include    "GPIO.h"  

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

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

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

4.3.編寫代碼

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

代碼清單:GPIO口初始化函數

1./************************************** 
2.功能描述:GPIO口初始化 
3.入口參數:無 
4.返回值:無 
5.***************************************/  
6.void    GPIO_config(void)  
7.{  
8.    GPIO_InitTypeDef  GPIO_InitStructure;  
9.   
10.    //設置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.}  

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

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

1.//========================================================================  
2.// 函數: uint8    GPIO_Inilize(uint8 GPIO, GPIO_InitTypeDef *GPIOx)  
3.// 描述: 初始化IO口.  
4.// 參數: GPIOx: 結構參數,請參考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;   //成功  
}  

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

代碼清單:主函數

1.int main()  
2.{  
3.  GPIO_config();   //設置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.頭文件引用和路徑設置

本實驗需要用到的頭文件以及添加頭文件包含路徑的方法請參考“實驗2-1-1:GPIO驅動LED(寄存器版本)”部分。
在程序設計中重新定義了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.編寫代碼

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

程序清單:流水燈點亮函數

1./************************************************************************* 
2.功能描述:流水燈 
3.入口參數:無 
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.}  

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

代碼清單:主函數

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

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

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

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

6.2.頭文件引用和路徑設置

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

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

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

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

6.3.編寫代碼

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

程序清單:延時函數

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

程序清單:延時函數

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

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

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

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

LED基本操作函數程序清單如下:

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

1. /************************************************************************** 
2.功能描述:點亮一個指定的指示燈(D1、D2、D3、D4) 
3.入口參數: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.入口參數: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.}  

程序清單:翻轉一個指定的LED的狀態

1./************************************************************************** 
2.功能描述:翻轉一個指定的指示燈(D1、D2、D3、D4) 
3.入口參數: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端口輸出不同于上一次的電平,翻轉用戶指示燈D1  
12.          break;          
13.        case LED_2:  
14.      LED_D2=~LED_D2;    //控制P2.7端口輸出不同于上一次的電平,翻轉用戶指示燈D2  
15.          break;  
16.        case LED_3:  
17.      LED_D3=~LED_D3;      //控制P7.2端口輸出不同于上一次的電平,翻轉用戶指示燈D3  
18.          break;          
19.        case LED_4:  
20.      LED_D4=~LED_D4;    //控制P7.1端口輸出不同于上一次的電平,翻轉用戶指示燈D4  
21.          break;  
22.        default:  
23.          break;  
24.  }  
25.}  

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

1./************************************************************************** 
2.功能描述:點亮開發板上的4個指示燈(D1、D2、D3、D4) 
3.入口參數:無 
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.}  

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

1./************************************************************************** 
2.功能描述:熄滅開發板上的4個指示燈(D1、D2、D3、D4) 
3.入口參數:無 
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文件中還編寫了一個流水燈點亮的函數LED_Blink,該函數調用LED的基本函數實現流水點亮4個用戶指示燈的目的。代碼如下。

程序清單:流水燈點亮函數

1./************************************************************************** 
2.功能描述:流水燈 
3.入口參數:無 
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頭文件中會聲明可供外部調用的函數,LED_Blink函數便是其中之一。如下。

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);  

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

代碼清單:主函數

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

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

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • led
    led
    +關注

    關注

    242

    文章

    23355

    瀏覽量

    663167
  • 指示燈
    +關注

    關注

    3

    文章

    416

    瀏覽量

    28382
  • 開發板
    +關注

    關注

    25

    文章

    5121

    瀏覽量

    98189
  • 硬件電路
    +關注

    關注

    39

    文章

    244

    瀏覽量

    29316
  • GPIO
    +關注

    關注

    16

    文章

    1216

    瀏覽量

    52377
收藏 人收藏

    評論

    相關推薦

    STC8A8K64S4A12系列單片機DAC數模轉換器講解

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

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

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

    STC8A8K64S4A12串口通信

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

    STC8A8K64S4A12開發板學習資料

    STC8A8K64S4A12教學,板載資源豐富。具體參考下圖: 此開發板將單片機STC8A8K64S4A12所有的外設資源都詮釋到,關聯到相應的模塊電路或接口上。
    發表于 01-06 10:25

    淺析STC8A8K64S4A12開發板

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

    如何去實現一種基于STC8A8K64S4A12開發板GPIO按鍵設計

    如何去實現一種基于STC8A8K64S4A12開發板GPIO按鍵設計?如何對基于STC8A8K64S4A12開發板
    發表于 08-19 07:24

    STC8A8K64S4A12靜態數碼管驅動的方法是什么

    STC8A8K64S4A12靜態數碼管驅動的方法是什么
    發表于 02-09 06:11

    基于STC8A8K64S4A12智能車設計資料分享

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

    STC8A8K64S4A12的命名規則是什么

    STC8A8K64S4A12的命名規則STC8 -- STC8系列A -- 子系列中的A子系列8K
    發表于 02-18 07:32

    STC8A8K64S4A12迷你開發板電路原理圖免費下載

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

    使用STC8A8K64S4A12單片機掉電喚醒定時器應用的實例

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

    STC8A8K64S4A12開發板】—聊聊單片機中斷原理

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

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

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

    STC8A8K64S4A12的命名規則

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

    基于STC8A8K64S4A12制作一個示波器

    摘要:此示波器的主控是STC8A8K64S4A12,是在B站老劉示波器基礎上的升級版,擴展了測量負電壓的功能,更新了UI設計,屏幕升級為1.3寸OLED屏。
    的頭像 發表于 02-06 11:48 ?2771次閱讀
    浦江县| 大发888有破解的没| 威尼斯人娱乐场66| 人民币棋牌游戏| 利津县| 网上百家乐官网哪家较安全| 风水24山分房图| 百家乐网站排名| 大发888线上投注| 华宁县| 百家乐官网电子发牌盒| 皇冠百家乐客户端皇冠| 威尼斯人娱乐备用622| 皇冠网 全讯通| 澳门百家乐官网会出千吗| 大众百家乐官网的玩法技巧和规则 | 网上赌百家乐官网的玩法技巧和规则 | 威尼斯人娱乐老品牌| 豪门网上娱乐| 百家乐官网视频游戏聊天| 百家乐官网老千| 新东泰百家乐的玩法技巧和规则| 大发线上娱乐| 百家乐官网赌场技巧论坛| 至尊百家乐20111110| 太阳城论坛| 百家乐官网玩法说明| 综合百家乐官网博彩论坛| 威尼斯人娱乐场55556| 百家乐官网游戏如何玩| 永利百家乐开户| 大发888游戏好吗| 百家乐官网机器昀程序| 玩百家乐如何看路| 棋牌室转让| 百家乐官网路单破| 百家乐网上真钱娱乐| 仙桃市| 百家乐论坛百科| 娱乐城注册体验金| 狮威百家乐官网娱乐场|