DZWON

Są tacy, którzy czytają tę wiadomość przed tobą.
Zapisz się, aby otrzymywać najnowsze artykuły.
E-mail
Imię
Nazwisko
Jak chcesz przeczytać The Bell
Bez spamu
  • Transfer

Tanie elektroniczne świece wydają się być ostatnio wszędzie. Nie zwróciłem na nie większej uwagi, dopóki nie zauważyłem, że faktycznie używają specjalnej diody LED - z wbudowanym „migającym” kontrolerem. Teraz sprawa wygląda zupełnie inaczej: kto nie lubi tajemniczych diod LED? Pół godziny później miałem już naręcze migoczących chińskich diod LED.

Oczywiście najciekawsze pytanie brzmi: jak one działają? Biorąc pod uwagę, że kosztują dosłownie kilka centów za sztukę, w środku nie może być drogiej elektroniki. W związku z tym nasuwa się inne pytanie: czy te diody są naprawdę gorsze od licznych „świec” na mikrokontrolerach, które programy są pełne w Internecie?

Urządzenie jest stosunkowo proste. Standardowy pakiet 5 mm zawiera kryształ LED i mikroukład, który jest nieco większy niż pierwszy rozmiar. Obwód sterownika jest podłączony do zacisków dodatnich i ujemnych. Trzecia zworka podłącza do niej anodę diody LED, natomiast katoda „siedzi” na zacisku ujemnym.

Na blogu Evil Mad Scientist pojawiła się ostatnio historia o podobnych diodach LED. Tam pokazano, jak „śpiewają”, jeśli zamieniamy zmiany jasności na dźwięk. A także - jak za ich pomocą sterować mocniejszą diodą. Te sztuczki polegają na tym, że dioda LED pobiera więcej prądu, gdy kontroler włącza ją jaśniej. Zwykła dioda LED połączona szeregowo z migoczącą wykazuje bardzo podobne zmiany jasności. Innymi słowy, spadek napięcia na dodatkowym rezystorze zmienia się proporcjonalnie do jasności.


To właśnie użyłem do wyodrębnienia sygnału sterującego sterownika i doprowadzenia go do analizatora stanów logicznych (patrz schemat powyżej). Regulując zmienny rezystor zapewniłem, że analizator odbiera prądy rozruchowe jako „zera” i „jedynki”, podczas gdy dioda LED pracuje normalnie.


Powyższy wykres przedstawia zmiany jasności diody w ciągu około minuty, rejestrowane przy częstotliwości próbkowania 1 MHz. Odstępy czasu są zauważalne, gdy dioda LED jest stale włączona, i okresy, gdy jej jasność jest w jakiś sposób modulowana. Dioda LED nigdy nie wyłącza się na długi czas. Ma to sens, ponieważ prawdziwa świeca również świeci jasno przez większość czasu, przyciemniając się na krótkie okresy migotania.


Bliższe spojrzenie ujawnia, że \u200b\u200bsygnał jest modulowany szerokością impulsu. Oznacza to, że mamy układ cyfrowy, bez żadnych sztuczek analogowych.

Co ciekawe, częstotliwość sygnału wynosi około 440 Hz, jak standardowy kamerton ( nuta A pierwszej oktawy - około. tłum. ). Zbieg okoliczności? A może deweloper po prostu wziął generator z jakiegoś schematu muzycznego? W opowieściach o „muzykalności” tych diod jest więc trochę prawdy. Każda „klatka” o stałej jasności ma dokładnie 32 cykle zegara i trwa około 72 ms. Odpowiada to 13-14 klatkom na sekundę.

Napisałem mały program do określania jasności w każdej klatce z cyklu pracy sygnału PWM. Program odczytuje strumień próbek z analizatora stanów logicznych i wyświetla serię liczb rzeczywistych - po jednej na każdą ramkę.


Wykres jasności w funkcji czasu nasuwa pewne myśli: zmiany jasności są przypadkowe, dyskretne i nierównomiernie rozłożone. Wydaje się, że istnieje 16 poziomów jasności, z których 4 niższe są bardzo rzadko używane. Odpowiada im tylko 13 z 3600 odczytów.


Zbudowanie histogramu ujawnia cały obraz: w rzeczywistości używanych jest tylko 12 poziomów jasności. Dokładnie połowa klatek ma maksymalną jasność, reszta wartości jest w przybliżeniu równa.

Jak można to zaimplementować w sprzęcie? Jest prawdopodobne, że używany jest równomiernie rozłożony generator liczb losowych, który jest przekazywany przez prostą funkcję generatora. Dystrybucja, którą obserwujemy, wymaga co najmniej 12x2 \u003d 24 dyskretnych poziomów. Połowa z nich jest wyświetlana w jednym. Jest to ciekawe, ponieważ generator prawdopodobnie będzie generował liczby binarne. Najbardziej logiczna liczba to 5 bitów, a są to 32 stany. Wyświetlanie 32-poziomowej 24-poziomowej dyskretnej zmiennej losowej bez zmiany rozkładu nie jest tak łatwe, jak się wydaje. Nie zapominamy też, że to wcale nie jest krytyczny schemat, a deweloper pewnie nie miał czasu na piękne rozwiązanie. Dlatego zastosował najprostszy, rodzaj hackowania.

Jedynym prostym sposobem, jaki przychodzi na myśl, jest po prostu odrzucenie nieodpowiednich wartości i wybranie następnej liczby losowej. Niepożądane wartości można łatwo oddzielić za pomocą maski bitowej. Ponieważ obwód jest synchroniczny, do rozpoczęcia następnej ramki jest tylko skończona liczba prób. Jeśli kontroler nie wykona określonej liczby prób, utknie na „złej” wartości. Pamiętasz rzadkie usterki na wykresie jasności?

Implementacja ANSI-C może wyglądać następująco:
próby znaków \u003d 0; zwęglać; while (próby ++ 15) out \u003d 15; // górna połowa zakresu odpowiada maksymalnej jasności

Ile prób jest podejmowanych? Według statystyk udział a \u003d 0,25 wszystkie liczby muszą zostać odrzucone i ponownie wygenerowane. Prawdopodobieństwo po co n nie będą podejmowane żadne próby wybrania „prawidłowej” liczby, równa się a n.
n \u003d 1 0,25 n \u003d 2 0,0625 n \u003d 3 0,015625 n \u003d 4 0,003906

Udział rażąco niskich poziomów jasności wynosi 13/3600=0,0036 , co dobrze pasuje do tej opcji n \u003d 4... A zatem, MAX_ATTEMPTS \u003d\u003d 4.

Zauważ, że prostszym rozwiązaniem byłoby po prostu użycie wartości z poprzedniej klatki, jeśli napotkano nieprawidłową liczbę. Ta opcja mogłaby zostać wykluczona na podstawie autokorelacji (patrz poniżej). Chyba najprostsze rozwiązanie - zmiana obwodów PWM - nie zostało tutaj zastosowane.

Ostatnim elementem układanki jest sam generator liczb losowych. Typowym sposobem generowania losowych sekwencji w obwodach cyfrowych jest wykorzystanie rejestrów przesuwnych z liniowym sprzężeniem zwrotnym. Taki rejestr tworzy pseudolosową sekwencję bitów, która zostanie powtórzona nie później niż później 2 x -1 zaznacza gdzie x - szerokość bitowa rejestru. Jedną z cech takich sekwencji (i ogólnie dobrych sekwencji pseudolosowych) jest to, że ich funkcja autokorelacji jest równa jedynce tylko w punkcie 0 i we współrzędnych, które są wielokrotnościami długości sekwencji. We wszystkich innych przedziałach wynosi zero.


Obliczyłem autokorelację całej sekwencji wartości. Samopodobieństwo nie zostało znalezione do 3500 klatek (tylko 1200 jest pokazanych na powyższym wykresie), co oznacza, że \u200b\u200bmigotanie jest unikalne przez co najmniej 4 minuty. Nie jest jasne, czy zaobserwowano dalsze powtórzenie sekwencji, czy też analizator logiczny autora po prostu nie pozwalał na dalsze nagrywanie - około. tłum. Ponieważ dla każdej ramki potrzeba co najmniej 5 bitów losowych danych (a nawet więcej, biorąc pod uwagę mechanizm odrzucania niechcianych liczb), sekwencja pseudolosowa ma długość co najmniej 17500 bitów. Będzie to wymagało rejestru o długości co najmniej 17 bitów lub rzeczywistego sprzętowego generatora liczb losowych. W każdym razie interesujące jest, jak wiele uwagi poświęcono podczas opracowywania, aby zapewnić, że wzór migotania się nie powtórzy.

Na zakończenie odpowiemy na pytania postawione na początku artykułu. Migotanie diody okazało się dużo trudniejsze niż się spodziewałem (też nie spodziewałem się spędzić nad nią 4 godzin). Wiele implementacji świec w mikrokontrolerach po prostu podaje bity z generatora liczb pseudolosowych na wyjście PWM. Zakupiona dioda LED wykorzystuje bardziej wyrafinowany algorytm ściemniania. Oczywiście zwrócono uwagę na opracowanie algorytmu, a jednocześnie wykorzystano kryształ o prawie najmniejszej możliwej powierzchni. Część grosza jest dobrze wydana.

Jaki jest najlepszy algorytm migotania? Czy można to poprawić?

Aktualizacja: w końcu poświęciłem czas na napisanie emulatora. Program napisany w ANSI-C, który emuluje zachowanie tej diody LED,

Piszemy pierwszy program!

Większość zaczyna od migania diod LED, a my nie jesteśmy inni. Jeśli mikrokontroler, nawet najszybszy, nie „komunikuje się” ze światem zewnętrznym, jego wartość spada do zera. Potrzebujemy mikrokontrolera do odbioru informacji, przetworzenia ich zgodnie z zadanym algorytmem i nadania wyniku w zrozumiałej dla nas formie.

Algorytm, (w imieniu perskiego matematyka al-Khwarizmi) - dokładny zestaw instrukcji opisujących kolejność działań wykonawcy w celu osiągnięcia wyniku rozwiązania problemu w określonym czasie.
Aby poprawnie pisać programy, musisz zrozumieć, jak działa mikrokontroler, co zrobimy, ale na razie skomponujemy pierwszy program w asemblerze.

Ogólnie rzecz biorąc, możesz napisać program w dowolnym edytorze tekstu, tak jak na przykład napisałbyś list do przyjaciela. Następnie tekst musi zostać skompilowany (czasami mówią - zmontowany), tj. przełożyć na formę zrozumiałą dla procesora. Wcześniej rozszerzenie pliku tekstowego .txt zostało zmienione na .asm i przetworzone przez specjalny program zwany kompilatorem. Istotą pracy kompilatora jest przetłumaczenie czytelnych dla człowieka znaków pisanych na kod maszynowy (na kod zer i jedynek) i utworzenie nowego pliku z rozszerzeniem .hex

Co zrobić z tym plikiem .hex? Konieczne jest, aby programista zapisał kod programu do pamięci ROM (pamięć tylko do odczytu) mikrokontrolera. Użyjemy programu zamiast programatora odmieniecktóry moduluje rzeczywisty obwód roboczy.
W AVR Studio 5 edytor, kompilator, debugger i programista w jednym!

Dyrektywa - to recepta dla redaktora, z którym będziemy pracować. W większości nazwa dyrektywy i jej funkcja są takie same w różnych edytorach. Na przykład, jeśli porównasz edytor MPLAB IDE w przypadku mikrokontrolerów PIC praktycznie nie ma różnicy!
Ale zespoły są różne. Lista zespołów jest tworzona przez producenta i zależy w pewnym stopniu od technologii produkcji. Nawet ten sam producent w różnych rodzinach może mieć inną listę poleceń, gdy zmienia się ich struktura.
KomendaTo pojedyncza funkcja, za pomocą której możemy sterować mikrokontrolerem.
Programto sekwencja poleceń odpowiadająca określonemu algorytmowi (opracowanemu przez nas).
Każdy program zaczyna się od „nagłówka”, w którym zapisane są główne funkcje programu, jego autor, nazwa sterownika, który będzie używany, częstotliwość taktowania i inne dane. „Czapka” to zasada „dobrej formy” w programowaniu.
Zwykle plik inicjalizacyjny.includeххххdef.inc jest zapisywany w nagłówku. dyrektywy .device, .list, .nolist i inne.
W AVR Studio 5 te dyrektywy są zapisywane domyślnie. W poprzedniej wersji AVR Studio 4 te dyrektywy musiały być napisane, więc zostawiłem je jako komentarze.
Komentarze są pisane arbitralnie, tak jak lubisz, a najważniejsze jest to, aby były one dla Ciebie zrozumiałe. Często z powodu niekompletnych komentarzy autor po pewnym czasie nie może sam wymyślić własnego programu. Komentarze poprzedzone są znakiem (;).
Przedstawiłem „czapkę” zaproponowaną przez Johna Mortona ...

Edytor AVR Studio 5 - rozumie napisy, polecenia i polecenia podświetlając je na niebiesko, dane liczbowe pozostają czarne, niezrozumiałe wyrażenia są podświetlane na czerwono, komentarze na zielono.

Zanim zaczniemy, przyjrzyjmy się dyrektywom asemblera mikrokontrolera AVR.
Każda dyrektywa jest poprzedzona kropką:
Dyrektywa Opis BYTE Bajty rezerwowe w pamięci RAM CSEG Segment programu DB Zdefiniuj stałą bajtową w pamięci Flash lub EEPROM .DEF Nadaj rejestrowi nazwę symboliczną DEVICE Definiuje urządzenie, dla którego program jest kompilowany. DSEG Segment danych DW Definiuje słowo we Flash pamięć lub EEPROM .ENDM Koniec makra.ENDMACRO Koniec makra.EQU Ustaw wyrażenie stałe.ESEG EEPROM segment .EXIT Wyjście z pliku.INCLUDE Załącz kolejny plik.LIST Włącz generowanie listingu.LISTMAC Włącz rozwijanie makr w listingu.MACRO Uruchom makro.NOLIST Wyłącz generowanie Listing ORG Ustaw pozycję w segmencie SET Ustaw zmienną na równoważne wyrażenie

Pełny opis poleceń i dyrektyw asemblera w tłumaczeniu na język rosyjski Rusłan Shimkevich można obejrzeć tutaj:
24/09/11 397,28 Kb 4 244 Witaj czytelniku! Nazywam się Igor, mam 45 lat, jestem Syberyjczykiem i zapalonym amatorem elektronikiem. Wymyśliłem, stworzyłem i utrzymuję tę wspaniałą stronę od 2006 roku.
Od ponad 10 lat nasz magazyn istnieje wyłącznie z moich funduszy.

Dobry! Freebie się skończyło. Jeśli chcesz pliki i przydatne artykuły - pomóż mi!

--
Dziękuję za uwagę!

Wrócimy do dyrektyw asemblera więcej niż raz, a teraz spróbujemy napisać mały kod programu, w którym włączymy diody LED.
Dla wygody wybierzemy mikrokontroler ATtiny2313A... Jeśli ktoś pójdzie dalej i będzie eksperymentował na sprzęcie, to ten kontroler jest jednym z najtańszych, bardzo często stosowanych w przeróżnych konstrukcjach, jakie można spotkać w rozległych przestrzeniach sieci.

--
Dziękuję za uwagę!
Igor Kotov, redaktor naczelny magazynu „Datagor”


Wystarczy rozpakować i uruchomić (pod warunkiem, że odmieniecjuż zainstalowane).
Powinien pojawić się następujący obraz:

Biegnijmy AVR Studio 5, aw edytorze napiszemy mały program ze szczegółowymi komentarzami:
.def temp \u003d r16; dyrektywa .def przypisuje r16 do nazwy temp; \u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d \u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d; Początek programu.cseg; dyrektywa .cseg definiuje początek segmentu, w którym będzie się znajdować; główny kod programu. W AVR Studio 5 ta dyrektywa nie jest; required.org 0; początek pierwszej linii programu rjmp Start; względny skok do etykiety Start (w PIC odpowiada; polecenie goto); \u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d \u003d\u003d Start: ser temp; ustawia wszystkie bity rejestru tymczasowego na 1 wyjście DDRB, temp; tłumaczy wszystkie bity na zewnątrz DDRD, temp; porty B i D do styku temp. clr; czyści rejestr tymczasowy (ustawia wszystkie bity rejestru tymczasowego na 0) z PortB, temp; wyłącza rezystory podciągające PortD, temp; porty B i D Cicle: ldi temp, 0b11001100; zapala diody LED PortB, temp; port B rjmp Cicle; Wróć do etykiety Cicle, pętla

Skompilujmy to, klikając F7
W oknie Output pojawi się informacja o kompilacji, na końcu powinien pojawić się napis Build powiodło się, co potwierdza pomyślny montaż pliku .hex.


Ten plik znajduje się domyślnie w folderze Moje dokumenty w projekcie AVR Studio 5.

Iść do odmieniec, kliknij na rysunek sterownika i podaj ścieżkę, w której znajduje się plik .hex:




Rozpoczynamy emulację programu.
Po naciśnięciu przycisku Start widzimy wynik!



Aby zatrzymać emulację, kliknij Zatrzymaj.
Jeśli sflashujesz mikrokontroler za pomocą programatora i zmontujesz obwód, wynik będzie taki sam.

Spróbujmy to rozgryźć za pomocą programu:

Linia:
.def temp \u003d r16; Dyrektywa .def przypisuje rejestrowi r16 nazwę temp
Dla wygody nadaliśmy rejestrowi r16 nazwę temp, co oznacza, że \u200b\u200bw dowolnym miejscu programu podczas wpisywania słowa temp program będzie odnosił się do rejestru r16.
Co to za rejestr - r16?
Odnosi się do rejestrów ogólnego przeznaczenia, które są oznaczone jako r0… .r31, to znaczy są tylko 32 z 8 bitów każdy. Druga połowa rejestrów ogólnego przeznaczenia r16 ... r31 pełni funkcję tymczasowego przechowywania informacji (podobnie jak baterie mogą odbierać i wysyłać informacje, dla porównania kontrolery PIC mają tylko jedną baterię W). Ostatnie 6 rejestrów ogólnego przeznaczenia jest konwencjonalnie połączonych w trzy 16-bitowe:

Zauważ, że najbardziej znaczący bajt jest zapisywany wcześniej, najmniej znaczący później.

r27: r26 nazywany jest rejestrem X,
r29: r28 nazywany jest rejestrem Y,
r31: r30 jest nazywany rejestrem Z.
Program zadziała również, jeśli słowo temp jest przypisane do dowolnego innego rejestru ogólnego od r16 do r31, np. Def temp \u003d r20. Po kompilacji (klawisz F7 w AVR Studio 5) nie ma różnicy w działaniu programu.
(Możesz spróbować, teraz wiesz, jak to zrobić!)

Linia:
.cseg; Dyrektywa cseg definiuje początek segmentu, w którym będzie zlokalizowany główny kod programu
W AVR Studio 5 ta dyrektywa jest zapisywana domyślnie.
W mikrokontrolerach AVR różne obszary pamięci są przydzielane do przechowywania kodu programu, danych w pamięci stałej lub EEPROM, istnieją katalogi do wyznaczenia tego obszaru:
.cseg - segment programu
.dseg - segment danych
.eseg - segment EEPROM

Linia:
.org 0; początek pierwszej linii programu
Program rozpoczyna się w wierszu określonym przez dyrektywę.org i wraca do niej po zakończeniu.

Linia:
rjmp Start; względny skok do etykiety Start (w PIC odpowiada poleceniu goto)
To jest względne polecenie skoku do etykiety Start.
Program jest wykonywany sekwencyjnie od górnego do dolnego odpływu. Jeśli chcesz przejść do innego obszaru programu, użyj polecenia rjmp

Linie:
ser temp; ustawia wszystkie bity rejestru temp na 1 clr temp; czyści rejestr tymczasowy (ustawia wszystkie bity rejestru tymczasowego na 0)
Polecenie ser jest wykonywane z rejestrami r16… r31, a polecenie clr może być wykonywane dla wszystkich rejestrów, w tym rejestrów we / wy (rejestry specjalnego przeznaczenia). Później przyjrzymy się celowi tych rejestrów.

Linia:
ldi temp, 0b11001100
Polecenie ldi zapisuje liczbę binarną 11001100 do rejestru tymczasowego (nie będzie to błąd, jeśli zamiast 0b11001100 napiszesz 204 lub CCh, w jednym przypadku w postaci dziesiętnej w drugim w szesnastkowym)

Linia:
poza DDRB, temp
Polecenie out zapisuje wartość rejestru tymczasowego do rejestru portu DDRB.

Co to jest port i jak działa?

W uproszczeniu do minimum port może być reprezentowany jako pin-out mikrokontrolera, do którego w trybie wyjściowym można dowolnie przykładać napięcie lub rozłączać, aw trybie wejściowym określać, czy jest napięcie dostarczane z zewnątrz, czy nie.
Istnieją trzy tryby pracy portu: są to stan wyjścia, wejścia i odłączenia.
Porty są kontrolowane przez rejestry PinX, PortX, DDRX.
X - oznacza port kontrolowany przez te rejestry.
Rejestr DDRX steruje trybami I / O, podobnie jak przekaźnik - załączony (zapis 1) - podłączony do linii wyjściowej, odłączony (zapis 0) - przełączany na linię wejściową (domyślnie).

Aby wysłać dane do portu X, musisz przełączyć rejestr DDRX w tryb wyjściowy (zapis 1) i wysłać dane do rejestru PortX.
Możesz odczytać wartość portu X, jeśli rejestr DDRX jest przełączony w tryb wejściowy (zapis 0) z rejestru PinX. Aby podłączyć rezystory podciągające w trybie wejściowym, należy wysłać dane do PortX.
Rezystory podciągające ratują nas przed koniecznością podłączania rezystorów zewnętrznych do przewodu dodatniego i za pomocą jednego polecenia same dostarczają logiczny na wejście.

Głos czytelnika

Artykuł został zaakceptowany przez 23 czytelników.

Aby wziąć udział w głosowaniu, zarejestruj się i wejdź na stronę podając swoją nazwę użytkownika i hasło.

W artykule rozważymy podłączenie diod LED do mikrokontrolera, współpracę z portami i napisanie programu w SI. Artykuł przeznaczony jest przede wszystkim dla początkujących, którzy dopiero rozpoczęli pracę nad mikrokontrolerami AVR.

Najpierw musisz wybrać mikrokontroler. W moim przypadku jest to ATmega8535. W takim przypadku możesz wziąć dowolny mikrokontroler, ponieważ zadanie to można łatwo zaimplementować dla dowolnego MC. Możesz napisać program dla mikrokontrolera w Assembler, SI, Pascal i Bascom. Użyłem języka C, wszystkie te języki są różne.
Specyficzną różnicę między C i Pascalem można zobaczyć poniżej.

// Migająca dioda LED void main () (ddrB \u003d 0b11111111; // ustaw porty B na port wyjściowyB \u003d 0b11111111; // domyślnie wszystko jest wyłączone while (1) (portB \u003d ˜portB; // przełącz stan diody LED na przeciwny delay_ms (100 ); // opóźnij 100 milisekund))

Program pierwszy; rozpocznij ddrB: \u003d $ FF; // ustaw port B na wyjście portB: \u003d $ FF; // domyślnie nic nie jest włączone while (1) do początku portB: \u003d not (portB); // przełącz stan diody LED na przeciwny delay_ms (100); // zrób małe opóźnienie końca; koniec.

Lista pierwiastków radioaktywnych

Przeznaczenie Typ Określenie ilość UwagaWynikMój notebook
U1 MK AVR 8-bitowy

ATmega8535

1 Do notatnika
R1-R8 Rezystor

220 Ohm - 1 kOhm

8 Do notatnika
R9 – R11 Rezystor

10 kΩ

3 Do notatnika
V1-V8 Dioda LED 8 Do notatnika
Przycisk taktu 3

Podczas pisania programu często konieczne jest utworzenie pewnego odstępu czasu między poszczególnymi poleceniami. Dobrym tego przykładem jest girlanda, w której światła zapalają się w określonej kolejności w odstępach czasu. W naszym przypadku do wskazania zwłoki czasowej posłużymy się migającą diodą lub najlepiej dwoma i różnymi kolorami. Będziemy kontrolować czas ich włączania i wyłączania, czyli zmienimy częstotliwość migania.

Większość poleceń w mikrokontrolerach AVR jest wykonywanych w jednym cyklu zegara zegara głównego. W charakterze którego obwód RC wbudowany w MK jest szeroko stosowany lub rezonator kwarcowy jest podłączony do pinów XTAL1 i XTAL2.

Na przykład, jeśli MK działa z częstotliwością 1 Hz, to jedno polecenie zostanie wykonane w ciągu jednej sekundy.

Domyślnie ATmega8 ma własny wewnętrzny generator częstotliwości, a raczej obwód RC, który działa z częstotliwością 1000 000 Hz \u003d 1 MHz. Dlatego czas wykonania jednego polecenia to:

Wynika z tego, że jeśli zapiszemy dwa polecenia z rzędu, z których każde zapali osobną diodę LED, to wizualnie zobaczymy, że oba zapalają się jednocześnie.

#zawierać

int main (nieważne)

DDRD \u003d 0b000000011;

podczas gdy (1)

PORTD \u003d 0b000000001; // Włącz pierwszą diodę LED

PORTD \u003d 0b000000010; // Włącz drugą diodę LED

W rzeczywistości druga dioda LED zaświeci się z różnicą czasu wynoszącą 0,000001 sekundy od pierwszej. Nasze oczy nie widzą tak małej różnicy czasu. Nawet przy częstotliwości obrazu większej niż 24 Hz (t \u003d 1/24 ≈ 0,042 s) nasz wzrok tworzy ciągły film z pojedynczych obrazów. Dlatego w większości przypadków nie rozróżniamy 25. klatki.

Aby obie diody zaświeciły się z różnicą czasu 0,5 sekundy, konieczne jest, aby między odpowiednimi dwoma poleceniami (PORTD \u003d 0b000000001; i PORTD \u003d 0b000000010;) umieścić kolejne 500000 pustych poleceń w jednym cyklu, to znaczy sprawić, aby MK nie wykonywał żadnych przydatnych poleceń przez pół sekundy akcja. Lub, jak mówią, trzeba „zabić” 500 000 kleszczy. Jeśli kod jest napisany w asemblerze, to programiści używają różnych pętli, które „zjadają” określoną liczbę cykli zegara, a tym samym uzyskują różne odstępy czasu.

#zawierać

int main (nieważne)

DDRD \u003d 0b000000011;

podczas gdy (1)

PORTD \u003d 0b000000001; // Włącz pierwszą diodę LED

Aby uzyskać opóźnienie 0,5 sekundy, musisz wstawić tutaj

500 000 poleceń na jeden cykl

PORTD \u003d 0b000000010; // Włącz drugi

Funkcjonować _delay_ms () i migająca dioda LED

Podczas pisania kodu C w Atmel Studio jest bardzo wygodna funkcja _delay_ms(). Aby ta funkcja działała, należy ją najpierw połączyć z dyrektywą preprocesora .

W nawiasach tej funkcji możesz ustawić czas w milisekundach, następnie musisz wpisać ms przed nawiasami lub nas w mikrosekundach:

Korzystając z tej funkcji, aby Atmel Studio nie generował żadnych ostrzeżeń podczas kompilacji, należy zadeklarować częstotliwość za pomocą instrukcji #define. Ponieważ wartość domyślna ATmega8 to 1 000 000 Hz, zadeklarujemy tę wartość. Odbywa się to za pomocą następującego wiersza:

#definiować F_CPU 1000000UL

W przyszłości, gdy podłączymy rezonator kwarcowy do MK, nie można zrezygnować z tej linii. Jego struktura pozostanie taka sama, tylko zamiast 1 000 000 będzie trzeba zarejestrować częstotliwość rezonatora kwarcowego.

Poprawmy nasz program tak, aby najpierw zapaliła się jedna dioda, potem po pół sekundy gaśnie, a po kolejnych pół sekundy zapala się druga, a po 0,5 sekundy znowu gaśnie.

# definiować

Spójrzmy ponownie na powyższy kod. Jeśli musimy zmienić wartość opóźnienia czasowego w funkcji _ opóźnienie od 500 np. do 300, to musimy znaleźć wszystkie linie z jego nazwą i dokonać odpowiedniej zamiany. Teraz wyobraźmy sobie, że takich wierszy jest sto, a nawet tysiąc. Niezwykle niewygodna i czasochłonna jest zmiana wartości każdej liczby z osobna. Dodatkowo możesz przypadkowo pominąć linię. Dlatego należy przyjąć inne, wygodniejsze i bardziej praktyczne podejście.

Istnieje kilka takich podejść. Najprościej jest zadeklarować zmienną i przypisać jej żądaną wartość. Ponadto zmienna ta jest zastępowana przez odpowiednie funkcje. To dobry sposób. Rozważymy to bardziej szczegółowo później. Teraz przyjrzymy się jeszcze lepszemu!

Używamy operatora #define, aby przypisać nazwę wartości liczbowej. To imię nazywa się stały... W przeciwieństwie do zmiennej, stałej nie można zmienić w programie. To wygląda tak:

#define MIG 300

_ opóźnienie_ sM(MIG);

Nazwę stałej można ustawić na prawie wszystko, używając znaków łacińskich i cyfr. W tym przypadku nazwa MIG wskazuje, że stosujemy opóźnienie za chwilęz diodami LED.

Po wierszu z dyrektywą preprocesora #define nie ma średnika. Pomiędzy nazwą stałej a wartością liczbową wstawiana jest spacja.

Ta linia działa w następujący sposób. Przed rozpoczęciem kompilacji wszystkie stałe o nazwie MIG są zastępowane przez 300.

#definiować i rejestry

Ponadto operator #define jest dobry, ponieważ można go używać do określania nazw rejestrów. Przykładowo, jeśli podłączymy diody do portu D, to zamiast PORTD możemy napisać np. VD:

#define VD PORTD

VD \u003d 0b00000001;

Przepiszmy program za pomocą dyrektywy #define:

#definiować F_CPU 1000000UL

#zawierać

#zawierać

Dodano: 28.06.2017 o godzinie 13:00

W tym przykładzie napiszemy nasz pierwszy program w C dla mikrokontrolera ATtiny13. Zakłada się, że przygotowaliśmy już do pracy wszystko, czego potrzebujesz: środowisko programistyczne, kompilator itp. W ramach eksperymentu będę miał własną tablicę debugowania, więc zacytuję cały związany z nią kod.
Jako program testowy napiszemy klasyczny, najprostszy przykład „mrugnięcia”, który będzie migał diodą LED z określoną częstotliwością.

Stwórzmy więc nowy projekt i zacznijmy. Od razu podam pełny kod programu, a potem wszystko wyjaśnię bardziej szczegółowo:

/ * * tiny13_board_blink * Demo-firmware płyty debugującej na ATtiny13 * w celu sprawdzenia funkcjonalności MK. * Mrugamy diodą LED. * / #define F_CPU 1200000UL // Określ częstotliwość taktowania MK #define LED PB2 // Użyj diody LED podłączonej do PB2 (7 pinów) # uwzględnij // Dołącz definicje I / O #include // Podłącz bibliotekę funkcji opóźniających int main (void) (// DDRB LED | \u003d (1<

Na samym początku ustawiamy wartości stałych i dołączamy pliki nagłówkowe oraz biblioteki.
Plik avr / io.h łączy definicje I / O dla określonego typu mikrokontrolera (typ MC jest określany jako opcja dla kompilatora).
Biblioteka util / delay. h łączymy się, aby skorzystać z funkcji opóźnienia, w naszym przypadku: _delay_ms ()... Aby funkcje latencji działały, musimy określić szybkość zegara procesora. w związku z tym PRZED znajomości util / delay. h zdefiniować stałą F_CPU (w tym przypadku - 1,2 MHz).

Następnie mamy główną funkcję główny - to jest w rzeczywistości treść naszego programu. W tym miejscu musimy najpierw opisać wszystkie akcje, które wystąpią po uruchomieniu mikrokontrolera, a następnie w nieskończonej pętli rozpocząć wykonywanie programu głównego:

podczas gdy (1) (...)

Najpierw musimy skonfigurować port I / O. W MK AVR może być kilka portów I / O (A, B, C, D). Do każdego portu można podłączyć do ośmiu pinów. Każdą z nóg można skonfigurować zarówno jako wejście, jak i wyjście. ATtiny13 ma tylko jeden port (B) z sześcioma pinami (PB0-PB5, patrz arkusz danych). Domyślnie wszystkie nogi są ustawione na wejście i aby sterować diodą LED, musimy użyć odpowiedniej nogi jako wyjścia. W mikrokontrolerach AVR cały sprzęt jest konfigurowany za pomocą ośmiobitowych rejestrów. Kierunek (wejście-wyjście) jest ustalany przez bity rejestrów DDRx (gdzie x to litera portu, w naszym przypadku B). Wartość bitu „0” - odpowiada wejściu, „1” - wyjściu. Zatem, aby użyć odnogi PB2 jako wyjścia, musimy ustawić drugi bit rejestru DDRB za sztukę:

DDRB | \u003d (1<

Rejestry PORTx służą do sterowania stanem wyjścia. Przykładowo, aby wyłączyć diodę LED podłączoną do nogi PB2 (wysłać niski poziom sygnału), musimy wpisać zero do drugiego bitu rejestru PORTB:

PORTB & \u003d ~ (1<

Aby włączyć (podać wysoki poziom sygnału) - odpowiednio zapisujemy jeden:

PORTB | \u003d (1<

Teraz, gdy port I / O jest skonfigurowany, uruchamiamy główną pętlę, w której będziemy odwracać stan wyjścia PB2 (naprzemiennie wysoki i niski) z opóźnieniem 500 ms. W ten sposób nasza dioda LED będzie migać 1 raz na sekundę.

DZWON

Są tacy, którzy czytają tę wiadomość przed tobą.
Zapisz się, aby otrzymywać najnowsze artykuły.
E-mail
Imię
Nazwisko
Jak chcesz przeczytać The Bell
Bez spamu