Jak działają rejestry IO Arduino Due? Arduino Uno tylko na ustawiony DDRx
, a następnie PINx
czytać, PORTx
pisać, chciałbym zrobić to samo z Arduino Due, ale ma wiele więcej rejestrów, takich jak PIO_OWER
, PIO_OSER
, PIO_CODR
, PIO_SODR
, itd. Nie znajduję żadnej korespondencji pomiędzy Arduino Uno i Rejestry Arduino Due.
Istnieje również kilka przydatnych funkcji, takich jak pio_clear
, pio_set
, pio_get
i innych, wszystko wyjaśnione tutaj:
http://asf.atmel.com/docs/3.19.0/sam3x/html/group__sam__drivers__pio__group.html
Myślę, że zrozumiałem, co robią te trzy wymienione funkcje, ale nie inne, na przykład:
pio_configure (Pio *p_pio, const pio_type_t ul_type, const uint32_t ul_mask, const uint32_t ul_attribute)
Nie mogę dowiedzieć się, co ul_attribute
i ul_type
są.
arduino-due
c
port-mapping
Alex
źródło
źródło
Odpowiedzi:
Jeśli zapoznałeś się z sekcją 31 arkusza danych, dostępną tutaj , sprawy mogą stać się dla ciebie trochę jaśniejsze.
Oto podsumowanie tego, co wiem:
PIO oznacza Parallel Input / Output i oferuje funkcję odczytu i zapisu wielu portów rejestrów jednocześnie. Gdzie arkusz danych wspomina o rejestrze, na przykład PIO_OWER, biblioteka Arduino ma makra umożliwiające dostęp do nich w tym formacie REG_PIO? _OWER gdzie? ma wartość A, B, C lub D dla różnych dostępnych portów.
Nadal używam powolnej funkcji pinMode () Arduino do ustawiania wejścia / wyjścia na pinach, ponieważ sprawia, że kod jest bardziej czytelny niż wywołania rejestrów oparte na akronimie, takie jak REG_PIOC_OWER = 0xdeadbeef, ale następnie używam rejestrów bezpośrednich, aby ustawić piny dla wydajność / synchronizacja. Jak dotąd nic nie zrobiłem z danymi wejściowymi, więc wszystkie moje przykłady są oparte na danych wyjściowych.
Do podstawowego użycia użyłbyś REG_PIO? _SODR, aby ustawić wysokie linie wyjściowe, a REG_PIO? _CODR, aby ustawić je na niskie. Na przykład REG_PIOC_SODR = 0x00000002 ustawiłby bit 1 (ponumerowany od zera) na PORTC (jest to cyfrowy pin 33) wysoki. Wszystkie pozostałe piny na PORTC pozostają niezmienione. REG_POIC_CODR = 0x00000002 ustawi bit 1 na PORTC na niski. Ponownie wszystkie pozostałe szpilki pozostaną niezmienione.
Ponieważ nadal nie jest to optymalne lub zsynchronizowane, jeśli pracujesz z danymi równoległymi, istnieje rejestr, który pozwala zapisać wszystkie 32 bity portu za pomocą jednego wywołania. Są to REG_PIO? _ODSR, więc REG_PIOC_ODSR = 0x00000002 ustawi teraz bit 1 na PORTC high, a wszystkie inne bity na PORTC zostaną natychmiast ustawione na niski w pojedynczej instrukcji CPU.
Ponieważ jest mało prawdopodobne, abyś kiedykolwiek znalazł się w sytuacji, w której musisz ustawić wszystkie 32 bity portu jednocześnie, musisz zapisać bieżącą wartość pinów, wykonać operację AND, aby zamaskować te, które chcesz zmienić, wykonaj operację LUB, aby ustawić te, które chcesz ustawić wysoko, a następnie wykonaj zapis i jeszcze raz, a to nie jest optymalne. Aby temu zaradzić, sam procesor wykona dla Ciebie maskowanie. Istnieje rejestr o nazwie OWSR (rejestr stanu zapisu wyjściowego), który zamaskuje wszystkie bity, które zapisujesz do ODSR, które nie pasują do bitów ustawionych w OWSR.
Więc teraz, jeśli wywołamy REG_PIOC_OWER = 0x00000002 (ustawia to bit 1 OWSR na wysoki) i REG_PIOC_OWDR = 0xfffffffd (to usuwa wszystkie bity oprócz bitu 1 OWSR), a następnie ponownie wywołamy REG_PIOC_ODSR = 0x00000002, tym razem zmieni tylko bit 1 PORTC i wszystkie inne bity pozostają niezmienione. Zwróć uwagę na fakt, że OWER włącza wszystkie bity, które są ustawione na 1 w zapisywanej wartości, oraz że OWDR wyłącza wszystkie bity, które są ustawione na 1 w zapisywanej wartości. Chociaż zrozumiałem to, kiedy to czytałem, nadal popełniłem błąd w kodzie podczas pisania mojego pierwszego kodu testowego, myśląc, że bity wyłączone OWDR, które nie były ustawione na 1 w wartości, którą napisałem.
Mam nadzieję, że dzięki temu przynajmniej zrozumiałeś PIO właściwego procesora. Przeczytaj i zagraj, a jeśli masz dodatkowe pytania, postaram się na nie odpowiedzieć.
Edycja: Jeszcze jedna rzecz ...
Skąd wiesz, które bity PORTÓW odpowiadają którym cyfrowym liniom należnym? Sprawdź to: Due Pinout
źródło
Występuje dość prosta równoważność podstawowego bezpośredniego dostępu do pinów. Poniżej znajduje się przykładowy kod, który pokazuje, jak ustawić pin wysoki, a następnie niski. Pierwszy dotyczy Arduino Due, drugi dotyczy Arduino Uno / Mega / etc.
Wszystko, co jest do tego potrzebne, powinno być domyślnie dołączone - a jeśli nie,
#include <Arduino.h>
powinno wystarczyć, aby to osiągnąć.W rzeczywistości dostępne są funkcje, które można wywołać, gdy
Pio
pojawi się wskaźnik do wykonania ustawień / usuwania / rezystorów pullup / itp. używając nieco czystszych wywołań funkcji. Pełna lista znajduje się w plik nagłówka.źródło
To przykład kodu, który miga diodą na pinie 33. Kod pożyczony z góry - wielkie dzięki za bardzo pomocne wyjaśnienia :) To początek projektu rozmowy z ekranem dotykowym TFT z zrzutem 16-bitowych kolorowych pikseli, które potrzebują szybki dostęp do portów. Myślę, że mam odpowiedni kod - szczególnie linię, która ustawia pin na niskim poziomie. Dioda LED szczęśliwie miga.
źródło