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.

[Bascom][AVR] wyświetlacz 7 seg LED

parklinson 14 Wrz 2010 20:17 3299 4
  • #1 14 Wrz 2010 20:17
    parklinson
    Poziom 15  

    Cześć

    Chciałem prosić kogoś o wskazówkę jak poradzić sobie z problemem wyświetlania wartości "Wartosc2" poniższego kodu.

    Mój problem polega na tym że w momencie naciśnięcia przycisku ( w programie to Up, Dwn ) gdy na wyświetlaczach jest np 1.1 wyświetlacze "resetują" się i wskazują wartość 00 po zwolnieniu przycisku wyświetlona zostaje poprawnie kolejna wartość zliczona. W jaki sposób wyeliminować to znikanie poprawnej wartości w chwili trzymania przycisku?

    Z góry dziękuję Michał

    Code:
    'Program sterujący 2 wyświetlaczami 7-segmentowym LED
    
    'Napisany by parklinson
    'Wykorzystano fragmenty z książki "Programowanie mikrokontrolerów AVR w języku BASCOM".


    $regfile = "m16def.dat"                                     'informuje kompilator o pliku
          'dyrektyw mikrokontrolera
    $crystal = 16000000                                         'informuje kompilator
          'o częstotliwości oscylatora
          'taktującego mikrokontroler
    Config Portc = Output
    Config Pinb.0 = Output                                      '
    Config Pinb.1 = Output
    Config Pinb.2 = Input
    Config Pinb.3 = Input
    Config Timer0 = Timer , Prescale = 256                      'konfiguracja Timer0 jako
            'timer z podziałem
            'preskalera przez 256
    On Timer0 Mult_wysw                                         'przerwanie od przepełnienia
            'Timer0‚ skok nastąpi do
            'podprogramu Mult_wysw
    Dim A As Byte , B As Byte                                   'definicje zmiennych A, B,
            'przechowywana wartość do
            'wyświetlenia
    Dim Nr_wysw As Byte                                         'zmienna określająca numer
            'zapalonego wyświetlacza
    Dim Kr1 As Bit , Kr2 As Bit                                 'zmienne bitowe sterujące
                                                                   'kropkami




    W1 Alias Portb.0                                            'przypisanie linii PB0 nazwy W1
    W2 Alias Portb.1                                            'przypisanie linii PB1 nazwy W2

    Declare Sub Pobr_znaku(cyfra As Byte)                       'deklaracja procedury
            'pobierającej kod cyfry do
            'wyświetlenia z tablicy
    Declare Sub Liczba
    Dim Wartosc2 As Byte
    Dim Wart As Byte
    Dim Wartosc As Byte                                         

    Up Alias Pinb.2
    Dwn Alias Pinb.3

    Set Portb.2
    Set Portb.3
    A = 0
    B = 0

    Kropka Alias Portc.7                                        'przypisanie bitowi 7 rejestru
          'PORTD nazwy Kropka

    Enable Interrupts                                           'odblokowanie globalnego
            'systemu przerwań
    Enable Timer0                                               'odblokowanie przerwania od
            'przepełnienia Timer0
    Load Timer0 , 150                                           'załadowanie do licznika
            'wartości początkowej
    Do                                                          'początek pętli nieskończonej

      If Up = 0 Then
       Waitms 25
       If Up = 0 Then

       Wartosc = Wartosc + 10

       Call Liczba
       Waitms 150
      End If
     End If

      If Wartosc > 0 Then

       If Dwn = 0 Then
          Waitms 25

          If Dwn = 0 Then

             Wartosc = Wartosc - 1

             Call Liczba
             Waitms 150
             Else
             Wartosc = 0
          End If
       End If
      End If

     Loop                                                       'koniec pętli nieskończonej
    End                                                         'koniec programu

    Sub Liczba

      If Wartosc > 99 Then
             Wartosc2 = Wartosc \ 10
          Else
             Wartosc2 = Wartosc
      End If

     Wart = Wartosc2
     Wart = Makebcd(wartosc2)                                   'zamiana wartości zmiennej
            'Wart na wartość zapisaną
            'w kodzie BCD

     B = Wart And &B00001111                                    'wyodrębnienie (przez
            'maskowanie) i wyświetlenie
            'pierwszej cyfry zapisanej
            'w zmiennej Wart (cyfra 5)
     Shift Wart , Right , 4                                     'przesunięcie wartości
            'drugiej cyfry w zmiennej
            'Wart na pozycje czterech
            'mniej znaczących bitów
     A = Wart                                                   'wyświetlenie na
            'wyświetlaczu 2 cyfry 3

    End Sub

    Sub Pobr_znaku(cyfra As Byte)                               'definicja procedury


            'Pobr_znaku
     If Cyfra < 10 Then                                         'jeżeli wartość otrzymanej do
                                                                       'wyświetlenia cyfry < od 10,
      Portc = Lookup(cyfra , Kody7seg )                         'to wpisanie do portu D
                                                                             'wartość kodu z tablicy
            'stałych Kody7seg
     Else                                                       'w przeciwnym razie
      Portc = 0                                                 'wpisanie do portu D wartości
            '0 która wygasza wyświetlacz
     'Reset Kropka

     End If                                                      'koniec warunku If...Then
    End Sub                                                     'koniec procedury


    Mult_wysw:                                                  'podprogramu obsługi
                                                                      'przerwania od przepełnienia
                                                                      'Timer0 w którym odbywa się
                                                                      'multipleksowanie
    Load Timer0 , 150                                           'załadowanie do licznika

                                                                   'wartości początkowej

     Set W1                                                     'wygaszenie wyświetlacza 1
     Set W2                                                     'wygaszenie wyświetlacza 2

     Select Case Nr_wysw                                        'w zależności od wartości
            'Nr_wysw, wykonaj:
      Case 0:                                                   'gdy Nr_wysw = 0, to
       Call Pobr_znaku(a)                                       'wywołanie procedury
                                                               'pobierającej z tablicy kod
                                                               'znaku dla wartości A
       If Wartosc > 10 Then
        Kropka = 0
          If Wartosc > 99 Then
             Set Kropka
          End If
       End If

       Reset W1                                                 'włączenie wyświetlacza 1
      Case 1:                                                   'gdy Nr_wysw = 1, to
       Call Pobr_znaku(b)                                       'wywołanie procedury
                                                                 'pobierającej z tablicy kod
                                                                 'znaku dla wartości B
       Reset W2                                                 'włączenie wyświetlacza 2

     End Select                                                 'koniec instrukcji wyboru
     Incr Nr_wysw                                               'zwiększenie o jeden wartości
            'Nr_wysw
     If Nr_wysw = 2 Then                               'jeśli wartość Nr_wysw
            'osiągnie 2, to
      Nr_wysw = 0                                         'zeruj wartość Nr_wysw
     End If
    Return                                                    'powrót z podprogramu



    Kody7seg:                                               'tablica stałych Kody7seg
                                                                'przechowująca kody wyświetlanych
                                                                'cyfr
                                                                'Kody cyfr

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

    0 4
  • #2 17 Wrz 2010 00:25
    mirekk36
    Poziom 42  

    Trzeba umieć zadawać pytania panie kolego a nie wkleić kobylasty jakiś tam kod i zapytać się o jakiś tam szczegół. Żeby odpowiedzieć to trzeba teraz próbować przeanalizować co poeta miał na myśli pisząc takie "cóś".

    I to to jeszcze jak szybko odpowiedzi oczekujesz?

    Albo sprecyzuj pytanie sam analizując co nieco napisany bądź co bądź przez ciebie kod i spróbuj dość w której części może być błąd żeby dopytać o jakiś szczegół którego nie rozumiesz.

    albo poczekaj może się zdarzy ktoś chętny na analizatora ;)

    Ja mogę tylko podpowiedzieć, że nie pisałeś tego kodu, tylko przepisywałeś z książki jakieś fragmenty i to bez zrozumienia dogłębnego o co w tym chodzi, próbując jednocześnie jakieś swoje modyfikacje robić. Nie tędy droga. Spróbuj najpierw sam bez przepisywania z książki zrobić multipleksowanie od podstaw - wtedy duuuużo ci się od razu rozjaśni a i pytania inne będziesz zadawał. Ot po prostu wszystko po kolei proponuję robić.

    0
  • #3 17 Wrz 2010 01:08
    Ilmarinen
    Poziom 13  

    ojejku strasznie zamotany ten kod. Pierwsza poprawka to niepotrzebnie zdublowany warunek

    Code:
    If Up = 0 Then 
    
       Waitms 25
       [b]If Up = 0 Then [/b]

       Wartosc = Wartosc + 10

       Call Liczba
       Waitms 150
     [b] End If [/b]
     End If


    jeżeli warunek pierwszy jest spełniony to automatycznie zagnieżdżony w nim warunek musi być spełniony. Chyba ze tu chodzi o odkłucanie przycisków to jest to jakieś rozwiązanie, chociaż w tym przypadku bezsensowne. Procedura waitms zatrzymuje pracę procesora na określony czas. W tym wypadku lepsza była by procedura debounce skutki uboczne sa takie same, kod staje sie bardziej przejrzysty, i nie musimy wymyślać kola od początku.

    0
  • #4 17 Wrz 2010 07:28
    parklinson
    Poziom 15  

    mirekk36 napisał:
    Trzeba umieć zadawać pytania panie kolego a nie wkleić kobylasty jakiś tam kod i zapytać się o jakiś tam szczegół. Żeby odpowiedzieć to trzeba teraz próbować przeanalizować co poeta miał na myśli pisząc takie "cóś".

    I to to jeszcze jak szybko odpowiedzi oczekujesz?

    Albo sprecyzuj pytanie sam analizując co nieco napisany bądź co bądź przez ciebie kod i spróbuj dość w której części może być błąd żeby dopytać o jakiś szczegół którego nie rozumiesz.

    albo poczekaj może się zdarzy ktoś chętny na analizatora ;)

    Ja mogę tylko podpowiedzieć, że nie pisałeś tego kodu, tylko przepisywałeś z książki jakieś fragmenty i to bez zrozumienia dogłębnego o co w tym chodzi, próbując jednocześnie jakieś swoje modyfikacje robić. Nie tędy droga. Spróbuj najpierw sam bez przepisywania z książki zrobić multipleksowanie od podstaw - wtedy duuuużo ci się od razu rozjaśni a i pytania inne będziesz zadawał. Ot po prostu wszystko po kolei proponuję robić.


    Twoim zdaniem który fragment kodu miałem zamieścić skoro nie wiem gdzie tkwi błąd ? Zasadę działania multiplexowania rozumiem a w przepisywaniu czegoś z książki nie widzę nic złego (pod warunkiem że nie próbuje przypisać sobie do tego autorstwa). Po co odkrywać Amerykę na nowo skoro można skorzystać z gotowego rozwiązania. Większość przykładów multiplexowania zamieszczona na elektrodzie jest właśnie z tej książki.
    Mimo wszystko dzięki za zainteresowanie

    Ilmarinen napisał:
    ojejku strasznie zamotany ten kod. Pierwsza poprawka to niepotrzebnie zdublowany warunek
    Code:
    If Up = 0 Then 
    
       Waitms 25
       [b]If Up = 0 Then [/b]

       Wartosc = Wartosc + 10

       Call Liczba
       Waitms 150
     [b] End If [/b]
     End If


    Jeżeli warunek pierwszy jest spełniony to automatycznie zagnieżdżony w nim warunek musi być spełniony. Chyba ze tu chodzi o odkłucanie przycisków to jest to jakieś rozwiązanie, chociaż w tym przypadku bezsensowne. Procedura waitms zatrzymuje pracę procesora na określony czas. W tym wypadku lepsza była by procedura debounce skutki uboczne sa takie same, kod staje sie bardziej przejrzysty, i nie musimy wymyślać kola od początku.


    Warunek na początku ma służyć zabezpieczeniu przed drganiem styków, Przyznaję jednak racje ze debounce lepiej wygląda i kod jest bardziej przejrzysty jednak robi to samo co moja instrukcja warunkowa więc w tym błędu nie ma.

    0
  • #5 17 Wrz 2010 10:26
    cepelia
    Poziom 20  

    Zamotane do granic i bez sensu. Chodzi ci o to żeby po naciśnięciu przycisku odbywało się dodawanie wartości albo odejmowanie.
    Kolega napisał ci żeby poznać dobrze zasadę multipleksowania i to bardzo dobra rada. Ja z reguły nie motam tego tak tylko staram się to robić po kolei. Zobacz na ten kod :

    Code:

    'Opoznienie
    Ms = 6

    ' PC - segmenty
    Led7 Alias Portb

    ' PB0...3 - katody
    Ds4 Alias Portc.0
    Ds3 Alias Portc.1
    Ds2 Alias Portc.2
    Ds1 Alias Portc.3


    Do

      ' display DS1
      Reset Ds4 : Reset Ds3 : Reset Ds2 : Set Ds1
      Led7 = Lookup(poz_1 , Led7s_table)
      Waitms Ms
      ' display DS2
      Reset Ds4 : Reset Ds3 : Set Ds2 : Reset Ds1
      Led7 = Lookup(poz_2 , Led7s_table)
      Waitms Ms
      ' display DS3
      Reset Ds4 : Set Ds3 : Reset Ds2 : Reset Ds1
      Led7 = Lookup(poz_3 , Led7s_table)
      Waitms Ms
      ' display DS4
      Set Ds4 : Reset Ds3 : Reset Ds2 : Reset Ds1
      Led7 = Lookup(poz_4 , Led7s_table)
      Waitms Ms
    Loop


    jak widzisz multipleksowanie odbywa się tutaj w pętli głównej programu bo jest na tyle czasu (właściwie to baaardzo dużo). Natomiast licznik robisz na przerwaniu i po wszystkim...

    Code:

    On Int0 Licz                                                ' Nosave
    Enable Int0
    Config Int0 = Falling

    Config Timer1 = Timer , Prescale = 1
    On Timer1 Licznik
    Enable Timer1

    Enable Interrupts

    Licz:
    incr a ' zmienna licznika
    Return


    potem tylko rozdzielasz liczbe na cyfry i po wszystkim, tylko matematyka.
    Ten kod do obsługi 7seg możesz równie dobrze wcisnąć w przerwanie i wywoływać go kiedy chcesz (tylko wycinasz z niego opóźnienie, ja zwykle ustawiam czas tak aby katody świeciły 4ms, świeci jasno i wyraźnie). A jeszcze jedno jak widać to kod obsługuje 4 wyświetlacze ale wystarczy skasować dwie ostatnie pozycje i masz multiplex na 2 cyfry.

    [Bascom][AVR] wyświetlacz 7 seg LED [Bascom][AVR] wyświetlacz 7 seg LED

    0