Elektroda.pl
Elektroda.pl
X

Search our partners

Find the latest content on electronic components. Datasheets.com
Elektroda.pl
Please add exception to AdBlock for elektroda.pl.
If you watch the ads, you support portal and users.

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

wader_669 19 Dec 2008 14:46 6000 21
  • #1
    wader_669
    Level 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


    Code:

    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
    Kamery 3D Time of Flight - zastosowania w przemyśle. Darmowe szkolenie 16.12.2021r. g. 10.00 Zarejestruj się
  • #3
    wader_669
    Level 28  
    zatrzymuje sie nie da sie go obudzic. Teraz badam jakie stany sa na pinach.
  • Helpful post
    #4
    mirekk36
    Level 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
    atom1477
    Level 43  
    Timera2 akurat na razie nie masz. To znaczy masz go w procesorze, ale nie w kodzie programu.

    Jak już to tak:
    Code:
    Config Timer2 = Timer , Async = On , Prescale = 128
    
    On Timer2 Timer2_int
    Enable Timer2



    Timer2_int:
        Incr Sek
        If Sek > 59 Then
            Sek = 0
            Incr Min_l
            If Min_l > 9 Then
                Min_l = 0

                Incr Min_h
                If Min_h > 5 Then
                    Min_h = 0

                    Incr Godz_l
                    If Godz_l > 9 Then
                        Godz_l = 0

                        Incr Godz_h
                    End If


                    If Godz_h >= 2 Then
                        If Godz_l > 3 Then
                            Godz_h = 0
                            Godz_l = 0
                        End If
                    End If
                End If
            End If
        End If
    Return
  • #6
    wader_669
    Level 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

    Code:

    '** 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
  • #8
    wader_669
    Level 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
    mirekk36
    Level 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
    wader_669
    Level 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.
  • #11
    K_o_n_r_a_d
    Level 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ć:
    Code:
    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:
    Code:
    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:
    Code:
    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
    wader_669
    Level 28  
    pisalem ze jest to czesc porgramu. Testuje wszystko na wyswietlaczu, wiec wszystko ladnie jest widoczne :D
  • #14
    wader_669
    Level 28  
    hmm no dobra w takim razie obadam motyw z dioda, zeby sie upewnic na 100%
  • #15
    K_o_n_r_a_d
    Level 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ś:
    Code:
    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
    wader_669
    Level 28  
    Code:

    $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
    mirekk36
    Level 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
    wader_669
    Level 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
  • Helpful post
    #19
    mirekk36
    Level 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
  • Helpful post
    #20
    zumek
    Level 39  
    wader_669 wrote:
    A teraz jeszcze jedno pytanie do kolegow jak zrobic budzenie, co sekunde za pomoca timer'a 2.

    Z tego co zauważyłem, ...
    Code:

    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 wrote:

    Szukalem ale nigdzie nie moge sie doczytac jak to zrobic

    Dziwne, bo ja znalazłem :D
  • #21
    wader_669
    Level 28  
    zumek wrote:

    wader_669 wrote:

    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
    manekinen
    Level 29  
    wader_669 wrote:
    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.

    Code:

    $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.