logo elektroda
logo elektroda
X
logo elektroda
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

[ATMega8][Bascom]Symulator układu 4017

fistach1992 01 Kwi 2010 18:44 1972 16
  • #1 7908100
    fistach1992
    Poziom 11  
    Witam chciałbym prosić o pomoc.
    Zacznę od tego ,że jestem początkujący, uczę się programować w bascom-avr
    i chciałbym napisać program, żeby działał podobnie do układu 4017, tylko z ulepszeniami.

    Po naciśnięciu przycisku, zapala się kolejna dioda, a po naciśnięciu drugiego, zapala się poprzednia.

    Mój program wygląda tak:

    $regfile = "m8def.dat"
    $crystal = 1000000
    
    
    Config Portc.0 = Input
    Config Portc.1 = Input
    Config Portd.0 = Output
    Config Portd.1 = Output
    Config Portd.2 = Output
    
    
    
    Dim X As Byte
    Dim Z As Byte
    
    
    Portc.0 = 1
    Portc.1 = 1
    Portd.0 = 1
    Portd.1 = 1
    Portd.2 = 1
    
    X = Z
    
    Do
    
    If Pinc.0 = 0 Then Z = X + 1
    
    If Pinc.1 = 0 Then Z = X - 1
    
    
    
    If Z = 1 Then
    Portd.0 = 0
    Else
    Portd.0 = 1
    End If
    
    If Z = 2 Then
    Portd.1 = 0
    Else
    Portd.1 = 1
    End If
    
    If Z = 3 Then
    Portd.2 = 0
    Else
    Portd.2 = 1
    End If
    
    
     Loop
    
     End


    Jest to napisane na 3 diody ale w razie potrzeby, dopisałbym na więcej.

    PROBLEM POLEGA NA TYM, ŻE TEN PROGRAM NIE DZIAŁA POPRAWNIE!!

    Prosił bym o pomoc co jest nie tak gdyż siedzę nad tym już kolejny dzień i próbowałem na różne sposoby.

    Poprawiłem tytuł i treść wiadomości.
    Regulamin p.15
    [zumek]
  • #2 7908210
    H0miczek
    Poziom 20  
    Oczywiście, że nie dziala i dzialac nie bedzie. przeciez jak wciskasz przycisk to trwa to (wcisniecie) prawdopodownie troche dluzej niz jeden obrot petli glownej, nie? zgadnij, ile razy zwiekszy sie/zmniejszy iks przy jednym wcisnieciu?
    najprostszym ze znanych sposobow jest chyba flaga sprawdzana jednoczesnie z obecnym warunkiem (Pinc.x = 0) i gaszona zaraz po tym, a ustawiana jak bedzie na pinie jeden (1).
  • #3 7908353
    fistach1992
    Poziom 11  
    Wiedz co mam zrobić (jestem trochę zielony bo dopiero zaczynam programować ) bo tak w zasadzie po podłączeniu to po naciśnięciu zapala sie dioda a po naciśnięciu drugiego gaśnie ale tylko ta z portd.0
  • #4 7908928
    tadzik85
    Poziom 38  
    W pętli czekaj aż przycisk zostanie naciśnięty, zrób co należy dla odpowiedniego przycisku po czym czekaj aż przycisk zostanie zwolniony. Unikniesz w ten sposób wielokrotnych operacji przy trzymaniu wciśniętego przycisku. Albo po wykonaniu poczekaj jakieś 0,5s wówczas diody zmieniać będą się co taki czas.
  • #5 7909456
    H0miczek
    Poziom 20  
    nie, nie czekac... po co?
    zrob sobie flage. albo dwie bo masz dwa przyciski.
    tam gdzie sprawdzasz czy pin jest zerem, sprawdzaj dodatkowo czy dana flaga jest ustawiona. jesli tak to rob co tam robisz i zeruj flage.
    dopisz gdziekolwiek if'a ktory bedzie sprawdzal czy pin jest jedynka. jesli tak to ustawiasz tą flage.
    i gotowe..
  • #6 7909470
    tadzik85
    Poziom 38  
    Tak tez można lecz kolega ma nikłe pojęcie więc tak zrozumiałby lepiej działanie procesora, poza tym jego program nie robi nic poza tym, więc czekanie nie zaszkodzi.
  • #7 7909518
    H0miczek
    Poziom 20  
    niech sie nauczy od razu pisac dobrze a nie polsrodkami... czekanie nie jest eleganckie ani praktyczne. no ale kolega sam wybierze jak napisac :)
  • #8 7909524
    tadzik85
    Poziom 38  
    Przynajmniej zdałby sobie sprawę z faktu z dla procesora 0,5 s to WIECZNOŚĆ prawie że.
  • #9 7909586
    grysek
    Poziom 19  
    Pomijam juz fakt że jeśli program ma działać jak 4017 czyli rejestr przesuwny to lepiej zastosować instrukcję ROTATE zamiast pisać tyle IF'ów :P Lub chociaz mnożyć zawartość rejestu PORT przez 2.
  • #10 7909592
    fistach1992
    Poziom 11  
    Dzięki wszystkim za pomoc i prosił bym o wytłumaczenie jak te flagi zrobić itd bo mam książkę do bascom'a i w niej tego niema a w necie konkretnego wytłumaczenia też niema. Fajnie by było jakby ktoś mi wstawił to w program i wytłumaczył na tym przykładzie bo najlepiej się uczyć na przykładach gdyż jak samą teorie przeczytam to mi średnio to wychodzi a jak przeanalizuje program to w miarę pojmuję.

    podziałałem trochę i napisałem tak:

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


    Config Portc.0 = Input
    Config Portc.1 = Input
    Config Portd.0 = Output
    Config Portd.1 = Output
    Config Portd.2 = Output



    Dim X As Byte
    Dim Z As Byte


    Portc.0 = 1
    Portc.1 = 1
    Portd.0 = 1
    Portd.1 = 1
    Portd.2 = 1



    Do



    If Pinc.0 = 0 Then Z = X + 1


    If Pinc.1 = 0 Then Z = X - 1

    X = Z


    If Z = 1 Then
    Portd.0 = 0
    Else
    Portd.0 = 1


    If Z = 2 Then
    Portd.1 = 0
    Else
    Portd.1 = 1

    If Z = 3 Then
    Portd.2 = 0
    Else
    Portd.2 = 1


    End If
    End If
    End If

    Loop

    End

    i jest taki efekt że po naciśnięciu przycisku zapala sie kolejna a poprzednia gaśnie ale jak naciskam przycisk który ma ,,cofać '' zaświecanie diod to się cofa ale poprzednie nie gasną.

    jak próbowałem coś z funkcjami debounce albo coś typu


    if...then
    waitms 25
    if...then
    ....
    (wiem że to zatrzymuje program)

    to to co napisałem wyżej przestawało działać.
  • #11 7909620
    tadzik85
    Poziom 38  
    Flaga to nic innego jak zmienna typu bitowego.

    Koledze chodzi o fakt ze przyciśniecie przycisku przy fladze ustawionej na 1 wywołuje jakąś akcję w twoim przypadku zmiana zapalonej diody po czym zerowana jest ta flaga. Flaga uniemożliwi ponowną zmianę diody przy ciągle przyciśniętym przycisku. Zwolnienie przycisku powoduje ustawienie flagi pozwalając na ponowne wywołanie akcji.
    Napisze w pseudokodzie:
    
    do
     if( przycisk1=0 and flaga1 = 0)
    {
       port wyjściowy = port wyjsciowy *2
       flaga1 = 1
    }
    if ( przycisk1=1)
    {
      flaga1= 0
    }
     if( przycisk2=0 and flaga2 = 0)
    {
       port wyjściowy = port wyjsciowy \ 2
       flaga2 = 1
    }
    if ( przycisk2=1)
    {
      flaga2 = 0
    }
    loop
    
  • #12 7909810
    fistach1992
    Poziom 11  
    mam pytanko czemu jeżeli pisze tak jak kolega tłumaczy

    portd.0 = portd.0 * 2

    to kompilator w tym widzi błąd?

    chyba że to źle interpretuje
  • #13 7910106
    fistach1992
    Poziom 11  
    Nie mogłem sobie poradzić z tymi flagami i napisałem to tak :
    $regfile = "m8def.dat"
    $crystal = 1000000


    Config Portc.0 = Input
    Config Portc.1 = Input
    Config Portd.0 = Output
    Config Portd.1 = Output
    Config Portd.2 = Output



    Dim X As Byte
    Dim Z As Byte


    Portc.0 = 1
    Portc.1 = 1
    Portd.0 = 1
    Portd.1 = 1
    Portd.2 = 1


    Do

    Debounce Pinc.0 , 0 , Pr1 , Sub

    Debounce Pinc.1 , 0 , Pr2 , Sub

    If Z = 1 Then
    Portd.0 = 0
    Else
    Portd.0 = 1

    If Z = 2 Then
    Portd.1 = 0
    Else
    Portd.1 = 1

    If Z = 3 Then
    Portd.2 = 0
    Else
    Portd.2 = 1

    End If
    End If
    End If

    Loop

    End

    Pr1:

    Z = X + 1
    X = Z
    Return

    Pr2:
    Z = X - 1
    X = Z
    Return

    program działa w ten sposób:
    po naciśnięciu i przycisku 1 zapala się kolejna i przy trzymaniu nie przesuwa się ,,linijka'' wiedz wszystko działa ok ale jak nacisne przycisk ,,powrotny'' to cofa się ,,linijka'' ale nie gasną poprzednie diody
    co robię źle??
  • Pomocny post
    #14 7910140
    grysek
    Poziom 19  
    fistach1992 napisał:
    mam pytanko czemu jeżeli pisze tak jak kolega tłumaczy

    portd.0 = portd.0 * 2

    to kompilator w tym widzi błąd?

    chyba że to źle interpretuje


    Bo musisz mnożyć zawartość całego portu. Jednego bitu nie możesz pomnożyć przez 2. Poprawne więc będzie portd=portd*2

    A i jeszcze na początku wpisz do portd wartość 1 :P
  • Pomocny post
    #15 7910597
    PiotrPitucha
    Poziom 34  
    Witam
    Strasznie komplikujecie zagadnienie, zasymulować 4017 jest niezmiernie łatwo, oczywiście najpierw musimy zaimplementować obsługę klawiszy a potem zaglądamy do Helpa Bascoma i czytamy o instrukcji ROTATE, ponieważ umozliwia ona przesywanie zarówno w prawo jak i w lewo to jedyne co zostaje to ustalić pozycję LEDa na starcie.
    Ponieważ ROTATE działa nie tylko na 8 bitach to możemy zasymulować dla przykładu dwa połaczone szeregowo 4017.
    Piotr
  • #16 7910775
    fistach1992
    Poziom 11  
    zrobiłem jak mi kolega poradził na funkcji rotate i działa tylko że gasnący punkt się przesuwa a ma się świetlny przesuwać. wiem że mogę odwrócić diody w schemacie ale to ma iść na inne cele wiedz potrzebuje sterowanie masą. javascript:emoticon(':D')


    programik wygląda tak:

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


    Config Portc.0 = Input
    Config Portc.1 = Input
    Config Portd = Output





    Portc.0 = 1
    Portc.1 = 1
    Set Portd



    Do
    Debounce Pinc.0 , 0 , Pr1 , Sub

    Debounce Pinc.1 , 0 , Pr2 , Sub

    Loop
    End
    Pr1:
    Rotate Portd , Left , 1

    Return

    Pr2:

    Rotate Portd , Right , 1

    Return:D:D

    Dodano po 10 [minuty]:

    problem już rozwiązałem wpisując
    Portd = 254 wartość początkowa portu

    dzięki wszystkim za pomoc i jeżeli by komuś się to udało zrobić innym sposobem to prosił bym o pokazanie gdyż wszystko się przyda do edukacji.

    Jeżeli jeszcze ktoś mi napisał jak to połączyć z innym portem żeby była ,,dłuższa linijka'' oraz ciekawi minie jak zrobić żeby przy świecącym porcie ostatnim nie zapalał się pierwszy tylko został cały czas chyba że się naciśnie przycisk cofający javascript:emoticon(':D')javascript:emoticon(':idea:')
  • #17 7912048
    PiotrPitucha
    Poziom 34  
    Witam
    Aby nie wyjechać zbyt daleko musisz sprawdzać warunek ile razy została wykonana funkcja rotate.
    Co do drugiego to możesz utworzyć zmienną typu WORD i ją potraktować poleceniem ROTATE, teraz tniesz zmienną na połowę, jedną część wysyłasz na jeden port a drugą na drugi, jest problem z tym że małe Atmele nie maja pełnych niektórych portów, chyba że zrobisz jakieś aliasy do pojedyńczych pinów.
    Co do cięcia WORD na BYTE to chyba najlepiej zamaskować zmienną zerami by wyłuskać młodszy bajt a potem potraktuj zmienną przesunięciem w prawo o 8 miejsc i znowu zamaskuj zerami... będzie starsza część
    Piotr
REKLAMA