Od dłuższego czasu używam płytki Arduino Uno, w tym jako przykłady do wielu moich artykułów. Zawsze zastanawiałem się, co byłoby potrzebne, aby uruchomić ATmega328P (oryginalny chip używany na starszych płytach Uno) całkowicie samodzielnie. Biorąc pod uwagę, jak Arduino ułatwia to za pomocą swojego bootloadera, przyjemnego interfejsu GUI i abstrakcji C++, można by się zastanawiać, dlaczego w ogóle chciałbym to próbować. Czasami, aby docenić to, co zrobili inni, ważne jest, aby spróbować zrobić to samemu. Ten projekt naprawdę pokazał, ile pracy włożyli ludzie z Arduino i jak zmienili świat tym przyjaznym małym produktem.
W tym artykule przejdziemy przez proces uruchamiania chipa całkowicie samodzielnie, używając tylko zewnętrznego źródła zasilania i programatora Atmel-ICE. Pokażemy, jak komunikować się z chipem za pomocą wbudowanego interfejsu szeregowego oraz jak mrugać jedną lub dwiema diodami LED.
Istnieje kilka sposobów konfiguracji ATmega328P. Jednym z nich, celowo nieomówionym, jak można wywnioskować z tytułu, jest włożenie chipa ATmega328P do Arduino Uno, zaprogramowanie go, a następnie przeniesienie na płytę stykową. Na podstawie opinii na forach niektórzy ludzie chcą pominąć proces Arduino i użyć bardziej tradycyjnego podejścia z programatorami takimi jak Atmel-ICE od Microchip. Najprostszym sposobem rozpoczęcia pracy z mikroprocesorem Microchip (dawniej Atmel) jest zainstalowanie Microchip Studio. W momencie pisania tego artykułu pełny pakiet Microchip Studio jest obsługiwany tylko w systemie Windows. Ponieważ lubię mieć wszystkie moje środowiska budowania uruchomione w CI (Continuous Integration), wybrałem alternatywne podejście.
GNU Compiler Collection (GCC) jest jednym z najpopularniejszych kompilatorów dla języka C. Kompiluje on określone platformy i architektury, ale nie dla rodziny chipów AVR (ATmega). Istnieje jednak zestaw kompilatorów dla AVR i innych rodzin Microchip dostępnych na ich stronie internetowej. Na szczęście, niektórzy życzliwi ludzie nawet spakowali te kompilatory do ładnych pakietów Debian, które można łatwo zainstalować w Debianie lub Ubuntu w ten sposób:
$ apt-get install gcc-avr binutils-avr avr-libc avrdude
Z tymi narzędziami zainstalowanymi jesteśmy teraz w stanie kompilować i programować ATmega328P tylko za pomocą programatora Atmel-ICE i zewnętrznego źródła zasilania (ustawionego na 5V). Użyjemy wersji AVR GCC do kompilacji kodu i AVRDUDE do zaprogramowania chipa ATmega328P.
Moim celem w tym projekcie było zademonstrowanie kilku podstawowych, ale funkcjonalnych możliwości ATmega328P. Prosta zewnętrzna migająca dioda LED i kilka poleceń szeregowych tam i z powrotem były wszystkim, czego potrzebowałem, aby udowodnić, że ten chip może stać na własnych nogach. W repozytorium projektu stworzyłem kilka folderów oprócz kodu źródłowego (nazwanego „src”), które pomagają w rozwoju tego projektu.
Ważnym elementem rozwoju oprogramowania (nawet tego, które jest przeznaczone na sprzęt) jest testowanie jednostkowe. Testowanie jednostkowe potwierdza, że funkcje lub fragmenty większego systemu działają zgodnie z oczekiwaniami. Jeśli ktoś dokona zmian w jednej z tych funkcji, test jednostkowy zapobiegnie regresji (tj. nieumyślne spowodowanie błędu w innym miejscu przez wprowadzenie nowej funkcji). W tym przykładzie napisałem podstawowy test jednostkowy, który symuluje sprzęt i przeprowadza inicjalizację biblioteki komunikacji szeregowej (USART).
Oprócz testowania jednostkowego (znajdującego się w folderze „tests”), istnieje również folder o nazwie „hil”, który oznacza Hardware in the Loop (Sprzęt w pętli). Folder ten zawiera skrypty niezbędne do przeprowadzenia testów z użyciem rzeczywistego sprzętu w pętli (jak omówiono w wielu moich poprzednich artykułach). To zapewnia, że mój kod jest funkcjonalny nie tylko w świecie wirtualnym (używając symulacji), ale również w rzeczywistym świecie, poprzez przeprowadzanie testów na prawdziwym sprzęcie.
Zapoznanie się z plikiem README.md dostarczy ci schematu połączeń do programatora Atmel-ICE z układem ATmega328P:
Rysunek 1: Rozpiska pinów Atmel ICE
Dodając kilka diod LED, podłączając port komunikacji szeregowej do Raspberry Pi i korzystając z linii +5V z Raspberry Pi, masz teraz gotowy do działania zestaw:
Rysunek 2: ATmega328P używający płytki rozszerzeń z Raspberry Pi i programatorem Atmel-ICE
Podczas rozwijania nowych funkcji, użyj Makefile do przeprowadzenia testów jednostkowych i kompilacji kodu. Po potwierdzeniu, że twój kod robi to, co ma robić (poprzez walidację testu jednostkowego), zbuduj plik binarny, wgraj go na urządzenie (również za pomocą Makefile) i przeprowadź testowanie Hardware in the Loop (HIL) używając portu komunikacji szeregowej Raspberry Pi.
Jednym z najważniejszych elementów jest poprawne zaprogramowanie bitów bezpieczników, aby włączyć wewnętrzny zegar 8 MHz. Jest to udokumentowane w pliku README, ale również dodane do polecenia programowania w Makefile:
avrdude -c atmelice_isp -p m328p -B 32 -U lfuse:w:0xe2:m
Po tym powinieneś być w stanie używać interfejsu szeregowego układu z założeniem, że wewnętrzny zegar działa z częstotliwością 8 MHz (jak określono na początku main.c). Od tego momentu powinieneś być w stanie dodać więcej funkcjonalności, takich jak obsługa dodatkowych poleceń szeregowych, interfejsy do zewnętrznych komponentów i czujników oraz wszystko, co przyjdzie ci do głowy z tym zabawnym małym mikrokontrolerem.
W tym artykule dowiedziałeś się, jak rozpocząć pracę z układem ATmega328P bez żadnych zewnętrznych układów, jak to często bywa w przypadku oryginalnych Arduino Uno i płyt ewaluacyjnych Microchip. Teraz znasz koncepcję testowania jednostkowego, budowania binarnego, programowania układu i przeprowadzania testów sprzętu w pętli. Dodatkowo, omówiono ważny szczegół, często pomijany, dotyczący programowania bitów bezpieczników w celu ustawienia wewnętrznego zegara na 8 MHz. Na tym etapie powinieneś być w stanie dodać więcej funkcjonalności za pomocą dodatkowych testów jednostkowych i HIL oraz uruchomić wszystko tylko z programatorem Atmel-ICE i zewnętrznym zasilaniem 5V. Dla uproszczenia, wykorzystanie Raspberry Pi jako źródła zasilania i do komunikacji szeregowej byłoby najłatwiejszym sposobem na kontrolę procesu od początku do końca.
Kod źródłowy projektu można znaleźć tutaj:https://gitlab.com/embedded-designs/atmega328p-serial-led-control.