天天看點

m0單片機io口_我的單片機學習之路(3)-玩轉LED(一)

m0單片機io口_我的單片機學習之路(3)-玩轉LED(一)

IO特性

在學習單片機時,最早接觸的就是端口IO操作。那種你讓他往左(設定高電平輸出),他不敢往右 (輸出低電平)的絕對服從,讓我們獲得極大的樂趣。但是要獲得這種樂趣,首先得摸透單片機的IO特性。

以IO輸出為例,首先我們要注意端口的輸出可以設定的狀态,如開漏輸出、推挽輸出。對應STM8S003,檢視資料手冊,PB4、PB5為隻能開漏輸出,在我需要使用該端口做輸出時,需要根據實際使用場景注意是否要接外部上拉電阻。同時還要注意一個電氣參數,就是拉電流和灌電流,電流方向為端口向負載流動,則為拉電流,反之為灌電流。以LED為例,可以有以下2中形式:

m0單片機io口_我的單片機學習之路(3)-玩轉LED(一)

1、拉電流方式

m0單片機io口_我的單片機學習之路(3)-玩轉LED(一)

2、灌電流方式

因為單片機的灌電流一般會比拉電流大,對于LED這種負載,在電流較大時(如一個IO口帶3個LED燈)一般會采用灌電流連接配接方式,為了統一友善,一般LED驅動電路都會采用灌電流連接配接。

單片機的“Hello World”

在我們學習C語言時,我們寫的第一個程式一般都是

print("Hello World")

。其實在單片機學習時,也同樣有一個“Hello World”程式---

點亮一個LED燈

根據原理圖,我們知道要點亮LED燈,隻要将對應單片機口設定成輸出低電平即可。于是我們很快就寫下一行代碼:

......
           

一頓編譯、燒錄,LED亮了,開心一下,今天任務完成,又可以刷會手機了。

m0單片機io口_我的單片機學習之路(3)-玩轉LED(一)

其實在實際應用過程中,很多人也是這麼寫。雖然功能實作了,但是也有很多其他問題會存在:

  1. 1 如果這個LED燈顯示在很多地方調用,突然有一天,項目要換單片機,這個時候修改就會成為一個問題。這個場景很熟悉,當時學習宏的時候就有說為了程式中的π精度要改變,是以使用 #define PI 3.14 進行定義,使用時都用 PI 進行計算。于是我們可以改成如下:
#define IO_LED P10
           
  1. 2 突然有一天,硬體工程師改闆時,因為布線困難,需要把灌電流變成拉電流模式。我們隻好先崩潰一會,默默打開工程,開始搜尋、修改替換。為了防止後面哪天又改回去,于是我們又想到了宏函數,程式又改成這樣:
#define IO_LED(state)    P10 = state
           

如果哪天改回去,我們隻要修改定義為

IO_LED(state) P10 = !state

即可。

對于

IO_LED(0);

這樣的寫法,在日後維護讀代碼時,容易誤解成是關閉LED燈。是以我會在項目中通用定義狀态開關,在應用邏輯層保持一緻性。同時為友善維護,所有關于IO的宏定義,我會放在

IO_Define.h

中。

DataType.h

中會有如下定義:

typedef 
           

IO_Define.h

中會定義如下端口宏:

#define IO_LED(state)    P10 = !state //灌電流模式,低電平點亮,邏輯取反
           

Main.c

中的應用代碼:

......
       
   
           
  1. 3 又突然有一天,需求更改了,需要實時上報LED狀态,雖然直接讀IO狀态也可以,但是為了規範性及後續擴充友善,建議進行封裝。一般對于一些操作比較頻繁,同時又有可能會有需求變動的地方,建議用函數進行封裝,友善再日後需求變更比較大的時候友善操作。
void 
           

Main.c

中的應用代碼:

......
           

總結

1、寫代碼時要注意後續維護可能,做好封裝,友善日後重構修改

2、寫代碼時要注意分層解耦,有子產品化的思維

3、對代碼不能直接表明的,要做好注釋

粗略寫了下,主要講下思路,這塊代碼比較簡單就不上傳github,後續涉及驅動部分的代碼會整理上傳。不對之處還望指正交流。

繼續閱讀