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

Problem z przerwaniami w atmega8 AVR-GCC

darek1632 21 Sty 2009 20:53 2014 17
REKLAMA
  • #1 6033998
    darek1632
    Poziom 15  
    Witam, zacząłem właśnie nauke C na AVR z kursu EDW prowadzonego przez Radosława Koppel. Nie wiem co źle robie ale w cz.3 ww. kursu program kompiluje się poprawnie jednak na wyswietlaczach nic nie widać. Sprzet mam podłączony dobrze gdyż w pętli programowej wyświetlał. Po przeprowadzeniu sumulacji w AVR Studio program zatrzymuje się przed pętlą for i dalej nic. Robie to na procesorze amega8. Podaje KOD i prosze o pomoc Pozdrawiam.

    
    #include <avr\io.h>
    #include <inttypes.h>
    #include <avr\interrupt.h>
    #include <avr\signal.h>
    
    
    #define LED_A 0
    #define LED_B 1
    #define LED_C 2
    #define LED_D 3
    #define LED_E 4
    #define LED_F 5
    #define LED_G 6
    #define LED_DP 7
    #define LEDPORT PORTB
    #define LEDDDR DDRB
    #define COM1 6
    #define COM2 5
    #define COM3 4
    #define COM4 3
    #define COMPORT PORTD
    #define COMDDR DDRD
    
    uint8_t g_AktWyswietlacz = 0;
    
    uint8_t g_DaneWyswietlacza[4];
    
    uint8_t g_DaneCom[4] = { (1<<COM1), (1<<COM2), (1<<COM3), (1<<COM4) };
    
       
    
    int main(void)
    {
    
            //////////////////////////////////
           // inicjalizacja
            LEDDDR = 0xff;
            COMDDR = 1<<COM1 | 1<<COM2 | 1<<COM3 | 1<<COM4;
            //Timer0
            TCCR0 = 1<<CS01 | 1<<CS01;
            TIMSK = 1<<TOIE;
            //KONIEC INICJALIZACJI
            //////////////////////////
            //GLOBALNE ZEZWOLENIE NA PRZERWANIE
            sei();
            //koniec inicjalizacji
            /////////////////////////////////////////////
           
    
            //Wpisanie do tablicy próbnych wartosci
            g_DaneWyswietlacza[0] = ~(1<<LED_B | 1<<LED_C);
            g_DaneWyswietlacza[1] = ~(1<<LED_A | 1<<LED_B | 1<<LED_D |
            1<<LED_E | 1<<LED_G);
            g_DaneWyswietlacza[2] = ~(1<<LED_A | 1<<LED_B | 1<<LED_C |
            1<<LED_D | 1<<LED_G);
            g_DaneWyswietlacza[3] = ~(1<<LED_B | 1<<LED_C | 1<<LED_F |
            1<<LED_G);
           
            for(;;)
            {
            }
           
            return 0;
    }       
    //Obsluga przerwan
    SIGNAL(SIG_OVERFLOW0)
    {
                    //Wygaszanie wyswietlaczy
                    COMPORT = ~(1<<COM1 | 1<<COM2 | 1<<COM3 | 1<<COM4);
                                    //wYSYLANIE ODPOWIEDNIEJ DANEJ
                    LEDPORT = g_DaneWyswietlacza[g_AktWyswietlacz];
                    //Wlaczenie odpowiedniego wyswietlacza
                    COMPORT &= g_DaneCom[g_AktWyswietlacz];
               
                    // Zwiekszenie stanu zmiennej wskazujacej na obslugiwany wyswietlacz
                   
                    ++g_AktWyswietlacz;
                    if(g_AktWyswietlacz > 3)
                        g_AktWyswietlacz = 0;
                   
    }    
    
  • REKLAMA
  • #2 6034102
    dawid512
    Poziom 32  
    uint8_t g_AktWyswietlacz = 0;
    
    uint8_t g_DaneWyswietlacza[4];
    
    uint8_t g_DaneCom[4] = { (1<<COM1), (1<<COM2), (1<<COM3), (1<<COM4) }; 


    Zadeklaruj te zmienne jako volatile.
  • REKLAMA
  • #4 6034622
    darek1632
    Poziom 15  
    Dzieki za odpowiedzi.
    Zmienilem deklaracje na volatile i niestety nic nie dziala.
    Dzieki pubus faktycznie blad w edycji postu sorki faktycznie w kodzie mam TIMSK = 1<<TOIE0;
    Pozdrawiam
  • #5 6034700
    dawid512
    Poziom 32  
    Nie sprawdzając czy odpowiednio ustawiłeś rejestry to rzuca się w oczy to że nie wpisujesz żadnej wartości do timera.
  • #6 6034760
    darek1632
    Poziom 15  
    TCCR0 = 1<<CS01 | 1<<CS01; tu mam ustawiony rejestr zeby zliczal mi impulsy podzielone w preskalerze przez 64 , chyba , ze cos jeszcze trzeba ustawic
  • REKLAMA
  • #7 6034800
    dawid512
    Poziom 32  
    Jak już to:
    TCCR0 = 1<<CS00 | 1<<CS01;
    oprócz tego tzreba jeszce wpisać wartość do timera czyli do TCNT0. W atmedze 8 ważne jest również to że każde wywołanie przerwania od timera0 powoduje wyzerowanie TCNT0.
  • REKLAMA
  • #8 6034830
    darek1632
    Poziom 15  
    czyli co tam mam wpisac do TCNT0 ? Bo w symulatorze AVR Studio mam tam pusto , rozumiem ze po kazdym przerwaniu musze wpisywac tam ta wartosc.
  • #9 6034846
    Dr.Vee
    VIP Zasłużony dla elektroda
    Cały czas masz wygaszone wyświetlacze.

    Powinno być:
    --- led7seg.c   2009-01-21 21:43:50.000000000 +0000
    +++ led7seg.c.new       2009-01-21 21:45:01.000000000 +0000
    @@ -21,7 +21,7 @@
     #define COMPORT PORTD
     #define COMDDR DDRD
     
    -uint8_t g_AktWyswietlacz = 0;
    +volatile uint8_t g_AktWyswietlacz;
     
     uint8_t g_DaneWyswietlacza[4];
     
    @@ -70,7 +70,7 @@
                                     //wYSYLANIE ODPOWIEDNIEJ DANEJ
                     LEDPORT = g_DaneWyswietlacza[g_AktWyswietlacz];
                     //Wlaczenie odpowiedniego wyswietlacza
    -                COMPORT &= g_DaneCom[g_AktWyswietlacz];
    +                COMPORT = g_DaneCom[g_AktWyswietlacz];
                
                     // Zwiekszenie stanu zmiennej wskazujacej na obslugiwany wyswietlacz

    Pozdrawiam,
    Dr.Vee
  • #10 6034855
    dawid512
    Poziom 32  
    Wpisanie odpowiedniej wartości da przerwanie co jakiś określony czas. Na początek musisz wpisać jakąś wartość w funkcji głównej a potem wpisywać za każdym razem tą wartość w przerwaniu.
  • #11 6034968
    darek1632
    Poziom 15  
    nie wiem co zle robie wpisalem do rejestru TCNT0 = 0x22 i nic problem polega na tym, ze program dochodzi do petli for( ;; ) i sie zatrzymuje a wyswietlacze nawet nie migna. Dzieki za odpowiedzi Pozdrawiam.
  • #12 6035273
    pubus
    Poziom 30  
    Kolego dawid512 radzę uzupełnić swoją wiedzę na temat pracy timerów i nie robić innym wody z mózgu...
    Oczywiście po przepełnieniu TCNT0 zostanie wyzerowane i zacznie się zliczanie od nowa...
    Wartość do TCNT0 podstawiamy tylko w przypadku kiedy chcemy uzyskać przepełnienie co pewien czas który jest nie do uzyskania przez samo ustawienie prescalera...
    Co do samego problemu jest jeszcze jedna sprawa...
    Z jakiej wersji win-avr korzystasz...?
    Z tego co wiem to w nowszych wersjach używa się tylko nagłówka interrupt.h natomiast sama obsługa wygląda tak
    
    ISR (TIMER0_OVF_vect) 
    {
     ...
    }
    
  • Pomocny post
    #13 6035308
    dawid512
    Poziom 32  
    pubus napisał:
    Kolego dawid512 radzę uzupełnić swoją wiedzę na temat pracy timerów i nie robić innym wody z mózgu...
    Oczywiście po przepełnieniu TCNT0 zostanie wyzerowane i zacznie się zliczanie od nowa...
    Wartość do TCNT0 podstawiamy tylko w przypadku kiedy chcemy uzyskać przepełnienie co pewien czas który jest nie do uzyskania przez samo ustawienie prescalera...
    Co do samego problemu jest jeszcze jedna sprawa...
    Z jakiej wersji win-avr korzystasz...?
    Z tego co wiem to w nowszych wersjach używa się tylko nagłówka interrupt.h natomiast sama obsługa wygląda tak
    
    ISR (TIMER0_OVF_vect) 
    {
     ...
    }
    


    Kolega sobie poczyta co napisałem bo właśnie to samo mówi :)
  • #14 6036178
    pubus
    Poziom 30  
    Nie był bym tego taki pewny...
    Czy według Ciebie timer nie będzie działał poprawnie jeżeli do rejestru TCNTx nie zostanie wpisana jakaś wartość...?.!.?
    Jaki jest cel wpisywania w tym przypadku wartości do TCNT0 na początku jak i po każdym przepełnieniu...?
  • #15 6038093
    dawid512
    Poziom 32  
    Jeżeli mamy do czynienia z multipleksowaniem to przerwanie co jakiś czas jest nam potrzebne do uzyskania jakiejś częstotliwości. Takiej aby ludzkie oko nie było w stanie wyłapać wyłączania i załączania wyświetlaczy.
  • #16 6038316
    darek1632
    Poziom 15  
    Problem rozwiązany co prawda tylko w symulacji mi chodzi ale dzis nie bede w domu wiec nie uruchomie sprzetu. Zmienilem na
    ISR (TIMER0_OVF_vect) i poszlo. Dzieki pozdrawiam Dzieki za odpowiedzi Pozdrawiam

    PS: Dr.Vee , nie rozumiem Twojego kodu tym bardziej wyrażenia
    @@ -21,7 +21,7 @@
    rozumiem , że dołączasz pliki nagłówkowe led7seg.c. Jestem początkujący w C wiec na razie musze się nauczyć podstaw krok po kroku. Pozdrawiam.
  • Pomocny post
    #17 6038349
    pubus
    Poziom 30  
    No to dobrze...
    uC taktowany jest najniższą dostępną z wewnętrznego RC częstotliwością 1MHz...
    Ustawiam prescaler na 1 i mam przerwanie co 256us...
    Czy nadal powinienem coś wpisywać do TCNT0...?.?.?
  • #18 6038581
    dawid512
    Poziom 32  
    On ma preskaler na 64 ale po co się kłocić. Autor rozwiązał problem. Zawsze pewne rzeczy można zrobić na wiele sposobów.
REKLAMA