Aktyw Forum

Zarejestruj się na forum.ep.com.pl i zgłoś swój akces do Aktywu Forum. Jeśli jesteś już zarejestrowany wystarczy, że się zalogujesz.

Sprawdź punkty Zarejestruj się

multopleksowany wyswietlacz led i bascom8051

Awatar użytkownika
karlos79
-
-
Posty: 8
Rejestracja: 19 sty 2005, o 18:29
Lokalizacja: fajne miasto

multopleksowany wyswietlacz led i bascom8051

Postautor: karlos79 » 11 lis 2007, o 10:33

Witam
Nie bardzo potrafię napisać procedurę do multipeksowego starowania czterema wyświetlaczami led.
Chcę wyświetlić na nim godziny i minuty odebrane z PCF8583, mikrokontroler to AT89S52.
Proszę o jakieś wskazówki, bo walczę z tym już długo i nici.
Jeśli ktoś ma taką procedurę z opisem to bardzo proszę o jej udostępnienie, nie szukam gotowca, tylko kawałka kodu z dokładnym opisem co i jak.
Po prostu chcę zrozumieć idee multipleksowego sterowania wyswietlaczem.
Pozdrawiam

Awatar użytkownika
pajaczek
Moderator
Moderator
Posty: 2650
Rejestracja: 24 sty 2005, o 00:39
Lokalizacja: Winny gród

Postautor: pajaczek » 11 lis 2007, o 14:45

Chodzi Ci o wyswietlacz 7-segm? Zreszta idea jest taka sama.

Do 4 wyswietlaczy bedzie Ci, w najprostszej kombinacji, potrzebny 1 pelny port + 4 linie z innego portu (nazwijmy je sterujacymi).

Zalozmy ze masz podpiete wyswietlacze bezposrednio do portow (i ze te porty to wytrzymaja pradowo). Wyswietlacze ze wspolna katoda. Oczywiscie rezystory ograniczajace prad to wymog, upewnienie sie ze porty wytrzymaja obiazenie, ale o tym juz wspominalem.

Na porcie sterujacym jest b1111. Na porcie pelnym wystawiasz co chcesz wyswietlic, czyli np. b00000110 (dla jedynki, w ukladzie DPgfedcba - DP to kropka), zas na 4 liniach sterujacych, zanegowany wybor wyswietlacza - np. b1110 - dla skrajnie prawego, b1011 - dla 2-go od lewej).

Odczekujesz chwile, i zmiana -> sterujacy na b1111, pelny na to co ma byc na nastepnej cyfrze, np. b01011011 - dla dwojki, i sterujacy na nastepny wyswietlacz, np. b1101).

Zauwaz ze wyswietlacze poza wybranym beda mialy segmenty spolaryzowane albo zaporowo, albo obie koncowki na potencjale 1. to samo sie tyczy zbednych segmentow wybranego wyswietlacza. Diody maja swoja bezwladnosc swietlna, a wiec tak zrealizowane wyswietlania bedzie przy odpowiednim "przemiataniu" niezauwazalne.

To byl najprostszy przyklad, teraz bardziej uniwersalne rozwiazanie, bezpieczniejsze dla ukladu sterujacego:
W zasadzie zamiany sa tylko takie, ze miedzy katode wyswietlacz (kazdego z 4 osobny) a mase ukladu wstawiasz tranzystor (tu NPN), baza (przez rezystorek) sterujesz z portu "sterujacego". Roznica jest jeszcze taka, ze teraz port sterujacy jest niezanegowany, tylko wprost wskazuje wyswietlacz, ktory chcemy obsluzyc -> b0001, b0010, b0100, b1000. Stan spoczynkowy b0000. Reszta bez zmian. Funkcjonalnie rozni sie tym, ze katoda niewybranego wyswietlacza jest w stanie wysokiej impedancji. Jest to wiec sterowanie bezpieczniejsze, pozatym dajace wieksze mozliwosci jesli chodzi o max prad swiecenia segmentu (juz nie przykladowe 20mA na wszystkie 7 segm w stanie niskim, tylko po 20 mA na kazdy segment w stanie wysokim).

Oczywiscie mozna to jeszcze rozwijac, np. zastosowac multiplexem 2 na 4, dzieki czemu ograniczymy liczbe linii sterujacych do 2. Zastosowac jakis rejestr przesowny czy dziwaczny licznik, to nawet do 1 linii.


Mam nadzieje, ze cos z tego zrozumiesz... mam dzis co prawda checi, ale niezbyt chyba forme na tlumaczenie :619: przemysl wiec dokladnie zanim cos wykonasz w sprzecie.


Segment - pojedyncza "belka" na wyswietlaczu - to jakby ktos mial watpliwosci.

Awatar użytkownika
karlos79
-
-
Posty: 8
Rejestracja: 19 sty 2005, o 18:29
Lokalizacja: fajne miasto

Postautor: karlos79 » 11 lis 2007, o 16:40

Witam
Tak się składa, że od strony sprzętowej wszystko jest ok.
Wyświetlacze, tranzystory sterujące katody- to wszystko działa i jest dla mnie oczywiste.
Znalazłem gdzieś w internecie kilka programów i wyłuskałem z nich procedurkę obsługi wyświetlacza.
Musze przyznać, że nawet działa :)
Mam problem z rozbiciem całego bajtu na części.
Dokładniej mówiąc mam w zmiennej cała liczbę (dziesiątki i jedności ), chcę wyswietlić dziesiatki na starszym wyświetlaczu, a jedności na młodszym i tu jest problem.

Kod: Zaznacz cały

cyfra = H / 10 ' dziesiątki godzin cyfra = H mod 10 ' jedności godzin (mod - to reszta z dzielenia)
Do 15 wyświetla dobrze od 16 wyświetlają się krzaki, to znaczy segmenty skaczą np. zamiast wyświetlić 7 to wyświetla się 1 i co jakiś czas dopala się segment A wyświetlacza.
Pozdrawiam

Awatar użytkownika
pajaczek
Moderator
Moderator
Posty: 2650
Rejestracja: 24 sty 2005, o 00:39
Lokalizacja: Winny gród

Postautor: pajaczek » 11 lis 2007, o 22:16

To moze pokaz co i jak robisz?

Awatar użytkownika
karlos79
-
-
Posty: 8
Rejestracja: 19 sty 2005, o 18:29
Lokalizacja: fajne miasto

Postautor: karlos79 » 12 lis 2007, o 10:31

Witam
Już pokazuję.

Kod: Zaznacz cały

$crystal = 8000000 Config Timer0 = Timer , Gate = Internal , Mode = 2 Load Timer0 , 125 On Timer0 Mult_wysw Enable Timer0 Enable Interrupts Start Timer0 Main: goto main Mult_wysw: Load Timer0 , 125 Hh = G Mm = M Hh = Makedec(hh) Mm = Makedec(mm) Hj = Hh / 10 hd = Hh Mod 10 Mj = Mm / 10 Md = Mm mod 10 Set Mux Set W4 Set W1 Set W2 Set W3 Incr Mux If Mux = 4 Then Mux = 0 Select Case Mux Case 0 : Digivalue = Hj Reset W1 Case 0 : Digivalue = Hd Reset W2 Case 0 : Digivalue = Mj Reset W3 Case 0 : Digivalue = Md Reset W4 End Select Seg = Lookup(digivalue , Digits) Reset Mux Return Digits: Data &B10000001 , &B11110011 , &B01001001 , &B01100001 , &B00110011 , &B00100101 , &B00000101 , &B11110001 , &B00000001 , &B00100001
teraz jest tak, że cały program zamula, mikrokontroler reaguje na wciśniecie przycisku z dużym opóźnieniem itp.
Kombinowałem z różnymi wartościami ładowanymi do timera, ale nic to nie dało.
no i dalej jest problem z wyświetlaniem...
Pozdrawiam

Awatar użytkownika
pajaczek
Moderator
Moderator
Posty: 2650
Rejestracja: 24 sty 2005, o 00:39
Lokalizacja: Winny gród

Postautor: pajaczek » 12 lis 2007, o 20:03

Ech... bascom... :614:

O powyzszym listingu powiem tak:
Jak dla mnie niespojny, nielogiczny i z masa niescislosci. Troche rzeczy mozna by ponadto zoptymalizowac.
Co to jest G i H, jaki typ i skad sie biora wartosci. Czy napewno sa w BCD? Pozatym dla wlasnej wygody zacznij trzymac sie malych_WIELKICH liter w nazwach, bo oczoplasu mozna dostac. Ps. Czyz nie lepiej bylo by jesli juz Hh=Makedec(G);
Mux, W1, W2, W3, W4.. mozna sie domyslic co za stale, ale... chwile pozniej Mux juz uzywasz jak zmiennej, inkrementujesz ja. Na dodatek konstrukcja case ma 4 przypadki, wszystkie dla Mux=0?? Absurd, po co wogole case w takim razie?
Co zawiera ta tabela digits? Bo takich hieroglifow jak tam sa to by sie chyba nawet predator nie powstydzil (i nie odczytal). No chyba ze masz jakos pomerdane te wyprowadzenia (ale nawet wowczas zapalone/zgaszone mi sie nie zgadzaja).


Czy Ty jestes pewien ze ten program choc w 10% dziala tak jak chciales, on cokolwiek robi sensownego?

Byc moze ja juz calkiem odroslem od bascoma, ale jak dla mnie to jest groch z kapusta.

Awatar użytkownika
karlos79
-
-
Posty: 8
Rejestracja: 19 sty 2005, o 18:29
Lokalizacja: fajne miasto

Postautor: karlos79 » 12 lis 2007, o 23:05

Witam
Dzięki za krytykę :)
Ten kod jest roboczy i dlatego trochę pokręcony.
G i H przechowują godziny i minuty odczytane z PCF8583 i są w kodzie BCD, no i oczywiście są to zmienne bajtowe.
Co do Tabeli digits wszystko się w niej zgadza znaki są poprawnie w niej zapisane i wyświetlane.
Przez tranzystor podaję na wyświetlacz +5V, a dane pobierane są z tej tabeli.
Podaję aktualny kod przerwania, problem z wyświetlaniem nie ustąpił.
Cały czas "latają cyfry", zamiast 17 wyświetla mi 11 i co jakiś czas dopala segment A, czyli miga mi między 1 a 7.

Kod: Zaznacz cały

Const Xtal = 8000000 $crystal = Xtal Const Sysclock = Xtal / 12 Const Timer0value = 65536 -(sysclock / 200) '200 przerwań od T0 na sekundę Seg Alias P3 Disp Alias P1 Dim Mux As Byte , T0cntr As Byte Dim Ss As Byte , Mm As Byte , Hh As Byte , Digivalue As Byte Config Timer0 = Timer , Gate = Internal , Mode = 1 On Timer0 T0_int Enable Timer0 Enable Interrupts Seg = 255 Disp = 255 T0cntr = 0 Counter0 = Timer0value Start Timer0 T0_int: Th0 = High(timer0value) Incr T0cntr If T0cntr > 200 Then T0cntr = 0 End If Hh = G Mm = M Hh = Makedec(hh) Mm = Makedec(mm) Set Disp.mux Incr Mux Mux = Mux And 3 Select Case Mux Case 0 : Digivalue = Hh / 10 Case 1 : Digivalue = Hh Mod 10 Case 2 : Digivalue = Mm / 10 Case 3 : Digivalue = Mm Mod 10 End Select Seg = Lookup(digivalue , Digits) Reset Disp.mux Return Digits: Data &B10000001 , &B11110011 , &B01001001 , &B01100001 , &B00110011 , &B00100101 , &B00000101 , &B11110001 , &B00000001 , &B00100001
Dzięuję za wszelką pomoc i pozdrawiam

Awatar użytkownika
pajaczek
Moderator
Moderator
Posty: 2650
Rejestracja: 24 sty 2005, o 00:39
Lokalizacja: Winny gród

Postautor: pajaczek » 12 lis 2007, o 23:51

Ok, teraz wyglada troszke ladniej ;) sprobuje przeanalizowac jutro, chyba ze do tej pory ktos z bascomowcow poda jakies uwagi.

Acha... cyfry faktycznie sa ok, tyle ze masz wyswietlacze ze wspolna ANODA (nie katoda), to mnie troche zmylilo, pozatym uklad jest lekko inny niz sam zwykle przyjmuje, ale w sumie tez przystepny.

Awatar użytkownika
karlos79
-
-
Posty: 8
Rejestracja: 19 sty 2005, o 18:29
Lokalizacja: fajne miasto

Postautor: karlos79 » 13 lis 2007, o 00:03

Witam
Ja już rwę włosy z głowy.
Dziwne bo na AVR multipleksowanie działa mi dobrze.
Początkowo przeniosłem procedurę z AVR na 8051 i lipa.
Wszystko było by ok gdyby nie błędne wyświetlanie...
Pozdrawiam

Po niedługim czasie znalazłem błąd :)
Po odczycie z RTC dane zamieniałem z kodu BCD na kod dziesiętny.
W przerwaniu wartość zmiennej w postaci dziesiętnej jeszcze raz zamieniałem na wartość dziesiętną.
Wystarczyło skasować jedną linijkę i wszystko ruszyło z kopyta.

Wróć do „8051”

Kto jest online

Użytkownicy przeglądający to forum: Obecnie na forum nie ma żadnego zarejestrowanego użytkownika i 74 gości