Zegar w BascomAVR

To forum jest dla wszystkich pasjonatów mikrokontrolerów AVR Atmela. Wymiana doświadczeń i pomoc dla początkujących w pisaniu programów zarówno w C, Asemblerze jak i BASCOM. Zapraszam znawców tematu, aby pomogli wszystkim początkującym!
ODPOWIEDZ
Tom27
-
Posty: 62
Rejestracja: 28 sie 2005, 12:07

Zegar w BascomAVR

Post autor: Tom27 » 11 paź 2008, 13:24

Witam
Próbuję napisać program zegara z wykorzystaniem LCD. Próbuję i próbuję, ale nie mogę poradzić sobie z problemem spóźniania się. Tak napisany program gubi 10 sekund już przy 5 minutach. Czy może ktoś pobieżnie zerknąć w kod i podpowiedzieć mi, co robię nie tak. Walczę już z tym tydzień czasu a że jestem bardzo „świeży” to efekt jest mizerny.
Będę bardzo wdzięczny za wszelkie wskazówki.
Pozdrawiam
Tomek

Kod: Zaznacz cały

$crystal = 4000000
$regfile "attiny2313.dat"


Config Lcd = 16 * 2
Config Portb = &B11111111
Portb = &B01111111
Config Portd = &B1111111
Portd = &B0111111
Config Timer0 = Timer , Prescale = 64
Enable Interrupts
Enable Timer0
On Timer0 Co4ms                                             'po przepełnieniu licznika T/C0 skocz do etykiety o nazwie Co4ms

Dim Opoznienie As Byte
Dim A As Byte
Dim Dg As Byte                                              'Dziesiątki godzin
Dim Jg As Byte                                              'Jednostki godzin
Dim Dm As Byte                                              'itd
Dim Jm As Byte                                              'itd
Dim Ds As Byte                                              'itd
Dim Js As Byte                                              'itd

Dg = 0                                                      'wstępnie wpisana wartość
Jg = 9
Dm = 5
Jm = 9
Ds = 5
Js = 0

Opoznienie = 0
A = 0
Portd.2 = 0


Cls

Do


Loop
End                                                         'to jest główny program - pusta nieskończona pętla



Co4ms:                                                      'przerwanie
Timer0 = 6                                                  'skrócenie zliczania do 4ms
Gosub Zegar

Return

Zegar:

If Opoznienie = 250 Then
   Opoznienie = 0
      Incr Js                                               'zwiększanie sekund w kółko

      If Js = 10 Then                                       'skrócenie zliczania jednostek sekund do 9
      Incr Ds                                               'zwiększenie dziesiątek sekund
      Js = 0                                                'wyzerowanie jednostek sekund
      End If

      If Ds = 6 Then                                        'skrócenie dziesiątek sekund do 60
      Incr Jm                                               'zwiększenie jednostek minut
      Ds = 0                                                'wyserowanie dziesiątek sekund
      End If

      If Jm = 10 Then                                       'jw
      Incr Dm
      Jm = 0
      End If

      If Dm = 6 Then
      Incr Jg
      Dm = 0
      End If

      If Jg = 10 Then
      Incr Dg
      Jg = 0
      End If

      If Dg = 2 And Jg = 4 Then                             'sprawdzenie czy nie ma godziny 24:00
      Dg = 0 : Jg = 0                                       'jeśli tak to wyzerowanie zegara i liczenie od nowa
      End If
      Gosub Wyswietlacz

Else
   Incr Opoznienie

End If

Return





Wyswietlacz:

Cls
Locate 1 , 1                                                'lokacja dziesiątek godzin
If Dg > 0 Then                                              'jeśli jest przed dziesiątą wygaś pierwsze zero
Lcd ; Dg                                                    'wyświetlenie dziesiątek godzin
Else
Cursor Off
End If

Locate 1 , 2                                                'lokacja jednostek godzin
Lcd ; Jg                                                    'jw
Locate 1 , 3
Lcd ":"
Locate 1 , 4
Lcd ; Dm
Locate 1 , 5
Lcd ; Jm
Locate 1 , 6
Lcd ":"
Locate 1 , 7
Lcd ; Ds
Locate 1 , 8
Lcd ; Js
Cursor Off

Return

KiciuR
-
Posty: 4
Rejestracja: 13 maja 2008, 16:38
Lokalizacja: okolice Krk
Kontakt:

Post autor: KiciuR » 11 paź 2008, 21:40

Zegar gubi Ci czas ponieważ na wykonanie instrukcji pomiędzy samym zliczaniem też jest potrzebny jakiś czas, poza tym jeśli procka masz odpalonego na wewnętrznym zegarze to dokładność odliczania jest dość mizerna.

Pev4
-
Posty: 44
Rejestracja: 06 sie 2007, 19:26
Lokalizacja: Ostrowiec Św.
Kontakt:

Post autor: Pev4 » 13 paź 2008, 14:19

witam, spojrzałem na Twój program i jak dla mnie jest zbyt skomplikowany na to co ma do wykonania. Skrobnąłem na szybko taki zegarek, i raczej robi to samo co Twój, spójrz:

Kod: Zaznacz cały

$regfile = "m8def.dat"                                      ' specify the used micro
$crystal = 8000000                                          ' used crystal frequency

Config Portb = Output
Config Portc = Output
Config Portd = Input


Config Lcdpin = Pin , Db4 = Portb.4 , Db5 = Portb.5 , Db6 = Portb.6 , Db7 = Portb.7 , E = Portb.3 , Rs = Portb.2
Cursor Off

$sim

Dim Sekundy As Word
Dim Minuty As Byte
Dim Godziny As Byte
Godziny = 0
Sekundy = 0
Minuty = 0

Do
Incr Sekundy
If Pind.0 = 0 Then Incr Godziny
If Pind.1 = 0 Then Incr Minuty
If Sekundy = 60 Then Incr Minuty
If Sekundy = 60 Then Sekundy = 0
If Minuty = 60 Then Incr Godziny
If Minuty = 60 Then Minuty = 0
If Godziny = 24 Then Godziny = 0
Cls

If Godziny < 10 And Minuty < 10 And Sekundy < 10 Then Lcd "0" ; Godziny ; ":0" ; Minuty ; ":0" ; Sekundy
If Godziny < 10 And Minuty < 10 And Sekundy >= 10 Then Lcd "0" ; Godziny ; ":0" ; Minuty ; ":" ; Sekundy
If Godziny < 10 And Minuty >= 10 And Sekundy < 10 Then Lcd "0" ; Godziny ; ":" ; Minuty ; ":0" ; Sekundy
If Godziny >= 10 And Minuty < 10 And Sekundy < 10 Then Lcd Godziny ; ":0" ; Minuty ; ":0" ; Sekundy
If Godziny < 10 And Minuty >= 10 And Sekundy >= 10 Then Lcd "0" ; Godziny ; ":" ; Minuty ; ":" ; Sekundy
If Godziny >= 10 And Minuty < 10 And Sekundy >= 10 Then Lcd Godziny ; ":0" ; Minuty ; ":" ; Sekundy
If Godziny >= 10 And Minuty >= 10 And Sekundy < 10 Then Lcd ; Godziny ; ":" ; Minuty ; ":0" ; Sekundy
If Godziny >= 10 And Minuty >= 10 And Sekundy >= 10 Then Lcd Godziny ; ":" ; Minuty ; ":" ; Sekundy

Waitms 999
Waitus 850
Loop

End
waitus służy do dokładniejszego ustawienia (gdy śpieszy lub późni) obecnie odjąłem tak na oko czas potrzebny na wykonanie programu.
Gdyby ktoś miał sugestie i pomysły do mojego programu, bardzo chętnie posłucham:)

Tom27
-
Posty: 62
Rejestracja: 28 sie 2005, 12:07

Post autor: Tom27 » 13 paź 2008, 17:32

Witam
Na wstępie dziękuję za chęć zabrania głosu i pomoc. Od razu napisze, że nie oczekuję gotowego programu zegara. Chodzi mi raczej o poprawienie lub wskazanie, co należy i jak poprawić w programie, który wkleiłem. Oczywiście uwagi, że ten program jest zły (zły tok myślenia) są również jak najbardziej na miejscu. To są moje pierwsze programy na mikrokontrolery i przerost formy nad treścią niestety często mi się zdarza a że przy banalnym programie zabraknie 2 K-bajtowej pamięci też już mnie nie dziwi. :oops: :lol:
Sam program, który wkleiłem jest oparty o schemat działania z książki „Mikrokontrolery dla początkujących” tyle, że w oryginale działał wykorzystując wyświetlacze LED i działał poprawnie. Ja chciałem zastosować LCD i tu powstał problem z opóźnieniem. Podejrzewam, że nieumiejętne wpięcie LCD w program wprowadza bałagan. Kolego Pev4 dziękuję Ci za wstawkę gotowego programu, ale myślę, że stosowanie polecenia wait w roli zegara nie jest chyba dobrym pomysłem tym bardziej, że zegar jest tylko częścią większego programu, w którym będzie jeszcze kilka innych poleceń. Dlatego raczej chcę powalczyć z timer-ami.
Jeszcze raz dziękuję za chęć pomocy i oczekuję dalszych wskazówek.
Pozdrawiam
Tomek

alaris
Użytkownik
Posty: 530
Rejestracja: 21 lut 2006, 14:56
Lokalizacja: Gorzow/Poznan

Post autor: alaris » 13 paź 2008, 17:56

Na wstępie dziękuję za chęć zabrania głosu i pomoc. Od razu napisze, że nie oczekuję gotowego programu zegara
Niestety nie uzywam Bascoma, wiec nie podejmuje sie jego analizy. W kazdym razie najlepszym wyjsciem jest stosowanie kwarcu zegarkowego i wykorzystanie dedykowanego licznika T2 - dostajesz przerwanie co 1 sekunde. Mozesz to rowniez zrobic na zwyklym kwarcu, ale musisz zwrocic uwage, aby po uwzglednieniu wszystkich dzielnikow nie wychodzily "ulamki".
Reasumujac: najlepszym wyjsciem sa po prostu przerwania...

Awatar użytkownika
RcTomek
Moderator
Posty: 243
Rejestracja: 27 wrz 2007, 21:15
Lokalizacja: Głogów / Wrocław

Post autor: RcTomek » 13 paź 2008, 21:51

alaris pisze:Niestety nie uzywam Bascoma, wiec nie podejmuje sie jego analizy.
Może to i nawet lepiej :) Bascom jest dobry tylko na początek, żeby zobaczyć z czym to się je; po kilku (tygo)dniach już tylko C albo ASM.

A tak na poważnie: jak mówisz, najlepiej wykorzystać do tego celu przerwania od któregoś Timera.
W kazdym razie najlepszym wyjsciem jest stosowanie kwarcu zegarkowego i wykorzystanie dedykowanego licznika T2 - dostajesz przerwanie co 1 sekunde.
Tak, ale Tom27 (z tego co widzę) pisze program pod ATtiny2313, który nie ma T/C2 - pozostaje tylko użycie 'zwykłego' timera w trybie CTC.

alaris
Użytkownik
Posty: 530
Rejestracja: 21 lut 2006, 14:56
Lokalizacja: Gorzow/Poznan

Post autor: alaris » 13 paź 2008, 23:37

Ddevil pisze:Tak, ale Tom27 (z tego co widzę) pisze program pod ATtiny2313
Nie zauwazylem, bo nie przegladalem programu. W takim wypadku rzeczywiscie zostaje uzycie "zwyklych" przerwan. Chyba, ze wymiana procesora jest mozliwa.
Może to i nawet lepiej :) Bascom jest dobry tylko na początek, żeby zobaczyć z czym to się je; po kilku (tygo)dniach już tylko C albo ASM.
Wlasnie dlatego korzystam z C/C++ :)

Tom27
-
Posty: 62
Rejestracja: 28 sie 2005, 12:07

Post autor: Tom27 » 14 paź 2008, 15:44

Też tak uważam, dlatego „uparłem” się na przerwania z precyzyjnego źródła, czyli timer-a. Cały projekt jest jeszcze w strzępach tak, więc wymiana na inny procesor jest jak najbardziej możliwa a wręcz konieczna, ponieważ już udało mi się dzielnie zapchać całe 2 KB w Atiny2313. Dodatkowo chciałem jeszcze termometr z 1-Wire i przetwornik A/D sterowany po I2C. Tak sobie myślę, że, po co mam walczyć z ograniczeniem wielkości kodu i dokładać PCF8591 (za 9 zł) skoro dokładnie w tej samej cenie, co Atiny2313 mam Atmega8 z większym zbiorniczkiem i wewnętrznym przetwornikiem.
Wracając do mojego problemu to przy wymianie na inny procesor mogę faktycznie zastosować inny tok myślenia, ale chciałem się dowiedzieć, co źle zrobiłem w przedstawionym programie skoro na LED-ach działa a na LCD się późni. Tak dla nauki i na przyszłość.
Pozdrawiam
Tomek

jotbeage
-
Posty: 4
Rejestracja: 21 lut 2006, 14:53

Post autor: jotbeage » 14 paź 2008, 15:58

Tom27 pisze:ale chciałem się dowiedzieć, co źle zrobiłem w przedstawionym programie skoro na LED-ach działa a na LCD się późni
Od razu powiem: Twoj program przejrzalem pobieznie. Wydaje mi sie jednak, ze to przerwanie zglaszane jest za czesto, bo na obsluge programu i LCD masz 4 ms (jezeli dobrze rozumiem). Co gorsza za kazdym razem zerujesz wyswietlacz, a to zajmuje duzo czasu. Zmien program tak, zeby przerwania zglaszaly sie co np 100ms i wtedy sprobuj.
Krotko: jezeli obslugiwane jest przerwanie, to kolejne zglosisie dopiero po zakonczeniu obslugi biezacego (chyba, ze Bascom rozwiazuje to inaczej).
Sprawdz to co mowie dla ciekawosci :)

K_o_n_r_a_d
Użytkownik
Posty: 123
Rejestracja: 29 lip 2005, 10:21
Lokalizacja: Lublin

Post autor: K_o_n_r_a_d » 14 paź 2008, 21:55

Przepraszam jeśli kogoś obrażę, ale jak widzę wypowiedzi, że Bascom nie nadaje się do profesjonalnych zastosowań i jest tylko dla początkujących to nie mogę nie zwrócić na to uwagi. Sam nie jestem wielkim zwolennikiem Bascoma, ale znam go moim zdaniem dobrze, znam tez dobrze C i asemblera kilku uK, w Bascomie zrobiłem kilka profesjonalnych projektów i wiem, że jak się pozna Bascoma to można w nim pisać programy prawie lub równie wydajne jak w C.

Program przejrzałem i widzę tu kilka błędów początkującego.
Obliczyłeś, że przy prekalerze=64 musisz wpisać do rejestru licznika T0 wartość 6 aby wyszło =4ms. niby dobrze, ale... bez znaczenia jakiego źródła sygnału zegarowego użyłeś zawsze jakiś błąd będzie, przy generatorze RC wbudowanym większy, przy generatorze z rezonatorem kwarcowym mniejszy itp.
Dodatkowo samo wejście w obsługę przerwania i dojście do instrukcji: Timer0 = 6 też zajmuje X czasu (ile dokładnie to trzeba byłoby policzyć instrukcje asemblera w skompilowanym już kodzie.
Taki zegar wymaga kalibracji, a przy preskalerze 64 mamy precyzję kalibracji i tak tylko z dokładnością do 64 taktów. Można zrobić zliczanie licznika T0 tak jakby dwustopniowe z różnymi ustawieniami preskalera i w ten sposób precyzyjnie kalibrować, albo lepiej wykorzystać licznik T1, 16bitowy z preskalerem =1.

Jeszcze jednym błędem, który mnie szczególnie tutaj razi jest obsługa wyświetlacza w przerwaniu i kompletnie niepotrzebne wywoływanie dodatkowych podprogramów w przerwaniu! Przerwanie powinno trwać możliwiw najkrócej (tylko zliczanie czasu) a cała obsługa wyświetlacza z obliczeniami w pętli głównej programu całkowicie poza przerwaniami. W przerwaniu tylko jakąś zmienną ustawiać, która będzie informowała, że należy zaktualizować wyświetlacz. Dodatkowo nie czyścić wyświetlacza a tylko nadpisywać zawartość. To też usunie efekt migania wyświetlacza.

Nie chce mi się liczyć czasów, ale bardzo prawdopodobne jest, że program w szczególnych przypadkach po prostu nie wyrabia się w tych 4ms pomiędzy przerwaniami z czyszczeniem i ustawianiem wyświetlacza i to daje dodatkowe opóźnienia przez pominięcie przerwań.

Tom27
-
Posty: 62
Rejestracja: 28 sie 2005, 12:07

Post autor: Tom27 » 15 paź 2008, 17:36

No i o to mi chodziło! Bardzo dziękuję jotbeage jak i K_o_n_r_a_d za taką właśnie odpowiedź. Tak jak napisałem jestem początkujący i robię wszystko jak przysłowiowy koń pod górę, gdy można prościej. W sieci można znaleźć wiele programów zegarów a i w książkach, z których korzystam też się znajdą gotowe, które działają. Mi zależało na wytknięciu błędów, które popełniłem w przedstawionym kodzie i/lub wskazanie właściwej drogi. Powoli zaczynam dochodzić do takich samych wniosków, jakie przedstawiliście w swoich wypowiedziach. Próbuję zmienić częstotliwość przerwań, zmieniam też źródło na timer1 i staram się analizować wyniki i wysuwać wnioski. Niestety z moim doświadczeniem każda zmiana wymaga wielu przemyśleń. Cóż nie ma chwały bez poświęcenia.
Dziękuję jeszcze raz za wszelką pomoc.

ODPOWIEDZ