Spisu treści:

AVRSH: powłoka interpretera poleceń dla Arduino/AVR.: 6 kroków (ze zdjęciami)
AVRSH: powłoka interpretera poleceń dla Arduino/AVR.: 6 kroków (ze zdjęciami)

Wideo: AVRSH: powłoka interpretera poleceń dla Arduino/AVR.: 6 kroków (ze zdjęciami)

Wideo: AVRSH: powłoka interpretera poleceń dla Arduino/AVR.: 6 kroków (ze zdjęciami)
Wideo: 👌Про Common Rail просто и понятно. Здесь (почти) всё, что вы хотели узнать про дизельный впрыск. 2024, Listopad
Anonim
AVRSH: powłoka interpretera poleceń dla Arduino/AVR
AVRSH: powłoka interpretera poleceń dla Arduino/AVR

Czy kiedykolwiek chciałeś być "zalogowany" do swojego mikrokontrolera AVR? Myślałeś kiedyś, że fajnie byłoby „kotować” rejestr, aby zobaczyć jego zawartość? Czy zawsze szukałeś sposobu na włączanie i wyłączanie poszczególnych podsystemów peryferyjnych swojego AVR lub Arduino w czasie *w czasie rzeczywistym*? Ja też, więc napisałem AVR Shell, powłokę podobną do UNIXa. Jest podobny do UNIXa, ponieważ przypomina konto powłoki, które kupiłeś i uruchomiłeś, aby uruchamiać swoje kolizje irc nick botów, a także posiada kilka wspólnych poleceń. Ma również system plików, który przypomina UNIX extfs, używający zewnętrznego EEPROM-u, ale jest to projekt sam w sobie, więc będę wydawał ten moduł osobno pod inną instrukcją, gdy będzie gotowy do produkcji. Oto lista rzeczy, które możesz obecnie zrobić z powłoką AVR:

  • Odczytuj wszystkie rejestry kierunku danych (DDRn), porty i szpilki w czasie rzeczywistym
  • Napisz do wszystkich swoich DDRn, portów i pinów, aby włączyć silniki, diody LED lub odczytać czujniki w czasie rzeczywistym
  • Wymień wszystkie znane rejestry w systemie
  • Twórz i przechowuj wartości w zmiennych zdefiniowanych przez użytkownika, których kopia zapasowa jest przechowywana w pamięci EEPROM.
  • Utwórz hasło roota i uwierzytelnij się przed nim (używane do dostępu przez telnet)
  • Odczytaj skonfigurowaną prędkość zegara procesora
  • Zmień szybkość zegara procesora, ustawiając preskaler
  • Uruchamiaj i zatrzymuj 16-bitowe zegary do pomiaru czasu różnych rzeczy
  • Włączanie i/lub wyłączanie podsystemów peryferyjnych: przetworniki analogowo-cyfrowe (ADC), szeregowy interfejs peryferyjny (SPI), interfejs dwuprzewodowy (TWI/I2C), UART/USART. Przydatne, gdy chcesz zmniejszyć pobór mocy mikrokontrolera lub włączyć niektóre funkcje.
  • Napisany w C++ z obiektami wielokrotnego użytku.

Ta instrukcja przeprowadzi Cię przez instalację, używanie i dostosowywanie avrsh.

Krok 1: Czego będziesz potrzebować

Co będziesz potrzebował
Co będziesz potrzebował

Ta instrukcja nie wymaga wiele, z wyjątkiem tego, że:

  • Posiadaj Arduino lub ATmega328P. Inne AVR mogą działać, ale może być konieczne zmodyfikowanie kodu, aby wyświetlić wszystkie rejestry, które są unikalne dla twojego MCU. Nazwy muszą tylko odpowiadać temu, co jest wymienione w pliku nagłówkowym unikalnym dla Twojego MCU. Wiele nazw rejestrów jest takich samych między AVR, więc Twój przebieg może się różnić podczas przenoszenia.
  • Mieć sposób na połączenie się z szeregowym USART swojego Arduino/AVR. System został przetestowany najbardziej szczegółowo z terminalem AVR, aplikacją Windows, która umożliwia połączenie szeregowe przez port USB lub COM. Współpracuje z Arduino za pomocą połączenia USB i dowolnym AVR za pomocą USB-BUB z Moderndevice.com. Inne opcje terminala to: Putty, minicom (Linux i FreeBSD), ekran (Linux/FreeBSD), Hyperterminal, Teraterm. Odkryłem, że putty i teraterm wysyłają trochę śmieci podczas łączenia, więc twoje pierwsze polecenie może być zniekształcone.
  • Zainstaluj i uruchom oprogramowanie wewnętrzne AVR Shell, które możesz pobrać z tych stron, lub zawsze pobierz najnowszą wersję z BattleDroids.net.

Aby zainstalować Terminal AVR, wystarczy go rozpakować i uruchomić. Aby zainstalować firmware AVR Shell, pobierz go i albo bezpośrednio prześlij plik hex i podłącz terminal szeregowy z prędkością 9600 bodów, albo skompiluj go samodzielnie za pomocą „make”, a następnie „make program”, aby wgrać hex. Uwaga, może być konieczna zmiana ustawień AVRDUDE, aby odzwierciedlić port COM. Uwaga: Atrybut PROGMEM jest uszkodzony w obecnej implementacji AVR GCC dla C++ i jest to znany błąd. Jeśli go skompilujesz, spodziewaj się wielu komunikatów ostrzegawczych mówiących „ostrzeżenie: tylko zainicjalizowane zmienne mogą być umieszczone w obszarze pamięci programu”. Poza tym, że jest irytujące, to ostrzeżenie jest nieszkodliwe. Ponieważ C++ na wbudowanej platformie nie znajduje się wysoko na liście priorytetów AVR GCC, nie wiadomo, kiedy zostanie to naprawione. Jeśli sprawdzisz kod, zobaczysz, gdzie dokonałem obejścia, aby zmniejszyć to ostrzeżenie, implementując własne instrukcje atrybutów. Dość proste. Pobierz i zainstaluj wszystko, co może być potrzebne, aby odwrócić stronę i zaczynajmy.

Krok 2: Odczytywanie i pisanie rejestrów

Czytanie i pisanie rejestrów
Czytanie i pisanie rejestrów

Powłoka AVR została napisana głównie w celu uzyskania dostępu do niektórych czujników, które podłączyłem do mojego AVR. Zaczęło się od prostej diody LED, a następnie przeniesiono do czujników światła, czujników temperatury, a na końcu do dwóch przetworników ultradźwiękowych. avrsh może ustawić cyfrowe komponenty tych czujników, zapisując je do rejestrów, które je kontrolują. Manipulowanie rejestrami AVR podczas pracy Aby uzyskać listę wszystkich znanych rejestrów na Arduino, wpisz:

rejestry wydruku a otrzymasz wydruk wyglądający tak

Znam następujące rejestry:

TIFR0 PORTC TIFR1 PORTD TIFR2 DDRD PCIFR DDRB EIFR DDRC EIMSK PINB EECR PINC EEDR PIND SREG EEARL GPIOR0 EEARH GPIOR1 GTCCR GPIOR2 TCCR0A TCCR0B TCNT0 OCR0A OCR0B SPCR SPDR ACSR SMCR MCUSR MCUCR SPMCSR WDTCSR CLKPR PRR OSCCAL PCICR EICRA PCMSK0 PCMSK1 TIMSK0 TIMSK1 TIMSK2 ADCL ADCH ADCSRA ADCSRB ADMUX DIDR0 DIDR1 TCCR1A TCCR1B TCCR1C TCNT1L TCNT1H ICR1L ICR1H OCR1AL OCR1AH OCR1BL OCR1BH TCCR2A TCCR2B TCNT2 OCR2A OCR2B ASSR TWBR TWSR TWARRRB TWARRRUCSRUC TW 0 Aby zobaczyć, jak poszczególne bity są ustawione w dowolnym rejestrze, użyj polecenia cat lub echo

kot %GPIOR0 Proszę tutaj interpretera poleceń o wyświetlenie lub wyświetlenie echa zawartości rejestru we/wy ogólnego przeznaczenia #0. Zwróć uwagę na znak procentu (%) przed nazwą rejestru. Potrzebujesz tego, aby wskazać powłoce, że jest to zastrzeżone słowo kluczowe identyfikujące rejestr. Typowe wyjście z polecenia echo wygląda tak

GPIOR0(0x0) ustawione na [00000000] Wyjście pokazuje nazwę rejestru, wartość szesnastkową znalezioną w rejestrze i binarną reprezentację rejestru (przedstawiając każdy bit jako 1 lub 0). Aby ustawić określony bit w dowolnym rejestrze, użyj operatora „indeks” . Załóżmy na przykład, że chcę, aby trzeci bit był 1

%GPIOR0[3] = 1 a powłoka udzieli odpowiedzi wskazującej na działanie i wynik

GPIOR0(0x0) ustawione na [00000000] (0x8) ustawione na [00001000] Nie zapomnij znaku procentu, aby powiedzieć powłoce, że pracujesz z rejestrem. Zauważ też, że ustawiając trzeci bit, to są 4 bity, ponieważ nasz AVR używa indeksu liczonego od zera. Innymi słowy, licząc do 3 bitu, liczysz 0, 1, 2, 3, czyli 4 miejsce, ale 3 bit. Możesz skasować bit w ten sam sposób, ustawiając bit na zero. Ustawiając takie bity, możesz zmienić działanie swojego AVR w locie. Na przykład zmieniając wartość dopasowania zegara CTC znalezioną w OCR1A. Pozwala także zajrzeć do określonych ustawień, które musiałbyś programowo sprawdzić w swoim kodzie, takich jak wartość UBBR dla szybkości transmisji. Praca z DDRn, PORTn i PINn Piny I/O są również przypisane do rejestrów i można je ustawić dokładnie w ten sam sposób, ale stworzono specjalną składnię do pracy z tego typu rejestrami. W kodzie istnieje normalny proces, na przykład włączania diody LED lub innego urządzenia, które wymaga cyfrowego wysokiego lub niskiego poziomu. Wymaga to ustawienia rejestru kierunku danych, aby wskazać, że pin jest do wyprowadzenia, a następnie wpisania 1 lub 0 do konkretnego bitu we właściwym porcie. Zakładając, że mamy diodę LED podłączoną do cyfrowego pinu 13 (PB5) i chcemy ją włączyć, oto jak to zrobić, gdy Twój AVR jest uruchomiony

ustaw pin pb5 outputwrite pin pb5 high Wyjście, oprócz możliwości zobaczenia, jak twoja dioda LED się włącza, wyglądałoby tak

root@ATmega328p> ustaw pin pb5 outputSet pb5 dla outputroot@ATmega328p> write pin pb5 highWrote logic high to pin pb5 "root@ATmega328p>" to znak zachęty powłoki, który wskazuje, że jest gotowa do przyjęcia poleceń od ciebie. Aby wyłączyć diodę LED, wystarczy wpisać stan niski do pinu. Jeśli chcesz odczytać wejście cyfrowe z pinu, użyj polecenia read. Korzystając z naszego powyższego przykładu

root@ATmega328p> przeczytaj pin pb5Pin: pb5 jest WYSOKI Alternatywnie, po prostu powtórz rejestr pinów, który kontroluje ten port pinów. Na przykład, jeśli mamy przełączniki DIP podłączone do pinów cyfrowych 7 i 8 (PD7 i PD8), można wysłać polecenie

echo %PIND a powłoka wyświetliłaby zawartość tego rejestru, pokazując wszystkie stany wejścia/wyjścia podłączonych urządzeń oraz czy stan przełącznika był włączony czy wyłączony.

Krok 3: Bezpieczniki czytania i pisania

Bezpieczniki do czytania i pisania
Bezpieczniki do czytania i pisania

Bezpieczniki to specjalne rodzaje rejestrów. Kontrolują one wszystko, od szybkości zegara mikrokontrolera po dostępne metody programowania w pamięci EEPROM chroniącej przed zapisem. Czasami będziesz musiał zmienić te ustawienia, zwłaszcza jeśli tworzysz samodzielny system AVR. Nie jestem pewien, czy powinieneś zmienić ustawienia bezpieczników na Arduino. Uważaj na bezpieczniki; możesz zablokować się, jeśli ustawisz je nieprawidłowo. W poprzedniej instrukcji zademonstrowałem, jak możesz czytać i ustawiać bezpieczniki za pomocą programatora i avrdude. Tutaj pokażę, jak odczytać bezpieczniki w czasie wykonywania, aby zobaczyć, jak faktycznie je ustawił MCU. Zauważ, że nie jest to ustawienie czasu kompilacji, które otrzymujesz z definicji, ale rzeczywiste bezpieczniki, gdy MCU odczytuje je w czasie wykonywania. Z tabeli 27-9 w arkuszu danych ATmega328P (databook, bardziej podobny) bity młodszego bajtu bezpiecznika są następujące:

CKDIV8 CKOUT SUT1 SUT0 CKSEL3 CKSEL2 CKSEL1 CKSEL0Warto zauważyć, że w przypadku bezpieczników 0 oznacza zaprogramowane, a 1 oznacza, że dany bit jest niezaprogramowany. Nieco sprzeczne z intuicją, ale kiedy już to wiesz, to już wiesz.

  • CKDIV8 ustawia zegar twojego procesora na dzielony przez 8. ATmega328P jest fabrycznie zaprogramowany na używanie wewnętrznego oscylatora 8 MHz z zaprogramowanym CKDIV8 (tj. ustawionym na 0), co daje ostateczną częstotliwość F_CPU lub procesora na poziomie 1 MHz. W Arduino uległo to zmianie, ponieważ są one skonfigurowane do korzystania z zewnętrznego oscylatora o częstotliwości 16 MHz.
  • CKOUT po zaprogramowaniu wyprowadzi zegar procesora na PB0, który jest cyfrowym pinem 8 na Arduino.
  • SUT[1..0] określa czas uruchomienia odbiornika AVR.
  • CKSEL[3..0] ustawia źródło zegara, takie jak wewnętrzny oscylator RC, oscylator zewnętrzny itp.

Kiedy przeczytasz swoje bezpieczniki, zostanie ci zwrócony w postaci szesnastkowej. Jest to format, którego potrzebujesz, jeśli chcesz napisać bezpieczniki przez avrdude. Na moim arduino oto, co otrzymuję, gdy czytam dolny bajt bezpiecznika:

root@ATmega328p> przeczytaj lfuseDolny bezpiecznik: 0xffTak więc wszystkie bity są ustawione na 1. Wykonałem tę samą procedurę na klonie Arduino i otrzymałem tę samą wartość. Sprawdzając jeden z moich samodzielnych systemów AVR, uzyskałem 0xDA, czyli wartość, którą ustawiłem jakiś czas temu podczas konfigurowania układu. Ta sama procedura jest używana do sprawdzania bezpieczników High Fuse Byte, Extended Fuse Byte i Lock. Bajty bezpiecznika kalibracji i podpisu zostały wyłączone w kodzie za pomocą dyrektywy preprocesora #if 0, którą można zmienić, jeśli czujesz się brzydki.

Krok 4: Inne polecenia

Inne polecenia
Inne polecenia

Istnieje kilka innych poleceń, które domyślny interpreter poleceń rozumie, a które mogą okazać się przydatne. Możesz zobaczyć wszystkie zaimplementowane i przyszłe polecenia, wydając pomoc lub menu w wierszu polecenia. Szybko omówię je tutaj, ponieważ w większości nie wymagają wyjaśnień. Ustawienia częstotliwości zegara procesora Możesz dowiedzieć się, jakie oprogramowanie układowe zostało skonfigurowane do używania jako ustawienia zegara procesora za pomocą polecenia fcpu:

root@ATmega328p> fcpuCPU Freq: 16000000To 16 milionów lub 16 milionów herców, bardziej znanych jako 16 MHz. Możesz to zmienić w locie, z dowolnego powodu, za pomocą polecenia zegara. To polecenie przyjmuje jeden argument: preskaler, który ma być używany podczas dzielenia szybkości zegara. Polecenie clock rozumie te wartości preskalera:

  • ckdiv2
  • ckdiv4
  • ckdiv8
  • ckdiv16
  • ckdiv32
  • ckdiv64
  • ckdiv128
  • ckdiv256

Za pomocą polecenia:

zegar ckdiv2 gdy prędkość twojego procesora wynosi 16 MHz, spowoduje to zmianę prędkości zegara na 8 MHz. Użycie preskalera ckdiv64 z początkową częstotliwością zegara 16 MHz da w rezultacie końcową częstotliwość zegara 250 KHz. Dlaczego u licha miałbyś chcieć spowolnić swój MCU? Cóż, po pierwsze, niższa częstotliwość taktowania zużywa mniej energii, a jeśli masz MCU wyładowany z baterii w obudowie projektu, możesz nie potrzebować jej do pracy z najwyższą prędkością, a zatem może obniżyć prędkość i zmniejszyć zużycie energii, zwiększając żywotność baterii. Ponadto, jeśli używasz zegara do jakichkolwiek problemów z synchronizacją z innym MCU, powiedzmy, implementując oprogramowanie UART lub coś podobnego, możesz chcieć ustawić go na konkretną wartość, która jest łatwa do uzyskania ładnej, równej szybkości transmisji z niższe wskaźniki błędów. Włączanie i wyłączanie podsystemów peryferyjnych Podobnie jak w przypadku wspomnianego wcześniej zmniejszenia zużycia energii, możesz chcieć jeszcze bardziej zmniejszyć pobór mocy, wyłączając niektóre z wbudowanych urządzeń peryferyjnych, których nie używasz. Interpreter poleceń i powłoka mogą obecnie włączać i wyłączać następujące urządzenia peryferyjne:

  • Przetwornik analogowo-cyfrowy (ADC). To urządzenie peryferyjne jest używane, gdy masz analogowy czujnik dostarczający dane (takie jak temperatura, światło, przyspieszenie itp.) i musisz przekonwertować je na wartość cyfrową.
  • Szeregowy interfejs peryferyjny (SPI). Magistrala SPI służy do komunikacji z innymi urządzeniami obsługującymi SPI, takimi jak pamięci zewnętrzne, sterowniki LED, zewnętrzne przetworniki ADC itp. Części SPI są używane do programowania ISP, a przynajmniej piny, więc bądź ostrożny podczas wyłączania tego jeśli programujesz przez ISP.
  • Interfejs dwuprzewodowy. Niektóre urządzenia zewnętrzne wykorzystują do komunikacji magistralę I2C, chociaż są one szybko zastępowane przez urządzenia obsługujące SPI, ponieważ SPI ma większą przepustowość.
  • USART. To jest twój interfejs szeregowy. Prawdopodobnie nie chcesz tego wyłączać, jeśli jesteś podłączony do AVR przez połączenie szeregowe! Jednak dodałem to tutaj jako szkielet do przenoszenia do urządzeń, które mają wiele USART, takich jak ATmega162 lub ATmega644P.
  • wszystko. Ten argument polecenia powerup lub powerdown włącza wszystkie wymienione urządzenia peryferyjne lub wyłącza je wszystkie jednym poleceniem. Ponownie używaj tego polecenia mądrze.

root@ATmega328p> powerdown twiPowerdown twi complete.root@ATmega328p> powerup twiPowerup twi zakończone.

Uruchamianie i zatrzymywanie timerów Powłoka ma wbudowany 16-bitowy timer, z którego można korzystać. Timer uruchamiasz poleceniem timera:

start timerai zatrzymaj stoper argumentem stop

zatrzymanie timeraTen zegar nie będzie kolidował z wewnętrznym zegarem USART. Zobacz kod dla szczegółów implementacji timera USART, jeśli ten rodzaj krwawych szczegółów Cię interesuje

root@ATmega328p> start timeraUruchomiony timer.root@ATmega328p> stop timeraUpływający czas: ~157 sekund Uwierzytelnianie Powłoka może przechowywać w pamięci EEPROM 8-znakowe hasło. Ten mechanizm haseł został stworzony w celu obsługi możliwości logowania przez telnet, ale można go rozszerzyć w celu ochrony innych rzeczy. Na przykład możesz wymagać pewnych poleceń, takich jak zmiana wartości rejestru, poprzez mechanizm uwierzytelniania. Ustaw hasło za pomocą polecenia password

root@ATmega328p> passwd blahWpisał hasło roota do EEPROMAutoryzuj za pomocą hasła (lub wymagaj autoryzacji programowo za pomocą kodu) za pomocą polecenia auth. Pamiętaj, że jeśli próbujesz zmienić hasło roota i masz już ustawione hasło roota, musisz autoryzować się przed starym hasłem, zanim będziesz mógł zmienić je na nowe hasło

root@ATmega328p> passwd blinkyMusisz się najpierw autoryzować.root@ATmega328p> auth blahAuthorized.root@ATmega328p> passwd blinkyNapisał NOWE hasło roota do EEPROMOczywiście będziesz musiał załadować plik avrsh.eep, jeśli usuniesz oprogramowanie układowe, aby przywrócić stare wartości i zmienne. Makefile utworzy dla ciebie plik EEPROM. Zmienne Powłoka rozumie pojęcie zmiennych zdefiniowanych przez użytkownika. Kod ogranicza to do 20, ale możesz to zmienić, jeśli chcesz, zmieniając definicję MAX_VARIABLES w script.h. Możesz zapisać dowolną wartość 16-bitową (to znaczy dowolną liczbę do 65, 536) do zmiennej, która zostanie przywołana później. Składnia jest podobna do rejestrów z wyjątkiem znaku dolara ($) używanego do oznaczenia zmiennych w powłoce. Wyświetl wszystkie zmienne za pomocą polecenia drukowania zmiennych

print zmienne Zmienne definiowane przez użytkownika: Nazwa indeksu -> Wartość(01): $FREE$ -> 0(02): $FREE$ -> 0(03): $FREE$ -> 0(04): $FREE$ -> 0(05): $WOLNY$ -> 0(06): $WOLNY$ -> 0(07): $WOLNY$ -> 0(08): $WOLNY$ -> 0(09): $WOLNY$ -> 0(10): $WOLNY$ -> 0(11): $WOLNY$ -> 0(12): $WOLNY$ -> 0(13): $WOLNY$ -> 0(14): $WOLNY$ -> 0(15): $WOLNY$ -> 0(16): $WOLNY$ -> 0(17): $WOLNY$ -> 0(18): $WOLNY$ -> 0(19): $WOLNY$ -> 0(20): $FREE$ -> 0Complete. Ustaw zmienną

$ newvar = 25 $ timeout = 23245Pobierz wartość danej zmiennej

root@ATmega328p> echo $nowazmienna$ nowazmienna 25Możesz zobaczyć, jakie wszystkie zmienne, które aktualnie utworzyłeś za pomocą polecenia drukowania, które już znasz

Zmienne zdefiniowane przez użytkownika: Nazwa indeksu -> Wartość(01): newvar -> 25(02): timeout -> 23245(03): $FREE$ -> 0(04): $FREE$ -> 0(05): $FREE$ -> 0(06): $FREE$ -> 0(07): $FREE$ -> 0(08): $FREE$ -> 0(09): $FREE$ -> 0(10): $FREE$ -> 0(11): $FREE$ -> 0(12): $FREE$ -> 0(13): $FREE$ -> 0(14): $FREE$ -> 0(15): $FREE$ -> 0(16): $FREE$ -> 0(17): $FREE$ -> 0(18): $FREE$ -> 0(19): $FREE$ -> 0(20): $FREE$ -> 0Zakończono. Nazwa $FREE$ wskazuje po prostu, że ta lokalizacja zmiennej jest wolna i nie została jeszcze przypisana nazwa zmiennej.

Krok 5: Dostosowywanie powłoki

Dostosowywanie powłoki
Dostosowywanie powłoki

Możesz włamać się do kodu i dostosować go do własnych potrzeb, jeśli chcesz. Gdybym wiedział, że wydam ten kod, stworzyłbym oddzielną klasę interpretera poleceń i strukturę poleceń i po prostu wykonałbym iterację, wywołując wskaźnik do funkcji. Zmniejszyłoby to ilość kodu, ale w obecnej postaci powłoka analizuje wiersz poleceń i wywołuje odpowiednią metodę powłoki. Aby dodać własne niestandardowe polecenia, wykonaj następujące czynności: 1. Dodaj swoje polecenie do listy parsowania Parser poleceń będzie przeanalizuj wiersz poleceń i podaj osobno polecenie i wszelkie argumenty. Argumenty są przekazywane jako wskaźniki do wskaźników lub jako tablica wskaźników, jakkolwiek lubisz z nimi pracować. Znajduje się w shell.cpp. Otwórz shell.cpp i znajdź metodę ExecCmd klasy AVRShell. Możesz dodać polecenie do pamięci programu. Jeśli tak, dodaj polecenie w progmem.hi progmem.cpp. Możesz dodać polecenie do pamięci programu bezpośrednio za pomocą makra PSTR(), ale wygenerujesz kolejne ostrzeżenie wspomnianego wcześniej typu. Ponownie, jest to znany błąd działający z C++, ale można go obejść, dodając polecenie bezpośrednio w plikach progmem.*, tak jak to zrobiłem. Jeśli nie masz nic przeciwko zwiększeniu wykorzystania pamięci SRAM, możesz dodać polecenie, jak zilustrowałem za pomocą polecenia „clock”. Załóżmy, że chcesz dodać nowe polecenie o nazwie „newcmd”. Przejdź do AVRShell::ExecCmd i znajdź dogodne miejsce do wstawienia następującego kodu:

else if (!strcmp(c, "newcmd")) cmdNewCmd(args);Spowoduje to dodanie polecenia i wywołanie metody cmdNewCmd, którą napiszesz w następnym kroku. 2. Wpisz własny kod komendy W tym samym pliku dodaj własny kod komendy. To jest definicja metody. Nadal będziesz chciał dodać deklarację do shell.h. Po prostu dołącz go do innych poleceń. W poprzednim przykładzie kod może wyglądać mniej więcej tak

voidAVRShell::cmdNewCmd(char ** args){ sprintf_P(buff, PSTR("Twoje polecenie to %s\r\n", args[0]); WriteRAM(buff);}Jest tu kilka rzeczy. Po pierwsze, "buff" to 40-znakowy bufor tablicy dostarczony w kodzie do użytku. Używamy wersji sprintf z pamięcią programu, ponieważ przekazujemy jej plik PSTR. Możesz użyć zwykłej wersji, jeśli chcesz, ale upewnij się, że nie przekazujesz formatu w PSTR. Ponadto argumenty znajdują się w tablicy args. Jeśli wpiszesz „newcmd arg1 arg2”, możesz uzyskać te argumenty za pomocą indeksów dolnych args[0] i args[1]. Możesz przekazać maksymalnie MAX_ARGS argumentów, zgodnie z definicją w kodzie. Możesz zmienić tę wartość podczas ponownej kompilacji, jeśli potrzebujesz wielu dodatkowych argumentów do przekazania naraz. WriteLine i WriteRAM to funkcje globalne, które zwracają metody UART o tej samej nazwie. Drugi argument tej funkcji jest niejawny. Jeśli nic nie podasz, później zostanie napisany wiersz polecenia. Jeśli jako drugi argument podasz 0, znak zachęty nie zostanie napisany. Jest to przydatne, gdy chcesz napisać kilka oddzielnych ciągów do wyjścia, zanim wiersz polecenia zostanie zwrócony użytkownikowi. 3. Spraw, aby powłoka wykonała kod polecenia. Powiedziałeś już executorowi powłoki, aby wykonał metodę cmdNewCmd podczas konfigurowania nowego polecenia, ale dodaj ją do pliku shell.h, aby była zrozumiała przez obiekt powłoki. Po prostu dodaj go pod ostatnim poleceniem lub przed pierwszym poleceniem lub w dowolnym miejscu. I to wszystko. Ponownie skompiluj i prześlij oprogramowanie układowe do Arduino, a nowe polecenie jest dostępne w powłoce po wyświetleniu monitu.

Krok 6: Podsumowanie

Powinieneś wiedzieć, jak zainstalować i połączyć się z AVR/Arduino i uzyskać komunikat na żywo na uruchomionym mikrokontrolerze. Znasz kilka poleceń, które będą pobierać dane środowiska wykonawczego z MCU lub ustawiać wartości do MCU w locie. Pokazano również, jak dodać własny niestandardowy kod, aby utworzyć własne unikalne polecenia w powłoce, aby jeszcze bardziej dostosować ją do własnych potrzeb. Możesz nawet wypatroszyć interpreter poleceń, aby zawierał tylko niestandardowe polecenia, jeśli odpowiada to Twoim potrzebom. Mam nadzieję, że podobało Ci się to instruktażowe i że powłoka AVR może być dla Ciebie przydatna jako interpreter poleceń w czasie rzeczywistym lub jako proces uczenia się we wdrażaniu własnego. Jak zawsze czekam na wszelkie komentarze lub sugestie, w jaki sposób można ulepszyć tę instrukcję! Baw się dobrze ze swoim AVR!

Zalecana: