Skip to content

gpio.pl

Xaeian edited this page Oct 23, 2026 · 2 revisions

Wejścia i wyjścia ogólnego przeznaczenia

GPIO (general-purpose input/output) to pin, z którego program korzysta bezpośrednio: ustawia stan wyjścia i odczytuje stan wejścia. Każdy pin należy do portu, GPIOA, GPIOB i kolejnych, i ma numer od 0 do 15, więc PA5 to pin 5 portu A. Jedna struktura GPIO_t opisuje jeden pin: gdzie się znajduje i jak działa. Programy na sterownikach OpenCPLC korzystają z DIN i DOUT, zbudowanych na GPIO, a bezpośrednio z GPIO korzystają sterowniki układów i projekty bare-metal.

Tryby

Tryby pinu

  • alternate wybiera peryferium numerem z tabeli funkcji alternatywnych w karcie katalogowej. Sterowniki UART, SPI i I2C konfigurują swoje piny z mapy pinów GPIO_Map_t, więc w programie rzadko jest to potrzebne.
  • W trybie analogowym cyfrowe wejście i wyjście są wyłączone, więc nic nie zakłóca pracy ADC ani DAC na tym pinie.
  • Pin może zmieniać tryb w trakcie pracy: sterownik 1-Wire ściąga linię do stanu niskiego jako wyjście, a potem odczytuje ją jako wejście.

Wyjście

Push-pull i open-drain

  • Push-pull wymusza oba stany: górny tranzystor łączy pin z VDD, a dolny z GND.
  • Open-drain tylko ściąga linię do stanu niskiego, a stan wysoki zapewnia rezystor. Wiele wyjść może dzielić jedną linię, jak w I2C, i każde z nich może ją ściągnąć do stanu niskiego.
  • speed ustala stromość zboczy: niską dla diody LED albo przekaźnika, bo strome zbocza emitują zakłócenia, a wysoką dla SPI albo PWM.

Wejście

Pull-up i pull-down

Wejście, którego nic nie wymusza, jest pływające: zbiera zakłócenia i daje przypadkowy odczyt. pull słabo łączy je z VDD albo z GND, więc wejście bez sygnału daje 1 z GPIO_Pull_Up i 0 z GPIO_Pull_Down. Wewnętrzny rezystor jest słaby, więc długi przewód albo silne zakłócenia w maszynie wymagają rezystora o mniejszej wartości na płytce.

Poziom logiczny

Aktywny stanem wysokim i niskim

reverse odwraca logikę: GPIO_Set ustawia na pinie stan niski, a GPIO_In odczytuje stan niski jako true. Dzięki temu kod wyraża znaczenie stanu: włączony, wciśnięty, wybrany, a sposób podłączenia zostaje w deklaracji pinu. Przycisk do GND, dioda LED od VDD albo linia wyboru układu aktywna stanem niskim mają .reverse = true.

Przerwania od zbocza

EXTI_t obsługuje zbocze narastające albo opadające od razu, bez czekania na kolejny przebieg pętli.

  • rise_detect i fall_detect wybierają zbocza, a RiseHandler i FallHandler to funkcje wywoływane przy każdym z nich.
  • Funkcja obsługi działa w przerwaniu, więc powinna być krótka: ustawić flagę albo zwiększyć licznik.
  • EXTI_Rise, EXTI_Fall i EXTI_Events zwracają liczbę zboczy od ostatniego odczytu i ją zerują, więc impulsy można liczyć bez żadnej funkcji obsługi.
  • Jedna linia przerwania obsługuje pin n wszystkich portów, więc PA3 i PB3 nie mogą mieć przerwania jednocześnie.

Konfiguracja

Pominięte pola mają wartość zero: wejście, bez podciągania, push-pull, najniższa prędkość, set wyłączone.

// A LED from PA5 to GND, a button from PC13 to GND
static GPIO_t led = { .port = GPIOA, .pin = 5, .mode = GPIO_Mode_Output };
static GPIO_t button = { .port = GPIOC, .pin = 13, .pull = GPIO_Pull_Up,
  .reverse = true };

// Pulses of a meter on PB3, an open collector to GND, counted on the falling edge
static EXTI_t meter = { .port = GPIOB, .pin = 3, .pull = GPIO_Pull_Up,
  .fall_detect = true, .irq_enable = true };

Użycie

GPIO_Init zapisuje konfigurację do portu i ustawia stan z pola set, więc od startu pin pracuje tak, jak go zadeklarowano.

static uint32_t pulses; // of the meter since the start

void loop(void)
{
  GPIO_InitList(&led, &button, NULL);
  EXTI_Init(&meter);
  while(1) {
    // A pressed button pulls the pin low, and `reverse` reads it as true
    if(GPIO_In(&button)) GPIO_Set(&led);
    else GPIO_Rst(&led);
    pulses += EXTI_Fall(&meter); // the edges since the last pass
    let();
  }
}

Clone this wiki locally