Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

[ATmega8][Bascom] Wyswietlacz 7 segmentowy LED.

Marek_RADOM 24 Maj 2008 22:03 9741 19
  • #1 24 Maj 2008 22:03
    Marek_RADOM
    Poziom 18  

    Witam

    Po raz pierwszy zabrałem się za sterowanie wyświetlaczem 7 segmentowym.
    Mam pewien problem jak zamienić liczby np. wartość temperatury 20.5°C na 3 liczby typu byte i umieścić je na wyświetlaczu ?.

    W moim programie mam podane 3 zmienne C1, C2, C3, które udaje mi się wyświetlić. Nie wiem tylko jak zapalić kropkę lub zgasić 0 z 1-wszego wyświetlacza.

    Program wygląda tak:

    Code:

    $regfile = "m8def.dat"
    $crystal = 1000000

    Declare Sub Wyswietlanie

    Dim Cyfra As Integer
    Dim C1 As Byte
    Dim C2 As Byte
    Dim C3 As Byte

    Config Portd = Output

    Config Pinb.0 = Output
    Config Pinb.1 = Output
    Config Pinb.2 = Output


    C1 = 1
    C2 = 2
    C3 = 4

    Do

    '*************Wyswietlanie****************


    Cyfra = C1
    Gosub Wyswietlanie
    Set Portb.0
    Waitms 30
    Reset Portb.0

    Cyfra = C2
    Gosub Wyswietlanie
    Set Portb.1
    Waitms 30
    Reset Portb.1

    Cyfra = C3
    Gosub Wyswietlanie
    Set Portb.2
    Waitms 30
    Reset Portb.2


    Loop




    '*************************** Wyświetlanie *********************************

    Sub Wyswietlanie:
    Portd = Lookup(cyfra , Segmenty )
    End Sub

     Segmenty:
    Data &B11000000 , &B11111001 , &B10100100 , &B10110000 , &B10011001 ,
    Data &B10010010 , &B10000010 , &B11111000 , &B10000000 , &B10010000 ,


    Poprawiłem tytuł -
    https://www.elektroda.pl/rtvforum/topic1015361.html [c_p]

    0 19
  • #2 25 Maj 2008 00:30
    kedzi1
    Poziom 18  

    1) Przenieś obsługę wyświetlania do przerwania, inaczej wyświetlacz będzie zmieniał jasność w stosunku do tego jak długo będzie wykonywała się główna pętla.

    2) Stwórz tablice w której kolejnym pozycjom odpowiadają kombinacje bitów zapalające dane cyfry. Tzn. po kolei kombinacja dla 0 potem dla 1 itd. Ułatwi to konwersję cyfry na kombinację bitów które włączają odpowiednie segmenty.

    3) Rozkładaj liczbę na cyfry następująco:
    -sprawdzasz czy większa od 100
    -jeżeli tak to dziel przez 100
    -część całkowita z dzielenia to cyfra setek
    -odejmij od liczby obliczoną cyfre setek razy 100
    -zostanie ci liczba bez setek
    -sprawdzasz czy większa od 10
    -jeżeli tak to dzielisz przez 10
    -całkowita część z dzielenia to cyfra dziesiątek
    -odejmujesz znowu cyfra dziesiątek razy 10
    -zostają już tylko jedności

    4) Zamieniasz cyfry na kombinacje bitów korzystając z tabeli (polecenie LOOKUP jak dobrze pamiętam, hehe kiedy to było jak sie na baskomie szkoliłem :) dziś asm i C)

    Powodzenia!!!

    0
  • #3 25 Maj 2008 13:07
    Utul
    Poziom 13  

    Witam
    Coś mi te Waitms 30 Sie nie podoba jakoś ch... powinno być w okolicach 4 ms. domyślam sie iż mają być 3 albo 4 wyświetlacze
    A reszta to tak jak napisał kolega powyżej.

    Pozdro.

    0
  • #4 25 Maj 2008 15:57
    Marek_RADOM
    Poziom 18  

    Nie wiem w jaki sposób ma być to wyświetlanie przeniesione do przerwania. Rozumiem, że przerwanie ma być np. co 4ms i w tym czasie będą wyświetlane kolejne cyfry ? Prosiłbym o jakiś przykład na moim programie.

    0
  • #5 25 Maj 2008 17:57
    cyberdar
    Poziom 31  

    Witam

    Zasada jest niezmienna i polega na tym aby co 4 milisekundy odświeżać kolejny wyświetlacz. Kwestia rozbicia liczby na poszczególne znaki to temat rzeka. Każdy robi to po swojemu. Mogę jako kolejne rozwiązanie podać zamianę liczby na string 3 lub 4 znakowy w zależności od potrzeb i wyłuskiwanie z owego stringu wybranego znaku. Jednak taka operacja powinna być przeprowadzana w pętli głownej a nie w przerwaniu. W pętli głównej obrabiasz sobie string wyłuskując poszczególne znaki i przypisujesz do kolejnych zmiennych. Takie rozwiązanie ma tą zaletę, że jeśli się nieco przeciągnie to wyświetlacz nie będzie dziwnie mrugał ani nie wystąpi nic podobnego. Wyświetlanie będzie płynne. Co do kropki to wiadomo, że ze stringu trzeba ją wyeliminować bo wprowadziłaby tylko zamieszanie. Wobec tego swoje 20.5 mnożysz przez 10 i otrzymujesz 205. Potem musisz pamiętać jednak o tym, że trzeba ją wyświetlić. Jeśli anody masz na jednym porcie to do kropki przypisana jest jakaś wartość np. 64. Jeżeli chcesz wyświetlić jedynkę z kropką, której kod wynosi np. 107 to do 107 dodajesz 64 i na port wystawiasz 171. Może trochę zagmatwane ale jeśli przeczytasz 10 razy to zaskoczysz.

    --
    pozdrawiam

    0
  • #6 25 Maj 2008 20:48
    Marek_RADOM
    Poziom 18  

    Właśnie teraz udało mi się zgasić jeden wyświetlacz, ale coś mi nie wychodzi zapalenie samej kropki.
    Zamieniłem sobie liczby w kodzie Bin na Dec przy pomocy kalkulatora windowsa i wszystko jest ok.
    Jeśli dobrze myślę to tak są przypisane liczby w linijce Data do cyfr od 0 - 9
    dodałem 255 (zgaszone segmenty), ale nie wiem jaką liczbę dodać aby zaświecić kropkę.

    Code:
     Data 192 , 249 , 164 , 176 , 153 , 146 , 130 , 248 , 128 , 144 , 255 ,
    
           0     1     2     3     4     5     6     7     8     9 zgaszony


    Dodam, że segmenty mam podłączone tak : A - Pd.0, B - Pd.1, C - Pd.2, D - Pd.3, E - Pd.4, F - Pd.5, G - Pd.6, H - Pd.7.

    Nie mogę w kalkulatorze wpisać 01111111, aby przetworzyć na Dec. A wydaje mi się, że aby zaświecić kropkę na początku musi być 0.

    0
  • #7 25 Maj 2008 20:57
    Utul
    Poziom 13  

    Możesz też najprościej napisać w programie w miejscu gdzie wyświetlasz ostatnią cyfrę całości portd.7 =0 (lub 1) aby zaświecić tą kropkę. Czaisz.
    Pozdro

    0
  • #8 25 Maj 2008 21:49
    Marek_RADOM
    Poziom 18  

    Ok zrobiłem kropkę, teraz próbuje już odczytać temperaturę z DS18b20 podłączonego pod Pc.5, ale nie wiem dokładnie jak się zabrać za przełożenie temperatury na 3 cyfry. Nie wiem też czy w ogóle odczytuje temperature. Jest jakiś sposób żeby to sprawdzić bez podłączania wyświetlacza LCD ?

    Program wygląda teraz tak i wyświetla 00.0:

    Code:

    $regfile = "m8def.dat"
    $crystal = 8000000

    Declare Sub Wyswietlanie
    Declare Sub Pokaztemp

    Dim Cyfra As Byte
    Dim W1 As Byte
    Dim W2 As Byte
    Dim W3 As Byte
    Dim Temp As Integer
    Dim Dsid As Byte

    Config Portd = Output
    Config Pinb.0 = Output
    Config Pinb.1 = Output
    Config Pinb.2 = Output
    Config 1wire = Portc.5

    Config Timer0 = Timer , Prescale = 256
    Load Timer0 , 15385
    On Timer0 Timer0_int
    Enable Timer0
    Enable Interrupts
    Start Timer0


    Do
    1wreset
       1wwrite &H55
       1wverify Dsid
       1wwrite &HBE
       Temp = 1wread(2)

       1wreset
       1wwrite &HCC
       1wwrite &H44

       Wait 1

       Temp = Temp * 10
       Temp = Temp / 16

       Temp = Temp / 10
       W1 = Temp

    Pokaztemp
    Loop






    '*************Wyswietlanie****************
    Sub Pokaztemp

    Timer0_int:
    Load Timer0 , 15385

    Cyfra = W1
    Gosub Wyswietlanie
    Set Portb.0
    Waitms 4
    Reset Portb.0

    Cyfra = W2
    Gosub Wyswietlanie
    Set Portb.1                                                 ' Zaświecenie kropki
    Reset Portd.7
    Waitms 4
    Reset Portb.1

    Cyfra = W3
    Gosub Wyswietlanie
    Set Portb.2
    Waitms 4
    Reset Portb.2

    Return
    End Sub



    '*************************** Wyświetlanie *********************************

    Sub Wyswietlanie:
    Portd = Lookup(cyfra , Segmenty )
    End Sub

     Segmenty:
    Data 192 , 249 , 164 , 176 , 153 , 146 , 130 , 248 , 128 , 144 , 255 ,

    0
  • #9 25 Maj 2008 23:02
    gregoorr
    Poziom 17  

    Procedurę odczytu masz trochę chyba skopaną. poszukaj na forum przykładów. Na początek sprawdź gdzie umieszcza się polecenie wait. Umieszczę moją procedurkę do obsługi wyświetlaczy (4), może się komuś przyda.

    Code:
    $regfile = "m8def.dat"
    
    $crystal = 8000000

    Config Portd = Output
    Config Pinb.0 = Output
    Config Pinb.1 = Output
    Config Pinb.2 = Output
    Config Pinb.3 = Output


    Config Timer0 = Timer , Prescale = 256

    Declare Sub Pobr_znaku(cyfra As Byte)

    On Timer0 Mult_wysw

    Dim A As Byte
    Dim B As Byte
    Dim C As Byte
    Dim D As Byte
    'Dim X As Byte

    'Dim Wart As Byte
    Dim Nr_wysw As Byte

    W1 Alias Portb.0
    W2 Alias Portb.1
    W3 Alias Portb.2
    W4 Alias Portb.3

    Wait 2
    Set W1
    Set W2
    Set W3
    Set W4
    Wait 2

    Enable Interrupts

    Enable Timer0
    Load Timer0 , 125


    Do

    Wait 1

    D = D + 1

    If D > 9then
    D = 0
    C = C + 1
    End If

    If C > 9then
    C = 0
    B = B + 1
    End If

    If B > 9 Then
    B = 0
    A = A + 1
    End If


    If A > 9 Then
    A = 0 : B = 0 : C = 0 : D = 0
    End If

    Loop

    End                                                         'end program


    Sub Pobr_znaku(cyfra As Byte)
    Portd = Lookup(cyfra , Kody7seg)
    End Sub


    Mult_wysw:

    Load Timer0 , 150
    Set W1
    Set W2
    Set W3
    Set W4


    Select Case Nr_wysw

    Case 0:
    Call Pobr_znaku(a)
    Reset W1


    Case 1:
    Call Pobr_znaku(b)
    Reset W2

    Case 2:
    Call Pobr_znaku(c)
    Reset W3


    Case 3:
    Call Pobr_znaku(d)
    Reset W4

    End Select

    Incr Nr_wysw
    If Nr_wysw = 4 Then
    Nr_wysw = 0
    End If
    Return


    Kody7seg:

    Data &B11000000 , &B11111001 , &B10100100 , &B10110000 , &B10011001,
    Data &B10010010 , &B10000010 , &B11111000 , &B10000000 , &B10010000














    0
  • #10 26 Maj 2008 19:46
    Utul
    Poziom 13  

    Marek_RADOM napisał:

    Code:


    Do

       1wreset
       1wwrite &HCC
       1wwrite &H44

     Wait 1

       1wreset
       1wwrite &HCC
       1wwrite &HBE
       Temp = 1wread(2)

     
    Shift Temp, Left 8
       Pokaztemp
    Loop
    End


    Zamień ten kawałek kodu. Tak przy okazji to Timer0 jest 8 bitowy liczy tylko do 255.
    Pozdro

    0
  • #11 26 Maj 2008 23:12
    Marek_RADOM
    Poziom 18  

    Jest błąd nr 92 w tej linii

    Code:
    Shift Temp, Left 8 



    Już poprawiłem brakowało przecinka przed 8, Wyświetla nadal same 000.

    Sprawdzałem czujnik na moim termometrze z zegarkiem i budzikiem w którym była poprzednia wersja procedury odczytu i jest ok.

    Zauważyłem jeszcze, że przy tej procedurze odczytu co teraz zamieniłem stan portu Pc5 się wcale nie zmienia, więc nie ma komunikacji z czujnikiem.
    Przy poprzedniej wersji komunikacja jest.

    Kolejna dziwna rzecz. W głównej pętli do... loop gdzie jest procedura odczytu to wyświetlanie działa do polecenia wait 1, jesli poniżej wait 1 umieszcze np. W1 = 2 to już nie wyświetli mi tego tylko nadal są zera.
    Nie wiem nawet czy działa poprawnie procedura odczytu nie mówiąc o zamianie wartości temperatury na 3 cyfry.

    0
  • #12 27 Maj 2008 23:13
    Utul
    Poziom 13  

    Witam
    Niedawno zauważyłem że masz tam coś namącone przy wyświetlaniu cyfr bo jest tam procedura "pokaztemp" a w niej obsługa przerwania. nie wiem o so chodzi :?:
    Sprawdź to, ale poustawiaj se końcówki wg. siebie mnie to chodziło na AT90S2313 :

    Code:


    '*****1 Wire na wyświetlaczu LED na Płytce testowej ***********


       Config 1wire = Portd.5
       Config Timer0 = Timer , Prescale = 64
       Enable Interrupts
       Enable Timer0
       On Timer0 Co4ms

          Dim Odczyt(2)as Byte , A As Integer , Licznik As Byte , T As Integer ,
          Dim Tysiace As Byte , Setki As Byte , Dziesiatki As Byte , Jednostki As Byte
          Dim Mux As Byte

       Do

       1wreset                                                  'reset
       1wwrite &HCC                                             'jedna kostka więc wykorzystujemy rozkaz SKIP ROM
       1wwrite &H44                                             'dokonaj konwersji
          Waitms 750                                            'poczekaj czas konwersji
       1wreset                                                  'reset
       1wwrite &HCC                                             'rozkaz adresowy SKIP ROM
       1wwrite &HBE                                             'rozkaz funkcyjny - polecenie odczytu
       Odczyt(1) = 1wread(2)                                    'odczytaj dwa pierwsze bajty
       T = Odczyt(2)                                            'przepisz starszy bajt do zmiennej Integrer
       Shift T , Left , 8                                       'przesuń ten bajt w lewo na wyższe pozycje




       T = T + Odczyt(1)                                        'przepisz - dodaj młodszy bajt
       T = 1 / 16                                               'wyraź w stopniach celsjusza, wynik wpisz do zmiennej Singel

       Loop
       End                                                      'end program


       Co4ms:
       'Standardowa konwersja binarna 0...255 na trzycyfrową BCD
       A = T
          If A > 100 Then
              Setki = 1
              A = A - 100
           Else
              Setki = 10
           End If




        A = Makebcd(a)
        Jednostki = A And 15
        Dziesiatki = A
        Shift Dziesiatki , Right , 4
        'Standardowa obsługa wyświetlaczy
        Incr Mux
        If Mux = 4 Then Mux = 0
        Portd = 127
        Select Case Mux
        Case 0
          Portb = Lookup(jednostki , Tabela)
          Portd.3 = 0
        Case 1
          Portb = Lookup(dziesiatki , Tabela)
          Portd.4 = 0
        Case 2
          Portb = Lookup(setki , Tabela)
          Portd.5 = 0
        Case 3
          Portb = Lookup(tysiace , Tabela)
          Portd.6 = 0
        End Select
       Return

     Tabela:
     Data 192 , 249 , 164 , 176 , 153 , 146 , 130 , 248 , 128 , 144 , 255 , 137



    Pozdro

    0
  • #13 28 Maj 2008 00:22
    Marek_RADOM
    Poziom 18  

    Poustawiałem końcówki, rezonator wewnętrzny na 8MHz ustawiłem, wywaliłem obsługę 4-go wyświetlacza, linia danych 1Wire podciągnięta do 5V przez 4,7k i wyświetla mi same 000, czujnik na 100% sprawny bo sprawdzałem w moim termometrze z LCD.

    0
  • #15 28 Maj 2008 17:02
    Marek_RADOM
    Poziom 18  

    Był podłączony 1wire VDD złączone z GND i to razem do masy a linia danych do 4,7k i do uC. Przerobiłem na 2 wire i nadal zera

    0
  • #16 28 Maj 2008 23:01
    Utul
    Poziom 13  

    Witam

    Code:

       Do

       1wreset                                                  'reset
       1wwrite &HCC                                             'jedna kostka więc wykorzystujemy rozkaz SKIP ROM
       1wwrite &H44                                             'dokonaj konwersji
          Waitms 750                                            'poczekaj czas konwersji
      Disable Interrupts
        1wreset                                                  'reset
        1wwrite &HCC                                             'rozkaz adresowy SKIP ROM
        1wwrite &HBE                                             'rozkaz funkcyjny - polecenie odczytu
       Odczyt(1) = 1wread(2)                                    'odczytaj dwa pierwsze bajty
      Enable Interrupts
       T = Odczyt(2)                                            'przepisz starszy bajt do zmiennej Integrer
       Shift T , Left , 8                                       'przesuń ten bajt w lewo na wyższe pozycje
       T = T + Odczyt(1)                                        'przepisz - dodaj młodszy bajt
       T = 1 / 16                                               'wyraź w stopniach celsjusza, wynik wpisz do zmiennej

       Loop
       End                                                      'end program


    Spróbój z tym :|

    0
  • #17 28 Maj 2008 23:28
    Marek_RADOM
    Poziom 18  

    Niestety nadal same zera wyświetla. Zmieniałem nawet pin 1wire,ale nic nie dało. Wrzucę aktualny cały program, może znajdziecie jakiś błąd.

    Code:

    $regfile = "m8def.dat"
    $crystal = 8000000


       Config Portd = Output
       Config Pinb.0 = Output
       Config Pinb.1 = Output
       Config Pinb.2 = Output
       Config 1wire = Portc.5
       Config Timer0 = Timer , Prescale = 64
       Enable Interrupts
       Enable Timer0
       On Timer0 Co4ms

          Dim Odczyt(2)as Byte , A As Integer , Licznik As Byte , T As Integer ,
          Dim Setki As Byte , Dziesiatki As Byte , Jednostki As Byte ,
          Dim Mux As Byte ,


       Do

       1wreset                                                  'reset
       1wwrite &HCC                                             'jedna kostka więc wykorzystujemy rozkaz SKIP ROM
       1wwrite &H44                                             'dokonaj konwersji
          Waitms 750                                            'poczekaj czas konwersji
       Disable Interrupts
        1wreset                                                  'reset
        1wwrite &HCC                                             'rozkaz adresowy SKIP ROM
        1wwrite &HBE                                             'rozkaz funkcyjny - polecenie odczytu
       Odczyt(1) = 1wread(2)                                    'odczytaj dwa pierwsze bajty
       Enable Interrupts
       T = Odczyt(2)                                            'przepisz starszy bajt do zmiennej Integrer
       Shift T , Left , 8                                       'przesuń ten bajt w lewo na wyższe pozycje
       T = T + Odczyt(1)                                        'przepisz - dodaj młodszy bajt
       T = 1 / 16                                               'wyraź w stopniach celsjusza, wynik wpisz do zmiennej

       Loop
       End                                                      'end program                                                      'end program


       Co4ms:
       'Standardowa konwersja binarna 0...255 na trzycyfrową BCD
       A = T
          If A > 100 Then
              Setki = 1
              A = A - 100
           Else
              Setki = 10
           End If




        A = Makebcd(a)
        Jednostki = A And 15
        Dziesiatki = A
        Shift Dziesiatki , Right , 4
        'Standardowa obsługa wyświetlaczy
        Incr Mux
        If Mux = 3 Then Mux = 0
        Portb = 127
        Select Case Mux
        Case 0
          Portd = Lookup(jednostki , Tabela)
          Portb.0 = 0
        Case 1
          Portd = Lookup(dziesiatki , Tabela)
          Portb.1 = 0
        Case 2
          Portd = Lookup(setki , Tabela)
          Portb.2 = 0
        End Select
       Return

     Tabela:
     Data 192 , 249 , 164 , 176 , 153 , 146 , 130 , 248 , 128 , 144 , 255 , 137

    0
  • #18 04 Maj 2011 18:04
    krzykrol
    Poziom 10  

    Kolega sobie poradził z tym kodem (jeśli tak to może się podzieli)??

    0
  • #19 05 Maj 2011 07:43
    Marek_RADOM
    Poziom 18  

    Nie poradziłem sobie. Zrobiłem sobie termometr na LM35.

    0
  • #20 05 Maj 2011 14:01
    sp3ots
    Poziom 36  

    Witam !

    krzykrol napisał:
    Kolega sobie poradził z tym kodem (jeśli tak to może się podzieli)??

    Po niżej działający program termometru.
    Code:
     
    
    'Wyświetlacze LED wsp. Anoda, bez tranzystorów
    '2011.05.5
    'Fuse bity ustawione fabrycznie
    $regfile = "m8def.dat"
    $crystal = 1000000
    Dim Jedn As Byte
    Dim Dzies As Byte
    Dim Setki As Word
    Config 1wire = Portc.5

    Dim Ktorywys As Byte
    Config Portd = Output
       Portd = &B11111111
    Config Portb = Output
       Portb = &B11111111

    Dim Db(2) As Byte
    Dim Temp As Integer
    Dim Temp1 As Integer

    Config Timer0 = Timer , Prescale = 64       
    On Timer0 Wyswietlanie
    Enable Interrupts
    Enable Timer0
    Start Timer0
    Load Timer0 , 150

    Do
    1wreset
    1wwrite &HCC
    1wwrite &H44
    Enable Interrupts
    Waitms 750
    Disable Interrupts
    1wreset
    1wwrite &HCC
    1wwrite &HBE
    Db(1) = 1wread(2)
    Temp = Makeint(db(1) , Db(2))
    Temp = Temp * 10
    Temp = Temp / 16
    Jedn = Temp Mod 10
    Temp1 = Temp / 10
    Dzies = Temp1 Mod 10
    Setki = Temp / 100
    Loop
    End

    Wyswietlanie:
    Load Timer0 , 150
    Incr Ktorywys
    If Ktorywys = 3 Then Ktorywys = 0

    Select Case Ktorywys
    Case 0:
    Portb.2 = 0       ' gasi LED 3
    Portd = Lookup(jedn , Tabela)
    Portb.0 = 1
    Case 1:
    Portb.0 = 0       ' gasi LED 1
    Portd = Lookup(dzies , Tabela10)
    Portb.1 = 1
    Case 2:
    Portb.1 = 0       ' gasi LED 2
    Portd = Lookup(setki , Tabela)
    Portb.2 = 1
    End Select
    Return

    Tabela:
    Data 192 , 249 , 164 , 176 , 153 , 146 , 130 , 248 , 128 , 144
    Tabela10:       ' dla cyfry z przecinkiem
    Data 64 , 121 , 36 , 48 , 25 , 18 , 2 , 120 , 0 , 16 , 255




    Poskładałem go z kilku programów i sprawdziłem działa.
    Pozdrawiam. Stefan

    0