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.

[Atmega16, DS18B20, Bascom]Pomiar temperatury i przerwanie

pier 21 Mar 2010 21:25 6606 29
  • #1 21 Mar 2010 21:25
    pier
    Poziom 23  

    Witam.
    Mam taki oto program do pomiaru temperatury przez DS18B20 i wyświetleniu jej na 14-sto pozycyjnym wyświetlaczu 14-sto segmentowym:

    Code:

    '-------------Zegar Kalendarz 14-segment LED-"

    'opis złącza ISP
    'czerwony - "+"
    'zielony - RESET
    'biały - MISO
    'niebieski - SCK
    'brązowy - MOSI
    'czarny  - "-"

    '------------dyrektywy dla kompilatora--------"
    $regfile = "m16def.dat"
    $crystal = 8000000

    '------------konfiguracja timera--------------"
    Config Timer2 = Timer , Prescale = 8 : Enable Interrupts : Enable Timer2
    On Timer2 Co4ms


    '------------zmienne--------------------------"
    Dim Ktorywysw As Byte
    Dim W1 As Byte
    Dim W2 As Byte
    Dim W3 As Byte
    Dim W4 As Byte
    Dim W5 As Byte
    Dim W6 As Byte
    Dim W7 As Byte
    Dim W8 As Byte
    Dim W9 As Byte
    Dim W10 As Byte
    Dim W11 As Byte
    Dim W12 As Byte
    Dim W13 As Byte
    Dim W14 As Byte
    'Termometr'
    Dim Odczyt(2) As Byte
    Dim T As Integer
    Dim T1 As Single
    Dim Temp As Byte
    '------------konfiguracja portów--------------"

    Config Portb = &B11111111
     Portb = &B00000000

    Config Portd = &B1111111
     Portb = &B11111111

    Config Porta = &B11111111
     Porta = &B11111111

    Config Pinc.0 = Output
     Portc.0 = 0

    Config 1wire = Portc.7


    '-----------program główny--------------------"
    Do
      1wreset : 1wwrite &HCC : 1wwrite &H44                     'SKIP ROM + dokonaj konwersji
      Waitms 750
      1wreset : 1wwrite &HCC : 1wwrite &HBE                     'odczytaj DS18x20
      Odczyt(1) = 1wread(2)                                     'odczytaj dwa pierwsze bajty
     T = Odczyt(2) : Shift T , Left , 8                         'przepisz, przesuń
     T1 = T + Odczyt(1)                                         'wynik do zmiennej typu Single
     T1 = T1 * 0.0625                                           'wyrażenie w stopniach celsjusza


    Temp = Round(t1)

    W1 = Temp / 10
    W2 = Temp Mod 10


    W3 = 36
    W4 = 12
    W5 = 35
    W6 = 35
    W7 = 35
    W8 = 35
    W9 = 35




    W10 = 35
    W11 = 35
    W12 = 35
    W13 = 35
    W14 = 35

    Loop
    End











    '-----------obsługa wyświetlacza------"
    Co4ms:
    Portd = &B00000000
    Portb = &B000000
    Incr Ktorywysw : If Ktorywysw = 14 Then Ktorywysw = 0
    Select Case Ktorywysw
    Case 0:
       Portb.6 = 1
       Porta = Lookup(w1 , Tabela1)
       Portb.6 = 0
       Porta = Lookup(w1 , Tabela2) : Portd.0 = 1
    Case 1:
       Portb.6 = 1
       Porta = Lookup(w2 , Tabela1)
       Portb.6 = 0
       Porta = Lookup(w2 , Tabela2) : Portd.1 = 1
    Case 2:
       Portb.6 = 1
       Porta = Lookup(w3 , Tabela1)
       Portb.6 = 0
       Porta = Lookup(w3 , Tabela2) : Portd.2 = 1
    Case 3:
       Portb.6 = 1
       Porta = Lookup(w4 , Tabela1)
       Portb.6 = 0
       Porta = Lookup(w4 , Tabela2) : Portd.3 = 1
    Case 4:
       Portb.6 = 1
       Porta = Lookup(w5 , Tabela1)
       Portb.6 = 0
       Porta = Lookup(w5 , Tabela2) : Portd.4 = 1
    Case 5:
       Portb.6 = 1
       Porta = Lookup(w6 , Tabela1)
       Portb.6 = 0
       Porta = Lookup(w6 , Tabela2) : Portd.5 = 1
    Case 6:
       Portb.6 = 1
       Porta = Lookup(w7 , Tabela1)
       Portb.6 = 0
       Porta = Lookup(w7 , Tabela2) : Portd.6 = 1
    Case 7:
       Portb.6 = 1
       Porta = Lookup(w8 , Tabela1)
       Portb.6 = 0
       Porta = Lookup(w8 , Tabela2) : Portb.7 = 1
    Case 8:
       Portb.6 = 1
       Porta = Lookup(w9 , Tabela1)
       Portb.6 = 0
       Porta = Lookup(w9 , Tabela2) : Portb.0 = 1
    Case 9:
       Portb.6 = 1
       Porta = Lookup(w10 , Tabela1)
       Portb.6 = 0
       Porta = Lookup(w10 , Tabela2) : Portb.1 = 1
    Case 10:
       Portb.6 = 1
       Porta = Lookup(w11 , Tabela1)
       Portb.6 = 0
       Porta = Lookup(w11 , Tabela2) : Portb.2 = 1
    Case 11:
       Portb.6 = 1
       Porta = Lookup(w12 , Tabela1)
       Portb.6 = 0
       Porta = Lookup(w12 , Tabela2) : Portb.3 = 1
    Case 12:
       Portb.6 = 1
       Porta = Lookup(w13 , Tabela1)
       Portb.6 = 0
       Porta = Lookup(w13 , Tabela2) : Portb.4 = 1
    Case 13:
       Portb.6 = 1
       Porta = Lookup(w14 , Tabela1)
       Portb.6 = 0
       Porta = Lookup(w14 , Tabela2) : Portb.5 = 1
    End Select
    Return





    Tabela1:                                                    'TABELA DLA PORTU A
    Data 63 , 6 , 219 , 207 , 230 , 237 , 253 , 7 , 255 , 239 , 247 , 143 , 57 , 15 , 249 , 241 , 189 , 246 , 0 , 30 , 112 , 56 , 54 , 54 , 63 , 243 , 243 , 237 , 1 , 62 , 54 , 0 , 0 , 9 , 0 , 0 , 227 , 192 , 48

    Tabela2:                                                    'TABELA DLA PORTU A-dodatkowe segmenty
    Data 12 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 18 , 0 , 18 , 0 , 0 , 0 , 0 , 18 , 0 , 36 , 0 , 5 , 33 , 0 , 0 , 32 , 0 , 18 , 0 , 40 , 45 , 21 , 12 , 8 , 0 , 0 , 0 , 12

    Problem w tym że program nie działa jak należy, niby pokazuje prawidłową temperaturę ale pokazuje też mnóstwo innych głupot. Problem jest pewnie w tym że obsługa wyświetlacza jest w przerwaniu. Nie potrafię się z tym uporać. Wiecie może co jest źle w tym programie?

    0 29
  • #2 21 Mar 2010 21:49
    arktik1
    Poziom 27  

    14 segmentowym??
    Znaczy 2 cyfry??

    0
  • #3 21 Mar 2010 21:57
    janbernat
    Poziom 38  

    Przerwanie masz co 0.256ms a nie co 4ms.
    A w przerwaniu dzieje się sporo- spróbuj dać prescale 64.
    Będziesz miał co 2ms.
    Z round jest coś niezgodnego z helpem podobno.
    Pisał o tym Atom tu:
    https://www.elektroda.pl/rtvforum/topic1616558.html
    Może- ale to są tylko niesprawdzone przypuszczena- daj na początku
    Dim t_1 as long
    A w pętli rzutowanie:
    t_1= T1
    a potem
    temp=round(t_1)

    0
  • #4 22 Mar 2010 05:23
    pier
    Poziom 23  

    Kolego arktik1 to jest wyświetlacz 14 segmentowy a nie dwa 7 segmentowe.
    Próbowałem już zwiększać prescaler ale nic to nie dawało. Zawsze jest tak że jest dobry pomiar później 00, jakieś inne pierdoły typu F3 i znów dobry pomiar. Funkcja round działa dobrze już nie pierwszy raz jej używam, zresztą zamiast rond dawałem też int i nic się nie zmieniło.

    0
  • #5 22 Mar 2010 07:36
    arktik1
    Poziom 27  

    U mnie działy się takie historie gdy miałem $crystal poniżej 8200000 .
    Włączyłem zewnętrzny oscylator i $crystal = 8300000 i było ok.
    Mam taki termometr na wyświetlacz 3x7,czyli po twojemu 21 seg.
    Jeśli chcesz to udostępnię gotowca.

    0
  • #6 22 Mar 2010 09:15
    mazomen
    Poziom 15  

    Ja też miałem takie cyrki z przerwaniem. napisałem więc program w ten sposób:

    Code:

    '///////////////////////////////////////////////////////////////////////////
    '//////////                    TERMOSTAT                     ///////////////
    '///////////////////////////////////////////////////////////////////////////


    $crystal = 4000000                                          'rezonator 4MHz
    $regfile "attiny2313.dat"                                   'attiny 2313

    'konfiguracja wyjść
    '-----------------------------------------------

    Config Portb = Output
            Portb = 255
    Config Pind.6 = Output
            Pind.6 = 1
    Config Pind.0 = Output
            Pind.0 = 1
    Config Pind.1 = Output
            Pind.1 = 1
    Config Pind.4 = Output
            Pind.4 = 0

    'deklaracja zmiennych
    '-----------------------------------------------

    Dim Zmienna As Byte
    Dim Liczba As Byte
    Dim Jednosci As Byte , Dziesiatki As Byte
    Dim Temp As Byte
    Dim 1cyfra As Byte , 2cyfra As Byte
    Dim A As Byte
    Dim Odczyt(2) As Byte
    Dim T As Integer
    Dim Term As Byte
    Dim Pomocnicza As Bit

    'odpalenie szyny 1Wire
    '-------------------------------------------------

    Config 1wire = Portd.5

    'ustawienia pieska
    '-------------------------------------------------

    Config Watchdog = 1024 : Start Watchdog

    Liczba = 77

    'pętla główna
    '-------------------------------------------------

    Do
         1wreset : 1wwrite &HCC : 1wwrite &HBE                              'polecenie odczytu DS18x20
       Odczyt(1) = 1wread(2)                                    'odczytaj dwa pierwsze bajty - temperaturę
       T = Odczyt(2)                                            '          starszy bajt temperatury
       Shift T , Left , 8                                       'przesuń w lewo o 8 miejsc
       T = T + Odczyt(1)                                        'w zmiennej Integer jest dziwna "ułamkowa" wartość
       Shift T , Right , 4                                      'zamiast dzielić przez 16 przesuń w prawo




         1wreset                                                '   dopiero teraz daj polecenie konwersji:
         1wwrite &HCC                                           'polecenie SKIP ROM, bo pojedyncza kostka
         1wwrite &H44                                           '   dokonaj konwersji - zmierz temperaturę

         Liczba = T
         Gosub Wyswietlanie
         Reset Watchdog
    Loop

    'obsługa wyswietlaczy LED
    '-----------------------------------------------------------------------

    Wyswietlanie:
    Portd.4 = 1
    Gosub Oblicz
    For A = 0 To 125
    Dziesiatki:
    If Dziesiatki = 0 Then
    Pind.0 = 1
    Goto Jednosci
    End If
    Portb = 1cyfra
    Portd.1 = 1
    Portd.0 = 0
    Waitms 3
    Jednosci:
    Portb = 2cyfra
    Portd.0 = 1
    Portd.1 = 0
    Waitms 3
    Next A
    A = 0
    Portd.4 = 0
    Return

    Oblicz:
    Temp = Makebcd(liczba)
    Jednosci = Temp And &B00001111
    Shift Temp , Right , 4
    Dziesiatki = Temp

    1cyfra = Lookup(dziesiatki , Tabela)
    2cyfra = Lookup(jednosci , Tabela)

    Return

    'tabela kodów wyświetlacza
    '-------------------------------------------------------------
    End
    Tabela:
    Data 192 , 249 , 164 , 176 , 153 , 146 , 130 , 248 , 128 , 144


    i zaczęło mi to ładnie działać

    0
  • #7 22 Mar 2010 16:34
    pier
    Poziom 23  

    Witam zaraz spróbuje czy sposób Kolegi Mazomen coś pomoże.
    Kolego arktkik1 dlaczego nie możesz zrozumieć co to wyświetlacz 14 segmentowy np. taki:
    [Atmega16, DS18B20, Bascom]Pomiar temperatury i przerwanie



    Sprawdziłem. Program dobry dla 4 wyświetlaczy ale nie dla 14. Wszystko miga, jak skrócę obsługę do 4 wyświetlaczy to działa dobrze. Dalej jestem w kropce.
    Ciekawe czy dała by coś zmiana kwarcu na np. 16MHz?

    0
  • #8 22 Mar 2010 17:08
    arktik1
    Poziom 27  

    To się nazywa wyświetlacz ALFANUMERYCZNY, dlatego nie mogliśmy się dogadać.
    Ja mówiłem o wyświetlaczu LED potrójnym takim do MULTIPLEKSOWANIA.
    Po co ci 14 cyfr?

    0
  • #10 22 Mar 2010 17:26
    arktik1
    Poziom 27  

    Żeby multipleksować 14 cyfr, nie wiem czy ci się uda.

    0
  • #11 22 Mar 2010 18:39
    pier
    Poziom 23  

    Multipleksowanie już mi się udało tylko nie mogę do tego wcisnąć pomiaru temperatury. Swoją drogą to ten wyświetlacz fabrycznie był multipleksowany a więc musi to być do zrobienia.

    0
  • #12 22 Mar 2010 19:36
    janbernat
    Poziom 38  

    Zacznij może od "posprzątania"

    Code:

    Config Portb = &B11111111
     Portb = &B00000000       ' Ustawione stany na 0

    Config Portd = &B1111111   'siedem bitów ustawionych- a ósmy?
     Portb = &B11111111       ' a teraz po ustawieniu kierunku PORTD ponownie     
                                       ' ustawiamy stan portb- ale na 1- a portd nie ustawiony 

    Config Porta = &B11111111
     Porta = &B11111111


    I tu też coś dziwnego:
    Code:

    Case 0:
       Portb.6 = 1         'ustawiasz portb.6 na 1
       Porta = Lookup(w1 , Tabela1)
       Portb.6 = 0         ' a po paru us ustawiasz na 0- chyba żeby uzyskać jakieś 
                                'miganie 
       Porta = Lookup(w1 , Tabela2) : Portd.0 = 1

    0
  • #13 22 Mar 2010 20:40
    pier
    Poziom 23  

    A rzeczywiście wkradło mi się kilka babolów na początku ale podejrzewam że nie ma to żadnego znaczenia. A to sterowanie portb.6 to tak naprawdę sterowanie zatrzaskiem 74HCT573 po to aby tylko portem a sterować wszystkimi segmentami.

    0
  • #14 22 Mar 2010 21:22
    janbernat
    Poziom 38  

    To teraz dalej.
    Polecenie waitms 750 daje konieczne opóźnienie dla przetwarzania wyniku z DS.
    Ale nie wyłącza przerwań.
    W czasie tego waitms przerwanie jest wywoływane ok. 2900 razy- przy tych ustawieniach timera.
    Za każdym razem jest wykonywana dość długa procedura obsługi przerwania - a odkładanie i zdejmowanie ze stosu też jakiś czas zajmuje.
    Tak że ten waitms 750 dość mocno się wydłuża- może nawet kilkunastokrotnie- a może i więcej.
    W tym czasie obsługujemy wyświetlacz- ale na nim nie ma nowych odczytów.
    Jak już jest przerwanie co 0.256ms to można to wykorzystać- ustawić w przerwaniu flagę- chodzą mi po głowie nawet dwie- a w pętli głównej dać licznik który sprawi że co np. 1s będzie sprawdzany stan DS i co 1s będzie ustawiany DS do odczytu.

    0
  • #15 23 Mar 2010 05:17
    pier
    Poziom 23  

    No tak wszystko to wiem tylko że próbowałem już podłączać zasilanie ds-a normalnie i program bez polecenia "waitms750" i nic to nie zmieniło. Teraz ds będzie tak właśnie podłączony.


    Dzisiaj podłączyłem kwarc 12MHz i nie bardzo to pomogło, dobrze pokazuje temperaturę ale wyświetlacz strasznie mruga. Wątpię aby podpięcie 16MHz coś pomogło.

    Czy nie da się zmusić tego procesora do prawidłowego obsłużenia tego wyświetlacza aby mógł coś jeszcze oprócz tego robić? W przyszłości mam zamiar dołożyć mu jeszcze odczyt DS1307.

    A tak z innej beczki. Z jaką maksymalną prędkością można używać Atmegi16? Wiem że w datascheet jest napisane 16MHz ale mi chodzi o to ile z niej można wyciągnąć?

    Taki program teraz siedzi w procku.

    Code:

    '-------------Zegar Kalendarz 14-segment LED-"

    'opis złącza ISP
    'czerwony - "+"
    'zielony - RESET
    'biały - MISO
    'niebieski - SCK
    'brązowy - MOSI
    'czarny  - "-"

    '------------dyrektywy dla kompilatora--------"
    $regfile = "m16def.dat"
    $crystal = 12000000




    '------------zmienne--------------------------"
    Dim Ktorywysw As Byte
    Dim W1 As Byte
    Dim W2 As Byte
    Dim W3 As Byte
    Dim W4 As Byte
    Dim W5 As Byte
    Dim W6 As Byte
    Dim W7 As Byte
    Dim W8 As Byte
    Dim W9 As Byte
    Dim W10 As Byte
    Dim W11 As Byte
    Dim W12 As Byte
    Dim W13 As Byte
    Dim W14 As Byte
    'Termometr'
    Dim Odczyt(2) As Byte
    Dim T As Integer
    Dim T1 As Single
    Dim Temp As Byte
    '------------konfiguracja portów--------------"

    Config Portb = &B11111111
     Portb = &B00000000

    Config Portd = &B11111111
     Portd = &B11111111

    Config Porta = &B11111111
     Porta = &B11111111

    Config Pinc.0 = Output
     Portc.0 = 0

    Config 1wire = Portc.7


    '-----------program główny--------------------"
    Do
         1wreset : 1wwrite &HCC : 1wwrite &HBE                  'polecenie odczytu DS18x20
       Odczyt(1) = 1wread(2)                                    'odczytaj dwa pierwsze bajty - temperaturę
       T = Odczyt(2)                                            '          starszy bajt temperatury
       Shift T , Left , 8                                       'przesuń w lewo o 8 miejsc
       T = T + Odczyt(1)                                        'w zmiennej Integer jest dziwna "ułamkowa" wartość
       T1 = T * 0.0625                                          'wyrażenie w stopniach celsjusza




         1wreset                                                '   dopiero teraz daj polecenie konwersji:
         1wwrite &HCC                                           'polecenie SKIP ROM, bo pojedyncza kostka
         1wwrite &H44                                           '   dokonaj konwersji - zmierz temperaturę

    Temp = Round(t1)

    W1 = Temp / 10
    W2 = Temp Mod 10


    W3 = 36
    W4 = 28
    W5 = 14
    W6 = 22
    W7 = 25
    W8 = 14
    W9 = 26
    W10 = 10
    W11 = 28
    W12 = 29
    W13 = 26
    W14 = 10
    Gosub Wyswietlanie
    Loop
    End











    '-----------obsługa wyświetlacza------"
    Wyswietlanie:
    Portd = &B00000000
    Portb = &B000000
    Incr Ktorywysw : If Ktorywysw = 14 Then Ktorywysw = 0
    Select Case Ktorywysw
    Case 0:
       Portb.6 = 1
       Porta = Lookup(w1 , Tabela1)
       Portb.6 = 0
       Porta = Lookup(w1 , Tabela2) : Portd.0 = 1
    Case 1:
       Portb.6 = 1
       Porta = Lookup(w2 , Tabela1)
       Portb.6 = 0
       Porta = Lookup(w2 , Tabela2) : Portd.1 = 1
    Case 2:
       Portb.6 = 1
       Porta = Lookup(w3 , Tabela1)
       Portb.6 = 0
       Porta = Lookup(w3 , Tabela2) : Portd.2 = 1
    Case 3:
       Portb.6 = 1
       Porta = Lookup(w4 , Tabela1)
       Portb.6 = 0
       Porta = Lookup(w4 , Tabela2) : Portd.3 = 1
    Case 4:
       Portb.6 = 1
       Porta = Lookup(w5 , Tabela1)
       Portb.6 = 0
       Porta = Lookup(w5 , Tabela2) : Portd.4 = 1
    Case 5:
       Portb.6 = 1
       Porta = Lookup(w6 , Tabela1)
       Portb.6 = 0
       Porta = Lookup(w6 , Tabela2) : Portd.5 = 1
    Case 6:
       Portb.6 = 1
       Porta = Lookup(w7 , Tabela1)
       Portb.6 = 0
       Porta = Lookup(w7 , Tabela2) : Portd.6 = 1
    Case 7:
       Portb.6 = 1
       Porta = Lookup(w8 , Tabela1)
       Portb.6 = 0
       Porta = Lookup(w8 , Tabela2) : Portb.7 = 1
    Case 8:
       Portb.6 = 1
       Porta = Lookup(w9 , Tabela1)
       Portb.6 = 0
       Porta = Lookup(w9 , Tabela2) : Portb.0 = 1
    Case 9:
       Portb.6 = 1
       Porta = Lookup(w10 , Tabela1)
       Portb.6 = 0
       Porta = Lookup(w10 , Tabela2) : Portb.1 = 1
    Case 10:
       Portb.6 = 1
       Porta = Lookup(w11 , Tabela1)
       Portb.6 = 0
       Porta = Lookup(w11 , Tabela2) : Portb.2 = 1
    Case 11:
       Portb.6 = 1
       Porta = Lookup(w12 , Tabela1)
       Portb.6 = 0
       Porta = Lookup(w12 , Tabela2) : Portb.3 = 1
    Case 12:
       Portb.6 = 1
       Porta = Lookup(w13 , Tabela1)
       Portb.6 = 0
       Porta = Lookup(w13 , Tabela2) : Portb.4 = 1
    Case 13:
       Portb.6 = 1
       Porta = Lookup(w14 , Tabela1)
       Portb.6 = 0
       Porta = Lookup(w14 , Tabela2) : Portb.5 = 1
    End Select
    Return





    Tabela1:                                                    'TABELA DLA PORTU A
    Data 63 , 6 , 219 , 207 , 230 , 237 , 253 , 7 , 255 , 239 , 247 , 143 , 57 , 15 , 249 , 241 , 189 , 246 , 0 , 30 , 112 , 56 , 54 , 54 , 63 , 243 , 243 , 237 , 1 , 62 , 54 , 0 , 0 , 9 , 0 , 0 , 227 , 192 , 48

    Tabela2:                                                    'TABELA DLA PORTU A-dodatkowe segmenty
    Data 12 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 18 , 0 , 18 , 0 , 0 , 0 , 0 , 18 , 0 , 36 , 0 , 5 , 33 , 0 , 0 , 32 , 0 , 18 , 0 , 40 , 45 , 21 , 12 , 8 , 0 , 0 , 0 , 12

    0
  • #17 28 Mar 2010 20:20
    323493
    Użytkownik usunął konto  
  • #18 28 Mar 2010 22:01
    sepako
    Poziom 14  

    Pewnie problem da się rozwiązać na różne sposoby - w moim przypadku było 8 wyświetlaczy 7-segmentowych podłączonych bez żadnych buforów do uC. Czyli pełne multipleksowanie do tego automatyczna regulacją jasności, 2 czujniki DS18b20, przetwornik ADC i odbiór RC5. Różne zabiegi zmniejszały mignięcia w czasie pomiaru temperatury tudzież odbioru RC5, jednak pomimo bezwładności oka multipleksowanie nawet nieznacznie zakłócone dawało efekt mignięcia. Z pomocą przyszła analiza czasu potrzebnego na przełączenie segmentów oraz protokołu 1wiere z DS-a.
    Krytyczny okazał sie zapis oraz odczyt bitu dla DS-a, to w którym momencie został zainicjowany ma mniejsze znaczenie natomiast po rozpoczęciu czytania/pisania bitu nic nie powinno go zakłócać. Multipleksowanie odbywało sie w przerwaniu więc wystarczyło poczekać na koniec przełączenia + margines bezpieczeństwa i wtedy odczytywać/zapisywać DS-a bit po bicie w "martwym" oknie czasowym. To samo rozwiązanie zastosowałem do RC5 czy ADC w efekcie całkowicie zostało wyeliminowane migotanie i nie występują żadne zakłócenia komunikacji z DS-em.

    0
  • #19 29 Mar 2010 10:51
    androot
    VIP Zasłużony dla elektroda

    Problem rozwiąże, odmierzanie czasu przez timer, a nie przez wait czy delay (nie znam BASCOMa). Jak już ktoś wspomniał odczyt i zapis bitu na 1-wire jest dość krytyczny czasowo.
    Miałem z tym problem w assemblerze i ADuC841. Przerwanie od multipleksowania wyświetlaczy skutecznie zakłócało transmisję.
    Polecam też sprawdzanie CRC, żeby ustrzec się przed błędnymi odczytami temperatury.

    0
  • #20 29 Mar 2010 13:24
    pier
    Poziom 23  

    Ale jakie odmierzanie czasu? Teraz w programie nie ma żadnego opóźnienia typu wait.
    Zresztą problem został rozwiązany w 99%, mam tylko malutkie, prawie niezauważalne mignięcia pojedynczych wyświetlaczy i to raz na 10 sekund.
    Nie wiem tylko co będzie jak dorzucę do układu DS1307?

    0
  • #22 29 Mar 2010 13:40
    pier
    Poziom 23  

    No i tu właśnie obsługa przerwania zakłóca komunikację 1W. Jeśli wyłączę przerwania na czas odczytu/zapisu DS-a to wyświetlacz miga.
    Bascom chyba nie pozwala na takie zagłębienie się w procedury zapisu/odczytu 1W aby można było zrobić to po swojemu.

    0
  • #23 29 Mar 2010 14:07
    androot
    VIP Zasłużony dla elektroda

    Dlatego:

    a) przepisz obsługę wyświetlacza, żeby zajmowała mniej czasu procesora, daj najszybszy możliwy kwarc do tego procka,

    b) zrób wstawki w asm

    c) przepisz całość w asm

    Mam podobny program tylko na wyświetlacz 4 x 7seg. i też miałem z tym problem, jednak w asm łatwiej zapanować nad wszystkim.

    0
  • #24 29 Mar 2010 14:17
    pier
    Poziom 23  

    Parę postów wyżej pytałem jaki najszybszy kwarc idzie podłączyć do tej megi ale nikt mi nie udzielił odpowiedzi. Nie da się już chyba inaczej napisać obsługi wyświetlacza. Jak zrezygnuje z zatrzasku to nie będę miał już wolnych portów procesora.

    0
  • #25 29 Mar 2010 15:01
    sepako
    Poziom 14  

    Problem wcale nie musi tkwić w prędkości zegara aczkolwiek ma ona wpływ. Przerwania wcale nie zakłócają komunikacji z DS o ile przeprowadzi sie ją w odpowiednim momencie a zatrzaski zwalniają porty uC ale zwiększają czas przełączenia wyświetlaczy. To wszystko można wcześniej policzyć i wybrać rozwiązanie. Nie znam bascoma w C na pewno się da i nie trzeba uciekać sie do ASM.

    0
  • #26 29 Mar 2010 17:58
    pier
    Poziom 23  

    Piszecie że na pewno da się to zrobić.

    Więc ja pytam jak konkretnie to zrobić?

    Na pewno w grę nie wchodzi język C tylko Bascom ewentualnie wstawki aseblerowe.
    Z zatrzasku też nie zrezygnuję bo przecież do tak prostego układu nie zaprzęgnę Atmegi128 która ma więcej portów I/0.

    0
  • #27 29 Mar 2010 20:51
    sepako
    Poziom 14  

    Załóżmy że każdy segment zapalasz na 1ms. Generujesz przerwanie co 1ms, zakładamy że licznik zegara liczy od 0 do 255 w przybliżeniu jeden takt na 4us. Co każde przerwanie zapala sie następny segment, zakładamy że zapalenie segmentu zajmuje 200us wtedy do następnego przerwania zostaje ci 800us w których masz pewność że jeśli nie generujesz innych przerwań nic nie zakłóci transmisji z DS-em. Na odczyt lub zapis bitu do DS-a potrzebujesz minimum 60us wiec zaczynasz operacje zapis/odczyt pod warunkiem ze licznik nie ma wartości większej niż 255-(60/4)=240 gdy ma czekasz do następnego przerwania i po czasie potrzebnym na przełączenie segmentu (licznik powyżej 200/4) robisz operacje odczyt/zapis bitu do DS-a
    masz wtedy pewność ze segment sie już przełączył i wystarczy czasu na odczyt/zapis bitu z DS-a. Prościej już nie potrafię.

    0
  • #28 29 Mar 2010 21:13
    janbernat
    Poziom 38  

    Ale Ty jesteś niecierpliwy.
    Masz odczyt DS bez wait- które to wait wszystko psuje.
    Flaga_dodatkowa wykorzystaj do multipleksowania wyświetlaczy.
    I podziękuj malon-owi za dobry pomysł.

    Code:

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

    '********* Konfiguracja wyświetlacza *********
    'oczywiście może być bez RW
    $lib "Lcd4busy.lib"
    Const _lcdport = Portd
    Const _lcdddr = Ddrd
    Const _lcdin = Pind
    Const _lcd_e = 1
    Const _lcd_rw = 2
    Const _lcd_rs = 3
    Config Lcd = 20 * 4

    Config Timer0 = Timer , Prescale = 64
    Config 1wire = Portc.0
    Config Portb = Output

    Dim Odczyt(2) As Byte
    Dim Liczniczek_przygotowanie_odczytu As Word
    Dim Flaga_przygotowanie_odczytu As Byte
    Dim Flaga_dodatkowa As Byte
    Dim T As Integer
    Dim T1 As Single
    Dim Temp_1 As Word
    Enable Interrupts
    Enable Ovf0
    On Ovf0 Przerwanie_0          ' co 2ms
    Cls
    Lcd "START"
    Cursor Off
    Waitms 300
    Cls

    '****************************************

    Do

      Gosub Przygotowanie_odczytu
      Toggle Portb.1
    Loop

    '***************************************

    Przerwanie_0:                 'co 2ms

       Flaga_przygotowanie_odczytu = 1
       Flaga_dodatkowa = 1        'do wykorzystania w innym sub- też co 2ms- to Twoje sterowanie w wyśw. multipleks

    Return

    '****************************************

    Przygotowanie_odczytu:

      If Flaga_przygotowanie_odczytu = 1 Then
       Incr Liczniczek_przygotowanie_odczytu
         If Liczniczek_przygotowanie_odczytu >= 400 Then       'co 800ms odzyt DS
           Liczniczek_przygotowanie_odczytu = 0
           1wreset
           1wwrite &HCC
           1wwrite &HBE           'odczytaj DS18x20
           Odczyt(1) = 1wread(2)  'odczytaj dwa pierwsze bajty
           T = Odczyt(2)
           Shift T , Left , 8     'przepisz, przesuń
           T = T + Odczyt(1)      'wynik do zmiennej typu Single
           T1 = T / 16
           Locate 1 , 1
           Lcd "Temp: " ; T1 ; " C        "
           1wreset
           1wwrite &HCC
           1wwrite &H44           'SKIP ROM + dokonaj konwersji
         End If
        Flaga_przygotowanie_odczytu = 0
       End If

    Return

    0
  • #29 30 Mar 2010 12:36
    pier
    Poziom 23  

    Sprawdziłem tą propozycję programu i nic z tego. Jest dobry pomiar temperatury ale wyświetlacz miga i łypkają nie potrzebne segmenty. Nawet jak dam kwarc 12MHz to nic to nie zmienia.

    0
  • #30 30 Mar 2010 19:40
    janbernat
    Poziom 38  

    pier- w tym programie który Ci podałem masz wykorzystać zmienną "flaga_dodatkowa" do sterowania wyświetlaczem w sub- a nie w przerwaniu Timer2.
    Timer2 wyłącz.
    I daj program po przeróbkach.
    Żaden kwarc na to nie pomoże- trzeba korzystać z przerwań.

    0