05 lipca 2018

Odczyt stanu przycisku

Odczytywanie stanu wejścia jest jeszcze łatwiejsze niż sterowanie wyjściami. Nie ma problemu z atomowymi dostępami, wystarczy po prostu pobrać zawartość rejestru IDR.


Oczywiście trzeba najpierw sprawdzić do którego portu i pinu jest podłączony przycisk. Odpowiednia informacja jest w dokumentacji płytki:

Czyli port A, pin 0. Na schemacie widać układ eliminujący drgania styków oraz rezystor pull-down (zawsze mnie ciekawi jak to się po polsku nazywa...).
Co więcej wciśnięcie przycisku odpowiada stanowi wysokiemu, czyli logicznej "1". To mniej popularne rozwiązanie niż zwieranie do masy, ale w sumie na jedno wychodzi.
Skoro już przy rezystorach podciągających i tych, no... pull-down jesteśmy, warto zwrócić uwagę że sam mikrokontroler też posiada takie rezystory. Można ich nie używać (co jest domyślnym ustawieniem), albo włączyć jeden z nich. Podobnie jak w przypadku rejestru MODER, teraz również do konfiguracji pinu przeznaczone są dwa bity. Znajdziemy je w rejestrze PUPDR:





Czyli chcąc uruchomić rezystor pull-down dla pinu 0, moglibyśmy napisać:

GPIOA->PUPDR |= GPIO_PUPDR_PUPD0_1;

Teraz można już napisać prosty program, który zmieni stany obu diod gdy naciśniemy przycisk:

#include <stdint.h>
#include "stm32f429xx.h"

int main(int argc, char *argv[])
{
        volatile uint32_t dly;

        RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN | RCC_AHB1ENR_GPIOGEN;

        GPIOG->MODER |= GPIO_MODER_MODE13_0|GPIO_MODER_MODE14_0;
        GPIOA->PUPDR |= GPIO_PUPDR_PUPD0_1;

        while (1) {
                if (GPIOA->IDR & 0x0001) {
                        GPIOG->BSRR = GPIO_BSRR_BS13;
                        GPIOG->BSRR = GPIO_BSRR_BR14;
                } else {
                        GPIOG->BSRR = GPIO_BSRR_BS14;
                        GPIOG->BSRR = GPIO_BSRR_BR13;
                }
        }

        return 0;
}

Program jest gotowy, a oczytywanie stanu wejścia jak widać bardzo proste. Warto jeszcze na moment wrócić do pliku Makefile. Pierwsza wersja używała na stałe zapisanej nazwy pliku wynikowego "test01". Ponieważ nowy program ma nazwę test02, więc musiałbym w kilku miejscach zmieniać plik - łatwiej zdefiniować odpowiednią zmienną. Nowy plik Makefile wygląda następująco:

CROSS_COMPILE=arm-none-eabi-

AS=$(CROSS_COMPILE)as
CC=$(CROSS_COMPILE)gcc
SIZE=$(CROSS_COMPILE)size

OUTPUT=bin/test02

CFLAGS=-mthumb -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -std=gnu11 -O0 \
        -ffunction-sections -fdata-sections -g -fstack-usage -Wall -specs=nano.specs

LDFLAGS=$(CFLAGS) -Wl,--gc-sections -specs=nosys.specs -Wl,-cref,-u,Reset_Handler \
        -Wl,-Map=$(OUTPUT).map -Tsrc/stm32f4_flash.ld

all: $(OUTPUT).elf
        $(SIZE) $<

$(OUTPUT).elf: obj/main.o obj/startup_stm32f429xx.o
        $(CC) $(LDFLAGS) -o $@ $^

obj/main.o: src/main.c
        $(CC) $(CFLAGS) -o $@ -c $<

obj/startup_stm32f429xx.o: src/startup_stm32f429xx.s
        $(CC) $(CFLAGS) -o $@ -c $<

debug: $(OUTPUT).elf
        openocd -f board/stm32f429discovery.cfg -f interface/stlink-v2.cfg \
                -c "init; sleep 200; reset halt; wait_halt; \
                flash write_image erase $(OUTPUT).elf; \
                reset run; sleep 10; shutdown"

clean:
        rm -f bin/* obj/*

W kolejnych kilku wpisach będę używał takiego pliku zmieniając tylko nazwy programów wynikowych.






Brak komentarzy:

Prześlij komentarz