Repository navigation
gpio.pl
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.
-
alternatewybiera peryferium numerem z tabeli funkcji alternatywnych w karcie katalogowej. Sterowniki UART, SPI i I2C konfigurują swoje piny z mapy pinówGPIO_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.
- 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.
-
speedustala stromość zboczy: niską dla diody LED albo przekaźnika, bo strome zbocza emitują zakłócenia, a wysoką dla SPI albo PWM.
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.
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.
EXTI_t obsługuje zbocze narastające albo opadające od razu, bez czekania na kolejny przebieg pętli.
-
rise_detectifall_detectwybierają zbocza, aRiseHandleriFallHandlerto 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_FalliEXTI_Eventszwracają 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
nwszystkich portów, więcPA3iPB3nie mogą mieć przerwania jednocześnie.
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 };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();
}
}