1. 程式人生 > >[基礎篇]ESP8266-NonOS學習筆記(四)之GPIO操作(按鍵、LED、中斷、定時器)

[基礎篇]ESP8266-NonOS學習筆記(四)之GPIO操作(按鍵、LED、中斷、定時器)

 

本篇文章我們再回到基礎篇,難道你還以為我會講UDP?啊哈哈哈,UDP肯定是會講的,但是應用場景不是很多,我們放到後面再講,不過也是簡單一講,畢竟熟悉UDP協議的人來說,都知道UDP一種不可靠的傳輸協議,可以這樣形容“我(Client)只管發,你(Server)愛收不收”,所以在一些實際應用場景中是不多見的,大多數時候我們還是要保證資料傳輸的可靠性,準確性!好了,不多扯了,開始今天的簡單卻很重要的知識學習~

我們先來了解一下什麼是GPIO吧,雖然經常說GPIO,但是你有沒有真正的去深入瞭解一下呢?隨著知識的不斷積累,有些時候去深入的瞭解某些東西,會讓你有很多新的收穫。

  • 什麼是GPIO

簡單來說就是通用輸入輸出埠,英文全稱:General Purpose Input Output。通俗地說,就是一些引腳,可以通過它們輸出高低電平,或者通過它們讀入引腳的狀態是高電平或是低電平。GPIO是個比較重要的概念,使用者可以通過GPIO口和硬體進行資料互動(如UART),控制硬體工作(如LED、蜂鳴器等),讀取硬體的工作狀態訊號(如中斷訊號)等。

  • GPIO的八種模式

這裡說的八種模式並不是指ESP8266的八種模式,據我所知ESP8266的GPIO口並沒有這麼多模式,這裡給大家說的是STM32 GPIO的八種模式,STM32微控制器的八種模式相對來說是非常全的了,我們這裡可以瞭解一下。

  1. 模擬輸入(GPIO_Mode_AIN)
  2. 浮空輸入(GPIO_Mode_IN_FLOATING)
  3. 下拉輸入(GPIO_Mode_IPD)
  4. 上拉輸入(GPIO_Mode_IPU)
  5. 開漏輸出(GPIO_Mode_Out_OD)
  6. 推輓輸出(GPIO_Mode_Out_PP)
  7. 複用開漏輸出(GPIO_Mode_Out_PP)
  8. 複用推輓輸出(GPIO_Mode_AF_PP)

這裡就不再詳細展開敘述了,因為要把這八種模式都搞明白,一兩句話是說不完了,有時間在跟大家分享。

  • GPIO可以用來做什麼

我們去學一個東西,最重要是知道這個東西可以做什麼,最終要落實到實際使用嘛,如果這個GPIO沒有實際使用價值,那我們也肯定不會去好好琢磨它了,簡單來說,實際使用場景非常多,比如我們常見的只有開關狀態的電子器件都可以用GPIO控制,或者間接使用GPIO去控制,舉個栗子!LED燈,納尼?怎麼老是說一些跟燈有關的東西,啊哈哈哈哈,因為我還是比較喜歡閃閃發光的小玩意,我們都知道燈只有兩種狀態,開或者關(不要跟我講還有壞了這種狀態!),開跟關的狀態其實就是有無電流經過它,而有無電流經過LED,最重要的是LED兩端要有一個電壓差,所以我們可以讓某一個管腳輸出高電平,這樣就會在LED兩端形成一定的電壓差,自然而然的燈就亮了,大家可以暫時這麼理解(這裡只是講給不怎麼懂電子的人的~)。又比如還可以控制繼電器、還可以獲取按鍵狀態,複雜一點的還可以模擬I2C匯流排,總之GPIO是很通用,但是也是非常重要的!

  • ESP8266GPIO介面函式

其實單就ESP8266的GPIO口操作來說,我起初是很不適應的,如果你之前接觸的是STM32微控制器開發的話,你會感到不適應,但是慢慢的熟悉一下,會發現其實很簡單,所以學習最重要的是摒棄固有思維,要能夠思維活躍一些。我們先看一下手冊當中對GPIO介面的說明,只有這個讀懂了,我們才能更好的去使用它。

我這裡把幾個常用的給圈出來了,基本上我們使用這幾個就足夠了,GPIO中斷這塊大家可以好好看一下,有時候我們會用到外部中斷的,我們使用管腳去控制一個LED燈的基本流程就是先PIN_FUNC_SELECT(PIN_NAME, FUNC),然後就可以輸出高低電平或者設定為輸入,或者去讀取管腳狀態,但是有一點我們需要注意的就是gpio16這個管腳,在官方的技術參考手冊中有說明,給大家截圖看一下:

什麼意思呢?就是gpio16這個管腳不是GPIO這一夥裡,使用它人家有自己的介面函式,不跟其他管腳使用同樣的介面函式,這裡大家需要注意一些,那麼為什麼這個管腳這麼特殊呢?其實主要時為了低功耗,要知道Wi-Fi的功耗是很大,但是我們如果拿ESP8266做一些便攜的裝置,靠電池供電是不足以支撐很久的,所以在它沒有什麼事情的時候,我們需要它進入睡眠模式,這時候整個晶片會關閉除RTC以外的所有模組,此時工作電流是在μA級別,可以說是非常省電的,下面我們看一下官方是如何介紹的低功耗模式:

可以看出在深度睡眠模式下功耗是極低的,所以我們是可以利用ESP8266做一些可穿戴裝置的,但是戴著出去的時候,我們要去連線哪一個Wi-Fi呢?這是很值得思考的,很顯然不能手機開熱點,那樣我們手機的功耗可就大大提高了,不過最近據說有家國內公司叫連尚網路的公司釋出了自家的Wi-Fi衛星,據說明年將會搭載長征系列火箭升空,估計到那時候可穿戴Wi-Fi裝置才有真正的應用場景,目前還是基於BLE的居多。詳情戳卡片:

連尚Wi-Fi衛星

我們看一下三種模式睡眠模式的功耗對比吧!

不對,好像又有點扯多了?怎麼睡眠模式又寫了這麼多,好吧,轉回正題,大家對低功耗感興趣的話可以留言,改天我單獨整理一篇文章詳細介紹一下,要是沒有那就先不整理了,啊哈哈哈哈~

我們正式開始我們的點燈、按鍵點燈、定時器點燈等點燈之旅,不過還有個問題,我們這裡如果是使用的NodeMCU(預設大家是使用的NodeMCU)話,我們還需要了解一下管腳定義,因為NodeMCU採用的管腳命名與ESP8266的預設管腳命名是不一樣的,所以我們需要對應起來,直接給大家上個圖片看一下,建議大家收藏一下,省的以後找起來麻煩。

話不多說?上程式碼?得嘞,客官您裡邊請~

 1 /************************
 2  *   STATIC VARIABLES   *
 3  ************************/
 4 os_timer_t blue_led_timer;
 5 os_timer_t key_read_timer;
 6 
 7 /************************
 8  *   STATIC FUNCTIONS   *
 9  ************************/
10 
11 /**
12  * LED定時反轉函式,1s狀態反轉一次
13  */
14 static void ICACHE_FLASH_ATTR
15 blue_led_timer_toggle(void){
16     os_timer_disarm(&blue_led_timer);//取消定時器
17     uint32 status = GPIO_INPUT_GET(GPIO_ID_PIN(2));//獲取藍燈管腳狀態
18     GPIO_OUTPUT_SET(GPIO_ID_PIN(2),!status);//取反實現藍燈管腳電平反轉,從而實現亮滅操作
19     os_timer_arm(&blue_led_timer, 1000, true);//使能定時器
20 }
21 
22 /**
23  * 按鍵定時狀態讀取函式,10ms獲取一次按鍵狀態
24  */
25 static void ICACHE_FLASH_ATTR
26 key_read_value(void){
27     os_timer_disarm(&key_read_timer);//取消定時器
28     if(GPIO_INPUT_GET(GPIO_ID_PIN(14)) == 0x00){//如果按鍵按下,低電平
29         os_delay_us(20000);//延時20ms消抖
30         if(GPIO_INPUT_GET(GPIO_ID_PIN(14)) == 0x00){//再次判斷狀態,防止誤觸
31             uint32 status = GPIO_INPUT_GET(GPIO_ID_PIN(4));//獲取當前管腳狀態
32             GPIO_OUTPUT_SET(GPIO_ID_PIN(4),!status);//取反實現管腳電平反轉
33             while(GPIO_INPUT_GET(GPIO_ID_PIN(14)));//等待按鍵鬆開
34         }
35     }
36     os_timer_arm(&key_read_timer, 10, true);//使能定時器
37 }
38 
39 /**
40  *按鍵中斷服務函式,高電平觸發
41  */
42 static void ICACHE_FLASH_ATTR
43 key_intr_handler(void){
44     uint32 gpio_status = GPIO_REG_READ(GPIO_STATUS_ADDRESS);//讀取GPIO暫存器狀態,獲取中斷資訊
45     uint8 level = 0;
46     GPIO_REG_WRITE(GPIO_STATUS_ADDRESS,gpio_status);//清楚中斷資訊
47     if(gpio_status & (BIT(15))){//判斷是否是gpio15
48         if(GPIO_INPUT_GET(15)){//如果是高電平
49             GPIO_OUTPUT_SET(GPIO_ID_PIN(5),0);//熄滅紅燈
50             GPIO_OUTPUT_SET(GPIO_ID_PIN(12),1);//熄滅黃燈
51             GPIO_OUTPUT_SET(GPIO_ID_PIN(4),0);//熄滅綠燈
52             GPIO_OUTPUT_SET(GPIO_ID_PIN(2),0);//熄滅藍燈
53             os_timer_disarm(&key_read_timer);//取消按鍵定時器
54             os_timer_disarm(&blue_led_timer);//取消藍燈定時反轉定時器
55         }else{//如果是低電平
56             //不做處理
57         }
58     }else{//如果不是gpio15
59         //不做處理
60     }
61 }
62 
63 /************************
64  *   GLOBAL FUNCTIONS   *
65  ************************/
66 void ICACHE_FLASH_ATTR
67 gpio_test(void){
68 
69     gpio_init();//初始化GPIO
70 
71     PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO5_U,FUNC_GPIO5);//紅燈
72     GPIO_OUTPUT_SET(GPIO_ID_PIN(5),1);//高電平點亮,常亮
73 
74     PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDI_U,FUNC_GPIO12);//黃燈
75     GPIO_OUTPUT_SET(GPIO_ID_PIN(12),0);//低電平點亮,常亮
76 
77     PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U,FUNC_GPIO2);//藍燈
78     os_timer_disarm(&blue_led_timer);
79     os_timer_setfn(&blue_led_timer, (os_timer_func_t *) blue_led_timer_toggle,NULL);//定時回撥函式
80     os_timer_arm(&blue_led_timer, 1000, true);//設定時間為1s
81 
82     PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO4_U,FUNC_GPIO4);//綠燈,按鍵觸發,反轉
83     PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U,FUNC_GPIO14);//按鍵
84     GPIO_DIS_OUTPUT(GPIO_ID_PIN(14));//按鍵設定為輸入模式
85     PIN_PULLUP_EN(PERIPHS_IO_MUX_MTMS_U);//引腳上拉使能
86     os_timer_disarm(&key_read_timer);
87     os_timer_setfn(&key_read_timer, (os_timer_func_t *) key_read_value,NULL);//定時回撥函式
88     os_timer_arm(&key_read_timer, 10, true);//設定時間為10ms
89 
90     PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U,FUNC_GPIO15);//中斷按鍵
91     GPIO_DIS_OUTPUT(GPIO_ID_PIN(15));//設定為輸入模式
92     PIN_PULLUP_DIS(PERIPHS_IO_MUX_MTDO_U);//下拉使能
93     ETS_GPIO_INTR_DISABLE();//禁止所有GPIO中斷
94     ETS_GPIO_INTR_ATTACH((void *)key_intr_handler,NULL);//註冊GPIO中斷處理函式
95     gpio_pin_intr_state_set(GPIO_ID_PIN(15),GPIO_PIN_INTR_HILEVEL);//設定高電平觸發中斷
96     ETS_GPIO_INTR_ENABLE();//使能所有GPIO中斷
97 
98 }

程式碼不是很多,都有註釋,大家可以自己看一下,最後我們來看一下實際執行效果,請原諒我這不標準的普通話,應該不用給大家加字幕吧?啊哈哈哈,請大家諒解~

視訊還在找託管方~

再附上一張手畫原理圖,電路連線相對簡單,就簡單一畫,應該很好看懂的。

原始碼可以在這裡下載:

makingfunxyz-esp8266

歡迎大家Star,您的鼓勵是我最大的動力,有問題可以私信我,或者提交issues~

本系列文章在知乎同步更新,知乎搜尋專欄:IAMLIUBO的神奇物聯網之旅