Na lekcji dowiemy się o schematach łączenia siedmiosegmentowych wskaźników LED z mikrokontrolerami, o tym, jak sterować wskaźnikami.

Siedmiosegmentowe wskaźniki LED pozostają jednym z najpopularniejszych elementów do wyświetlania informacji cyfrowych.

Jest to ułatwione dzięki następującym cechom.

  • Niska cena. Nie ma nic tańszego w środkach sygnalizacyjnych niż cyfrowe wskaźniki LED.
  • Różnorodność rozmiarów. Najmniejsze i największe wskaźniki to diody LED. Znam kierunkowskazy LED o wysokości cyfr od 2,5 mm do 32 cm.
  • Świecić w ciemności. W niektórych zastosowaniach ta właściwość jest prawie decydująca.
  • Mają różne barwy światła. Są nawet dwa kolory.
  • Wystarczająco niskie prądy sterujące. Nowoczesne wskaźniki LED można podłączyć do wyjść mikrokontrolerów bez dodatkowych klawiszy.
  • Pozwalają na trudne warunki pracy (zakres temperatur, wysoka wilgotność, wibracje, agresywne środowisko itp.). Pod względem tej jakości wskaźniki LED nie mają sobie równych wśród innych rodzajów elementów wyświetlacza.
  • Nieograniczona żywotność.

Rodzaje wskaźników LED.

Siedmiosegmentowy wskaźnik LED wyświetla znak za pomocą siedmiu segmentów LED cyfry. Ósma dioda LED oświetla kropkę dziesiętną. Tak więc we wskaźniku siedmiosegmentowym jest 8 segmentów.

Segmenty są oznaczone literami łacińskimi od „A” do „H”.

Anody lub katody każdej diody LED są połączone we wskaźniku i tworzą wspólny przewód. Dlatego istnieją wskaźniki ze wspólną anodą i wspólną katodą.

Wskaźnik LED ze wspólną anodą.

Wskaźnik LED wspólnej katody.

Statyczne sterowanie LED.

Konieczne jest podłączenie wskaźników LED do mikrokontrolera poprzez rezystory ograniczające prąd.

Obliczenia rezystora są takie same jak dla poszczególnych diod LED.

R = (U podaż - U segment) / I segment

Dla tego obwodu: I segment = (5 - 1,5) / 1000 = 3,5 mA

Nowoczesne wskaźniki LED świecą dość jasno już przy prądzie 1 mA. W przypadku obwodu ze wspólną anodą zaświecą się segmenty, na których wyjściach sterujących mikrokontroler wygeneruje niski poziom.

Na schemacie połączeń wskaźnika ze wspólną katodą zmienia się polaryzacja zasilania i sygnałów sterujących.

Zaświeci się segment, na którego wyjściu sterującym zostanie utworzony wysoki poziom(5 V).

Tryb sterowania multipleksowanego LED.

Aby połączyć każdy wskaźnik siedmiosegmentowy Do mikrokontrolera wymagane jest osiem pinów. Jeśli są 3 - 4 wskaźniki (cyfry), zadanie staje się praktycznie niemożliwe. Po prostu za mało pinów mikrokontrolera. W takim przypadku wskaźniki mogą być połączone w trybie multipleksowym, w trybie dynamicznego wskazania.

Wnioski z segmentów o tej samej nazwie każdego wskaźnika są łączone. Okazuje się, że matryca diod LED jest połączona między wyjściami segmentów a wspólnymi wyjściami wskaźników. Oto obwód do multipleksowego sterowania trzycyfrowym wskaźnikiem ze wspólną anodą.

Do podłączenia trzech wskaźników wymagane było 11 pinów, a nie 24, jak w trybie sterowania statycznego.

Przy wskazaniu dynamicznym na raz świeci tylko jedna cyfra. Sygnał wysokiego poziomu (5 V) jest podawany na wspólne wyjście jednego z bitów, a sygnały niskiego poziomu są wysyłane do wyjść segmentu dla tych segmentów, które powinny być oświetlone w tym bicie. Po pewnym czasie następuje zapłon kolejnego wyładowania. Do jego wspólnego wyjścia podawany jest wysoki poziom, a sygnały stanu dla tego bitu są wysyłane do wyjść segmentu. I tak dla wszystkich bitów w nieskończonej pętli. Czas cyklu nazywany jest czasem odświeżania wskaźnika. Jeśli czas regeneracji jest wystarczająco krótki, to ludzkie oko nie zauważy przełączania wyładowań. Wygląda na to, że wszystkie wyładowania świecą stale. Aby uniknąć migotania wskaźników, uważa się, że częstotliwość cyklu regeneracji powinna wynosić co najmniej 70 Hz. Staram się używać co najmniej 100Hz.

Obwód sygnalizacji dynamicznej dla diod LED ze wspólną katodą wygląda tak.

Polaryzacja wszystkich sygnałów jest odwrócona. Teraz niski poziom jest stosowany do wspólnego przewodu aktywnego wyładowania, a wysoki poziom jest stosowany do segmentów, które powinny się świecić.

Obliczanie elementów dynamicznej sygnalizacji wskaźników diodowych (LED).

Obliczenia są nieco bardziej skomplikowane niż w trybie statycznym. Podczas obliczeń konieczne jest określenie:

  • średni prąd segmentów;
  • segmenty prądu impulsowego;
  • rezystancja rezystora segmentowego;
  • prąd impulsowy wspólnych wniosków wyładowań.

Dlatego cyfry wskaźnika zapalają się kolejno, a następnie jasność blasku określa średni prąd. Musimy go wybrać na podstawie parametrów wskaźnika i wymaganej jasności. Średni prąd określi jasność wskaźnika na poziomie odpowiadającym statycznej kontroli przy tym samym stałym prądzie.

Wybierzmy średni prąd segmentu 1 mA.

Teraz obliczmy prąd impulsowy segmentu. Aby zapewnić wymagany średni prąd, prąd pulsacyjny musi być N razy większy. Gdzie N to liczba cyfr wskaźnikowych.

segm. chochlik. = I segm. śr. * N

Dla naszego schematu segm. chochlik. = 1 * 3 = 3 mA.

Obliczamy rezystancję rezystorów ograniczających prąd.

R \u003d (moc U - segment U) / segment I. chochlik.

R \u003d (5 - 1,5) / 0,003 \u003d 1166 omów

Określamy prądy pulsacyjne wspólnych wniosków wyładowań. Jednocześnie może świecić 8 segmentów, co oznacza, że ​​prąd impulsu jednego segmentu należy pomnożyć przez 8.

I kategoria imp. = I segm. chochlik. * osiem

Dla naszego schematu rozładowuję imp. = 3 * 8 = 24 mA.

  • rezystancja rezystorów jest wybrana 1,1 kOhm;
  • wyjścia mikrokontrolera sterującego segmentem muszą dostarczać prąd co najmniej 3 mA;
  • wyjścia mikrokontrolera do wyboru cyfry wskaźnika muszą dostarczać prąd co najmniej 24 mA.

Przy takich wartościach prądu wskaźnik można podłączyć bezpośrednio do zacisków płytki Arduino, bez użycia dodatkowych klawiszy. W przypadku jasnych wskaźników takie prądy są wystarczające.

Schematy z dodatkowymi kluczami.

Jeśli wskaźniki wymagają większego prądu, należy zastosować dodatkowe przełączniki, szczególnie w przypadku sygnałów wyboru cyfr. Całkowity prąd rozładowania jest 8 razy większy niż prąd jednego segmentu.

Schemat podłączenia wskaźnika LED ze wspólną anodą w trybie multipleksowym z przełącznikami tranzystorowymi do wyboru cyfr.

Aby wybrać bit w tym obwodzie, konieczne jest wygenerowanie sygnału o niskim poziomie. Odpowiedni klucz otworzy się i dostarczy zasilanie do rozładowania wskaźnika.

Schemat połączeń dla wskaźnika LED ze wspólną katodą w trybie multipleksowym z przełącznikami tranzystorowymi do wyboru cyfr.

Aby wybrać bit w tym obwodzie, konieczne jest wygenerowanie sygnału o wysokim poziomie. Odpowiedni przełącznik otworzy i zamknie wspólne wyjście rozładowania do ziemi.

Mogą istnieć obwody, w których konieczne jest zastosowanie przełączników tranzystorowych zarówno dla segmentów jak i wspólnych przewodów wyładowczych. Takie schematy można łatwo zsyntetyzować z dwóch poprzednich. Wszystkie pokazane obwody są używane, gdy wskaźnik jest zasilany napięciem równym napięciu mikrokontrolera.

Klawisze do kierunkowskazów o podwyższonym napięciu zasilania.

Istnieją wskaźniki o dużych rozmiarach, w których każdy segment składa się z kilku połączonych szeregowo diod LED. Do zasilania takich wskaźników wymagane jest źródło o napięciu większym niż 5 V. Przełączniki muszą zapewniać przełączanie wysokiego napięcia sterowane sygnałami poziomu mikrokontrolera (zwykle 5 V).

Obwód kluczy zamykających sygnały wskaźnika do masy pozostaje niezmieniony. A klawisze zasilania powinny być zbudowane według innego schematu, na przykład tego.

W tym schemacie aktywne wyładowanie jest wybierane przez wysoki poziom sygnału sterującego.

Pomiędzy przełączeniem bitów wskaźnika na krótki czas (1-5 µs) wszystkie segmenty powinny się wyłączyć. Czas ten jest niezbędny do zakończenia przejściowych procesów przełączania kluczy.

Strukturalnie, wnioski z wyładowań można łączyć jak w jednym przypadku wskaźnika wielocyfrowego, lub wskaźnik wielocyfrowy można składać z oddzielnych jednocyfrowych. Ponadto istnieje możliwość złożenia wskaźnika z poszczególnych diod połączonych w segmenty. Odbywa się to zwykle, gdy konieczne jest zmontowanie wskaźnika o bardzo dużych wymiarach. Wszystkie powyższe schematy będą ważne dla takich opcji.

W kolejnej lekcji podłączymy siedmiosegmentowy wskaźnik LED do płytki Arduino, napiszemy bibliotekę do sterowania nią.

Kategoria: . Możesz dodać zakładkę.

Czasami wymagane jest podłączenie do mikrokontrolera kilku wskaźników siedmiosegmentowych lub matrycy LED, natomiast wskazanie dynamiczne służy do wyświetlania informacji. Istotą sygnalizacji dynamicznej jest sukcesywne wyświetlanie informacji na wskaźnikach. Poniższy schemat pokazuje przykład połączenia kilku wskaźników siedmiosegmentowych (na przykład ze wspólną katodą) w celu wdrożenia wskazania dynamicznego, ogólnie biorąc pod uwagę punkt, uzyskuje się 8 segmentów, ale w staromodny sposób są one nazywany w ten sposób. Wszystkie wyprowadzenia (anody) segmentów o tej samej nazwie są połączone razem, w sumie 8 linii, które są połączone z mikrokontrolerem za pomocą rezystorów. Wspólna katoda każdego wskaźnika jest połączona z mikrokontrolerem przez tranzystor.


Algorytm wskazań jest następujący: najpierw ustawiamy wymagane poziomy logiczne na liniach, w zależności od tego, które segmenty mają być włączone na pierwszym wskaźniku (wskazanie od lewej do prawej), z wysokim poziomem logicznym do włączenia, niskim aby wyłączyć segment. Następnie stosujemy wysoki poziom logiczny do podstawy tranzystora VT1, tym samym wspólna katoda pierwszego wskaźnika jest podłączona do wspólnego przewodu, w tym momencie te segmenty świecą się, na anodach których znajduje się jednostka logiczna. Po pewnym czasie (pauzie) wskaźnik jest wyłączany przez przyłożenie niskiego poziomu logicznego do bazy tranzystora, następnie ponownie zmieniamy poziomy logiczne na liniach zgodnie z informacją wyjściową przeznaczoną dla drugiego wskaźnika i stosujemy sygnał włączenia do tranzystora VT2. Tak więc, w kolejności w cyklu kołowym, przełączamy wszystkie wskaźniki, to jest cała sygnalizacja dynamiczna.

Aby uzyskać solidny obraz bez migotania, przełączanie musi odbywać się z dużą prędkością, aby zapobiec migotaniu diod LED, częstotliwość odświeżania musi być ustawiona na 70 Hz lub więcej, zwykle ustawiam 100 Hz. Dla powyższej konstrukcji pauza jest obliczana w następujący sposób: dla częstotliwości 100 Hz okres wynosi 10 ms, są odpowiednio tylko 4 wskaźniki, czas świecenia każdego wskaźnika jest ustawiony na 10/4 = 2,5 ms. W jednej obudowie znajdują się wielocyfrowe siedmiosegmentowe wskaźniki, w których segmenty o tej samej nazwie są połączone wewnątrz samej obudowy, oczywiście do ich użycia konieczne jest zastosowanie dynamicznej sygnalizacji.

Aby zaimplementować dynamiczne wskazanie, konieczne jest zastosowanie przerwań przy przepełnieniu jednego z timerów. Poniżej znajduje się kod za pomocą timera TMR0:

;Wdrożenie dynamicznej sygnalizacji dla 4 wskaźników siedmiosegmentowych ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; zamiana STATUS,W ; STATUS clrf ; movwf STATUS_TEMP ; ; bcf ind1 ;wyłączyć pierwszy wskaźnik bcf ind2 ;wyłączyć drugi wskaźnik bcf ind3 ;wyłączyć trzeci wskaźnik bcf ind4 ;wyłączyć czwarty wskaźnik; incf shet,F ;przyrost rejestru shet movlw .5 ;sprawdzić zawartość rejestru shet xorwf shet,W ;sprawdzić, czy jest równy 5 btfss STATUS,Z ; goto met1 ;numer w rejestrze shet nie jest równy 5 movlw .1 ;numer w rejestrze shet jest równy 5: zapisz numer 1 movwf shet ;do rejestru shet ; met1 movlw .1 ;sprawdzić zawartość rejestru shet xorwf shet,W ;równy numerowi 1 btfss STATUS,Z; goto met2 ;numer w rejestrze shet nie jest równy 1: skok do met2 movf datind1,W ;numer w rejestrze shet jest równy 1: skopiuj movwf PORTB ;zawartość rejestru datind1 do rejestru PORTB bsf ind1 ;włącz pierwszy wskaźnik met2 movlw .2 ;sprawdzić zawartość rejestru shet xorwf shet,W ;równą 2 btfss STATUS,Z; goto met3 ;numer w rejestrze shet nie równy 2: skocz do met3 movf datind2,W ;numer w rejestrze shet to 2: skopiuj movwf PORTB ;zawartość rejestru datind2 do rejestru PORTB bsf ind2 ;włącz drugi wskaźnik goto exxit ;skok do label exxit met3 movlw .3 ;sprawdź zawartość rejestru shet xorwf shet,W;równe 3 btfss STATUS,Z; goto met4 ;numer w rejestrze shet nie równy 3: skocz do met4 movf datind3,W ;numer w rejestrze shet to 3: skopiuj movwf PORTB ;zawartość rejestru datind3 do rejestru PORTB bsf ind3 ;włącz trzeci wskaźnik goto exxit ;skok do label exxit met4 movf datind4,W ;skopiuj zawartość rejestru datind3 movwf PORTB ;do rejestru PORTB bsf ind4 ;włącz czwarty wskaźnik; movlw .100 ;zapisz 156 do rejestru timera TMR0 movwf TMR0 ; ; STAN movwf ; swapf W_TEMP,F ; swapf W_TEMP,W ; ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;Program główny ..............................movlw b"11010011" ;OPTION_REG, tym samym ustawiając wewnętrzny ;ustawiając współczynnik preskalera 1:16 ; clrf shet ;zerowanie rejestru shet przed uruchomieniem;przerwania przy przepełnieniu TMR0, w toku; clrf datind1 ;czyszczenie rejestrów do wyprowadzania informacji do clrf datind2 ;wskaźniki, jest to równoznaczne z wyłączeniem clrf datind3 ;wskaźniki, ponieważ wskaźniki ze wspólnym clrf datind4 ;katoda; bcf INTCON,T0IF ;wyczyść flagę przerwania przepełnienia TMR0 bsf INTCON,T0IE ;włącz przerwania przepełnienia TMR0 bsf INTCON,GIE ;włącz globalne przerwania; movlw b"00000110";13,52 przykład wyjścia movwf datind1; movlw b"11001111" ; movwf z dnia2 ; movlwb"01101101" ; movwf z dnia3 ; movlwb"01011011" ; movwf z dnia4 ; ; . ................; .................; .................; ; koniec ;koniec całego programu;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;Wdrożenie dynamicznej sygnalizacji dla 4 wskaźników siedmiosegmentowych

;Przykładowa częstotliwość taktowania 4 MHz, cykl maszyny 1 µs

org 0000h ;rozpocznij wykonywanie programu pod adresem 0000h

przejdź do Start ;przejdź do etykiety Start

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;Procedura przerywania

org 0004h ;rozpocznij wykonywanie podprogramu pod adresem 0004h

movwf W_TEMP ;zapisz wartości rejestru kluczy

zamiana STATUS,W ;

movwf STATUS_TEMP ;

bcf ind1; wyłącz pierwszy wskaźnik;

bcf ind2 (wyłącz drugi wskaźnik)

bcf ind3 (wyłącz trzeci wskaźnik)

bcf ind4; wyłącz czwarty wskaźnik;

incf shet,F ;przyrost rejestru shet

movlw .5 ;sprawdź zawartość arkusza rejestru

xorwf shet,W ; równy 5

btfss STATUS,Z ;

goto met1 ;numer w kartotece nie jest równy 5

movlw .1 ;numer w rejestrze shet to 5: wpisz numer 1

movwf shet ;aby zarejestrować shet

met1 movlw .1 ; sprawdź zawartość rejestru shet

xorwf shet,W ; równa liczbie 1

btfss STATUS,Z ;

goto met2 ;liczba w rejestrze shet nie równa 1: skocz do met2

movf datind1,W ;numer w rejestrze shet to 1: kopia

movwf PORTB ; zawartość rejestru datind1 do rejestru PORTB

bsf ind1 ;włącz pierwszy wskaźnik

przejdź do wyjścia ; przejdź do etykiety wyjście

met2 movlw .2 ; sprawdź zawartość rejestru shet

xorwf shet,W ; równa liczbie 2

btfss STATUS,Z ;

goto met3 ;liczba w rejestrze shet nie równa 2: skocz do met3

movf datind2,W ;numer w rejestrze shet to 2: kopia

movwf PORTB ; zawartość rejestru datind2 do rejestru PORTB

bsf ind2 ;włącz drugi wskaźnik

przejdź do wyjścia ; przejdź do etykiety wyjście

met3 movlw .3 ; sprawdź zawartość rejestru

xorwf shet,W ; równa liczbie 3

btfss STATUS,Z ;

goto met4 ;liczba w rejestrze nie równa 3: skocz do met4

movf datind3,W ;numer w rejestrze shet to 3: kopia

movwf PORTB ;zawartość rejestru datind3 do rejestru PORTB

bsf ind3 ;włącz trzeci wskaźnik

przejdź do wyjścia ; przejdź do etykiety wyjście

met4 movf datind4,W ; skopiuj zawartość rejestru datind3

movwf PORTB ;do rejestru PORTB

bsf ind4 ;włącz czwarty wskaźnik

exxit bcf INTCON,T0IF ;zresetuj flagę przerwania przepełnienia TMR0

movlw .100 ;zapisz numer 156 do rejestru timera TMR0

swapf STATUS_TEMP,W ;przywróć zawartość rejestrów kluczy

swapf W_TEMP,F ;

swapf W_TEMP,W ;

retfie ;wyjście z procedury przerwania

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;Główny program

Początek ................. ; początkowe ustawienia rejestry

................. ;specjalny cel

.................

bsf STATUS,RP0 ;zapis Liczba binarna 11010011 do rejestracji

movlw b"11010011" ;OPTION_REG, tym samym ustawiając wewnętrzny

movwf OPTION_REG ;źródło zegara dla TMR0

bcf STATUS,RP0 ;włącz preskaler przed TMR0

;Ustaw współczynnik preskalera na 1:16

clrf shet ; zresetuj rejestr shet przed rozpoczęciem

;przerwanie przepełnienia TMR0, wykonane

;raz po włączeniu zasilania

clrf datind1 ;wyczyść rejestry do wysyłania informacji do

clrf datind2 ;wskaźniki, równoważne off

clrf datind3 ;wskaźniki, ponieważ wskaźniki ze wspólnym

clrf datind4 ;katoda

bcf INTCON,T0IF ;zresetuj flagę przerwania przepełnienia TMR0

bsf INTCON,T0IE ;włącz przerwania przepełnienia TMR0

bsf INTCON,GIE ;włącz globalne przerwania

movlw b"00000110"; 13.52 przykład wyjścia

movlw b"11001111" ;

movlwb"01101101" ;

movlwb"01011011" ;

................. ;

................. ;

................. ;

koniec ;koniec całego programu

W głównym programie najpierw ustawiamy timer za pomocą rejestru OPTION_REG, wcześniej mówiłem o użyciu timerów dla . Następnie dla każdego wskaźnika czyścimy rejestr kartotek, przeznaczony do wprowadzania liczby od 1 do 4. Ten rejestr jest zwiększany w procedurze przerwania i tam dostosowywany (będzie liczył od 1 do 4), więc to sprzątanie wykonywane raz po włączeniu. Na podstawie tego rejestru ustalimy, który wskaźnik uwzględnić i wydamy odpowiadające mu dane. Następnym krokiem jest wyczyszczenie rejestrów przechowywania informacji, czterech rejestrów dataind1,2,3,4 odpowiadających czterem wskaźnikom. Kasowanie jest równoznaczne z wyłączeniem wskaźników, ponieważ w procedurze obsługi przerwań zawartość tych rejestrów jest przekazywana do rejestru PORTB, do którego podłączone są anody wskaźników. Jest to konieczne, aby żadne śmieci nie były wyświetlane na wskaźnikach po włączeniu przerwań, w zasadzie nie można tego zrobić, jeśli prawidłowe informacje zostaną natychmiast zapisane do wyjścia. Następnie zresetuj flagę przerwania przepełnienia timera, włącz przerwania przepełnienia TMR0 i na koniec włącz przerwania globalne.

W procedurze przerwania najpierw wyłączamy wszystkie wskaźniki (poprzez zastosowanie niskich poziomów logicznych do baz tranzystorów), ponieważ nie wiadomo, który z nich jest włączony. Zwiększamy rejestr shet, sprawdzając równość do liczby 5, jeśli jest takie dopasowanie, wpisujemy liczbę 1 do rejestru, ponieważ konieczne jest liczenie od 1 do 4. Następnie sprawdzamy, która liczba jest w shet rejestru, za pomocą którego ładujemy dane z PORTB do rejestrów przechowywania informacji PORTB (dataind) dla odpowiedniego wskaźnika i włączamy go. Następnie resetujemy flagę przerwania przepełnienia TMR0, zapisujemy liczbę 100 do timera (obliczanie tej wartości podano poniżej), dla opóźnienia czasowego i wychodzimy z obsługi przerwań. Przy pierwszej przerwie zapala się pierwszy wskaźnik, przy drugiej przerwie drugi i tak dalej w cyklu okrężnym. W programie głównym pozostaje tylko załadowanie danych do rejestrów przechowywania informacji dla każdego wskaźnika. W podprogramie przerwań nie zapomnij zapisać i przywrócić wartości rejestrów kluczy, o czym pisałem w artykule.

Do wyprowadzania liczb lepiej jest użyć generatora znaków w postaci tabeli danych. Na przykład, aby wyświetlić numer 3456 na wskaźnikach, należy go podzielić na cyfry, natomiast lepiej jest użyć oddzielnych rejestrów do przechowywania numerów cyfr (od 0 do 9), a następnie uruchomić te rejestry przez generator znaków, tym samym uzyskanie prawidłowych bajtów (załadowanych do rejestrów dataind) w celu zapalenia odpowiednich segmentów.

Przyjmiemy częstotliwość generatora zegara jako 4 MHz, cykl maszyny to 1 μs. Niech częstotliwość odświeżania każdego wskaźnika wynosi odpowiednio 100 Hz (okres T = 10 ms), wymagane opóźnienie to 10/4 = 2,5 ms. Współczynnik preskalera dla TMR0 jest ustawiony na 1:16, podczas gdy maksymalne możliwe opóźnienie wynosi 256x16 = 4096 µs, a potrzebujemy pauzy 2,5 ms. Obliczmy liczbę do zapisania w TMR0: 256-((256x2,5)/4,096) = 256-156,25 = 99,75. Po zaokrągleniu otrzymujemy liczbę 100.

Poniżej można pobrać model programu Proteus, firmware oraz kod źródłowy z implementacją wskazania dynamicznego na 4-cyfrowym wskaźniku ze wspólną katodą z wykorzystaniem mikrokontrolera PIC16F628A. Na przykład na wskaźniku wyświetlane są liczby 0000; 0001; 0002; 13,52; 9764.

Teraz rozważ podłączenie matrycy o rozdzielczości 8x8 pikseli (diody LED). Strukturę macierzy postrzega się zwykle w kategoriach wierszy i kolumn. Na poniższym rysunku w każdej kolumnie katody wszystkich diod LED są połączone, aw każdym rzędzie anody. Ciągi (8 linii, anody LED) są podłączone poprzez rezystory do mikrokontrolera. Każda kolumna (katody LED) jest podłączona do mikrokontrolera poprzez 8 tranzystorów. Algorytm wskazań jest taki sam, najpierw ustawiamy niezbędne poziomy logiczne w wierszach, zgodnie z którymi diody mają świecić w kolumnie, następnie łączymy pierwszą kolumnę (wskazanie od lewej do prawej). Po pewnej przerwie wyłączamy kolumnę i zmieniamy poziomy logiczne na liniach, aby wyświetlić drugą kolumnę, następnie łączymy drugą kolumnę. I tak na przemian przejeżdżamy wszystkie kolumny. Poniżej schemat podłączenia matrycy do mikrokontrolera.


W sumie do podłączenia takiej matrycy potrzeba 16 pinów mikrokontrolera, co jest całkiem sporo, dlatego aby zredukować linie sterujące, lepiej zastosować szeregowe rejestry przesuwne.

Najpopularniejszym rejestrem szeregowym jest mikroukład 74HC595, który zawiera rejestr przesuwny do ładowania danych oraz rejestr wstrzymania, przez który dane są przesyłane do linii wyjściowych. Łatwo załadować do niego dane, ustawić logiczne 0 na wejściu zegara SH_CP, następnie ustawić wymagany poziom logiczny na wejściu danych DS, po czym przełączamy wejście zegara na 1, natomiast wartość poziomu (na wejściu DS ) jest przechowywany w rejestrze przesuwnym. Jednocześnie dane są przesuwane o jeden bit. Zresetuj ponownie wyjście SH_CP na 0, ustaw wymagany poziom na wejściu DS i podnieś SH_CP na 1. Po pełnym załadowaniu rejestru przesuwnego (8 bitów), ustaw wyjście ST_CP na 1, w tym momencie dane są przesyłane do rejestru pamięci i podawane na linie wyjściowe Q0...Q7, po czym resetujemy wyjście ST_CP. Podczas ładowania sekwencyjnego dane są przesuwane z Q0 do Q7. Pin Q7' jest podłączony do ostatniego bitu rejestru przesuwnego, ten pin może być podłączony do wejścia drugiego mikroukładu, dzięki czemu można ładować dane do dwóch lub więcej mikroukładów jednocześnie. Kołek OE przełącza linie wyjściowe do stanu trzeciego (wysokiej rezystancji) po zastosowaniu do niego logiki 1. Kołek MR jest przeznaczony do resetowania rejestru przesuwnego, czyli ustawiania niskich poziomów logicznych na wyjściach wyzwalaczy rejestru , co odpowiada załadowaniu ośmiu zer. Poniżej znajduje się schemat ładowania danych do mikroukładu 74NS595, ustawiający wartość 11010001 na liniach wyjściowych Q0 ... Q7, pod warunkiem, że początkowo były zera:


Rozważ podłączenie matrycy 8×8 do mikrokontrolera PIC16F628A za pomocą dwóch rejestrów przesuwnych 74HC595, schemat pokazano poniżej:


Dane są ładowane do układu DD2 (kontrola poziomu logicznego na wierszach, anody LED), następnie są przesyłane przez pin Q7 odpowiednio do DD3 (kontrola kolumny), najpierw ładujemy bajt, aby włączyć kolumnę, potem bajt z poziomami logicznymi w wierszach. Do linii wyjściowych DD3 podłączone są kolumny z matrycą przełączającą tranzystorów (katody LED). Poniżej znajduje się kod programu do wyświetlania obrazu na matrycy:

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;Wdrożenie dynamicznego wskazania dla matrycy o rozdzielczości 8x8 ;Częstotliwość generatora zegara dla przykładu to 4 MHz, takt maszyny to 1 μs lub 0000h ;start wykonywania programu od adresu 0000h goto Start ;przeskocz do etykiety Start ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;przerwanie procedury org 0004h ;rozpoczęcie wykonywania podprogramu od adresu 0004h movwf W_TEMP ;zapis wartości rejestru kluczy swapf STATUS,W ; STATUS clrf ; movwf STATUS_TEMP ; ; movwf FSR_osn ;do rejestru FSR_osn movf FSR_prer,W ;przywrócenie wcześniej zapisanej wartości movwf FSR ;rejestru FSR z rejestru FSR_prer ;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;załaduj zawartość rejestru stolb do chipa movf stolb,W ;skopiuj zawartość rejestru stolb movwf var ;do rejestru var met2 btfsc var,0 ;ustaw wyjście ds zgodnie z btfss var,0 ; bcf ds ; bcf sh_cp ; rrf var,F ;przesuń rejestr var w prawo do przygotowania;następny bit przejdź do met2 ;scetbit nie równy zero: skocz do etykiety met2 ;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;załaduj zawartość rejestru INDF do chipa ;74HC595 (szeregowy rejestr przesuwny) movf INDF,W ;skopiuj zawartość rejestru INDF movwf var ;do rejestru var movlw .8 ;wpisz liczbę 8 do rejestru scetbit, do zliczania movwf ssetbit ;przesyłane bity met1 btfsc var ,7 ;ustaw wyjście ds zgodnie z bsf ds ;wartość 7 bitu rejestru var btfss var,7 ; bcf ds ; bsf sh_cp ;zegar sh_cp wyjście do zatrzaśnięcia danych bcf sh_cp ; rlf var,F ;Przesuń rejestr w lewo do przygotowania;następny bit decfsz scetbit,F ;Dekrementacja z warunkiem rejestru scetbit goto met1 ;scetbit różny od zera: skocz do etykiety met1 ; bsf st_cp ;zegaruj wyjście st_cp, aby przesłać załadowane bcf st_cp ;bajty do linii wyjściowych układów 74HC595; bcf STATUS,C ;zresetuj bit C stanu rejestru przed przesunięciem rrf stolb,F ;lewy rejestr przesuwny stolb ; incf FSR,F ;Zwiększ rejestr FSR, przygotuj dalej ;Rejestr, aby wysłać dane do 74HC595 decfsz shet,F ;Zmniejszenie z warunkiem rejestru shet goto exxit ;Shet rejestr nie równy 0: Skocz do exxit movlw data1 ;Shet rejestr równy 0: Najpierw zapisz adres movwf FSR ;Rejestr do przechowywania informacji w rejestrze FSR movlw .8 ;Zapis liczby 8 w rejestrze shet, do utrzymania movwf shet ;Zliczanie kolumn ; exxit bcf INTCON,T0IF ;resetuj flagę przerwania przepełnienia TMR0 movlw . 124 ;zapisz numer 124 do rejestru timera TMR0 movwf TMR0 ; ; movf FSR,W ;Zapisz aktualną wartość FSR movwf FSR_prer ;Do FSR_prer movf FSR_osn ,W ;Przywróć poprzednio zapisaną wartość movwf FSR ;FSR z FSR_osn ; swapf STATUS_TEMP, W;przywrócenie zawartości rejestrów kluczy movwf STATUS; swapf W_TEMP,F ; swapf W_TEMP,W ; ; retfie ;wyjdź z podprogramu przerwania;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;Program główny Start ............... ;Wstępne ustawienie rejestrów ............ ;Przeznaczenie specjalne..... ............ bsf STATUS,RP0 ;zapisz numer binarny 11010011 do rejestru movlw b"11010010" ;OPTION_REG, tym samym ustawiając wewnętrzny movwf OPTION_REG ;źródło zegara dla TMR0 bcf STATUS,RP0 ;włącz preskaler przed TMR0;ustaw proporcję preskalera 1:8; movlw .8 ;wpisz numer 8 do rejestru shet, przed uruchomieniem movwf shet ;tmr0 przerwania przepełnienia, wykonywane;raz, po włączeniu movlw b"10000000" ;zapisz binarną liczbę 10000000 do movwf stolb ;rejestr stolb, aby włączyć pierwszą kolumnę; jest wykonywane raz, po włączeniu zasilania; movlw data1 ;Zapisz adres pierwszego rejestru (rejestry pamięci movwf FSR_prer ;informacje) do rejestru FSR_prer, wykonane;raz po włączeniu zasilania; movlw .8 ;czyszczenie 8 rejestrów informacji wyprowadzanych do movwf tmp ;macierz, co odpowiada wyłączeniu movlw data1 ;matrix movwf FSR ; met3 clrf INDF ; incf FSR,F ; decfsz tmp,F ; przejdź do met3 ; ; bcf INTCON,T0IF ;wyczyść flagę przerwania przepełnienia TMR0 bsf INTCON,T0IE ;włącz przerwania przepełnienia TMR0 bsf INTCON,GIE ;włącz globalne przerwania; m1 movlw data1;przykład wyjścia R movwf FSR; movlw b"00000000" ; movwf INDF ; incf FSR,F ; movlw b"01111111" ; movwf INDF ; incf FSR,F ; movlwb"00001001" ; movwf INDF ; incf FSR,F ; movlwb"00011001" ; movwf INDF ; incf FSR,F ; movlwb"00101001" ; movwf INDF ; incf FSR,F ; movlw b"01000110" ; movwf INDF ; incf FSR,F ; movlw b"00000000" ; movwf INDF ; incf FSR,F ; movlw b"00000000" ; movwf INDF ; ; .................; .................; .................; ; koniec ;koniec całego programu;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;Wdrożenie dynamicznego wskazania dla matrycy o rozdzielczości 8x8

;Przykładowa częstotliwość taktowania 4 MHz, cykl maszyny 1 µs

org 0000h ;rozpocznij wykonywanie programu pod adresem 0000h

przejdź do Start ;przejdź do etykiety Start

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;Procedura przerywania

org 0004h ;rozpocznij wykonywanie podprogramu pod adresem 0004h

movwf W_TEMP ;zapisz wartości rejestru kluczy

zamiana STATUS,W ;

movwf STATUS_TEMP ;

movf FSR,W ;zapisz aktualną wartość rejestru FSR

movwf FSR_osn ;do rejestru FSR_osn

movf FSR_prer,W ;przywróć wcześniej zapisaną wartość

movwf FSR ;FSR z FSR_prer

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;74HC595 (szeregowy rejestr przesuwny)

movf stolb,W ; skopiuj zawartość rejestru stolb

movwf var ;aby zarejestrować var

movlw .8 ;wpisz liczbę 8 do rejestru scetbitowego, aby zliczyć

movwf scetbit ;przesyłane bity

met2 btfsc var,0 ;ustaw wyjście ds zgodnie z

bsf ds ;7-ta wartość bitowa rejestru var

bsf sh_cp ;zegar sh_cp wyjście do zatrzasku danych

rrf var,F ;przesuń rejestr w prawo do przygotowania

;następny bit

decfsz scetbit,F ;dekrementacja z warunkiem rejestru scetbit

goto met2 ;scetbit nie równy zero: skocz do etykiety met2

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;74HC595 (szeregowy rejestr przesuwny)

movf INDF,W ; kopiuje zawartość rejestru INDF

movwf var ;aby zarejestrować var

movlw .8 ;wpisz liczbę 8 do rejestru scetbitowego, aby zliczyć

movwf scetbit ;przesyłane bity

met1 btfsc var,7 ;ustaw wyjście ds zgodnie z

bsf ds ;7-ta wartość bitowa rejestru var

bsf sh_cp ;zegar sh_cp wyjście do zatrzasku danych

rlf var,F ;przesunięcie w lewo var do przygotowania

;następny bit

decfsz scetbit,F ;dekrementacja z warunkiem rejestru scetbit

goto met1 ;scetbit nie równy zero: skocz do etykiety met1

bsf st_cp ;taktowanie wyjścia st_cp do przesłania załadowanego

bcf st_cp ;bajty na linie wyjściowe 74HC595

bcf STATUS,C ; wyczyść bit C rejestru stanu przed przesunięciem

rrf stolb,F ;lewy rejestr przesuwny stolb

incf FSR,F ;Zwiększ rejestr FSR, przygotuj następny

;zarejestruj się, aby wysłać dane do 74HC595

decfsz shet,F ;dekrementacja z warunkiem rejestru shet

goto exxit ;shet register nie jest równy 0: skocz do wyjścia

movlw data1 ;shet register to 0: wpisz adres pierwszego

movwf FSR ;Zarejestruj się, aby przechowywać informacje w FSR

movlw .8 ;wpisz numer 8 do rejestru shet, dla odniesienia

arkusz movwf ;liczba kolumn

movlw b"10000000" ;wpisz liczbę binarną 10000000 do

movwf stolb ;zarejestruj stolb, aby uwzględnić pierwszą kolumnę

exxit bcf INTCON,T0IF ;zresetuj flagę przerwania przepełnienia TMR0

movlw .124 ;zapisz numer 124 do rejestru timera TMR0

movf FSR,W ;zapisz aktualną wartość rejestru FSR

movwf FSR_prer ;do rejestru FSR_prer

movf FSR_osn ,W ;przywróć wcześniej zapisaną wartość

movwf FSR ;FSR z FSR_osn

swapf STATUS_TEMP,W ;przywróć zawartość rejestrów kluczy

swapf W_TEMP,F ;

swapf W_TEMP,W ;

retfie ;wyjście z procedury przerwania

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;Główny program

Start ............... ;wstępne ustawienie rejestrów

................. ;specjalny cel

.................

bsf STATUS,RP0 ;zapisz liczbę binarną 11010011 do rejestru

movlw b"11010010" ;OPTION_REG, tym samym ustawiając wewnętrzny

movwf OPTION_REG ;źródło zegara dla TMR0

bcf STATUS,RP0 ;włącz preskaler przed TMR0

;Ustaw współczynnik preskalera na 1:8

movlw .8 ;zapisz numer 8 do rejestru shet przed uruchomieniem

movwf shet ;przerwania przepełnienia TMR0, uruchomione

;raz po włączeniu zasilania

movlw b"10000000" ;wpisz liczbę binarną 10000000 do

movwf stolb ;zarejestruj stolb, aby uwzględnić pierwszą kolumnę

Informacje z poziomami logicznymi dla wierszy każdej kolumny są przechowywane w 8 rejestrach pamięci informacji, do których dostęp jest możliwy. Adres pierwszego rejestru nosi nazwę data1. Oprócz wstępnego zapisu rejestrów shet i stolb konieczne jest wpisanie adresu pierwszego rejestru przechowywania informacji do rejestru FSR_prer (rejestr to data1, wpis w FSR_prer jest wykonywany raz, następnie jest korygowany w handler), dopiero potem włącz przerwania przepełnienia TMR0.

Przed włączeniem przerwań pożądane jest wyczyszczenie rejestrów przechowywania informacji, operacja ta jest wykonywana przy użyciu dodatkowego rejestru tmp (jako licznika) i adresowania pośredniego, wyczyszczenie jest równoznaczne z wyłączeniem macierzy.

W procedurze obsługi przerwań ładujemy zawartość rejestru stolb do układu DD2 (przy pierwszym wprowadzeniu funkcji obsługi po włączeniu przerwań rejestr zawiera liczbę 10000000, jak wspomniano powyżej). Ładowanie rozpoczyna się od niskiego bitu rejestru stolb, który przesuwa się w kierunku od Q0 do Q7 (wewnątrz układu DD2) podczas ładowania, algorytm ładowania został omówiony powyżej, więc myślę, że nie będzie trudno zrozumieć kod . Następnie ładujemy zawartość rejestru INDF do DD2, jest to jeden z rejestrów przechowywania informacji, którego adres znajduje się w FSR (przy pierwszym wprowadzeniu funkcji obsługi po włączeniu przerwań, FSR zawiera adres pierwszego rejestr przechowywania informacji o nazwie data1). Ładowanie rozpoczyna się od wyższego bitu rejestru INDF. Po załadowaniu rozważanych 2 bajtów taktujemy wyjście st_cp, dzięki czemu pobrane dane są przesyłane do linii wyjściowych mikroukładów DD2, DD3. Tak więc przy pierwszym wejściu do handlera przełączana jest pierwsza kolumna matrycy, w której świecą się diody LED, na anodach których występuje wysoki poziom logiczny, zgodnie z zawartością rejestru data1 ( pierwszy rejestr przechowywania informacji).

Następnie przesuwamy rejestr stolb w prawo o jeden bit, aby przygotować drugą kolumnę macierzy do przełączania przy następnym wejściu do procedury obsługi przerwań. Flaga C rejestru STATUS musi zostać wyczyszczona przed przesunięciem, ponieważ przesunięcie następuje przez tę flagę, a jej stan nie jest znany w momencie przesunięcia. Po przesunięciu zwiększamy rejestr FSR, przygotowując kolejny rejestr pamięci (po rejestrze data1) z logicznymi poziomami wierszy dla drugiej kolumny. Następnie zmniejszamy rejestr shet o warunek, a jeśli nie jest równy zero, resetujemy flagę przerwania przepełnienia TMR0, zapisujemy numer do timera i wychodzimy z obsługi przerwań.

Następnym razem, gdy wejdziesz do obsługi, zostanie włączona druga kolumna macierzy i tak dalej. Po zresetowaniu rejestru shet (po przełączeniu 8 kolumny) zapisywana jest do niego liczba 8 na kolejny cykl przełączania biegunów, dodatkowo korygowana jest wartość rejestru stolb, adres pierwszego rejestru przechowywania informacji ( data1) jest zapisywana w rejestrze FSR.

Obliczmy opóźnienie czasowe dla timera TMR0, częstotliwość zegara to 4 MHz, cykl maszyny to 1 µs. Aby uniknąć migotania diod, przyjmijmy częstotliwość odświeżania każdej kolumny jako 100Hz (okres T=10ms), opóźnienie czasowe to 10/8 = 1,25ms. Ustawiamy współczynnik preskalera TMR0 na 1:8, natomiast maksymalne możliwe opóźnienie to 256x8 = 2048 µs. W przypadku przerwy trwającej 1,25 ms licznik powinien odliczać (256x1,25) / 2,048 = 156,25 razy, zaokrąglając w górę otrzymujemy 156 zliczeń. W związku z tym konieczne jest zapisanie do timera liczby 256-156 = 100. Ale nie jest to do końca poprawna wartość, ponieważ wykonanie procedury obsługi przerwań zajmuje trochę czasu, w tym przypadku zajmuje to około 190 µs, przeliczone biorąc biorąc pod uwagę współczynnik preskalera, otrzymujemy 190/8 = 23,75 lub 24 zliczenia. Prawidłowa wartość do zapisania do TMR0 to: 100+24=124.

W programie głównym piszemy 8 rejestrów przechowywania informacji, zgodnie z tym, co chcemy wyświetlić na matrycy. Poniżej znajduje się diagram wyjaśniający wyprowadzanie informacji do macierzy dla powyższego kodu.


Oprócz rejestrów przesuwnych istnieją wyspecjalizowane sterowniki do wyświetlania informacji na wskaźnikach siedmiosegmentowych i Matryca LED, w tym przypadku sygnalizacja dynamiczna realizowana jest przez sam sterownik, pozostaje tylko przesłanie do niego danych do wyświetlenia. Omówiłem jeden z tych popularnych sterowników w artykule na temat.

Poniżej linku można pobrać firmware i kod źródłowy mikrokontrolera PIC16F628A, z zaimplementowaniem dynamicznego wskazania na matrycy 8x8 z wykorzystaniem dwóch rejestrów przesuwnych 74HC595, schemat podłączenia omówiono powyżej. Litery R, ​​L, liczba 46, buźka i tylko wzór w postaci krzyża są wyświetlane naprzemiennie na matrycy, ta animacja jest pokazana na poniższym filmie.

z tagami , . Czytać .

Dynamiczne wskazywanie to jeden z problemów, z jakimi borykają się początkujący programiści mikrokontrolerów. Dużo się o tym mówiło, ale postanowiłem wzmocnić to, co znane, obrazkami i przykładami tekstów źródłowych w C, aby łatwiej było opanować tę metodę wyświetlania.

1 Podstawy podstaw, czyli wprowadzenie

Przede wszystkim zdefiniujmy terminologię, której będziemy używać w całym artykule.

Jeśli chcesz sterować wyświetlaczem składającym się z pojedynczej siedmiosegmentowej znajomości, nie sprawia to żadnych problemów - może być reprezentowany jako 8 niezależnych diod LED. Jeśli potrzebujesz wyświetlić więcej informacji niż jeden znak, zaczynają się problemy: 2 znajome to 16 diod LED, trzy - 24 itd., To znaczy dla wyświetlacza trzycyfrowego wyjścia mikrokontrolera mogą po prostu nie wystarczyć, nie wspominając Wyświetlacze 6 lub więcej bitów, a zwłaszcza wskaźniki matrycowe.

Dla uproszczenia zgadzamy się, że wszystkie nasze wskaźniki mają wspólną katodę. Rozwiązanie problemu jest dość proste: połącz ze sobą wyjścia segmentów wszystkich wskaźników. Teraz, jeśli chcesz wyświetlić informacje w pierwszej znajomości, powinieneś zastosować wymagane poziomy do linii segmentów i podłączyć wspólne wyjście pierwszego wskaźnika do wspólnego przewodu obwodu. Oczywiście wysokie poziomy muszą być obecne na wspólnych katodach wszystkich innych wskaźników. Oczywiście zaświecą się żądane segmenty pierwszego wskaźnika. Dla wyjścia do drugiego, trzeciego itd. wskaźniki powinny robić to samo, tj. przypisując logiczne zero do jednej ze wspólnych katod, wybieramy aktualnie wyświetlany bit, a stan linii segmentowych określa widoczny symbol.

Aby cały wyświetlacz był postrzegany jako stale świecący, cyfry muszą być zmieniane szybko – częściej niż 25 razy na sekundę. Jak widać, poziomy wszystkich wniosków (które, nawiasem mówiąc, stały się znacznie mniejsze niż przy zwykłym podejściu) stale się zmieniają, tj. nie mają poziomów statycznych, ale dynamiczne, stąd nazwa metody wyświetlania - dynamic.

Obraz z dynamicznym wyświetlaczem

2 Odmiany implementacji sprzętu

2.1 Matryce płaskie

Abstrahując od wskaźników siedmiosegmentowych, nasz wyświetlacz można przedstawić jako matrycę pojedynczych diod LED, których anody są połączone w rzędy matrycy, a katody w kolumny. Właściwie tak właśnie jest.

Oczywiście, stosując wymagane poziomy do wierszy i kolumn naszej matrycy, możemy zapalić dowolny elementarny segment LED (aka piksel - jest to bardziej tradycyjne określenie wyświetlaczy matrycowych). W zależności od tego, jak dokładnie zmienimy poziomy na wierszach i kolumnach, możemy uzyskać kilka rodzajów wskazania dynamicznego:

  • przez linię;
  • według kolumn;
  • segment po segmencie (na piksel);
  • w mieszany sposób.

Rozważaliśmy tę opcję według kolumn w poprzednim rozdziale. Opcja wierszami różni się od niej tylko tym, że wiersze i kolumny naszej macierzy są zamienione. Metoda segment po segmencie polega na tym, że w danym momencie tylko jeden wiersz i jedna kolumna ma poziom niezbędny do świecenia diody. Oznacza to, że w dowolnym momencie może świecić tylko jedna dioda LED całej matrycy (w przeciwieństwie do poprzednie opcje gdy cały rząd lub cała kolumna może być oświetlona w tym samym czasie). Ta metoda przypomina skanowanie telewizora, gdy wiązka krąży wokół całego ekranu, oświetlając w właściwe miejsca fosfor. Wersja mieszana, jak sama nazwa wskazuje, polega na tym, że jednocześnie „aktywne” poziomy mogą być obecne w kilku wierszach i kolumnach jednocześnie.

Pierwsze dwie opcje są bardzo łatwe do wdrożenia i dlatego są szeroko stosowane. Trzecia opcja jest używana rzadziej, ponieważ. wymaga więcej wysokie prędkości aktualizacje informacji o wierszach i kolumnach, a średni prąd płynący przez segment (czyli jasność segmentu) w tym przypadku jest znacznie niższy niż w innych. Ostatnia metoda mieszana jest najmniej powszechna, choć ma szereg pozytywnych cech. Przede wszystkim ta metoda wymaga zastosowania stabilnych źródeł prądu w obwodach rzędowych i kolumnowych, w przeciwnym razie jasność segmentów świetlnych będzie nieuchronnie zależeć od ich całkowitej liczby. A obliczanie kombinacji sygnałów w wierszach i kolumnach nie jest łatwe.

2.2 Macierze wielowymiarowe

Rozważane przez nas przykłady zakładają wdrożenie wyświetlacz monochromatyczny, tj. składający się z jednokolorowych diod LED. A co, jeśli chcesz uzyskać wielokolorowy wyświetlacz, na przykład z diod LED RGB? Możliwe są dwa rozwiązania.

Pierwszym z nich jest po prostu zwiększenie liczby rzędów (lub kolumn) naszej matrycy, traktując każdą diodę RGB jako 3 niezależne indywidualne diody LED. Dużą wadą tego podejścia jest 3-krotny wzrost liczby wierszy (lub kolumn). Na prosty przykładłatwo zauważyć, na co to przekłada się w praktyce: za pomocą dwóch ośmiobitowych występów mikrokontrolera możemy mieć monochromatyczną matrycę 8x8 segmentów lub kolorową 4x4. Zgadzam się, że w drugim przypadku praktycznie niemożliwe jest wyświetlenie niczego zrozumiałego ...

Drugi sposób to przejście od „płaskiej” macierzy segmentów do „wielowymiarowej”. Jeżeli sygnał z każdej linii przechodzi przez multiplekser 1x3, wówczas układ wyświetlania diod RGB możemy przedstawić jako 3 niezależne macierze o wymiarze początkowym: każda matryca składa się z diod o tym samym kolorze, a żądaną matrycę wybieramy z multiplekserem sygnały sterujące. Rysunek wyjaśnia, co zostało powiedziane.

Oczywiście w przypadku matrycy wielowymiarowej wymagana jest również dodatkowa liczba linii sterujących, jednak ta liczba nie jest aż tak duża: na tych samych dwóch portach kontrolera możemy uzyskać kolorowy wyświetlacz 7x7 !!!

2.3 Sposoby zmniejszenia wymiaru macierzy

Jeśli liczba wyprowadzeń mikrokontrolera jest bardzo ograniczona, będziemy musieli szukać sposobów na zmniejszenie liczby wierszy i kolumn naszej matrycy. Oczywiście cuda się nie zdarzają i w tym przypadku będziemy musieli zapłacić tym, że oprócz mikrokontrolera zostaną użyte dodatkowe mikroukłady. Jak można się domyślić, tutaj można zastosować rozważaną wcześniej metodę „wielowymiarowych” matryc – w końcu nikt nie zabroni nam po prostu używać potrójnej liczby jednokolorowych diod LED zamiast diod RGB? Najważniejsze, żeby je odpowiednio ułożyć...

Możemy więc zmniejszyć wymiar matrycy, stosując:

  • dekodery lub multipleksery;
  • rejestry przesuwne.

Z multiplekserami spotkaliśmy się już wcześniej, dekoder, jak można się domyślić, zasadniczo różni się od multipleksera. Należy tylko dodać, że stosując dekodery/multipleksery zarówno dla wierszy, jak i dla kolumn można osiągnąć redukcję wymiaru matrycy w obu wymiarach na raz, jednak w tym przypadku może być konieczne zastosowanie tylko segment po- dynamiczne wskazanie segmentu, ze wszystkimi jego wadami.

Rejestry przesuwne mogą pomóc znacznie lepiej niż dekodery. Rozważ diagram na poniższym rysunku.

Łatwo zauważyć, że dowolna liczba wierszy i kolumn będzie wymagała jedynie zwiększenia liczby rejestrów, a liczba zaangażowanych linii sterujących mikrokontrolera pozostanie taka sama! Mały minus to podejście jest to, że wraz ze wzrostem liczby rejestrów w łańcuchu konieczne będzie zwiększenie szybkości sekwencyjnego wyprowadzania w nich informacji, co nie zawsze jest łatwo osiągalne. Czyli na przykład popularne mikrokontrolery z rodziny AVR, praktycznie nie pozwalają przekroczyć prędkości wyjścia szeregowego 10 megabitów/sek. Z drugiej strony, jeśli użyjesz innych kontrolerów, które mogą szybciej wysyłać sygnały, mogą wystąpić problemy innej kolejności: propagacja sygnału zegara o wysokiej częstotliwości wzdłuż długiej linii (i kiedy duże liczby rejestrów, nieuchronnie tak będzie) jest zupełnie inny niż niskiej częstotliwości, więc podczas okablowania wymagane będą specjalne środki płytka drukowana i inne rzeczy, których nie rozważymy w tym artykule.

3 sposoby wdrożenia oprogramowania

Nie będziemy brać pod uwagę implementacji programowej wszystkich wymienionych opcji dynamicznego wskazywania - spowoduje to nieuzasadnione zawyżenie artykułu. Ograniczymy się tylko do trzech najbardziej „biegających” przykładów: płaskiej macierzy z bezpośrednią kontrolą wierszy i kolumn, ta sama z użyciem dekodera i wreszcie wariant z wykorzystaniem rejestrów przesuwnych. We wszystkich przypadkach szczególna uwaga zostanie zwrócona na wszystkie niuanse wdrożenie oprogramowania, czyli kodowi C będą towarzyszyć wyjaśnienia tylko w przypadkach, gdy jest to zgodne z intencją autora, a w żadnym wypadku z twoim poziomem wyszkolenia. W ten sposób sugeruję, że powinieneś znać podstawy C beze mnie.

Dla wszystkich przykładów zgodzimy się, że nasz wyświetlacz jest zbudowany na wskaźnikach siedmiosegmentowych ze wspólną katodą.

3.1 Najprostszy sposób

Oczywiście w programie najwygodniej byłoby mieć tablicę, której zawartość jednoznacznie określiłaby, które segmenty, w których świecą się znane obszary wyświetlacza - rodzaj analogu pamięci RAM ekranu.

Wprowadźmy definicję następujących stałych:

#define SCR_SZ 6 /* liczba wyświetlanych spacji znaków */ #define ROWS PORTB /* port wyświetlania "wierszy", tj. zarządzanie segmentami */ #define COLS PORTD /* port do zarządzania "kolumnami", tj. wspólne katody */

Teraz zadeklarujmy tablicę-screen:

niepodpisany znak SCR;

Na początek założymy, że każdy element tablicy odpowiada znajomości wyświetlacza, a każdy bit tego elementu odpowiada pewnemu segmentowi wskaźnika. Który bit odpowiada jakiemu segmentowi - w tym przypadku nie ma znaczenia, jak nie ma znaczenia, jak te bity są ustawione w bajtach naszej tablicy, na razie założymy, że już tam są. Dla uproszczenia założymy również, że wspólne katody są podłączone do pinów portu COLS po kolei: najmniej znaczący bit jest wskaźnikiem najbardziej po prawej stronie, potem drugi, potem trzeci i tak dalej.

Jak sprawić, by ta tablica „wyświetlała się” na wyświetlaczu? Napiszmy następujący kod:

< SCR_SZ; pos++){ ROWS = SCR; COLS = ~(1 << pos); }

Czy spełni wymaganą funkcję? TAk. Ale jest źle.

Przede wszystkim zwróć uwagę, że nie mamy kontroli nad szybkością, z jaką aktualizowana jest zawartość wierszy i kolumn. Po drugie, zauważ, że zanim nowy element tablicy zostanie wyprowadzony do WYDZIWIANIE na liniach COLS stara wartość jest nadal obecna! Dokąd to prowadzi? A poza tym przez jakiś ułamek sekundy będą wyświetlane segmenty sąsiedniej znajomości, tj. niektóre segmenty będą fałszywie podświetlone.

Możesz uniknąć tego efektu w ten sposób: przed aktualizacją treści WYDZIWIANIE, zawsze anuluj znajomość, która była poprzednia. Aby nie zawracać sobie głowy definicją poprzedniej znajomości, możesz zgasić wszystko na raz. Nasz kod wygląda więc tak:

niepodpisany znak poz; while(1) for(poz = 0; poz< SCR_SZ; pos++){ COLS = 0xFF; ROWS = SCR; COLS = ~(1 << pos); delay(); }

Dodaliśmy wygaszenie całego wyświetlacza przed aktualizacją stanu linii segmentowych (ustawiając wysoki poziom na wspólnych katodach, wskaźnik wyłączymy niezależnie od tego, co jest na anodach) oraz wprowadziliśmy opóźnienie na końcu cykl. Teraz wyświetlacz będzie działał znacznie lepiej. Ale czy napisaliśmy dobry program? Niestety nie.

Faktem jest, że niekończący się cykl wyświetlania podczas gdy po prostu nie pozwoli nam zrobić nic innego. Jaki będziemy mieli program, który tylko wie, jak wyświetlić coś na wskaźniku?! Oczywiście nie wszystko jest w 100% złe, bo na przerwaniach można zrobić coś pożytecznego… i zamiast opóźnienia opóźnienie() możesz wykonać pewne czynności ... Ale to wszystko jest bardzo, bardzo krzywe: nie jest pożądane wykonywanie czegoś złożonego i niewygodnego w procedurach obsługi przerwań; z drugiej strony, jeśli zamiast opóźnienia zrobi się coś skomplikowanego i niewygodnego, to trudno zapewnić ten sam czas obliczeń, w przeciwnym razie okaże się, że znajomośc świeci przez inny okres czasu, co wizualnie będzie wyglądało jak ich blask lub migotanie o różnej jasności.

Ogólnie rzecz biorąc, ta opcja może być dozwolona tylko jako wyjątek, tylko jako przykład szkoleniowy lub w przypadku (ale pięć, tylko jako wyjątek!), Gdy główny problem do rozwiązania jest bardzo prosty (może to być na przykład przykład, problem pomiaru ADC napięcie i wyświetl je).

Co powinno być zrobione? Odpowiedź, jak zawsze, jest prosta: wszystkie procesy, które powinny być wykonywane niepostrzeżenie od rozwiązania zadania głównego (a wskazanie, oczywiście, jest takim procesem) powinny być wykonywane przez przerwania czasowe.
Przerwy będą następować w ściśle określonych odstępach czasu, co zapewni jednolitość blasku znajomości. Wskazanie tła pozwoli nam po prostu napisać coś do tablicy w odpowiednim momencie w pętli głównej SCR- i natychmiast pojawi się na wyświetlaczu! A wszystkie zmiany w kodzie sprowadzają się do tego, że zamiast pętli używamy funkcji obsługi przerwań:

ISR(TIMER0_OVF_vect)( statyczny znak bez znaku = 0; COLS = 0xFF; WIERSZE = SCR; COLS = ~(1<< pos); if(++pos == SCR_SZ) pos = 0; }

Kilka uwag.

zmienny pozycja, oznaczający numer bieżącej świecącej znajomości, tworzymy lokalną zmienną statyczną, aby zachowała swoją wartość od przerwania do przerwania. Pod koniec funkcji sami (w końcu nie mamy już cyklu) zwiększamy liczbę znajomości, aż osiągniemy granicę - w tym przypadku wracamy do początku.

W programie głównym będziemy musieli tylko zainicjować porty i timer (w tym przypadku - Zegar 0), aby przepełniał się w wymaganych odstępach czasu i pozwalał na przerwania. Po tym nie można już pamiętać o wskazaniu - będzie działać samoczynnie cicho i spokojnie. Ale jak określić żądany interwał przepełnienia timera? Bardzo prosta. Ludzkie oko odbiera migotanie o częstotliwości ponad 25 Hz jako ciągły blask. Mamy 6 wskaźników, każdy z nich powinien migotać z taką częstotliwością, co oznacza, że ​​informacje na wyświetlaczu powinny być aktualizowane z częstotliwością 25 x 6 = 150 Hz lub więcej. Teraz obliczmy wartość preskalera timera: podziel częstotliwość zegara MK przez 256 ( Zegar 0 wszyscy mają AVR ośmiobitowy, co oznacza, że ​​się przelewa, licząc do 256) - będzie to pożądana wartość preskalera timera. Oczywiście jest mało prawdopodobne, że wynik będzie pasował do jednej ze standardowych wartości preskalera – nie stanowi to problemu, można przyjąć najbliższą mniejszą odpowiednią wartość. Wskazanie będzie działać z wyższą częstotliwością, ale nie pogorszy to jego jakości! Efektem ubocznym będzie duże obciążenie rdzenia MK dla wskazania. Jeśli to znacznie koliduje z głównym programem, będziesz musiał przenieść wskazanie do innego timera, na przykład 16-bitowego Zegar 1 lub wprowadź licznik, aby pominąć przepełnienia licznika czasu:

#define SKIP 15 /* liczba przerwań czasowych do pominięcia */ ISR(TIMER0_OVF_vect)( static unsigned char poz = 0; static unsigned char skip = SKIP; if (--skip) return; skip = SKIP; COLS = 0xFF; ROWS = SCR ; COLS = ~(1<< pos); if(++pos == SCR_SZ) pos = 0; }

W tych uproszczonych przykładach zakładamy, że port COLS, z wyjątkiem wspólnych katod wskaźników, nic więcej nie jest połączone. Jednak w prawdziwym życiu takie szczęście nie zdarza się często, a z pozostałymi liniami tego portu wiąże się najprawdopodobniej coś jeszcze. Dlatego organizując wskazania dynamiczne, należy zawsze zapewnić niezmienność stanu wszystkich linii portowych, które nie są bezpośrednio zaangażowane we wskazanie. Robi się to po prostu: zamiast po prostu wpisywać nową wartość do portu, należy użyć maskowania niepotrzebnych bitów:

COLS |= 0x3F; // więc gasimy wszelką znajomość COLS &= ~(1<

Oba stwierdzenia nie zmieniają wartości wysokich bitów portu COLS.

3.2 Metoda dekodera

Dekoder można wykorzystać do konwersji KLĄTWA lub BCD kod na znaki siedmiosegmentowe lub wybrać jedną z kolumn macierzy. Obie opcje będą się różnić od najprostszej metody rozważanej wcześniej tylko tym, jak zostaną zorganizowane dane wyjściowe do portów. WYDZIWIANIE i/lub COLS do którego zostaną podłączone wejścia dekodera.
Możliwość użycia dekodera w celu uzyskania znaku siedmiosegmentowego:

ISR(TIMER0_OVF_vect)( static unsigned char poz = 0; COLS |= 0x3F; ROWS = (ROWS & 0xF0) | (SCR & 0x0F); COLS &= ~(1<< pos); if(++pos == SCR_SZ) pos = 0; }

Jak widać zmiany są minimalne - zanim zostaną wyświetlone w WYDZIWIANIE kod znaku z tablicy SCR, górne bity są maskowane, po czym niższe bity są ustawiane zgodnie z kodem znaku. Oznacza to, że uważamy, że dekoder jest podłączony do 4 najmniej znaczących bitów portu WYDZIWIANIE.

Mam nadzieję, że nie ma sensu podawać przykładu dekodowania kolumn - i tak wszystko jest jasne.

3.3 Metoda z rejestrami

Chociaż dynamiczne wskazywanie za pomocą rejestrów przesuwnych nie różni się zasadniczo od wcześniej omawianych metod, istnieje kilka możliwości jego realizacji. Rozważymy najprostsze - wyprowadzanie bitów za pomocą środków czysto programowych. I w realizacji innych (za pomocą USI/USART/SPI/TWI) możesz spróbować swoich sił.

Dla wariantu wybranego wcześniej wyświetlacza 6 siedmiosegmentowych spacji znakowych stosujemy 2 rejestry przesuwne typu 74HC595. Ten rejestr jest kontrolowany przez trzy sygnały: szeregowy zegar wejściowy danych CLK, rzeczywiste dane DANE i impuls jednoczesnego równoległego wyprowadzania informacji zapisanych do rejestru USTAWIĆ. Zadeklarujmy odpowiednie makra (dla uproszczenia „przeniesiemy” wszystkie sygnały do ​​jednego portu):

#define CLK _BV(PB0) #define DATA _BV(PB1) #define SET _BV(PB2) #define REG_PORT PORTB

Aby pisać do rejestru, wygodnie jest napisać osobną funkcję:

Statyczne przesunięcie pustki(unsigned char d)( unsigned char i; for (i=0; i< 8; i++){ // устанавливаем нужный уровень DATA if(d & 1) REG_PORT |= DATA; else REG_PORT &= ~DATA; REG_PORT |= CLK; // даем импульс CLK REG_PORT &= ~CLK; d >>= 1; } }

Jest wysoce pożądane, aby ta funkcja była statyczna, ponieważ będzie używany w obsłudze przerwań. Kompilator najprawdopodobniej utworzy funkcje statyczne w postaci wbudowany-wstawia w obsłudze przerwań, tj. stos nie będzie niepotrzebnie używany, co nie jest gwarantowane dla funkcji niestatycznych.

Teraz nasz program obsługi przerwań będzie wyglądał tak:

ISR(TIMER0_OVF_vect)( statyczny znak bez znaku = 0; shift(SCR); shift(~(1<< pos)); REG_PORT |= SET; // выдаем импульс SET REG_PORT &= ~SET; if(++pos == SCR_SZ) pos = 0; }

Ponieważ dane zapisywane do rejestrów pojawiają się na jego wyjściach jednocześnie, nie ma potrzeby wcześniejszego wyłączania wskaźników. Należy pamiętać, że sekwencyjne wyprowadzanie programu to dość długi proces, szczególnie dla macierzy o dużych wymiarach, dlatego należy go maksymalnie zoptymalizować pod względem szybkości. Najlepiej to zrobić za pomocą sprzętu wyjścia szeregowego znajdującego się w MCU.

4 Dla tych, którzy nigdy nie mają dość

Zapoznałeś się więc z podstawami implementacji wskazania dynamicznego. Ale jak zwykle pytania nie maleją, ale rosną. Uprzedzając niektóre z nich, postaram się od razu udzielić niezbędnych odpowiedzi.

4.1 Anody, katody - co wybrać?

Wszystko, co rozważaliśmy wcześniej, odnosiło się do wskaźników ze wspólnymi katodami. A jeśli chcesz używać ze zwykłymi anodami? Ogólnie wszystko pozostaje takie samo, z wyjątkiem tego, że przed wyjściem konieczne będzie odwrócenie danych - wygaszenie znajomości odbywa się poprzez wyprowadzenie zer do COLS, zapłon - odpowiednio, jednostki i segmenty w WYDZIWIANIE będzie zawierać zera zamiast jedynek. Więc procedura obsługi przerwań staje się mniej więcej taka:

ISR(TIMER0_OVF_vect)( static unsigned char poz = 0; COLS &= 0xC0; WIERSZE = ~SCR; COLS |= (1<< pos); if(++pos == SCR_SZ) pos = 0; }

Wszystko jest proste. O ile oczywiście nie spróbujesz napisać uniwersalnego kodu, który będzie pasował zarówno do zwykłych anod, jak i wspólnych katod. Można to zrobić na dwa sposoby: za pomocą dyrektyw kompilacji warunkowej lub za pomocą funkcji transformacji. Zademonstruję pierwszą opcję, a drugą sugeruję samodzielne przemyślenie.

#define COMMON_ANODE 1 ISR(TIMER0_OVF_vect)( static unsigned char poz = 0; #if COMMON_ANODE != 1 COLS &= 0xC0; WIERSZE = ~SCR; COLS |= (1<< pos); #else COLS |= 0x3F; ROWS = SCR; COLS &= ~(1 << pos); #endif if(++pos == SCR_SZ) pos = 0; }

Jest to trochę kłopotliwe, ale jeśli napiszesz go raz, możesz go używać we wszystkich projektach prawie bez zmian.

4.2 Migotanie

W wielu przypadkach wyświetlacz służy nie tylko do wyświetlania informacji pochodzących z wnętrza urządzenia, ale także do wyświetlania informacji wprowadzanych przez użytkownika. I w tym przypadku trzeba umieć jakoś oddzielić niezmienione od tego, co zmienne na wyświetlaczu. Najprostszym sposobem, aby to zrobić, jest migotanie odpowiedniej znajomości (lub kilku znajomych).

Bardzo łatwo to zrobić. Wprowadźmy zmienną globalną, której każdy bit będzie oznaczał migającą znajomość:

znak bez znaku miga = 0;

Teraz trochę modyfikujemy procedurę obsługi przerwań:

ISR(TIMER0_OVF_vect)( static unsigned char poz = 0; statyczny wpis unsigned char = 0; COLS |= 0x3F; if(!(mignięcie & (1<

Jak widać, została dodana tylko jedna zmienna statyczna - licznik wejść do obsługi przerwań wejście i operator testu warunku. Logika jest prosta: wyjście następnej znajomości odbywa się tylko wtedy, gdy którykolwiek z odpowiednich bitów migać zero lub najbardziej znaczący bit licznika wejście równa się 1. Załóżmy, że migać zawiera wszystkie zera, to warunek ten jest zawsze spełniony - wyświetlane są wszystkie znajomości. Jeśli migać zawiera 1 w jednym ze swoich bitów, to odpowiedni znak będzie wyświetlany tylko w czasie, gdy najbardziej znaczący bit licznika wynosi 1. Ponieważ licznik jest zwiększany za każdym razem, gdy wprowadzany jest program obsługi przerwania, odpowiedni znak będzie migotał częstotliwość 128 razy mniejsza niż częstotliwość przerwań.

4.3 Regulacja jasności segmentów

O regulacji jasności pisałem w osobnym artykule, który tak się nazywał.

4.4 Arbitralny rozkład wniosków

Wcześniej mówiono, że szczęście przeznaczania całego portu MK na wskazanie wypada dość rzadko. Ale jeszcze rzadziej udaje się uzyskać wygodny ślad PCB, jeśli jeden port jest używany w całości dla wierszy, a drugi dla kolumn matrycy wyświetlacza. Znacznie częściej optymalny routing uzyskuje się tylko wtedy, gdy wiersze i kolumny są przemieszane między dwoma lub nawet większą liczbą portów mikrokontrolera. Nie będziesz musiał poświęcać piękna płytki drukowanej, jeśli zorganizujesz wymianę bitów oprogramowania podczas wskazania.

Rozważmy jakiś abstrakcyjny przykład. Niech najlepsze śledzenie zapewni następujący rozkład sygnałów wzdłuż linii portów MC:

Segment A

Segment B

odcinek H

Segment C

Segment D

segment G

Segment E

Segment F

Jak widać linie matrycy są przemieszane pomiędzy trzema portami, a wszystkie niewykorzystane linie tych portów oczywiście nie powinny zmieniać swoich poziomów w trakcie procesu wskazania.

W tym przypadku najlepiej jest rozpocząć opracowywanie funkcji dynamicznego wskazania od rozmieszczenia segmentów na bitach symboli. Wcześniej uważaliśmy, że w tablicy SCR przechowujemy maski bitowe postaci, tj. jednostki w bajcie oznaczają świecące segmenty. Nie zastanawialiśmy się, który bit odpowiada jakiemu segmentowi. Więc teraz nadszedł czas, aby się nad tym zastanowić.

Wygodnie jest pomalować przeznaczenie linii portowych w postaci trzech płyt:

1

A

0

4

H

3

2

B

F

mi

5

G

D

C

Musimy zebrać wszystkie segmenty w jeden bajt. Będziesz musiał to zrobić za pomocą operacji zmianowych, więc powinieneś starać się je rozłożyć tak, aby zrobić jak najmniej zmian. Podyskutujmy.

Jeśli segment bity FEGDC zostaw w symbolu, aby wpadły w PORTD bez przesunięć, to segment H może również pozostać w szóstym bicie znaku, a także nie musi być przesuwany przed wyjściem PORTC, ale dla segmentów ALE oraz W pozostaną bity 7 i 3, czyli najprawdopodobniej segment W będzie musiał być przesunięty o 3 pozycje przed wyjściem, a segment ALE- do 6. Zatrzymam się na tej opcji i można kontynuować wyszukiwanie minimum zmian (przesunięcia o kilka pozycji nie są tak szybką operacją, dlatego wskazane jest ograniczenie ich liczby do minimum).

Tak więc w naszym przypadku otrzymaliśmy następujący rozkład bitów według znaku bajtowego:

A

H

F

mi

B

G

D

C

Zwróć uwagę na maski bitowe dla wyjścia do odpowiednich portów:

D

0

0

1

1

0

1

1

1

0x37

B

1

0

0

0

0

0

0

0

0x80

C

0

1

0

0

1

0

0

0

0x48

Za pomocą tych masek, korzystając z operacji „bitowej AND”, wybieramy niezbędne bity do wyprowadzenia na port.

Zadeklarujmy stałe maski:

#define MASKA 0x37 #define MASKA 0x80 #define MASKA 0x48

Wcześniej wysyłaliśmy znak do jednego portu WYDZIWIANIE, teraz ta procedura jest podzielona na trzy części:

PORTD = (PORTD & ~MASKD) | (SCR&MASKD); PORTB = (PORTB & ~MASKB) | ((SCR & MASKB) >> 6); PORTC = (PORTC & ~MASKC) | ((SCR & _BV(6)) | (((SCR & _BV(3)) >> 3);

Należy pamiętać, że w przypadku wyjścia do PORTC jeden bit musi być wyprowadzany bez przesunięcia, a drugi z przesunięciem, więc zamiast MASKA musiałem używać osobnych makr _BW().

Teraz pozostaje zdecydować, jak ugasić i oświetlić odpowiednią znajomość. Zadeklarujmy stałe odpowiadające bitom kontrolnym znajomości:

#define COM0 _BV(0) #define COM1 _BV(3) #define COM2 _BV(4) #define COM3 _BV(5) #define COM4 _BV(7) #define COM5 _BV(3) #define COM_D (COM5) #define COM_C (COM2 | COM3 | COM4) #definiuj COM_B (COM0 | COM1)

Aby zgasić wszelką znajomość, konieczne jest wyprowadzenie odpowiednich stałych do portów COM_x:

PORTD |= COM_D; PORTC |= COM_C; PORTB |= COM_B;

Ale aby umożliwić znajomość, będziesz musiał być sprytny (nie ma sensu wysyłać do wszystkich trzech portów, ponieważ tylko jeden bit będzie aktywny w określonym porcie, w zależności od wartości pozycja), na przykład za pomocą operatora przełącznik:

Switch(pos)( przypadek 0: PORTB &= ~COM0;przerwa; przypadek 1: PORTB &= ~COM1;przerwa; przypadek 2: PORTC &= ~COM2;przerwa; przypadek 3: PORTC &= ~COM3;przerwa; przypadek 4: PORTC &= ~COM4;przerwa;przypadek 5: PORTD&= ~COM5;przerwa;)

To nie jest najładniejszy sposób, ale działa.

Zatem nasz program obsługi przerwań przyjmuje następującą postać:

ISR(TIMER0_OVF_vect)( statyczny znak bez znaku poz = 0; statyczny wpis znaku bez znaku = 0; // zgaś PORTD |= COM_D; PORTC |= COM_C; PORTB |= COM_B; // wyjście PORTD = (PORTD & ~MASKD) | ( SCR & MASKD); PORTB = (PORTB & ~MASKB) | ((SCR & MASKB) >> 6); PORTC = (PORTC & ~MASKC) | ((SCR & _BV(6)) | (((SCR & _BV (3)) >> 3); // miga jeśli(!(miga & (1 .)<< pos)) || (++entry & 0x80)) { switch(pos){ case 0: PORTB &= ~COM0; break; case 1: PORTB &= ~COM1; break; case 2: PORTC &= ~COM2; break; case 3: PORTC &= ~COM3; break; case 4: PORTC &= ~COM4; break; case 5: PORTD &= ~COM5; break; } } if(++pos == SCR_SZ) pos = 0; }

Teraz pozostaje wymyślić, jak opisać symbole dla wyjścia w wygodniejszy sposób ... Proponuję wykonać następujące czynności: zdefiniować stałe odpowiadające bitom segmentów, a następnie „skonstruować” niezbędne symbole z tych stałych:

// segmenty elementarne #define _A _BV(7) #define _B _BV(3) #define _C _BV(0) #define _D _BV(1) #define _E _BV(4) #define _F _BV(5) #define _G _BV (2) #define _H _BV(6) // symbole cyfr #define d_0 (_A | _B | _C | _D | _E | _F) #define d_1 (_B | _C) #define d_2 (_A | _B | _G | _D | _E) // i tak dalej

Tak więc, jeśli chcesz wydrukować zero po prawej stronie wyświetlacza, musisz po prostu napisać we właściwym miejscu:

SCR = d_0;

Jeśli w innym projekcie musisz inaczej rozłożyć bity, zmienisz tylko liczby w makrach _BW() dla segmentów elementarnych, a wszystkie postacie zostaną „przerobione” automatycznie. W najprostszych przypadkach opisanych na początku nie będziesz musiał robić nic więcej, ale w przypadku opcji „podmiana bitów” będziesz oczywiście musiał majstrować.

4.5 Obsługa przycisków

Przy tradycyjnym braku wyjść MK problem dużej liczby przycisków, bez których rzadko kiedy każde urządzenie może się obejść, jest bardzo dotkliwy. Stosowane są różne wtrącenia matrycowe itp. Sztuczki jednak komplikując nieco funkcję dynamicznej sygnalizacji, łatwo jest uzyskać do dyspozycji tyle przycisków, ile jest znanych na wyświetlaczu, a dodatkowo trzeba korzystać tylko z jednego portu mikrokontrolera. To prawda, że ​​każdy przycisk wciąż musi być nałożony na diodę.

Schematycznie pokazano to na rysunku.

A programowo wygląda to tak:

#define keypin() (!(PIND & _BV(KEY))) ISR(TIMER0_OVF_vect)( static unsigned char poz = 0; static unsigned char entry = 0; static unsigned char tmp_key = 0; ROWS = 0; if(keypin( klucz_tmp |= 1<< pos; COLS |= 0x3F; if(!(blink & (1<< pos)) || (++entry &0x80)){ ROWS = (ROWS & 0xF0) | (SCR & 0x0F); COLS &= ~(1 << pos); } if(++pos == SCR_SZ){ pos = 0; key = tmp_key; tmp_key = 0; } }

Tutaj klucz- jest to makro, które ustawia bit wybranego portu, na który wszystkie przyciski są "podłączone", makro klucz() zwraca wartość logiczną TRUE, jeśli wybrany pin jest logicznie niski. W tym przykładzie przyciski są połączone z PORTD.

Za każdym razem, gdy wystąpi przerwanie czasowe, wszystkie segmenty są najpierw wygaszane - jest to konieczne, aby prąd płynący przez diody LED nie doprowadził do błędnego niewykrycia naciśniętego przycisku. Następnie wejście przycisku jest odpytywane - jeśli jest niski poziom, naciskany jest przycisk podłączony do odpowiedniej katody poz. W zmiennej klucz_tmp stany przycisków są gromadzone, które są przepisywane do zmiennej globalnej klucz po zakończeniu cyklu wyświetlania. Wystarczy od czasu do czasu analizować wartość klucz i obsłużyć wykryte prasy:

Static unsigned char get_key()( unsigned char tmp = 0; tmp = klucz; _delay_ms(10); if(key == tmp) return tmp; else return 0; )

Ta prosta funkcja gwarantuje, że nie będzie gadania przycisków, chociaż ze względu na „dynamiczną” naturę odpytywania przycisków, prawdopodobieństwo gadania jest już niskie.

5 Co jeszcze?

Tak więc opanowałeś dość typowe techniki implementacji wskazań dynamicznych. Myślę, że to wystarczy na pierwszy raz, a może nawet na resztę życia. Ostatecznie najważniejsze jest zrozumienie technik i algorytmów, a subtelności i niuanse zawsze można dodawać samodzielnie. Ale co jeszcze może czekać „w pobliżu” dynamicznego wskazania?

Jak wspomniałem wcześniej, można dodawać, a nawet do niezależnej regulacji każdego segmentu.

Możesz pomyśleć o optymalności obsługi przerwań - do celów edukacyjnych napisałem raczej szorstki kod, na przykład używałem wszędzie SCR, chociaż lepiej byłoby raz wczytać wartość do zmiennej lokalnej, a następnie operować jej wartością. Chociaż optymalizator na pewno pomoże w moim podejściu, to dla praktyki warto spróbować i zoptymalizować się samemu, kontrolując się wielkością wynikowego kodu i/lub szybkością działania programu.

Możesz pomyśleć o ciekawym pomyśle automatycznego dostosowywania jasności wyświetlacza w zależności od poziomu oświetlenia otoczenia. Jak wiadomo, kierunkowskazy LED są tym gorzej rozróżnialne, im ciemniej jest dookoła - po prostu się rozmywają. Dlatego w ciemności rozsądne jest zmniejszenie jasności wskaźników, zwiększając je w ciągu dnia. Najprościej jest zastosować osobny fotorezystor lub diodę LED jako czujnik światła, ale można to zrobić inaczej: wiadomo, że dioda LED może również pracować jako fotodioda, więc jeśli użyjesz portu podłączonego do wejścia do sygnalizacji ADC, w razie potrzeby możesz zmierzyć fotoemf nie świecącego segmentu wskaźnika i użyć tej wartości do regulacji jasności ...

Możesz pomyśleć o wykorzystaniu sprzętowego wyjścia szeregowego, o czym już wspomniałem.

Ciekawą wersję całkowicie uniwersalnego podejścia do wskazywania dynamicznego, z którym również polecam się zapoznać, zaproponowali: MOLCHEC. Krótko mówiąc, sedno: podział segmentów według bitów znaków, przydział portów do sterowania wskaźnikiem, a nawet typ wskaźnika - w skrócie parametry all-all-all - są ustawione w formie tabeli konfiguracyjnej w EEPROM. Programowo wszystko jest zorganizowane na podstawie tej tabeli: od inwersji w zależności od typu wskaźnika, po wymianę bitów na różnych portach. Jednocześnie kod źródłowy programu sygnalizacji dynamicznej zawsze pozostaje niezmieniony, a tabelę konfiguracyjną zestawia użytkownik końcowy, w zależności od jego preferencji. Metoda jest rzeczywiście uniwersalna i elastyczna, jednak wiąże się ze zwiększonym zużyciem pamięci programu.


3 Scenariusz ARV, o 06:48 25.08.2010
Misza na Twoim miejscu nie dałbym takich stanowczych stwierdzeń „nie da się tego zrobić”, „nikt nie napisał” czy „prawa autorskie”, bo po pierwsze to niegrzeczne, a po drugie:
1. Dawno temu zrobiłem biegnącą linię na matrycy 10x16 (co to było) - film z jej pracy znajdziesz w tej notce http://site/content/view/160/38/
2. Napisałem artykuł (znajdziecie go w newsach - ostatni na dziś) o tym, jak zrobić ticker na LCD. jeśli trochę nadwyrężysz swój mózg, powtórzenie algorytmu wyprowadzania danych do macierzy jest drobnostką.
3. na mojej stronie nie ma ani jednego artykułu skopiowanego skądś (kopiuj-wklej nie jest prawem autorskim, błędnie wpisałeś), wszystkie materiały są całkowicie oryginalne. wiele serwisów posiada kopie tych materiałów za moją zgodą (lub za zgodą autorów materiałów, którzy mają pełne prawo do publikowania swoich materiałów jednocześnie w wielu miejscach).

Tylko zarejestrowani użytkownicy mogą dodawać komentarze.
Proszę się zarejestrować lub zalogować do swojego konta.

Wskaźniki zwykle znajdują się w miejscach dogodnych do przeglądania wyświetlanych na nich informacji. Reszta obwodu cyfrowego może znajdować się na innych płytkach drukowanych. Wraz ze wzrostem liczby wskaźników zwiększa się liczba przewodów między tablicą wskaźników a tablicą cyfrową. Prowadzi to do pewnych niedogodności w rozwoju konstrukcji i eksploatacji sprzętu. Ten sam powód prowadzi do wzrostu jego kosztów.

Liczbę przewodów łączących można zmniejszyć, uruchamiając wskaźniki w trybie pulsacyjnym. Ludzkie oko ma bezwładność, a jeśli wskaźniki są zmuszone do wyświetlania informacji naprzemiennie z wystarczająco dużą prędkością, człowiekowi wydaje się, że wszystkie wskaźniki wyświetlają swoje informacje w sposób ciągły. Dzięki temu możliwe jest naprzemienne przesyłanie wyświetlanych informacji na tych samych przewodach. Zwykle wystarcza częstotliwość odświeżania 50 Hz, ale lepiej jest zwiększyć tę częstotliwość do 100 Hz.

Spójrzmy na schemat blokowy włączenia siedmiosegmentowych wskaźników LED, pokazany na rysunku 1. Obwód ten może zapewnić dynamiczne wskazanie wyjściowej informacji cyfrowej.


Rysunek 1. Schemat strukturalny wskazania dynamicznego

Obwód pokazany na rysunku 1 wyświetla cztery cyfry cyfrowe. Każdy bit jest na krótko podłączony do swojego wejścia przełącznika. Generator służy do ustawienia szybkości aktualizacji informacji na wskaźnikach. Licznik binarny sekwencyjnie generuje cztery stany obwodu, a za pomocą klawiszy zapewnia alternatywne zasilanie wskaźników siedmiosegmentowych.

W rezultacie, gdy przełącznik dostarcza kod BCD z wejścia A na wejścia dekodera siedmiosegmentowego, kod ten jest wyświetlany na wskaźniku HL1. Gdy przełącznik dostarcza kod binarno-dziesiętny z wejścia B na wejścia dekodera siedmiosegmentowego, kod ten jest wyświetlany cyklicznie na wskaźniku HL2 i tak dalej.

Szybkość aktualizacji informacji w rozważanym obwodzie będzie czterokrotnie mniejsza niż częstotliwość generatora. To znaczy, aby uzyskać częstotliwość migotania wskaźnika wynoszącą 100 Hz, wymagana jest częstotliwość oscylatora 400 Hz.

Ile razy w rezultacie zmniejszyliśmy liczbę przewodów łączących? To zależy od tego, gdzie narysujemy przekrój obwodu. Jeżeli na tablicy wyświetlacza zostawimy tylko wskaźniki, to ich działanie będzie wymagało 7 sygnałów informacyjnych dla segmentów i 4 sygnałów przełączających. Łącznie jest 11 przewodników. W obwodzie wskazań statycznych potrzebowalibyśmy 7 × 4 = 28 przewodów. Jak widać, jest wygrana. Przy implementacji 8-bitowego wyświetlacza wzmocnienie będzie jeszcze większe.

Jeszcze większy zysk będzie, jeśli przekrój obwodu zostanie narysowany wzdłuż wejść wskaźników. W takim przypadku czterocyfrowy wyświetlacz będzie wymagał tylko sześciu przewodów sygnałowych i dwóch przewodów zasilających obwodu. Jednak taki punkt przekroju obwodu sygnalizacji dynamicznej jest stosowany bardzo rzadko.

Teraz obliczmy prąd przepływający przez każdy segment diody LED, gdy się świeci. W tym celu wykorzystujemy równoważny obwód przepływu prądu przez jeden z segmentów wskaźnika. Schemat ten pokazano na rysunku 2.


Jak wspomniano wcześniej, do prawidłowego działania dioda LED wymaga prądu od 3 do 10 mA. Ustawmy minimalny prąd diody na 3 mA. Jednak w trybie pulsacyjnym jasność świecenia wskaźnika zmniejsza się N razy, gdzie współczynnik N jest równy cyklowi pracy impulsów prądowych dostarczanych do tego wskaźnika.

Jeśli zamierzamy utrzymać tę samą jasność świecenia, to musimy N-krotnie zwiększyć wartość prądu pulsującego przepływającego przez odcinek. W przypadku wskaźnika ośmiocyfrowego współczynnik N jest równy ośmiu. Załóżmy, że początkowo wybraliśmy prąd statyczny przez diodę LED równy 3 mA. Następnie, aby utrzymać tę samą jasność diody LED na ośmiocyfrowym wskaźniku, wymagany jest prąd pulsacyjny:

Seg din = Seg stat× N= 3mA×8 = 24mA.

Tylko niektóre serie mikroukładów cyfrowych z trudem zapewniają taki prąd. W przypadku większości serii mikroukładów wymagane będą wzmacniacze wykonane na przełącznikach tranzystorowych.

Ustalmy teraz prąd, który będzie przepływał przez klawisz, przełączając zasilanie na poszczególne bity ośmiobitowego wyświetlacza. Jak widać na schemacie przedstawionym na rysunku 2, prąd dowolnego segmentu wskaźnika może przepływać przez klucz. Gdy wyświetli się cyfra 8, konieczne będzie zapalenie wszystkich siedmiu segmentów wskaźnika, co oznacza, że ​​prąd pulsacyjny płynący w tym momencie przez klawisz można określić w następujący sposób:

cl \u003d seghałas× N seg= 24mA×7 = 168mA.

Jak ci się podoba ten prąd?! W amatorskich obwodach radiowych często spotykam się z rozwiązaniami, w których prąd przełączania pobierany jest bezpośrednio z wyjścia dekodera, który nie może dostarczyć prądu większego niż 20 mA i zadaję sobie pytanie - gdzie mogę zobaczyć taki wskaźnik? W całkowitej ciemności? Okazuje się, że to „noktowizor”, czyli urządzenie, którego odczyty widoczne są tylko w całkowitej ciemności.

A teraz spójrzmy na schemat powstałej jednostki wyświetlacza. Pokazano to na rysunku 3.



Rysunek 3. Schemat ideowy bloku wskazań dynamicznych

Teraz, po otrzymaniu układu sygnalizacji dynamicznej, możemy omówić jego zalety i wady. Niewątpliwą zaletą sygnalizacji dynamicznej jest niewielka liczba przewodów połączeniowych, co czyni ją niezastąpioną w niektórych przypadkach, np. przy pracy ze wskaźnikami matrycowymi.

Jako wadę należy wymienić obecność dużych prądów pulsacyjnych, a ponieważ każdy przewodnik jest anteną, wskazanie dynamiczne służy jako silne źródło zakłóceń. Inną drogą zakłóceń jest zasilanie.

Należy zauważyć, że fronty impulsów przełączających są bardzo krótkie, więc ich składowe harmoniczne obejmują zakres częstotliwości radiowych do fal ultrakrótkich.

Tak więc zastosowanie sygnalizacji dynamicznej pozwala zminimalizować ilość przewodów łączących urządzenie cyfrowe z sygnalizatorem, ale jednocześnie jest potężnym źródłem zakłóceń, dlatego jego stosowanie w odbiornikach radiowych jest niepożądane.

Jeśli z jakiegoś powodu, np. w celu zastosowania wskaźników matrycowych, musisz użyć wskazania dynamicznego, to musisz podjąć wszelkie działania, aby wytłumić zakłócenia.

Jako środki tłumienia zakłóceń spowodowanych dynamicznym wskazaniem można wymienić ekranowanie urządzenia, kabel połączeniowy i płytki. Zastosowanie minimalnej długości przewodów połączeniowych, zastosowanie filtrów mocy. Podczas osłaniania bloku może być konieczne osłanianie samych wskaźników. W takim przypadku zwykle stosuje się metalową siatkę. Ta siatka może jednocześnie zwiększyć kontrast wyświetlanych znaków.

Literatura:

Wraz z artykułem „Wskazywanie dynamiczne” czytają:

Wskaźniki są przeznaczone do wyświetlania różnego rodzaju informacji dla osoby. Najprostszy rodzaj informacji to...
http://website/digital/Indic.php

Wskaźniki rozładowania są używane zarówno do wskazywania informacji bitowych, jak i do wyświetlania informacji dziesiętnych. Podczas konstruowania dziesiętnych wskaźników katodowych...
http://strona internetowa/cyfrowy/GazIndic/

Obecnie diody LED są używane niemal wszędzie do wyświetlania informacji binarnych. Jest to spowodowane...
http://strona internetowa/digital/LED.php

Zasady działania wskaźników ciekłokrystalicznych ... Tryby działania wskaźników ciekłokrystalicznych ... Tworzenie obrazu kolorowego ...
http://strona internetowa/cyfrowy/LCD.php

DAby wyświetlić na wskaźniku liczbę wielocyfrową, należy najpierw przeprowadzić z nią podstępną manipulację, polegającą na rozbiciu liczby na jej składowe. Jako przykład podam wyświetlanie numeru 1234 na poczwórnym siedmiosegmentowym wskaźniku ze wspólną anodą.


Aby wyświetlić czterocyfrową liczbę, musisz utworzyć jedną wspólną zmienną, która będzie zawierać liczbę, którą chcesz wyświetlić (zmienna W), cztery zmienne, które będą przechowywać dane dla każdego znaku (N) i jeszcze cztery zmienne dla przekształceń pośrednich (M), aby nie dotykać zmiennej głównej. Zmienna musi odpowiadać wartości, która będzie w niej przechowywana.I. Więc dla zmiennejWtyp wystarczyliczba całkowita , ponieważ zmienna tego typu jest zdolna do xpAnimuj wartości od -32768 do +32767 (lubsłowo chyba że planujesz używać liczb ujemnych). W zmiennychNbędą leżeć liczby od 0 do 9, więc wystarczy użyć zmiennej typubajt
. I w zmiennychM będziete same wartości co w zmiennejW, więc ustawiamy typ liczba całkowita .

Dim W jako liczba całkowita
Dim N1 jako bajt
Dim N2 jako bajt
Dim N3 jako bajt
Dim N4 jako bajt
Dim M1 jako liczba całkowita
Dim M2 jako liczba całkowita
Dim M3 jako liczba całkowita
Dim M4 jako liczba całkowita


Po zadeklarowaniu zmiennych ustawiamy porty na wyjściektóry posłuży do podłączenia wskaźnika:

DDRC = &B11111111
DDRD = &B11111111


DDRC=&B 00001111 i DDRD=&B 01111111 (cztery pierwsze nogi portu Cna anody i sześć pierwszych portów segmenty D).

Następnie przypisz do zmiennej W wartość, którą będziemy wyświetlać na wskaźniku:

W=1234

"Arial","bezszeryfowy""> W głównej pętli programu zmiennym M przypisujemy wartość zmiennejW , robię to:

M1=W
M2 = M1
M3 = M1
M4 = M1


"Arial","bezszeryfowy""> To nie jest paranoja)), jest to robione w celu, aby we wszystkich zmiennych M był ten sam numer, ponieważ podczas operacji przypisania przerwanie (jeśli jest i nie jest wyłączone) może łatwo się włamać, w obsłudze którego zmiennaW może zmienić. A jeśli zadanie poszło tak: М1= W , M 2= W , M 3= W , M 4= W w zmiennych M będzie leżeć różne znaczenia co doprowadzi do bałaganu w odczytach.

Po przypisaniu wartości zmiennych zacznij pracować z
każdy z nich, konwertując w taki sposób, że na zmienną N otrzymał wartość, która będzie
wyświetlane na wskaźniku: w zmiennej
N 1 powinno być „1”, w N 2 - „2”, w N 3 - „3”, aw N 4 - „4”.

M1=M1/1000" M1=1234/1000=1.234
N1=Abs(m1)" N1=Abs(1.234)=1

abs – funkcja zwracająca liczbę całkowitą zmiennej.Do zmiennej N Trafiłem jednostkę, co było rzeczywiście wymagane.

Aby przypisać dwójkę do zmiennej N 2 operacja będzie nieco bardziej skomplikowana:

M2= M2 Mod 1000 " M2 =1234 Mod 1000 = 234
M2=M2/100" M2=234/100=2,34
N2= Abs (m2) " N2 = Abs (2,34) = 2

"Arial","bezszeryfowy""> Aby zacząć od funkcjiMod zwracamy pierwsze trzy
cyfry liczby (pozostała część dzielenia przez 1000), a następnie wszystko jest jak w pierwszym przypadku.

Z dwiema ostatnimi cyframi prawie to samo:

M3 = M3 Mod100
M3=M3/10
N3 = Abs (m3)

M4 = M4 Mod 10
N4= Abs (m4)


Teraz nasze zmienne zawierają wartości, które chcemy wyświetlić, czas, aby mikrokontroler kopnął nogami i wyświetlił te wartości na wskaźniku, w tym celu nazywamy podprogram przetwarzania wyświetlania:

"Arial","bezszeryfowy"">

Gosub Led

"Arial","bezszeryfowy""> Procesor przejdzie do podprogramu oznaczonegoDoprowadziło:

Doprowadziło:

Portc = &B00001000

"Arial","bezszeryfowy""> Tutaj serwujemy na wysokim poziomiePORTC .3 do tej nogi podłączyliśmy anodę pierwszej kategorii. Następnie wybieramy, które segmenty mają być podświetlone, aby wyświetlić wartość pierwszej zmiennej. Jest jedną z nas, więc zero będzie na nogach Portd .1 i Portd .2, co odpowiada segmentom Wskaźnik B i C.

Wybierz przypadek N1









Koniec Wybierz
Czekam 5

"Arial","bezszeryfowy""> Po zapaleniu się niezbędnych segmentów czekamy 5 ms i przechodzimy do wyświetlania następujących liczb:

Portc = &B00000100
Wybierz przypadek N2
Przypadek 0 : Portd = &B11000000
Przypadek 1: Portd = &B11111001
Przypadek 2: Portd = &B10100100
Przypadek 3: Portd = &B10110000
Przypadek 4: Portd = &B10011001
Przypadek 5: Portd = &B10010010
Przypadek 6 : Portd = &B100000010
Przypadek 7: Portd = &B11111000
Przypadek 8: Portd = &B10000000
Przypadek 9 : Portd = &B10010000
Koniec Wybierz

Czekam 5

Portc = &B0000010

Wybierz przypadek N3
Przypadek 0 : Portd = &B11000000
Przypadek 1: Portd = &B11111001
Przypadek 2: Portd = &B10100100
Przypadek 3: Portd = &B10110000
Przypadek 4: Portd = &B10011001
Przypadek 5: Portd = &B10010010
Przypadek 6 : Portd = &B100000010
Przypadek 7: Portd = &B11111000
Przypadek 8: Portd = &B10000000
Przypadek 9 : Portd = &B10010000
Koniec Wybierz

Czekam 5

Portc = &B0000001

Wybierz przypadek N4
Przypadek 0 : Portd = &B11000000
Przypadek 1: Portd = &B11111001
Przypadek 2: Portd = &B10100100
Przypadek 3: Portd = &B10110000
Przypadek 4: Portd = &B10011001
Przypadek 5: Portd = &B10010010
Przypadek 6 : Portd = &B100000010
Przypadek 7: Portd = &B11111000
Przypadek 8: Portd = &B10000000
Przypadek 9 : Portd = &B10010000
Koniec Wybierz

Czekam 5

"Arial","bezszeryfowy""> Po wyświetleniu informacji na wskaźniku należy wrócić do głównej pętli programu, gdzie należy dokończyć pętlę i zaznaczyć koniec programu.

"Arial","bezszeryfowy""> Oto, co otrzymujemy na końcu:

"Arial","bezszeryfowy"">

"Arial","bezszeryfowy""> Ze względu na małe opóźnienie przełączenie nie będzie widoczne dla ludzkiego oka i zobaczymy liczbę całkowitą 1234.

Poniżej możesz pobrać kod źródłowy i projekt w Proteus:"Arial","bezszeryfowy"">