Kurs esp32/esp8266 | #2 – porty GPIO

Obsługa portów GPIO | esp-idf

W tej części kursu zajmiemy się kwestią najbardziej podstawową – już jeśli chodzi o programowanie każdego mikrokontrolera, czyli obsługą portów wejścia-wyjścia naszych układów. Poniższy tekst dotyczy zarówno esp32, jak i esp8266. Konfiguracja wyprowadzeń gpio w tych dwóch procesorach wygląda identycznie.

W przypadku esp32 porty: 6, 7, 8, 9, 10, 11 są podłączone do zewnętrznej pamięci flash, więc ich konfiguracja wygląda inaczej niż pozostałych. Z kolei porty GPIO34 – GPIO39, mogą być tylko skonfigurowane jako wejścia bez możliwości programowego podciągania.

Zaczniemy od zaimportowania do naszego kodu biblioteki odpowiedzialnej za obsługę gpio:

#include "driver/gpio.h"

Dostarcza nam ona proste polecenia, dzięki którym szybko możemy konfigurować porty gpio bez potrzeby znajomości rejestrów procesora. Następnie trzeba skonfigurować wybrane porty w pożądany sposób. Zrobimy to następująco…

gpio_config_t io_config;
io_conf.intr_type = GPIO_INTR_DISABLE;
io_conf.mode = GPIO_MODE_OUTPUT;
io_conf.pin_bit_mask = ((1<<16) | (1<<4) | (1<<5) | (1<<0) | (1<<14) | (1<<12));
io_conf.pull_down_en = 0;
io_conf.pull_up_en = 0;
gpio_config(&io_conf);

Powyższym zestawem poleceń ustawiłem piny (16,4,5,0,14,12) jako wyjścia z wyłączonymi podciągnięciami programowymi i wyłączonymi przerwaniami.

Poniżej znajduje się szczegółowe objaśnienie kodu.

gpio_config_t io_config;

Powołałem zmienną „io_config” typu „gpio_config_t”. Jest to struktura, w której ustawiamy nasze wymagania co do funkcjonowania danego pinu/pinów.

Następnie elementowi „intr_type” naszej struktury nadałem wartość „GPIO_INTR_DISABLE”. Jak się można domyśleć, element ten odpowiada za ustawienie typu przerwania na pinie/pinach. Użyłem zdefiniowanej w pliku nagłówkowym makrodefinicji wyłączającej jakiekolwiek przerwania. Do dyspozycji mamy cztery opcje:

  • GPIO_INTR_DISABLE – przerwania wyłączone
  • GPIO_INTR_POSEDGE – przerwanie wywoływane zboczem narastającym
  • GPIO_INTR_NEGEDGE – przerwanie wywoływane zboczem opadającym
  • GPIO_INTR_ANYEDGE – przerwanie wywoływane dowolnym zobczem
  • GPIO_INTR_LOW_LEVEL – stan niski wywołuje przerwanie
  • GPIO_INTR_HIGH_LEVEL – stan wysoki wywołuje przerwanie

Kolejny element definiuje tryb pracy portu i do wyboru mamy:

  • GPIO_MODE_DISABLE – port wyłączony
  • GPIO_MODE_INPUT – wejście
  • GPIO_MODE_OUTPUT – wyjście
  • GPIO_MODE_OUTPUT_OD – wyjście z otwartym drenem
  • GPIO_MODE_INPUT_OUTPUT_OD – wejście i wyjście z otwartym drenem
  • GPIO_MODE_INPUT_OUTPUT – wejście i wyjście

Tryb pracy typu „wejście i wyjście” wybieramy gdy chcemy mieć możliwość zarówno ustawiania konkretnego stanu na pinie oraz jego odczytywania. W przypadku esp8266 odczytywać stan można nawet w trybie output.

io_conf.pin_bit_mask = ((1<<16) | (1<<4) | (1<<5) | (1<<0) | (1<<14) | (1<<12));

Element „pin_bit_mask” odpowiada za wybór pinów GPIO, których dotyczy konfiguracja. Pamiętaj, że jeśli korzystasz z płytki prototypowej to piny na niej nadrukowane nie muszą równać się numeru podłączonemu do tego wyprowadzenia GPIO.

Kolejne dwa polecenia dotyczą programowego podciągania pinu do GND i VCC (podajemy 0/1).

gpio_config(&io_conf);

Finalnie wystarczy tylko przekazać funkcji „gpio_config” wskaźnik do naszej struktury, a ta skonfiguruje wybrane przez nas piny według założeń.

Odczytywanie i ustawianie stanu portu GPIO

Bardzo ważna kwestia jeżeli chodzi o piny gpio – zmienianie ich stanu oraz jego odczytywanie. Jest to banalnie proste. Do dyspozycji mamy dwa polecenia:

int a = gpio_get_level(5);
gpio_set_level(5, 1);

Pierwsze z poleceń zwróci nam stan panujący na pinie GPIO5. Drugie ustawi stan wysoki na pinie GPIO5.

Pierwszy program – miganie diodą

Skoro już wiemy w jaki sposb skonfigurować wyprowadzenia naszego mikrokontrolera, oraz wiemy jak nimi sterować napiszmy pierwszy program wykorzystujący tę wiedzę.

#include <stdio.h>
#include <stdlib.h>

#include "freertos/freeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"

void app_main(void)
{
	gpio_config_t io_conf;
	io_conf.intr_type = GPIO_INTR_DISABLE;
	io_conf.mode = GPIO_MODE_OUTPUT;
	io_conf.pin_bit_mask = ((1<<16));
	io_conf.pull_down_en = 0;
	io_conf.pull_up_en = 0;
	
	gpio_config(&io_conf);
  
  
	while (1)
    {
    	gpio_set_level(16, 0);
    	vTaskDelay(1000 / portTICK_RATE_MS);
    	gpio_set_level(16, 1);
    	vTaskDelay(1000 / portTICK_RATE_MS);
    }
}

Powyżej podany kod sprawi, że dioda podłączona do portu GPIO16 będzie migać z częstotliwością 1Hz. Poniżej przedstawiłem efekt wgrania programu. Korzystam z płytki prototypowej NodeMCU więc port GPIO16 znajduje się na pinie oznaczonym jako D0.

Jak możesz zauważyć do projektu dołączyłem dwie biblioteki pochodzące od freertosa. Na razie nie trzeba się nimi przejmować i dołączyłem je tylko po to by realizować opóźnienie za pomocą funkcji „vTaskDelay”.


Kolejna część: #3 – przerwania i timery

Kurs esp32 i esp8266 – spis treści

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *