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

[atmega32][bascom] 4 przyciski, jedno przerwanie i powerdown

wader_669 19 Gru 2008 14:46 6225 21
REKLAMA
  • #1 5877597
    wader_669
    Poziom 28  
    chcialem zrobic budzenie procesora za pomoca ktoregos z 4 przyciskow.
    schemat jest podobny do tego (tylko tutaj jest wykorzystany attiny2313 ja chce atmega32):
    https://obrazki.elektroda.pl/85_1226413800.jpg

    Przed wejsciem w tryb powerdown chcialem wystawic na przyciski stan niski, wtedy bym mial mozliwosc wychodzenia z powerdown za pomoca przerwania wykonywanego po wykryciu stanu niskiego na int0. Po wyjsciu z trybu powerdown spowrotem sie ustawiaja stany wysokie na przyciski i stan niski na int0 i wtedy moge normalnie badac w petli ktory przycisk jest wcisniety.

    jeszcze do tego mam na timerze2 zegarek i tez nie wiem jak w nim uruchomic przerwanie


    
    Config Clock = Soft , Gosub = Sectic
    Enable Interrupts
    Time$ = "00:00:00"
    
    dim x as byte
    
    Config Pina.4 = Input
    Config Pina.5 = Input
    Config Pina.6 = Input
    Config Pina.7 = Input
    
    S1 Alias Pina.4
    S2 Alias Pina.5
    S3 Alias Pina.6
    S4 Alias Pina.7
    
    Set Porta.4
    Set Porta.5
    Set Porta.6
    set Porta.7
    
    '****** przerwanie *****
    Config Pind.2 = Input
    Reset Portd.2
    Config Int0 = Low Level
    On Int0 Przerwanie
    Disable Int0
    
    
    Do
    If S1 = 0 Then
    
    Elseif S2 = 0 Then
    
    Elseif S3 = 0 Then
    
    Elseif S4 = 0 Then
    
    End If
    
    Enable Int0
    Set Portd.2
    
    Reset Porta.4
    Reset Porta.5
    Reset Porta.6
    Reset Porta.7
    
    Powerdown
    
    Loop
    End
    
    sectic:
    toggle x
    return
    
    
    Przerwanie:
    Disable Int0
    Set Porta.4
    Set Porta.5
    Set Porta.6
    Set Porta.7
    
    Reset Portd.2
    Return 
    
  • REKLAMA
  • #2 5877785
    Konto nie istnieje
    Poziom 1  
  • #3 5877790
    wader_669
    Poziom 28  
    zatrzymuje sie nie da sie go obudzic. Teraz badam jakie stany sa na pinach.
  • Pomocny post
    #4 5877794
    mirekk36
    Poziom 42  
    Witam,

    w dobrym kierunku idziesz, ale to ci nie zadziała bo jak? skoro na początku programu tylko raz ustawiasz piny klawiszy jako wejścia oraz pin przerwania INT0 też jako wejście. Więc co ma tutaj wymuszać stan niski na wejściu INT0? nic!.

    Aby ten sposób zadziałał - musisz jeszcze pomyśleć o zmianie kierunków portów wtedy gdy trzeba.

    Generalnie założenie masz takie, że przerwanie INT0 ma służyć tylko do wybudzenia procka tak? jeśli tak? - to na początku programu przed pętlą główną nie ustawiaj pinu przerwania jako wejście. Tylko jako wyjście - i podaj tam stan niski tak? a piny klawiszy jako wejścia plus podciąganie do VCC

    potem gdy w pętli głównej sprawdzisz już stany przycisków to tak jak masz - aktywujesz przerwanie INT0 ale nie zapomnij dopiero wtedy zmienic kierunku portu tego pinu na wejściowy i podciągnięcie go do VCC , natomiast kierunki pinów klawiszy na wyjściowe (a ich stany na niskie) - a dalej PowerDown - rozumiesz? dzięki temu do linii wejściowej przerwania masz podłączone przyciski i teraz każde wciśnięcie klawisza wybudzi procka.

    Wtedy tak jak masz w swoim przerwaniu blokujesz sobie przerwanie INT0, ale już w nim znowu zmieniasz kierunki portów na odwrotne - takie jakie były podczas inicjalizacji, czyli teraz znowu kierunek pinu INT0 na wyjściowy i stan niski, natomiast kierunki pinów klawiszy na wejściowe i stan wysoki czyli podciągnięcie do VCC - to dosyć istotne jeśli nie stosuje się zewnętrznych rezystorów podciągających.

    wtedy po wybudzeniu - program rozpoczyna się dalej po poleceniu PowerDown czyli tak na prawdę pętla rozpoczyna się ponownie - sprawdza stany klawiszy itd itd itd
  • #5 5877800
    Konto nie istnieje
    Poziom 1  
  • #6 5878081
    wader_669
    Poziom 28  
    do atom1477 mam odliczanie zrobione za pomoca config clock. To ze tak jak ty pokazales tez sie da to wiem, dziwne jest to ze jak samemu zrobisz to wiecej flashu zajmuje niz config clock, po 2 mi pasuje ten gotowy kod w bascomie.

    do mirekk36 dziekuje bardzo jak zwykle mnie uratowales, zaraz postaram sie napisac kod i powiem czy dziala. Myslalem ze nie da sie pozniej zmieniac kierunku pinow, wiedzialem ze np. magistrale i2c i 1wire sa 2 kierunkowe ale myslalem ze tylko one taka opcje posiadaja.

    _____________________________________________________________

    a wiec zmienilem kod i mimo to nadal nie dziala

    
    '** przyciski **
    Config Pina.4 = Input
    Config Pina.5 = Input 
    Config Pina.6 = Input
    Config Pina.7 = Input
    
    S1 Alias Pina.4 
    S2 Alias Pina.5
    S3 Alias Pina.6 
    S4 Alias Pina.7
    
    Set Porta.4
    Set Porta.5
    Set Porta.6
    Set Porta.7
    
    '****** przerwanie *********
    Config Pind.2 = Output
    Portd.2 = 0
    Config Int0 = Low Level
    On Int0 Przerwanie
    Disable Int0
    
    '** clock **
    Config Clock = Soft , Gosub = Sectic
    Enable Interrupts
    Time$ = "00:00:00"
    
    do
    If S1 = 0 Then
    
    Elseif S2 = 0 Then
    
    Elseif S3 = 0 Then
    
    Elseif S4 = 0 Then
    
    End If 
    
    
    Config Pina.4 = Output
    Config Pina.5 = Output
    Config Pina.6 = Output
    Config Pina.7 = Output
    Porta.4 = 0
    Porta.5 = 0
    Porta.6 = 0
    Porta.7 = 0
    
    Config Pind.2 = Input
    Set Portd.2
    
    Enable Int0
    Powerdown
    loop
    end
    
    przerwanie:
    Disable Int0
    Config Pina.4 = Input
    Config Pina.5 = Input
    Config Pina.6 = Input
    Config Pina.7 = Input
    
    Set Porta.4
    Set Porta.5
    Set Porta.6
    Set Porta.7
    
    Config Pind.2 = Output
    Portd.2 = 0
    return
    


    nadal nie chce wyjsc z trybu powerdown
  • REKLAMA
  • #8 5878178
    wader_669
    Poziom 28  
    hehehe nie do tego jest jeszcze reszta kodu, jest on mocno rozbudowany i nie chcialem umieszczac.
    Jest do projektu dodany wyswietlacz. Jak na samym poczatku jak procesor startuje wcisne przycisk to jest ok ale jak dojdzie do trybu powerdown to juz z niego nie wychodzi.

    jak zadales takie pytanie rozumiem, ze w takim razie kod jest ok
  • #9 5878244
    mirekk36
    Poziom 42  
    no tak mi się wydaje, że teraz powinno być ok - ale skoro nie działa to znaczy, że jednak coś nie tak

    hmmm tak zajrzałem sobie do helpa bascoma i widzę, że chyba tu bęedzie kiszeczka z takim rozwiązaniem bo polecenie Config INTx - powoduje automatyczne ustawienie tego pinu jako wejście i nie wiem czy później polecenie Config Pinx.2 = output może w ogóle nie działa???

    A może spróbuj przed wejściem w PowerDown dopiero dać ten cały Config INT ....... , enable INT0 oraz Enable Interrupts

    tylko czy instrukcja Config INTx może działać w RunTime czy jest tylko raz wykonywana w czasie kompilacji - tego nie wiem

    a tamten kod do tego schematu co podałeś pisałem w C

    .... aha jeszcze inaczej można, zamiast uzywać Config INT0 - postaraj się wszędzie gdzie można zadziałać poprzez bezpośrednie ustawianie odpowiednich rejestrów tak jak to się robi w asm. Np dla ustawiania kierunkow portów można zamiast Config Pinx.x = input/output to można użyć:

    Set DDRx.x czy RESET DDRx.x

    tak samo można inicjalizować rejestry od ustawiania przerwań itp - tylko musisz sobie doczytać które to są, jakie, do czego służą i jakie bity przestawiać.

    Wtedy będziesz niezależny od Config INTx
  • #10 5878262
    wader_669
    Poziom 28  
    rozumiem o co ci chodzi. Nie programuje w assamblerze, ale z rejestrami juz sie bawilem, poczytam troche i postaram sie ten problem jakos rozwiazac.
  • REKLAMA
  • #11 5878617
    K_o_n_r_a_d
    Poziom 23  
    1. W takich sytuacjach zawsze próbuję debugować program. Akurat do AVRów nie mam debugera to radzę sobie inaczej. A więc tutaj zacząłbym od sprawdzenia czy na pewno nie działa przerwanie, np. dodając diodę i zapalając ją w przerwaniu lub za poleceniem POWERDOWN dać:
    set dioda
    waitms 100
    reset dioda
    waitms 100

    2. Nie masz nigdzie redukcji drgań styków. Jest taka możliwość, że uK się wybudza, przechodzi przez pętlę, drgania styków powodują, że gdy dochodzi program do sprawdzania przycisków nie są wciśnięte, więc je przeskakuje itd. ale to raczej objawiałoby się tym, że nie zawsze by działło a nie tym, że zawsze nie działa.

    Dodano po 5 [minuty]:

    3. To akurat nie ma wpływu na Twój problem, ale fragment:
    Config Pina.4 = Output
    Config Pina.5 = Output
    Config Pina.6 = Output
    Config Pina.7 = Output
    Porta.4 = 0
    Porta.5 = 0
    Porta.6 = 0
    Porta.7 = 0
    
    Config Pind.2 = Input
    Set Portd.2 
    proponuję zamienić na:
    Config Pind.2 = Input
    Set Portd.2
    
    Config Pina.4 = Output
    Config Pina.5 = Output
    Config Pina.6 = Output
    Config Pina.7 = Output
    Porta.4 = 0
    Porta.5 = 0
    Porta.6 = 0
    Porta.7 = 0
    W ten sposób wyeliminujesz krótkie zwarcie występujące gdy przycisk jest wciśnięty a program dochodzi w to miejsce.
  • #12 5878767
    wader_669
    Poziom 28  
    pisalem ze jest to czesc porgramu. Testuje wszystko na wyswietlaczu, wiec wszystko ladnie jest widoczne :D
  • REKLAMA
  • #13 5878873
    Konto nie istnieje
    Poziom 1  
  • #14 5878941
    wader_669
    Poziom 28  
    hmm no dobra w takim razie obadam motyw z dioda, zeby sie upewnic na 100%
  • #15 5879069
    K_o_n_r_a_d
    Poziom 23  
    Dodatkowo, dla zdiagnozowania gdzie może być problem, proponuję podłączyć dodatkowy przycisk pomiędzy pin przerwania a GND i spróbować tak go obudzić i jeszcze spróbowałbym (tylko na czas testów) tylko raz usypiać. Czyli np. zamiast POWERDOWN dodać takie coś:
    If Xxx = 0 Then
       Xxx = 1
       Powerdown
    End If
    (xxx zmienna typu BYTE lub BIT) w ten sposób wykluczymy sytuację, w której uK jest usypiany chwilę po tym jak jest wybudzany, np. poprzez drgania styków. Nie wiem co jest wewnątrz tych warunków sprawdzających przyciski - stąd ten pomysł.
  • #16 5885598
    wader_669
    Poziom 28  
    
    $regfile = "m32def.dat"
    $crystal = 8000000
    
    Config Pind.5 = Output                                      ' dioda 1
    Config Pind.6 = Output                                      ' dioda2
    
    
    Config Pind.3 = Input                                       ' przycisk int1
    Set Portd.3
    
    Enable Interrupts
    Config Int1 = Low Level
    On Int1 Przerwanie
    
    Config Int0 = Low Level
    On Int0 Przerwanie
    
    Config Pina.7 = Input                                       ' przycisk
    Config Pina.6 = Input                                       ' przycisk
    Config Pind.2 = Output                                      ' przycisk int0
    
    Portd.2 = 0
    Set Porta.7
    Set Porta.6
    
    
    
    Do
    Reset Portd.5
    Reset Portd.6
    
    If Pina.7 = 0 Then
    Waitms 25
    Bitwait Pina.7 , Set
    
       Set Portd.5
    
    End If
    
    If Pina.6 = 0 Then
    Waitms 25
    Bitwait Pina.6 , Set
    
       Set Portd.6
    
    End If
    
    
    Config Pina.7 = Output                                      ' przycisk
    Config Pina.6 = Output                                      ' przycisk
    Config Pind.2 = Input
    Set Portd.2
    Config Int0 = Low Level
    Porta.7 = 0
    Porta.6 = 0
    
    Enable Int0
    Enable Int1
    
    Powerdown
    Loop
    End
    
    Przerwanie:
    Disable Int0
    Disable Int1
    Set Portd.5
    Set Portd.6
    Wait 1
    Config Pina.7 = Input                                       ' przycisk
    Config Pina.6 = Input                                       ' przycisk
    Config Pind.2 = Output                                      ' przycisk int0
    
    Portd.2 = 0
    Set Porta.7
    Set Porta.6
    Return
    
    
    


    napisalem taki kod i dziala!!!!!!
  • #17 5885642
    mirekk36
    Poziom 42  
    A dlaczego aż dwa przerwania? tak z ciekawości zapytam?
    (może da radę z jednym)

    i ten "wait 1" hmmm musi tam być - choć jest to rzeczywiście mało istotny.

    i chyba w tym wklejonym kodziku wcięło ci Enable Interrupts ;)

    ale generalnie dobrze, że sofcik już spełnia zadania jakie mu postawiłeś
  • #18 5885692
    wader_669
    Poziom 28  
    Na int0 sa podlaczone 2 przyciski, a int1 jest podlaczony prosto do massy. Zrobilem to po to zeby sie przekonac ze przerwanie dziala.
    A teraz jeszcze jedno pytanie do kolegow jak zrobic budzenie, co sekunde za pomoca timer'a 2. Szukalem ale nigdzie nie moge sie doczytac jak to zrobic
  • Pomocny post
    #19 5885859
    mirekk36
    Poziom 42  
    Żeby zrobić za pomocą Timera - to nie możesz używać trybu PowerDown tylko Sleep - żeby właśnie Timery mogły działać to po pierwsze. W taki trybie jednak będziesz miał nieco większy pobór prądu niż w pełnym PowerDown. Więc wszystko zależy na ile ma wystarczać bateria o ile jest to coś zasilane z baterii. Bez PowerDown'a na pewno będzie to sporo krótszy czas podtrzymania.

    Po drugie - wiadomo, że Timer może nie da się ustawić równo co sekundę - ale możesz zliczać w jego przerwaniu jakiś licznik i dopiero gdy będzie właściwy czas to się w pełni procek obudzi. Jeśli natomiast licznik w tym przerwaniu nie osiągnął jeszcze maksymalnej wartości to znowu Sleep
  • Pomocny post
    #20 5886200
    zumek
    Poziom 39  
    wader_669 napisał:
    A teraz jeszcze jedno pytanie do kolegow jak zrobic budzenie, co sekunde za pomoca timer'a 2.

    Z tego co zauważyłem, ...
    
    Config Clock = Soft , Gosub = Sectic
    

    ... to masz podpięty do swojej M32, kwarc "zegarkowy".
    Do usypiania M32 pracującej jako zegarek, producent przewidział tryb Power-save, więc wykorzystaj ten tryb.

    wader_669 napisał:

    Szukalem ale nigdzie nie moge sie doczytac jak to zrobic

    Dziwne, bo ja znalazłem :D
  • #21 5887773
    wader_669
    Poziom 28  
    zumek napisał:

    wader_669 napisał:

    Szukalem ale nigdzie nie moge sie doczytac jak to zrobic

    Dziwne, bo ja znalazłem :D


    no tez juz znalazlem:
    https://www.elektroda.pl/rtvforum/topic377162.html

    szkoda nie zbytnio mi to pasuje, ze jest wyzszy pobor pradu.

    Kwarc zegarkowy mam podlaczony do tosc1/2. Chcialem zeby godzina sie aktualizowala co sekunde i zarazem co sekunde sie aktualizowal wyswietlacz, jeszcze z trybu uspienia mozna by wyjsc przyciskami.
    W takim razie co polecacie jakis zewnetrzny uklad? cel jest jak najmniejszy pobor pradu. Pytanie czy bedzie mi sie oplacac zewnetrzny uklad i procesor w trybie powerdown czy nie lepiej dac procesora w powersave i wtedy bym nie musial dodawac dodatkowego ukladu

    _________________________________________

    dziekuje wszystkim za odpowiedzi problem sie rozwiazal po tym jak zbadalem ile zabiera powersave u mnie skacze pobor pradu od 0,6mA do 0,3mA przy powerdown stale 0,3mA. Wiec nie bede dodawac zewnetrznego ukladu mierzacego czas chyba sie nie oplaca.

    Jednka pojawil sie nastepny problem ktorego nie moge rozwiazac, jak badalem ten kod ktory mowilem, ze dziala; to duszac pare razy na przycisk program sie zawieszal. Wie ktos moze dlaczego?
  • #22 6990757
    manekinen
    Poziom 29  
    wader_669 napisał:
    Jednka pojawil sie nastepny problem ktorego nie moge rozwiazac, jak badalem ten kod ktory mowilem, ze dziala; to duszac pare razy na przycisk program sie zawieszal. Wie ktos moze dlaczego?


    Może kolega rozwiązał ten problem? Szukałem podobnego rozwiązania i ten wątek okazał się bardzo pomocny, ale mam identyczny problem. Jeśli będe dusił przycisk co chwile albo go przytrzymam, program wykona dwa razy instrukcje z przerwania i się zawiesza (nie wychodzi z przerwania (pin INT0 nie zmienia stanu na wejściowy)) będe wdzięczny za pomoc bo już nie wiem co jest źle.

    Cała reszta działa znakomicie, migam diodą tyle razy, w zależności od tego o jakim numerze przycisk naciśnięto. Kod.

    
    $regfile = "m8def.dat"
    $crystal = 8000000
    
    Dim Licznik As Byte
    Dim X As Byte
    
    Config Portc.5 = Output                                     'dioda
    Portc.5 = 1                                                 'dioda
    
    
    Enable Interrupts
    Config Int0 = Low Level
    On Int0 Jazdaaaaa
    
    '_______________________________________________________________________________
    
    
    Do
    
    'przyciski jako wyjścia, stan niski:
    Config Portb.0 = Output                                     'p1
    Config Portb.1 = Output                                     'p2
    Config Portb.2 = Output                                     'p3
    Reset Portb.0                                               'p1
    Reset Portb.1                                               'p2
    Reset Portb.2                                               'p3
    
    
    'INT0 jako wejście, stan wysoki:
    Config Portd.2 = Input
    Set Portd.2
    
    Waitms 1                                                    'bez tego sam wchodzi w przerwanie i się zawiesza
    
    'zezwalam na przerwanie:
    Enable Int0
    
    'powerdown:
    Powerdown
    
    Loop
    End
    
    '_______________________________________________________________________________
    
    Jazdaaaaa:
    Disable Int0
    
    'przyciski jako wejścia, stan wysoki:
    Config Portb.0 = Input                                      'p1
    Config Portb.1 = Input                                      'p2
    Config Portb.2 = Input                                      'p3
    Set Portb.0                                                 'p1
    Set Portb.1                                                 'p2
    Set Portb.2                                                 'p3
    
    'INT0 jako wyjście, stan niski:
    Config Portd.2 = Output
    Portd.2 = 0
    
    'czytam stan przycisków:
    If Pinb.0 = 0 Then Licznik = 1
    If Pinb.1 = 0 Then Licznik = 2
    If Pinb.2 = 0 Then Licznik = 3
    
    
    For X = 1 To Licznik
       Portc.5 = 0
       Waitms 50
       Portc.5 = 1
       Waitms 200
    Next X
    
    Return
    



    DODANO


    Wywaliłem wszystko z przerwania i dałem tam tylko zmianę flagi, sprawdzam ją w głównej pętli do loop i tam wszystko wykonuje. Problemu nie ma. Ale nadal nie rozumiem czemu program reagował na nowe przerwanie podczas trwania poprzedniego, skoro je wyłączyłem na samym początku. przecież sprawdzenie stanu flagi i wyłączenie przerwania w głównej pętli trwa o wiele dłużej niż bezpośrednie wyłączenie.
REKLAMA