Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek dla www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

Przerwanie. Nie można wywołać przerwania INT0.

24 Lis 2006 00:34 1434 8
  • Poziom 10  
    Witam

    Mam problem z uruchomieniem przerwania od przycisku INT0 w mikrokontrolerze at89c5131. Ustawiam wszystkie znaczniki tzn. odblokowuje przerwania EA=1 przerwanie od INT0 EX0=1 wywoluje zboczem IT0=1 ale nic to nie daje tzn efekt nie jest taki jak byc powinien np kiedy w akcie desperacji napisalem w przerwaniu program mrugajacy dioda w ktorym czas swiecenia diody mial wynosic jedna sekunde to jakims cudem wydluzyl mi sie on do 15 sekund;/ bede wdzieczny za wszelkie trafne wnioski i uwagi;]

    Tomek
    Darmowe szkolenie: Ethernet w przemyśle dziś i jutro. Zarejestruj się za darmo.
  • Poziom 28  
    pokaż program
  • Poziom 10  
    Tak wiec plik glowny wyglada to nastepujaco


    #include <at89c5131.h>
    #include "zmienne.h"
    #include "funkcje_lib.h"

    extern GET_KEY();



    BYTE Tablica[10]; //Tablica[0] sekundy
    //Tablica[1] minuty
    //Tablica[2] godziny
    //Tablica[3] dni




    void RTC_INIT()
    {

    RCAP2H = (0-10000)>>8; // licznik zlicza impulsy
    RCAP2L = (0-10000); // opoznienie 10ms - sprawdzone na symulatorze
    T2MOD= 0x01; //wlaczony tryba automatycznego przeladowania


    EA = 1; // globalne przerwanie zezwolone
    EX0 = 1; // przerwanie od INT0
    IT0 = 1; // przerwanie wywolane zboczem opadajacym
    ET2 = 1; // przerwanie od licznika T2

    IPH0 |= 0x20; // zmiana priorytetu przerwania
    CKCON0&=~0x04;

    TR2 = 1; // uruchomienie licznika T2

    }


    void main ()
    {

    BYTE *sek, *min, *godz;
    RTC_INIT();
    init_lcd();
    sek = &Tablica[0];
    min = &Tablica[1];
    godz = &Tablica[2];

    text_lcd(1,1,"Time:");
    text_lcd(1,7,":");
    text_lcd(1,10,":");
    for(;;)
    {



    digit_lcd(1,6,*godz);
    digits_lcd(1,8,*min);
    digits_lcd(1,11,*sek);

    }



    while(1);
    }




    void przerwanie_T2(void) interrupt 5 using 2
    {
    static BYTE T2_counter=0;
    TF2=0; //wyzerowanie flagi przepelnienia
    T2_counter++; //zwiekszenie liczika przerwan

    if(T2_counter==100)
    {
    T2_counter=0;
    Tablica[0]=Tablica[0]+1 ; // ZMIENNE[10] sekundy
    P1_1=0;
    if( Tablica[0]==60)
    {
    Tablica[0]=0;
    Tablica[1]=Tablica[1]+1; // ZMMIENNE[9] minuty
    P1_1=1;
    if( Tablica[1]==60)
    {
    Tablica[1]=0;
    Tablica[2]=Tablica[2]+1; // ZMMIENNE[8] godziny


    if (Tablica[2]==24)
    {
    Tablica[2]=0;
    Tablica[3]=Tablica[3]+1;

    }
    }
    }
    }
    }


    void INT_0(void) interrupt 0 using 1
    {


    BYTE i=10;
    while(i)
    {
    P1_1 = 0;
    DELAY_m(1000);
    P1_1 = 1;
    DELAY_m(1000);
    i--;
    }



    }


    //***********************************************************

    funkcja opozniajaca

    #include "at89c5131.h"
    #include "zmienne.h"



    void Delay_T0();


    void DELAY_m(WORD time) reentrant
    {

    while(time)
    {
    Delay_T0();
    time--;
    }



    }


    void Delay_T0()
    {
    WORD czas;
    czas = 0 - 1000;

    TF0 = 0;
    TL0 = czas;
    TH0 = czas >>8;
    TMOD = TMOD | 0x01;
    TR0 = 1;
    while(~TF0);
    TR0 = 0;

    }

    Glownie chodzi mi o to zeby w przerwaniu od INT0 uruchomic wywolanie funkcji GET_KEY ktora sprawdza wcisniecie przycisku z klawiatury. Funkcja ta jest napisana w asemblerze i dziala (wywolywalem ja w main i dzialala jak nalezy).Nie wiem co jest grane z tym przerwaniem od INT0 nic mi w nim nie dziala wyskakuja same krzaki;/.

    $NOMOD51
    #include <at89c5131.h>

    PUBLIC GET_KEY

    UP EQU P1.6
    DOWN EQU P1.5
    LEFT EQU P1.7
    RIGHT EQU P1.4
    OK EQU P3.2


    KLAWIATURA SEGMENT CODE
    RSEG KLAWIATURA

    /*********************************************************************************/
    GET_KEY:
    PUSH PSW
    PUSH Acc
    PUSH B


    MOV C,UP
    JC brak_nacisku_UP
    MOV R7,#1
    clr P1.0
    JMP Koniec

    brak_nacisku_UP:
    MOV C,DOWN
    JC brak_nacisku_DOWN
    MOV R7,#3
    clr P1.2
    JMP Koniec

    brak_nacisku_DOWN:
    MOV C,LEFT
    JC brak_nacisku_LEFT
    MOV R7,#4
    clr P1.3
    JMP Koniec

    brak_nacisku_LEFT:
    MOV C,RIGHT
    JC brak_nacisku_RIGHT
    MOV R7,#2
    JMP Koniec
    brak_nacisku_RIGHT:

    MOV C,OK
    JC brak_nacisku_OK
    MOV R7,#5
    JMP Koniec

    brak_nacisku_OK:
    MOV R7,#0 /* oznacza to ze nie nacisnieto zadnego przycisku*/


    Koniec:

    POP B
    POP Acc
    POP PSW
    RET
    /************************************************************************************/
    END


    Aaaa zapomnial bym przerwanie od timera 2 odmierzajace czas dziala poprawnie;]
  • Poziom 33  
    Proponuję w przerwaniu ustawić wkaźnik, że nastąpiło przerwanie oraz wyłaczyć to przerwanie. Później w pętli głownej while sprawdzić ten wskaźnik i podjąć odpowiednią reakcję. Jeżeli funkcja reagująca na przerwanie zakończy swoje działanie ponownie włączyć przerwanie. Lepiej nie umieszczać za dużo kodu w obsłudze przerwania i szybko "z niego wyskakiwać". Kompilator czasami sobie nie radzi z "dużą" obsługą przerwania.
  • Poziom 32  
    markosik20 napisał:
    Kompilator czasami sobie nie radzi z "dużą" obsługą przerwania.
    Co ty czepiasz się kompilatora. To nie on ma sobie radzić z przerwaniem tylko programista musi wiedzieć ile daje mu zadań do obsługi w przerwaniu.
  • Poziom 33  
    Proszę zauważyć, że program to nic tylko przerwania (pętla while(1) jest pusta). O ile składnia programu jest ok to niestety pomimo tego, że toretycznie powinno działać to tak nie jest. Nie zwalam winy na kompilator ale czasami jest tak, że generuje on kod "inny" jakibyśmy chcieli. Proszę nie zapomniec , że trzeba te funkcje przekonwertować na 8-bitowca i w pewnych złych ustawieniach i braku dyrektyw dla kompilatora może on sobie to źle wszystko "poustawiać" :). W takich przypadkach dobrze sobie spojrzeć na ASM'a jaki został wygenerowany.
  • Poziom 26  
    INT0 na najwyższy priorytet

    void INT_0(void) interrupt 0 using 1
    {

    od tego miejsca

    BYTE i=10;
    while(i)
    {
    P1_1 = 0;
    DELAY_m(1000);
    P1_1 = 1;
    DELAY_m(1000);
    i--;
    }

    do tego nie są przyjmowane inne przerwania

    Aaaa zapomnial bym przerwanie od timera 2 odmierzajace czas dziala poprawnie;]

    Czy aby napewno w obsłudze przewania funkcja DELAY_m(1000) się kiedyś skończy a tym samym całe przerwanie INTO??
    Reszty już nie analizowałem.
  • Poziom 33  
    Jak już napisałem wcześniej wyrzuć te opóźnienia z obsługi przerwania i zrób to wszystko w pętli głównej while(1). W obsłudze przerwania ustaw wskaźnik, że przerwanie przysżło, potem wyłącz to przerwanie i koniec. Tu masz za dużo zagnieżdzonych funkcji w obsłudze przerwania.
  • Poziom 10  
    Tez wlasnie metoda prob i bledow zaczynam dochodzic do wniosku ze to przerwanie od przycisku to sie nadaje tylko do tego zeby jakis znacznik ustawic...migajaca dioda to byl tylko taki przyklad glownie chodzi mi o sprawdzenie ktory przycisk zostal wcisniety oczywiscie dopiero po wywolaniu przerwania od int0