BASCOM + Atmega 8 = problem w obsłudze wyświetlacza LED

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
Artizzz
-
Posty: 41
Rejestracja: 03 mar 2007, 11:59
Lokalizacja: xx

BASCOM + Atmega 8 = problem w obsłudze wyświetlacza LED

Post autor: Artizzz » 04 lis 2009, 15:06

Witam!
Jestem bardzo początkujący w programowaniu. Natrafiłem na następujący problem i nijak nie mogę go rozgryźć:/

Programik ma za zadanie wyświetlić na podwójnym wyświetlaczu LED (wyświetlanie multipleksowane) wartość zmiennej. Ale od początku: W pętli głównej chcę przypisywać zmiennej A jakieś wartości (dodawać i odejmować przez naciśnięcie odpowiedniego przycisku). Samo wyświetlanie ma się realizować w przerwaniu od Timera0. Programik niby działa ale....

Załóżmy że wyświetla się wartość 17 (jedynka na pierwszym wyświetlaczu od zmiennej B wyświetla się zawsze, mogę tylko zmieniać drugą liczbę od zmiennej A). Przy naciśnięciu S1 - dodaj do zmiennej - wyświetlacz pokazuje mi na pół sekundy DWA ZERA, po czym przechodzi do wyświetlenia liczby 18. Analogicznie przy odejmowaniu - przez pół sekundy dwa zera i potem "normalna" wartość 16. Jak obejść ten problem dwóch zer?? Zmniejszenie w odpowiedniej pętli obsłui przycisku opóźnienia z 500 ms nie pomaga.
Próbowałem analizować kod, wg mnie przy naciśnięciu przycisku zeruje się zmienna lokalna "cyfra" w procedurze "pobierz". Dlaczego?

A może ktoś ma inny pomysł na realizację obsługi multipleksowania wyświetlacza LED w tle programu głównego?

Kod: Zaznacz cały

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


'*************** KONFIGURACJE
Config Portd = Output
Config Pinb.0 = Input
Config Pinb.1 = Input
Config Pinb.3 = Output
Config Pinb.4 = Output
Config Timer0 = Timer , Prescale = 256

Set Portb.0
Set Portb.1



'*************** ALIASY
S1 Alias Pinb.0
S2 Alias Pinb.1
W1 Alias Portb.3
W2 Alias Portb.4



'*************** ZMIENNE
Dim A As Byte                                               'przechowuje wartosc do wyswietlenia na 1 wyswietlaczu
Dim B As Byte                                               'przechowuje wartosc do wyswietlenia na 2 wyswietlaczu
Dim Nrwys As Byte                                           'numer wyswietlacza do wlaczenia
Dim Wart As Byte                                            'wartosc do wyswietlenia
Dim Wartbcd As Byte                                         'wartosc do wyswietlenia w BCD



'*************** DEKLARACJE
Declare Sub Pobierz(byval Cyfra As Byte)



'*************** PROGRAM

On Timer0 Multi

Enable Interrupts
Enable Timer0


Load Timer0 = 255


Do

   If S1 = 0 Then                                           ' jesli nacisniety S1
      Waitms 25                                             ' eliminacja drgan

         If S1 = 0 Then
            Incr Wart                                       ' dodaj 1 do zmiennej Wart
            Waitms 500                                      ' czekaj 500 ms
         End If

         If Wart = 9 Then                                   ' jesli Wart = 9
            Wart = 0                                        ' to zeruj zmienna Wart
         End If

   End If



  If S2 = 0 Then                                            ' jesli nacisniety S2
      Waitms 25                                             ' eliminacja drgan
         If S2 = 0 Then


            Decr Wart                                       ' odejmij 1 od zmiennej Wart
            Waitms 500                                      ' czekaj 500 ms
         End If

         If Wart = 0 Then                                   ' jesli Wart = 0
            Wart = 9                                        ' to przypisz jej 9
         End If

   End If

   A = Wart
   B = 1                                                    ' przypisanie zmiennym A i B wartosci do wyswietlenia


Loop

End



Multi:                                                      ' podprogram obslugi przerwania

   Load Timer0 = 255

      Set W1
      Set W2                                                'wygaszenie wyswietlaczy

      Select Case Nrwys

         Case 0:

            Call Pobierz(b)                                 'wywolanie procedury pobierajacej ze zmiennej A
            Reset W1                                        'wlaczenie anody W2 (prawy)

         Case 1:

            Call Pobierz(a)                                 'wywolanie procedury pobierajacej ze zmiennej B
            Reset W2                                        'wlaczenie anody W1 (lewy)

      End Select

      Incr Nrwys

   If Nrwys = 2 Then
      Nrwys = 0
   End If

Return





Sub Pobierz(byval Cyfra As Byte)                            'procedura pobierajaca i wyswietlajaca wartosc znaku

   If Cyfra < 10 Then                                       ' jesli pobierana cyfra jest mniejsza niz 10

      Portd = Lookup(cyfra , Kody7seg)                      ' to pobierz wartosc PortuD z tablicy i wyswietl go

   Else

      Portd = 0                                             'wygaszenie wyswietlacza

   End If

End Sub




Kody7seg:
Data &B00111111 , &B00000110 , &B01011011 , &B01001111 , &B01100110 ,       ' 0, 1, 2, 3, 4
Data &B01101101 , &B01111101 , &B00000111 , &B01111111 , &B01101111       ' 5, 6, 7, 8, 9

Awatar użytkownika
Wesker
-
Posty: 27
Rejestracja: 01 lut 2006, 10:33
Lokalizacja: Leżajsk

Post autor: Wesker » 04 lis 2009, 17:54

Składnia polecenia Load powinna być następująca

Kod: Zaznacz cały

 Load Timer0, 255
gdzie 255 to liczba impulsów po których zliczeniu nastąpi przepełnienie. Dla 8-bitowego timer0 można z niej zrezygnować. Warunki przy zmianie wartości Wart są nie do końca przemyślane. Przykładowo zwiększasz wartość Wart ponad 9 co daje 0, a zmniejszając 0 Wart będzie równe 255. Może by zmienić tak by nie "przekręcać tej wartości" ale zatrzymać. Jeśli Wart=10 to przypisać 9, a jeśli równe 255 to przypisać 0.

Artizzz
-
Posty: 41
Rejestracja: 03 mar 2007, 11:59
Lokalizacja: xx

Post autor: Artizzz » 05 lis 2009, 16:57

Wesker, zmiejszając Wart do 0 zostaje jej przypisana wartość 9 - także nieśmiało twierdzę, że pod tym względem program jest "idioto-odporny" ;)

Dla wszystkich zainteresowanych - sam doszedłem do rozwiązania problemu. W programie wykorzystuję procedurę, a ta jak się dowiedziałem, wymaga zadeklarowania rozmiaru ramki i stosów. uzupełniłem program o następujące dyrektywy:

$swstack = 4 ' 4 bajty stosu programowego - gdyż procedurze jest przekazywany 1 parametr i posiada ona 1 zmienną lokalną "cyfra", a każda z nich zajmuje 2 bajty;

$hwstack = 2 ' wywołuję 1 procedurę, co wykorzystuje 2 bajty pamięci;

$framesize = 1 ' jedna zmienna lokalna "cyfra" typu Byte zajmuje 1 bajt.


Może komuś z potomnych to się przyda ;)

Awatar użytkownika
Wesker
-
Posty: 27
Rejestracja: 01 lut 2006, 10:33
Lokalizacja: Leżajsk

Post autor: Wesker » 05 lis 2009, 17:35

Tak zmniejszając do 0 z 1 rzeczywiście zostanie wpisana wartość 9, ale jeśli Wart=0 po zwiększeniu do 9 to co będzie?
Mam jeszcze pytanie jakie były domyślne wartości w opcjach kompilatora:
$HWSTACK
$SWSTACK
$FRAMESIZE
Oczywiście lepiej jest wszystko pisać w kodzie wtedy inni korzystający z programu nie maja z nim problemu.

Artizzz
-
Posty: 41
Rejestracja: 03 mar 2007, 11:59
Lokalizacja: xx

Post autor: Artizzz » 05 lis 2009, 17:49

Albo jestem zakręcony dzisiaj albo nie kumam o co Ci chodzi.. :p wprowadziłem nieco zmian do kodu, min zerowanie zmiennych gdy wyświetlacz pokazuje 99 oraz przypisanie zmiennym 99 gdy wynoszą one 0 i próbuję zmniejszyć ich wartość.

Hmmm z tymi wartościami domyślnymi to mnie zmartwiłeś nieco, domyślnie w opcjach wynosiły one odpowiednio:
$HWSTACK = 32
$SWSTACK = 8
$FRAMESIZE = 24.

W każdym razie po dodaniu odpowiednich dyrektyw do kodu, zaczął on działać prawidłowo.

Awatar użytkownika
kayron
Użytkownik
Posty: 2088
Rejestracja: 21 wrz 2008, 12:53
Lokalizacja: Poland
Kontakt:

Post autor: kayron » 05 lis 2009, 18:52

Hm.. :?: rzadko kiedy zmienia się ustawienia $HWstack itd. tylko w programach które korzystają intensywnie z stosu, i potrzebują dużego bufora ramki, lub trzeba wyściubić parę bajtów z RAM bo brakuje. Ale raczej multipleksowanie 4 LEDów tego nie wymaga. Ustawienia domyślne BASCOMA wystarczają w 99% przypadków. Natomiast pożerają aż 64 Bajty RAMu, ale to nabiera znaczenia w przypadku małych procesorów jak AT90S2313 czy ATTIny, gdzie RAMu jest faktycznie mało i czasami zaczyna brakować na zmienne.

Artizzz
-
Posty: 41
Rejestracja: 03 mar 2007, 11:59
Lokalizacja: xx

Post autor: Artizzz » 05 lis 2009, 21:19

Kayron, dopiero zaczynam wgryzać się w temat programowania. O zmianie wartości ramki i stosów wyczytałem z książki Marcina Wiązani "Programowanie mk AVR w języku BASCOM", gdzie przy opisie opcji kompilatora wspomniano o tym (pokazano również jak obliczyć wymagane wartości).

ODPOWIEDZ