PIC na wodę - fotomontaż wiedźmy czary-mary z mikrokontrolerami PIC |
|
❦ nieco zmodyfikowane preludium Nie będę tu pisała o swoich problemach z pisaniem programów w assembler dla PIC ponieważ póki co jedyny problem w tym wszystkim to ja sama i jak się okazało bagaż przyzwyczajeń i nawyków związanych z innymi rodzajami mikrokontrolerów i składnią assemblera czy dziwacznymi mnemonikami, ale wszystko idzie zwalczyć. Testowy układzik na PIC16F876 ruszył przed noworoczną północą, albo to znak od duchów albo za dużo grzańca, nie wiem i nieważne. Istotne, że udało mi się w miarę gładko pokonać jak to się mawia - próg wejścia, "coś tam" sklecić i to coś - zadziałało, a fakt ten uskrzydla i motywuje do dalszych prac. Nie chcę tu pisać jakichś sążnistych tutoriali i tłumaczyć firmowej (btw. w moim przekonaniu naprawdę dobrej dokumentacji). Chce podzielić się drobnymi prawie projektami, które niejako z marszu można sobie wczytać do swojego MPLABX i skleciwszy układzik na płytce stykowej - mieć punkt startu do własnych eksperymentów i przeróbek. Ten i kolejne posty to czytanie na przemian pdf do kostek 16F oraz googlowanie za detalami w sieci, to jakoś wystarczyło. To lecimy... ❦pickitowa piaskownica - migaj sobie ledzie PICKIT3 z Chinowa oczywiście i cokolwiek by nie mówić o ichniejszych "realizacjach" - programator ruszył bez problemu, skomunikował się z kostką, finalnie - zaprogramował ją tym prościtkim wsadem. Układ na płytce stykowej, garstka drucików oraz kwarc póki co 8MHz, robiłam z tego co poniewierało się po biurku. Ledy vintage, próbnik logiczny też, a garstka zdjęć w załączniku. Aha, no i oprogramowanie - najnowszy dostępny MPLAB-X (dograne XC8 oraz XC16, wersje free, to na potem) oraz konfigurator MCC, fajna sprawa, też na potem. Oczywiście Linux Mint Tina na średnich lotów maszynie. W rolach głównych wspomniany w tagu PIC16F876, jak samplusie od Microchipów nadjadą - będą i inne okazy. Sztandarowy przykład migadełka na dwóch diodach LED - elementy na wyjściach kontrolera RB.0 oraz RB.1 przez rezystory 200R do masy, aktywują się stanem logicznym H. Programator PICKIT3 zapięty klasycznie, zasilanie całości z Meratronik P303 @ 5V/50mA (klauzula minimalnego zaufania) W projekcie cudów nie ma - pętla główna zmieniająca stan diodek:
Oraz zrobiona na kolanie procedurka opóźniająca, eksploatuje dwa programowe licznik wrzucone gdzieś na początek banku 0.
Cały projekcik jak ktoś ma ochotę się pobawić jest tu: ⇨https://github.com/bienata/picnawode/tree/master/asm-simple-led-1.X No i oczywiście tradycyjne filmiki - migające lampki oraz sesja z MPLAB-X na żywo, włącznie z zamulaniem IDE, ono bazuje na NetBeans, a te mają swoje problemy... Aha, ten projekcik da się odpalić pod symulatorem, ładnie widać zmieniające się bity portu B podczas pracy krokowej. ❦UART, komunikacja szeregowa Kolejny odcinek grafomanii będzie traktował o komunikacji szeregowej z wykorzystaniem pokładowego UART-a. Napisano o tym w sieci wiele, ja akurat zerkałam na te stronki: ⇨ http://www.oz1bxm.dk/PIC/628uart.htm ⇨https://www.teachmemicro.com/serial-usart-pic16f877a ⇨ https://www.exploreembedded.com/wiki/Serial_Communication_with_PIC16F877A ⇨ serial communication with uart ⇨ http://ww1.microchip.com/downloads/en/devicedoc/31029a.pdf Wprawdzie korzystam z cudzego, no ale niech będzie, że świadomie. Aby nie robić wioski dołączam schemat ideowy piaskownicy jak i fotki. Ledy tym razem są trzy, ponieważ celem ćwiczenia jest spreparowanie programiku, który oprócz realizacji prostego echa (znaczkowej papugi) będzie identyfikował czy ma do czynienia z cyfrą czy literą (zarówno dużą jak i małą) i pokaże to na żółtej lub zielonej lampce. W przypadku odebrania znaczka innego niż wymienione - pozostaje mu lampka czerwona. Oczywiście nie wszystko na raz, najpierw powstał prosty progamik realizujący znakowe echo:
Powyższe jest w pewnym sensie średnią z detali dostępnych na wskazanych stronkach, pogrupowałam całość w trzy główne procedurki: initUart,getChar,putChar, delay już znamy. No i tu mpasm pokazał pazury, a w pewnym momencie cztery litery. Wyliczanie stałej dla szybkości transmisji to był zonk. Proszę, niby proste (pomijając literówkę - miało być FREQ, oczywiście, sorki):
Sztuczka polega na tym, że gdy zerkniemy na ustawienia IDE: Project Properties -> Conf -> mpasm to znajdziemy tam:Default radix : HEX, co oznacza, że wszelkie stałe numeryczne pozbawione prefiksu (czy 0x, D', B') są traktowane jako szesnastkowe. Łatwo zgadnąć, że w takim wypadku powyższe wyliczenia dadzą wartości z koziej trąbki, co nie zmieni faktu, że program się skompiluje, załaduje, tylko nie zadziała. Oj nagoniłam się chwilę zanim oko me nie zawisło na dyrektywie assemblera radix, która mówi jak narzędzie ma domyślnie potraktować liczby bez żadnych ozdobników. Następna rzecz, której nie jestem do końca jeszcze pewna to końcówka inicjalizacji uarta, a mianowicie delay i potem kilka pustych odczytów, aby wysycić fifo, PIC-owy Uart posiada FIFO (dwa znaczki) więc jakiś sens to ma, ale pewnie zalety objawią się, gdy urządzenie nadawcze będzie już coś wysyłało, podczas gdy systemik z PIC-em dopiero się ogarnia. No i z ewidentnie słabych stron, to zabrakło mi oprogramowania błędów odbierania, overrun i framig error, no tak. Programik testowałam w warunkach cieplarnianych, strona nadawcza (mój PC) raczej-*** nie wycinała numerów. Filmik z działania tej wersji mamy poniżej. I tu taka ciekawostka - GTK Term na skutek ENTER wysyła tylko znaczek CR. No i linijki się nie łamały w okienku. Rozwiązanie proste - dorobić wysyłanie ekstra znaczka LF gdy przyjdzie CR, wtedy jest dobrze. Wiem, że jest w opcjach `auto cr-lf`, ale wtedy nie było by tej odrobiny prostej algorytmiki. Ten fragment kodu mamy w pętli głównej chwilowo objęty komentarzem, na filmie są oba. Z całego tego programiku najciekawsze jest ciągłe żaglowanie bankami, normalnie masakra aby się nie pomylić, ale autentycznie zaczyna się pamiętać, w którym co siedzi, choć dlaczego akurat tak rozsypali SFR-y po przestrzeni adresowej - to jest ciągle dla mnie zagadka. Cały projekt dla MPLAB-X: ⇨ https://github.com/bienata/picnawode/tree/master/asm-echo-rxtx-simple-1.X *** kluczowe jest słowo - raczej No więc właśnie, po wczorajszych śwatełkowych zbytkach, prosto z trasy i mocno po północy - myślę sobie: a coś jeszcze podłubię, nie szło klecenie więc w bety. Od rana do komputera i brzdęk! Coś co wcześniej - dam sobie głowę uciąć - działało, rano szaleje. UART zachowywał się idiotycznie, w sensie nie reagował w ogólne na nadchodzące znaki lub po odebraniu jednego - przestawał reagować i tylko jego zwracał, masakra z elementami paniki. Faktem jest, że płytka stykowa została pod prądem (i z podłączonymi próbnikami logicznymi), nie porozłączałam USB od PICKIT-a, a system zahibernowałam zamiast zamknąć, możliwe że to wprowadziło całość w jakiś dziwny stan i nawet clean+build i przeprogramowanie kostki nie dawało rezultatu. I tu powstało zagadnienie - nie mam pewnego, mega-prostego kawałka softu, którym mogę niezależnie zweryfikować czy cześć sprzętowa jest ok. No i łatwo zgadnąć - tu przydało się C, na kolanie sklecony ratunkowy program wygląda tak:
Program realizuje echo i mruga lampkami, to taki test czy chiński PICKIT3 oraz
biedny mały PIC w ogóle jeszcze żyją, filmik pamiątkowy:I kolejny projekt dla MPLAB-X ⇨ https://github.com/bienata/picnawode/tree/master/c-echo-rxtx-simple-1.X Totalny restart całego mojego majdanu na szczęście pomógł, dalsza zabawa to zgodnie ze wstępem - rozróżniaczka do cyferek i literek. Zaczęłam coś tam szkicować w assemblerze i powstało zagadnienie porównywania wartości numerycznych, a do obsłużenia są trzy zakresy wartości kodów ASCII - "0"..."9", "a"..."z" oraz "A"..."Z" no i to co pomiędzy nimi. I tak goglując wpadłam na bardzo ciekawe opisy różnych implementacyjnych przydasiów, proszę: ⇨ http://picprojects.org.uk/projects/pictips.htm A to spodobało mi się najbardziej: mpasm posiada garść pseudo instrukcji (12-Bit/14-Bit Instruction Width Pseudo-Instructions) ponieważ to mega ułatwienie moim zdaniem. ⇨ http://picprojects.org.uk/projects/pseudoins.htm BTW, chwila poszukiwań wykazała, że takie instrukcje są dostępne w burżuazyjnych kostkach 18F, małe bidy mają to udawane na poziomie translatora. Finalnie wyszedł mi niezbyt skomplikowany programik, ale pokręceń nieco tam jest, pętla główna:
No i procedurka rozpoznająca znaki i jej zmienne robocze:
Procedurki putChar, getChar i reszta jak w poprzednim programie, a tak wygląda całość na żywo:W podsumowaniu odcinka - na chwilę obecną moje zdanie jest takie, że mpasm jest całkiem sprytnym narzędziem, a mnemoniki typu btfss można nawet polubić. W końcu `ipmdbk butelka,2` rozwinięte do `idź po mleko do Biedry, kup 2 butelki` nie budzi wątpliwości... Do trzech razy sztuka, ostatni dziś zatem projekt dla MPLAB-X ⇨ https://github.com/bienata/picnawode/tree/master/asm-echo-rxtx-sel-led-1.X a kolejna opowiastka będzie o ... ❦ SPI z PIC16F876 vs układ DAC MCP4802 No właśnie, czyli podobnie jak w przypadku niegdysiejszej historii o Księżniczce Motoroli - szukam po pudełkach, co by tu do małego PIC-a fajnego podłączyć, oprogramować i pokazać jak działa. Z okazji segregowania próbek (serio, bez kitu, czasem coś układam) wpadła w ręce listewka z kostkami MCP4802 - to bardzo przyjemne w wykorzystaniu przetworniki cyfrowo-analogowe, sympatyczne o tyle, że mają wbudowane "okrągłe" źródło napięcia odniesienia 2.048V i nie wymagają symetrycznego zasilania. A to, że rozmawiają po SPI daje mi teraz możliwość przetestowania z czym się zajada ten interfejs w plebejskich PIC-ach 16F. Dokumentacja przetwornika tutaj: ⇨ http://ww1.microchip.com/downloads/en/devicedoc/20002249b.pdf a schemat instalacji po koniecznych modyfikacjach poniżej. Na potrzeby interfejsu SPI oddelegowano w PIC-u końcówki RC3 jako SCK, RC5 - SDO oraz (tu nieużywane) RC4 dla SDI. U mnie PIC pracuje jako master, więc w ruchu są SCK i SDO, do wybierania układu podrzędnego służy mi sterowany niezależnie bit RB3. Z programowego punktu widzenia wiele przy SPI do roboty nie ma - po ogarnięciu kierunku portu C (TRISC), należy skonfigurować rejestry SSPSTAT (krytyczna jest wartość CKE) oraz SSPCON (tu tylko włączyć całość bitem SSPEN). Jeżeli nasze urządzenie peryferyjne da czasowo radę - możemy wykorzystać domyślne ustawienia SSPM3:SSPM0 dające maksymalna szybkość zegara SPI - Fosc/4, przykładowy DAC-ek 4802 śmiga cudnie. Więcej teorii o SPI w dokumencie, zapraszam do poczytania: ⇨ http://ww1.microchip.com/downloads/en/devicedoc/spi.pdf No i oczywiście strzępki kodu - inicjalizacja i wysłanie na DAC wartości dla kanałów A i B:
Procedurka updateDAC wysyłająca dane do DAC-a:
Tu dwa słowa - jak zerkniemy w dokumentację do przetworników MCP48xx (strona 22) to zauważymy w jak dziwny (ale i spójny) sposób pozycjonowane są dane dla DAC w ramce SPI - a mianowicie po odbębnieniu czterech bitów sterujących (wybór kanału, wzmocnienie, itp ) zaczyna się sekcja danych, od MSB począwszy. Dla wypasionego 12-bitowego DAC-ka nie ma tu nic szczególnego, po prostu cztery zupełnie najstarsze bity są młodszym nibblem pierwszego bajtu (MSB), osiem niższych bitów DAC to kolejny bajt danych, ten LSB. W przypadku wersji 8-bitowej (jak tutaj maltretowana) jest śmiesznie, bo bajt wejściowy dla DAC trzeba rozsmarować po 16-bitowej ramce SPI tak, aby jego starsze cztery bity stały się młodszymi pierwszego (MSB) bajta ramki, młodszy nibble DAC trzeba utknąć jako starszy w bajcie LSB. Kołomyja normalnie, ale z pomocą przychodzi nam instrukcja swapf robiąca bitowego przekładańca, no super. Oczywiście sterowanie /CS-em przetwornika na piechotę, przy okazji ten sygnał można wykorzystać do pomierzenia ile trwa tu cała transakcja SPI (dla najszybszego zegara ~20us, nieźle). No i oczywiście - surowy zapis bajta do SPI z oczekiwaniem, na koniec wysyłki z bufora szeregowego.
Wszystko to poskładane w całość daje programik w miarę sensownie sterujący
układem MCP4802, zdjęcie z pierwszych eksperymentów gdzie dla wartości
0xFF przetwornik zwraca 4.096V, co w sumie cieszy:Skoro DAC jest skłonny współpracować, dalsze eksperymenty to oczywiście generowanie przebiegów okresowych na podstawie definicji w postaci serii stałych z ROM. No, teraz rozumiem skąd te wszystkie narzekania na stronicowanie pamięci w PIC (głównie małych). Pobranie zawartości komórki wskazanej innym rejestrem dla takiego na przykład Z80 jest banalne i raczej intuicyjne:
W PIC16 niestety trzeba się deko pomęczyć. Zagadnienie przechowywania
stałych w ROM jest dość popularne, googlując za np. "assembly PIC16F
lookup table" dostaniemy sporo do poczytania, ja osobiście polecam
dokument prosto od źródła wszelkiego zła, czyli notę aplikacyjną
⇨ http://ww1.microchip.com/downloads/en/appnotes/00556e.pdf
oraz garść ciekawych wskazówek implementacyjnych: ⇨ https://phanderson.com/PIC/16C84/mult_string.html a także ⇨ http://www.piclist.com/techref/microchip/tables.htm No to robimy tego sinusa. Wartości próbek przebiegu wygenerowałam sobie na poczekaniu stronką ⇨ (Sine Lookup Table Generator Calculator), w kodzie opakowane są dyrektywą DT assemblera. Funkcyjka zwracająca przy każdym wywołaniu kolejną próbkę wygląda u mnie następująco:
Do kompletu jest blok zmiennych roboczych oraz procedura je inicjująca:
I teraz tak: zmienne sineHiPtr/sineLoPtr jako para stanowią w istocie
szesnastobitowy licznik wskazujący aktualną próbkę do zwrócenia. Sztuka
polega na tym, aby znieczulić procedurę zwracającą dane na fakt, że idąc
po kolejnych próbkach właśnie minęliśmy podział stron (cześć LO
wykręciła się z FF nazat na 00). Zauważmy, że inkrementacja zmiennej
sineLoPtr w przypadku przekręcenia się na 0 będzie skutkowała
inkrementacja sineHiPtr. Wprawdzie w tym, n-tym obiegu wiele to nie
wniesie, bo mamy już zapisany adres w PCLATH (program counter latch
high), ale następna iteracja dostanie już adres wskazujący kolejna
stronę, całość będzie szła liniowo do końca tabeli. Oczywiście ilość
iteracji kontrolujemy na zewnątrz - u mnie to zmienna sineSampleCntr, bo
nie mogłam wykorzystać `magicznej wartości` np. 0x00 jak dla napisów
tekstowych. Samo zwracanie danych do rejestru W też jest przedziwne, w
dokumentacji mpasm ⇨ http://ww1.microchip.com/downloads/en/devicedoc/33014j.pdf rozwija się do rozkazu RETLW
ze argumentem w postaci wymaganej akurat stałej. Jeden taki elementarny
`return NN` per bajt danych. No a jak tam skoczyć? Ano wpisując na
żywioł do PCL dolny adres docelowy rozkazem `movwf PCL`. Oczywiście gdy
starsze bity adresu będą chybione - program pójdzie w buraki, bo
powyższe to nie jest tylko odczyt danych, to jest przekazanie sterowania
skutkujące zwróceniem wskazanej wartości. Mając funkcyjkę do próbek sinusa i obsługę przetwornika C/A można sobie tego sinusa wyświetlić na oscyloskopie, taką na przykład pętelką:
Inicjujemy wskaźniki na start, w pętli wybieramy kolejne próbki i podajemy na DAC, póki co na oba kanały naraz.W każdym obiegu sprawdzamy, czy może doszliśmy do ostatniej próbki, gdy tak - resetujemy wskaźniki i kręcimy się dalej. Finalnie daje to ciągły, niezakłócony przebieg wyjściowy, jak na zdjęciach poniżej. Na pamiątkę mamy też zdjęcie z trudnych początków (uzyskałam prawie jak sinus) oraz pokazanie, że przebiegi z kanałów A oraz B przetwornika w tej implementacji są odrobinę przesunięte w fazie. To przesunięcie wynika z sekwencyjnego odświeżenia wartości w kanałach, dzieje się to megaszybko ale drobne zmulenie jest. Gdy takie zjawisko jednak nam przeszkadza to należy wykorzystać sygnał /LDAC przetwornika MCP4802 i nim kontrolować symultaniczny wpis obu wartości, ot drobiazg taki. Kompletny projekt testowy dla MPLAB tu: ⇨ https://github.com/bienata/picnawode/tree/master/asm-mcp4802-dac-1.X Taka mnie myśl za rękaw capła, że programowanie PIC-ów w asseblerze wyzwaniem pewnym jest, nie przeczę. I oprzeć się nie mogę pokusie porównania tego całego szaleństwa do pole-dance. Co się poobijam, siniaków i odcisków narobię czy zakwasów dostanę to moje własne i nikt mi juz tego nie zabierze. A można przecież na poślad nalepić sobie plasterek slim-patch z napisem "C-lang", leżeć i pachnieć i będzie to samo. Z dokładnością do satysfakcji z każdego, choćby najdrobniejszego progresu. Ot, refleksja taka... Tematem kolejnej dobranocki jest: ❦ okiełznanie modułu wyświetlacza matrycowego 8x8 z układem MAX7219 Zacznę typowo, czyli od wskazania dokumentacji: ⇨ https://datasheets.maximintegrated.com/en/ds/MAX7219-MAX7221.pdf i tam tak naprawdę jest wszystko co potrzeba do oswojenia tej kostki. Z moich spostrzeżeń to takie, że na ogólnie pojętym rynku mamy dwa konkurencyjne wydania modułków matrycowego LED i tegoż układu sterującego (przykłady z lokalnych źródeł, na Aliexpress tego od cholery mają): a) ⇨ https://www.gotronik.pl/modul-wyswietlacza-matrycy-led-matrix-8x8-max7219-p-4874.html b) ⇨ https://www.gotronik.pl/modul-wyswietlacza-matrix-8x8-sterowanego-ukladem-max7219-p-2353.html W pogadance występuje wersja A, z kostką w DIP na wierzchu, ponieważ właśnie kilka takich modułów sprawiłam na zajęcia z Arduino mojej zbójeckiej szkolnej gromadce i ostał mi się jeden, ostatni. Na nich można było wyświetlać emotikony, tajne znaczki i inne bezeceństwa, modułki rozlazły się więc, że tak ujmę błyskiem, ale na zdrowie. Konstrukcja mechaniczna jest wygodna do tymczasowych podłączeń, bo wszystko ładnie opisane i wyprowadzone, do edukacji jak znalazł. Wersja B jest praktyczniejsza jeżeli chcemy budować większą matrycę, ponieważ mamy dużą swobodę w orientowaniu modułu - jest na obrysie kwadratu i można go obracać o 90'. To polecam to poważniejszych zastosowań. Do komunikacji z układem wykorzystamy sprzętowe SPI, znane juz z DAC-ka MCP4802 i w sumie na tym czary się kończą. Pozostaje inicjalizacja układu MAX7219 zgodnie z wytycznymi przedstawionymi w dokumentacji, ja do tego celu spreparowałam sobie makro-przydasia setMAX7219reg
oraz przepisaną z dokumentu garstkę stałych:
przez co zainicjowanie układu jest dość klarowne, równie czytelne jest wpisanie wartości do rejstrów danych:
Oczywiście początki były z sękami, ale w końcu udało się skomunikować z układem, wersja fotograficzna poniżej:Skoro można wyświetlić jedną `bitmapkę` to można i kilka, ich sekwencja da nam prymitywną, ale w sumie sympatyczną animację, tak wygląda na żywo: a kompletny projekt dla MPLAB-X znajdziemy tu: ⇨ https://github.com/bienata/picnawode/tree/master/asm-max7219-led-1.X Następny krok to już deko bardziej skomplikowana zabawka - wyświetlanie ruchomych napisów. No cóż, mam jeden wyświetlacz 8x8 więc za bardzo nie poszalejemy, ale od czegoś zacząć trzeba. Chyba od rozpoznania, jaka jest orientacja bitowo-geometryczna naszego modułku, bo to będzie rzutowało na dalszą implementację przesuwającego się jak w autobusie napisu. Wszystko mówi zdjęcie: Prawa dolna kropka to bit zerowy zerowego rowka danych, będzie to odpowiadało zerowemu elementowi ośmiobajtowej zmiennej screenBuff zadeklarowanej w programie. No i właśnie - program. Sztuczka polega na tym, aby mieć w pamięci bufor odzwierciedlający zawartość wyświetlacza (screenBuff) oraz funkcję updateDisplay, która jego zawartość przepisze na fizyczną matrycę, niech wygląda to następująco:
Powyższy okruch kodu to przykład wykorzystania adresowania pośredniego w PIC16F, mega fajowy wynalazek, który ułatwia iterowanie po dostępnej wewnątrz
PIC-a pamięci RAM. A mianowicie mamy dwa magiczne rejestry - FSR, do którego wpisujemy (jak do każdego innego rejestru) wartość liczbową, ona będzie adresem komórki pamięci gdy odwołamy się do niej odczytując/zapisując/przeliczając rejestr INDF. INDF to takie jakby *FSR - chyba na miejscu jest porównanie do C-owego
operatora wyłuskania. To umożliwia nam wyliczenie lokalizacji na której
chcemy wykonać żądaną operację, tu jest to tylko odczyt - iterujemy po
elementach buforka matrycy celem wysłania ich via SPI do układu MAX.Aby zrealizować płynący napis, potrzeba nam jeszcze procedurki, która jakby przewinie bufor wyświetlacza, zastępując N+1 element N-tym, a finalnie robiąc miejsce na nową wartość (w miejscu zerowego elementu), która pojawi się z prawej, skrajnej strony matrycy. No, przyznaję z tej procedury dumna nie jestem, jest ciosana siekierką normalnie, ale byłam tak omamiona wizją działającej aplikacji, że odstawiłam przyznaję bez bicia - wioskę. Ale jakby nie patrzeć - działającą.
Sama pętla główna nie jest specjalnie skomplikowana, ot pozyskanie kolejnego
bajta napisu (bannera) do wstawienia do bufora, przewinięcie bufora,
odświeżenie matrycy i kontrola czy poszły na wyświetlacz wszystkie dane.
Jak tak - reset wskaźników i zabawa od nowa.
Pokazywałam na zdjęciu, jak wygląda bitowa organizacja wyświetlacza i szybko
okazało się, że definiowanie napisów z wykorzystaniem na większą skalę
dyrektywy DT i notacji binarnej doprowadzi mnie do spazmów. Panaceum
jest zdefiniowanie sobie zestawu makr odpowiadających kolejnym kształtom
znaków czy emotków, dopiero ich wywołania definiują nam zawartość
napisu:
Oczywiście naturalną konsekwencją w/w podejścia jest powstanie procedurki
tłumaczącej ciąg znaków ASCII na sekwencję adresów ze wzorcami bitowymi
kolejnych znaków, ale to może później. Za to testowy programik
wyświetlający pozdrowienia mamy na filmiku:A drugi komplet źródełek dla MPLAB znajduje się tu: ⇨ https://github.com/bienata/picnawode/tree/master/asm-max7219-led-2.X Temat napisu reklamowego wydaje się mieć spory potencjał, tym bardziej, że z klasowej wystawki wypożyczono mi (sic!) na kilka dni dwa moje własne modulki ledowo-matrycowe, mam zatem szansę zmierzyć się z oprogramowaniem tego o mało co bannera z LED i z paroma ciekawostkami translatora mpasm, niejako przy okazji. Zdjęcie banerka poskładanego z trzech modułów mamy poniżej, załączam też focię jednego ze zdjętą matrycą diodową, chcę pokazać jak opisane są konektory modułu. Kaskadę (czy jak kto woli łańcuch) robimy tak, że sygnały SCK, /CS są wspólne, a DOUT n-tego modułu łączymy z DIN modułku n+1. Oczywiście dane wprowadzamy na DIN pierwszego dostępnego. Programowych podejść do kaskady jest kilka, jedni wykorzystują technikę "ślepych zapisów" wartości no-op (0x00) i w ten sposób trafiają ramką danych w wybrany moduł. Inne podejście to potraktowanie kaskady jako 16*N bitowego rejestru przesuwnego i ja takie właśnie zastosowałam. Ułatwia to w/g mnie bardzo konfigurowanie kaskady, po prostu wpisujemy N razy to samo do wszystkich ciurkiem. Natomiast upierdliwe nieco staje się ładowanie danych, bo musimy oprogramować mapowanie pomiędzy obrazem danych w RAM (bufor ekranowy) a zawartością rejestrów w kaskadzie. Ale to jest wykonalne, zaraz zobaczymy. makra i modernizacje Zacznę od najprostszej sprawy - wyrzucenia definicji znaczków do osobnego pliku i dołączania go do głównego programu dyrektywą include i to nawet ładnie działa, a w głównym pliku jest jakby mniejszy śmietnik. Kolejna rzecz to podglądnięty gdzieś na PIC-owym forum patent, aby makra nazywać w specyficzny sposób np. prefiksujac jakimś wybranym (ale dopuszczonym przez mpasm) znaczkiem. U mnie padło na małpkę (@) i w sumie to sama już nie wiem, czy to nie jest udziwnienie. W kodzie niby widać od razu, że symbol jest czymś nietypowym - tu: makrem i nie wykonam pod to skoku goto ani nie użyje jako argumentu do call. Inna sprawa, że to od razu wyrzuci błędy translacji więc poprawienie też nieskomplikowane. Tak więc @ w makrach zostaje ale tymczasowo. Definicje znaczków jak łatwo zgadnąć wyglądają tak:
a znaczki same w sobie choć szpetne, to mają specyficzny urok...takiej prowizorki. Wykorzystanie definicji makr znakowych (z małpką) takowe:
Grubsza modyfikacja spotkała makro do inicjowania układu MAX7219, a to z racji
tego, że mamy kaskadę całą, a nie jedną sztukę, małpka w nazwie to przy
tym pikuś. Popatrzmy na fragment kodu:
O, i to jest megafajny wynalazek - możliwość wykonywania obliczeń i
aktywnego oddziaływania ich wynikami na przebieg translacji. Powyższe
makro ma za zadanie wygenerowanie tylu par zapisów SPI (bajt rejestru,
bajt danych) ile jest modułków w łańcuchu, pisałam wyżej - traktuje
całość jako dłuuuuugi rejestr. Deklarujemy zatem lokalną zmienną,
inkrementujemy ją w kontrolowanej porównaniem pętelce (na poziomie
translacji), w efekcie makro rozwinie się do tylu par `movlw + call
writeSPI` ile nakażmy parametrem `how_many_modules`, przykładowo tak:
Oto fragment wynikowego listingu:
Z rzeczy upierdliwych co mi wyszło przy okazji, to konieczność zaczynania
operacji na zmiennych makra od pierwszej kolumny, tam gdzie zwyczajowo
jest miejsce na etykietę. Albo ja coś nie doczytałam, albo gdzieś jakiś
prztyczek jest nieustawiony, to mam zaparkowane do wyjaśnienia, bo kod
źródłowy makra wygląda brzydko i mnie to wkurza. Tak czy inaczej kaskadę
MAX-ów udało się zainicjować, czas na ładowanie danych.W programie ekranik rozwinął się do 24-bajtowej tabelki w pamięci RAM, oczywiście tam gdzie się dało - kod jest sparametryzowany. I teraz pierwsza zabawka - przeładowanie tych 24 bajtów do kaskady wyświetlaczy, znana z ostatniego postu procedura updateDisplay. Skoro traktuję je jako jeden mega-rejestr to znaczy, że wpisując jako adres rejestru w MAX to samo, ale z trzeba różnymi wartościami danych - ustalam wygląd pierwszych, drugich...ósmych pasków na trzech modułach jakby jednocześnie. Nie ma konieczności omijania żadnych rejestrów w MAX tym całym no-op, programowa realizacja jest dajmy na to taka:
Tu naprawdę przydaje się adresowanie pośrednie via FSR/INDF, bez tego to
byłaby masakra normalnie. Przyznaje, to co powyżej to któreś tam z rzędu
podejście do tematu, pętla zewnętrzna w updateDiplay iteruje po
pionowych paskach, w procedurze updateSelectedLine
jest wyliczanie skąd (z jakiego miejsca bufora ekranu) pobierać dane i w
pętli zależnej od ilości modułów - wysyłanie do kaskady. Podrasowaniu uległa procedurka do przewijania ekranu scrollBuffer,
no i cóż rzec...wersja, która pracowała podczas uruchamiania
updateDisplay (bo to mi dało do wiwatu) bazuje na prostackim, siłowym,
podejściu, ale żeby nieco wybielić - z wykorzystaniem makr, a zatem:
W uzasadnieniu - musiałam mieć kawałek kodu, którego działania byłam już
na 100% pewna, gdy wykluła się updateDisplay nabazgrałam mniej
obciachową wersję scrollBuffer, o taką:
I ponownie podziękowania za FSR/INDF, szkoda wielka, że to nie działa po
pamięci ROM, no ale trudno. Pętla główna aplikacji praktycznie bez
zmian, ale tego można się było spodziewać - w niej było wybieranie
kolejnego bajtu dla pierwszego elementu bufora ekranowego i wołanie
scroll-a, tu na szczęście nie grzebałam. I filmiki - pierwsze podejście do kaskady i efekty specjalne, ponieważ pomyliłam kolejność modułów.Wyświetlanie napisu z ROM na większej matrycy, w sumie sympatycznie wygląda: Kompletny projekt MPLAB-X tu: ⇨ https://github.com/bienata/picnawode/tree/master/asm-max7219-led-banner-1.X ❦ zabawa z generatorem DDS AD9833 Temat wieczorynki napatoczył się nieco przypadkowo, niemniej jednak wdzięczy się okazał i trafił na warsztat. Jest nim moduł generatorka DDS na bazie układu AD9833 od Analog Devices, dyskusja o nim toczy się, że tak ujmę w niedalekim sąsiedztwie. Rzeczony modułek dostałam na zatracenie od koleżanki z fabrycznej zagrody, pozostał się w formie `odpadu` po przygotowaniach do dyplomu, a teraz (modułek) ma szanse pobrylować w mediach, przynajmniej do chwili, kiedy nie zrobię mu krzywdy. Przy okazji poruszę pewną kwestię związaną z tym, jak ma się symulacja komputerowa układu elektronicznego do rzeczywistości i gdzie są zasadzki. Oprogramowanie w C, ponieważ bardziej zależało mi na zabawie generatorkiem niż na masochistycznych kombinacjach z rejestrem W i przełączaniem banków. AD9833 Modułek tytułowego generatora jest całkiem sympatyczną konstrukcją i tak po prawdzie nie nastręcza kłopotów przy podłączaniu do mikrokontrolera, sygnały opisane, reszta detali jest w dokumentacji do wykorzystanych w nim układów. Oczywiście byłoby fajnie posiadać schemat tego cudaka, tak więc inżynieria odwrotna w moim wykonaniu sprowadziła się do kilku minut z Googlem i proszę: ⇨ https://pmdway.com/products/ad9833-dds-programmable-frequency-function-generator Podłączenie do PIC16F876 typowe dla poprzednio męczonych układów z SPI więc schemat sobie daruję. Dla formalności tylko dwa drobiazgi: sygnał /FSYNC kostki AD9833 idzie do wyprowadzenia RB3 kontrolera, sygnał /CS potencjometru MCP41010 do RB4. Testowa instalacja wygląda aktualnie tak: Program sterujący powstał w C, wielką pomocą były strzępki kodu znalezione w sieci, a przygotowane dla AVR, linki do materiałów w kodzie źródłowym. Z sympatycznych wynalazków - powstało drobne zagadnienie: jak sterować sygnałami /CS i /FSYNC aby mieć w miarę spójne API realizujące zapis 16-bitowej wartości przez SPI, ale do wielu układów. No i wydumałam sobie tak, że funkcja spiWrite16() oprócz danej do wysłania dostanie też ... wskaźnik na funkcję odpowiedzialną za odpowiednie ustawienie sygnałów wybierających docelową kostkę. Funkcyjek tych mam tyle co układów, czyli całe dwie, niemniej jednak patent jest generyczny i raczej skuteczny, a kod (w mojej opinii przynajmniej) w miarę czytelny, o, proszę:
I zastosowanie:
Cały projekt z pierwszego podejścia do oswojenia generatorka znajdziemy tu: ⇨ https://github.com/bienata/picnawode/tree/master/AD9833-gen-1.X Kolejny krok to oprogramowanie generatora, którym można by sterować przez port szeregowy, taki jakby model. Polecenia z konsoli to 4/6 do zmiany częstotliwości, 8/2 lub +- do zmiany amplitudy (to jak łatwo zauważyć klawiatura numeryczna), literki s-t-p przełączają odpowiednio sinus, trójkąt i prostokąt. Oczywiście na ekranie oscyloskopu przebieg ma czasem ADHD, to jest jednak sztuka napisać program tak, aby zmiana parametrów sygnału była płynna i bez wierzgnięć. Garść zdjęć: Oraz filmiki - test sterowania amplitudą: Sterowanie częstotliwością, amplitudą i przełączanie generowanych kształtów: Przy okazji ładnie widać, jakie cuda dzieją się na oscyloskopie podczas programowania PIC-a, normalnie kolejne wcielenie `Matki` z Nostromo. Komplet źródełek do tej wersji programu: ⇨ https://github.com/bienata/picnawode/tree/master/AD9833-gen-fun-1.X symulacja Wspomniałam na początku o dyskusji o AD9833 w pobliżu, szczególnie zaintrygowała mnie sprawa programowalnego wzmacniacza ochrzczonego PGA (programmable gain amplifier) i wątpliwości odnośnie jego działania na podstawie wyników symulacji. No więc sprawa jest w sumie prosta - wzmacniacz wespół z cyfrowym potencjometrem stanowią technicznie poprawna konstrukcję, ale pod mocnym warunkiem, że wykorzystamy WO, który jest dedykowany do zasilania unipolarnego i który może pracować z sygnałami bliskimi potencjałowi dolnej szyny zasilania, więcej poczytajki tu: ⇨ https://www.analog.com/en/analog-dialogue/raqs/raq-issue-38.html Kostka AD8051 doskonale się tu sprawdza, pierwsze testy po uruchomieniu sinusa to własnie było sprawdzenie, jak działa to całe PGA: Zrobiłam symulację po swojemu, ja lubię dłubać w plikach więc oto pisany wsad dla symulatora ngspice:
Drugi model - OP183G wyszukałam specjalnie na stronie Anaglog Devices, filtrując po `single supply amplifier` Bipolarny klasyk 741 przyciął dolną połówkę sygnału i trudno się dziwić, preferuje zasilanie symetryczne. Koleżka OP183 doskonale poradził sobie z sygnałem sterującym w okolicy masy, czyli de facto - dolnego potencjału zasilania układu. Pliki do symulatora dla ciekawskich: ⇨99_sim-ngspice.zip #slowanawiatr, styczeń 2020 |