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

[Atmega8][C/AVR Studio] Problem z przerwaniem

vectra96 28 Gru 2008 21:21 4304 19
  • #1 5915615
    vectra96
    Poziom 12  
    Witam, zacząłem zabawę z przerwaniami i jakoś ni mogę sobie poradzić, poniżej mój skromny kod programu który miał za zadanie do 1 sek zapalać diodę podłączoną do PORTB 0, ale coś nie "bangla", czy może mi ktoś wskazać co robię źle?

    #include <avr/io.h> // dostęp do rejestrów
    #include <avr/interrupt.h> // funkcje sei(), cli()
    #include <avr/signal.h> // definicje SIGNAL, INTERRUPT
    
    void delay(unsigned int mstime) {			/* prosta funkcja czasu, */
    long int i, j;
    for(j=0; j<mstime; j++)
    for(i=0; i<=1000; i++);
    }
    
    SIGNAL(SIG_OVERFLOW0){
    
    PORTB ^= _BV(0);
    
    }
    
    void Timer0Init()
    {
    TCNT0=49911; //wartość początkowa timera
    TCCR0|=(1<<CS01)|(1<<CS00); //preskaler CK/64
    TIMSK |= (1 << TOIE0); // zezwolenie na przerw. od przepełnienia
    } 
    
    
    
    
    int main(void)
    {
        DDRB  |= _BV(0)|_BV(1); /*ustawiamy 0 1 wejscie Portu B.*/
        PORTB &= ~_BV(0); /*ustawiamy stan niski na koncowce 0 Portu B.*/
    
    Timer0Init();
    
    sei();
    while(1)
    {
    
    } 
    
    return 0;
    }
    
  • #4 5915760
    vectra96
    Poziom 12  
    Zmieniłem TCNT0 = 0x00; ustawiłem prescaler na 1024 ale dalej nie działa. Według moich obliczeń dioda powinna mrugać co 0,26 sek. Czy mam jakiś jeszcze błąd w kodzie, czy czegoś nie umieściłem?
  • #6 5915825
    BoskiDialer
    Poziom 34  
    Może zamiast pytać napisz jaki masz kwarc, czy uC w ogóle się załącza, na czym polega owe "niebanglanie", czy dioda w ogóle się zaświeca kiedy się odpowiednio wysteruje wyjście, czy korzystasz z bootloadera, wtedy może znajdzie się ktoś, kto będzie umiał rozwiązać problem.
  • #7 5915940
    vectra96
    Poziom 12  
    BoskiDialer napisał:
    Może zamiast pytać napisz jaki masz kwarc, czy uC w ogóle się załącza, na czym polega owe "niebanglanie", czy dioda w ogóle się zaświeca kiedy się odpowiednio wysteruje wyjście, czy korzystasz z bootloadera, wtedy może znajdzie się ktoś, kto będzie umiał rozwiązać problem.


    Nie używałem żadnego kwarcu, dioda mi mrugała gdy pisałem program z dwoma przyciskami, jeden włączał diodę, drugi wyłączał. Co to bootloader nie wiem, dopiero zaczynam naukę programowania mikrokontrolerów (zresztą jak widać) podany powyżej kod jest całością jaką programuję Atmegę8.
    Wiem że to z czym teraz sobie nie radzę to są zupełne podstawy no ale niestety staram się dopiero tego nauczyć.

    Dopisałem TCNT0=0x00; ale daje to samo

    #include <avr/io.h> // dostęp do rejestrów
    #include <avr/interrupt.h> // funkcje sei(), cli()
    #include <avr/signal.h> // definicje SIGNAL, INTERRUPT
    #define F_CPU 1000000UL
    
    void delay(unsigned int mstime) {			/* prosta funkcja czasu, */
    long int i, j;
    for(j=0; j<mstime; j++)
    for(i=0; i<=1000; i++);
    }
    
    SIGNAL(SIG_OVERFLOW0){
    TCNT0=0x00;
    PORTB ^= _BV(0);
    
    } 
    
    void Timer0Init()
    {
    TCNT0 = 0; //wartość początkowa timera
    TCCR0|=(1<<CS01)|(1<<CS00); //preskaler CK/256
    TIMSK |= (1 << TOIE0); // zezwolenie na przerw. od przepełnienia
    } 
    
    
    
    
    int main(void)
    {
        DDRB  |= _BV(0)|_BV(1); /*ustawiamy 0 1 wejscie Portu B.*/
        PORTB &= ~_BV(0); /*ustawiamy stan niski na koncowce 0 Portu B.*/
    
    Timer0Init();
    
    sei();
    while(1)
    {
    
    } 
    
    return 0;
    }
  • #8 5916063
    BoskiDialer
    Poziom 34  
    Sprawdziłem ten kod, jest sprawny. Musisz szukać błędu w innym miejscu. Żeby sprawdzić, czy procesor rusza wrzuć takie coś:
    #define F_CPU 1000000
    #include <avr/io.h>
    #include <util/delay.h>
    
    int main(void) 
    { 
    	DDRB = 0x03;
    	PORTB = 0;
    
    	while(1) 
    	{ 
    		_delay_ms(500);
    		PORTB ^= 1;
    	} 
    	return 0; 
    }
    lub wersja skompilowana, postać ihex:
    :1000000012C02CC02BC02AC029C028C027C026C0BF
    :1000100025C024C023C022C021C020C01FC01EC0D4
    :100020001DC01CC01BC011241FBECFE5D4E0DEBF25
    :10003000CDBF10E0A0E6B0E0E0E9F0E002C005903E
    :100040000D92A036B107D9F710E0A0E6B0E001C0EC
    :100050001D92A036B107E1F702D018C0D1CF83E0DE
    :1000600087BB18BA28E833E161E049E150E005C0F8
    :10007000CA010197F1F72150304021153105C1F730
    :1000800088B3862788BB28E833E1F2CFF894FFCF06
    :00000001FF
  • #9 5916089
    vectra96
    Poziom 12  
    Dioda mruga ;] coś to oznacza?

    używam avr-studio 4.13 Build 528
    WinAVR-20080610

    jeżeli to ma jakieś znaczenie


    _________________________

    taki mały offtopic

    Mam programator zgodny z STK500 i mogę nim zaprogramować układ, wyczyścić ale nie mogę sprawdzić poprawności zapisu bo wywala błąd.
    Zmieniłem podczas używania go z ustawień domyślnych procesor, oraz "Oscilator Calibration byte - Calibrate for frequency: 4.0 Mhz"

    _____________________________


    Przesyłając coś takiego do procesora dioda cały czas się świeci, według obliczeń powinno być co 0,262 S, gdy dałem w miejscu komentarza "delay(10);" opuźnienie to dopiero dioda mrugała.

    #include <avr/io.h> // dostęp do rejestrów
    #include <avr/interrupt.h> // funkcje sei(), cli()
    #include <avr/signal.h> // definicje SIGNAL, INTERRUPT
    
    void delay(unsigned int mstime) {
    long int i, j;
    for(j=0; j<mstime; j++)
    for(i=0; i<=1000; i++);
    }
    
    SIGNAL(SIG_OVERFLOW0){
    PORTB ^= _BV(0);
    TCNT0=0x00;
    }
    
    int main(void)
    {
        DDRB  |= _BV(0)|_BV(1); /*ustawiamy koncowke 0 jako wejscie, koncowke 2 wyjscie Portu B.*/
        PORTB &= ~_BV(0); /*ustawiamy stan wysoki na koncowce 0 Portu B.*/
    TCCR0 = (1 << CS02) | (1 << CS00);
    TCNT0 = 0;
    TIMSK |= (1 << TOIE0);
    sei();
    while(1){
    PORTB ^= _BV(0);
    TCNT0=0x00;                    /* tu dałem delay(10); */
    }
    return 0;
    }
    
  • #10 5916228
    BoskiDialer
    Poziom 34  
    Nie jesteś zbytnio wymowny, nie powiesz szacunkowo z jaką częstotliwością miga dioda, więc sprawdź jeszcze takie coś:
    #define F_CPU 1000000UL 
    #include <avr/io.h>
    #include <avr/interrupt.h>
    
    unsigned char tovs;
    
    SIGNAL(SIG_OVERFLOW0){ 
    	tovs++;
    	// zmiana stanu co 16 przepełnień timera
    	if(tovs == 16)
    	{
    		PORTB ^= _BV(0);
    		tovs = 0;
    	}
    } 
    
    int main(void) 
    { 
        DDRB = 0x03;
        PORTB = 0;
    	
    	// ustawienie timera, CK/1024, pełen zakres
    //	TCNT0 = 0;
    	TCCR0 = (1<<CS02)|(1<<CS00);
    	TIMSK = (1<<TOIE0);
    
    	sei(); 
    	while(1) 
    		;
    	return 0; 
    }
    skompiluj to i sprawdź, jak również sprawdź to:
    :1000000012C02CC02BC02AC029C028C027C026C0BF
    :1000100025C025C023C022C021C020C01FC01EC0D3
    :100020001DC01CC01BC011241FBECFE5D4E0DEBF25
    :10003000CDBF10E0A0E6B0E0EAEAF0E002C0059033
    :100040000D92A036B107D9F710E0A0E6B0E001C0EC
    :100050001D92A136B107E1F71DD025C0D1CF1F9267
    :100060000F920FB60F9211248F939F93809160008F
    :100070008F5F80936000803131F488B391E08927ED
    :1000800088BB109260009F918F910F900FBE0F90D0
    :100090001F90189583E087BB18BA85E083BF81E085
    :0A00A00089BF7894FFCFF894FFCFDA
    :00000001FF
    to jest dokładnie to samo, dzięki porównaniu obu wersji będzie można wykluczyć kompilator jako źródło problemów (swoją drogą mam ten sam)
  • #11 5916255
    Qdlaty
    Poziom 11  
    U mnie po dopisaniu linijki, którą podałem Ci w poprzednim poście program działa i dioda mruga :)
  • #12 5916325
    vectra96
    Poziom 12  
    w pierwszym podanym przez Ciebie przykładzie dioda mruga na oko coś ponad 1 sek.

    drugi przykład - dioda nie mruga, czy powodem może być źle ustawiony avr? czy coś muszę zmienić poza rodzajem procesora oraz frequency po zainstalowaniu programu ?


    Qdlaty napisał:
    U mnie po dopisaniu linijki, którą podałem Ci w poprzednim poście program działa i dioda mruga :)


    A czy możesz mi powiedzieć jak masz dokłądnie ustawiony AVR? W jakich zakładkach co pozaznaczane?
  • #13 5916341
    dawid512
    Poziom 32  
    Kolego vectra96 nie zmieniaj postów, pokaż program o który ci chodzi nie licz na to że ktoś będzie się domyślał...
  • #14 5916378
    vectra96
    Poziom 12  
    dawid512 napisał:
    Kolego vectra96 nie zmieniaj postów, pokaż program o który ci chodzi nie licz na to że ktoś będzie się domyślał...


    Mam problem oczywiście z programem z 1 postu. Moje poprzednie posty edytowalem i dopisywalem kolejne komentarze aby nie nabijać sobie kolejnych postów/punktów.
  • #15 5916430
    Qdlaty
    Poziom 11  
    Tutaj masz kod programu, u mnie działa, dioda miga.

    #include <avr/io.h> // dostęp do rejestrów
    #include <avr/interrupt.h> // funkcje sei(), cli()
    #include <avr/signal.h> // definicje SIGNAL, INTERRUPT
    #define F_CPU 8000000UL //definicja czestotliwosci w moim wypadku 8Mhz
    void delay(unsigned int mstime) {         /* prosta funkcja czasu, */
    long int i, j;
    for(j=0; j<mstime; j++)
    for(i=0; i<=1000; i++);
    }
    
    SIGNAL(SIG_OVERFLOW0){
    
    TCNT0=0x00;
    PORTB ^= _BV(0);
    
    }
    
    void Timer0Init()
    {
    TCNT0=0x00; //wartość początkowa timera np 0
    TCCR0|=5; //preskaler CK/1024
    TIMSK |= (1 << TOIE0); // zezwolenie na przerw. od przepełnienia
    }
    
    
    
    
    int main(void)
    {
        DDRB  |= _BV(0)|_BV(1); /*ustawiamy 0 1 wejscie Portu B.*/
        PORTB &= ~_BV(0); /*ustawiamy stan niski na koncowce 0 Portu B.*/
    
    Timer0Init();
    
    sei();
    while(1)
    {
    
    }
    
    return 0;
    }
    
  • #16 5916437
    dawid512
    Poziom 32  
    Kod podany przez BoskiegoDialera jest poprwany a oto on:
    #define F_CPU 1000000UL
    #include <avr/io.h>
    #include <avr/interrupt.h>
    
    unsigned char tovs;
    
    SIGNAL(SIG_OVERFLOW0){
       tovs++;
       // zmiana stanu co 16 przepełnień timera
       if(tovs == 16)
       {
          PORTB ^= _BV(0);
          tovs = 0;
       }
    }
    
    int main(void)
    {
        DDRB = 0x03;
        PORTB = 0;
       
       // ustawienie timera, CK/1024, pełen zakres
    //   TCNT0 = 0;
       TCCR0 = (1<<CS02)|(1<<CS00);
       TIMSK = (1<<TOIE0);
    
       sei();
       while(1)
          ;
       return 0;
    }


    Jeżeli u ciebie nie działa to znaczy że:
    -korzystasz z innej częstotliwości niż podana w programie
    -masz błędy podczas wgrywania programu

    Proponuję zobaczyć jak masz ustawione fuse bity oraz zmniejszyć prędkość ISP.
  • #17 5916452
    mklos1
    Poziom 25  
    Ja bym to zrobił tak:

    #define F_CPU 1000000UL
    #include <avr/io.h>
    #include <avr/interrupt.h>
    
    unsigned char tovs;
    
    SIGNAL(SIG_OVERFLOW0){
       TCNT0 = 1; // timer stop
       tovs++;
       // zmiana stanu co 16 przepełnień timera
       if(tovs % 16 == 0)
          PORTB ^= _BV(0);
       TCNT0 = 0; //timer start
    }
    
    int main(void)
    {
        DDRB = 0x03;
        PORTB = 0;
       
       // ustawienie timera, CK/1024, pełen zakres
       TCCR0 = (1<<CS02)|(1<<CS00);
       TIMSK = (1<<TOIE0);
       TCNT0 = 0;
    
       sei();
       while(1)
          ;
       return 0;
    }
  • #18 5916472
    BoskiDialer
    Poziom 34  
    mklos1: Jeśli jesteś pewien, że wpisanie 1 do TCNT0 powoduje zatrzymanie timera, a wpisanie 0 do TCNT0, to dokumentacja wyprowadzi Cię z błędu.

    ps. dzielenia modulo unikał bym, nawet jeśli kompilator jest w stanie to zoptymalizować.
  • #19 5916527
    mklos1
    Poziom 25  
    BoskiDialer napisał:
    mklos1: Jeśli jesteś pewien, że wpisanie 1 do TCNT0 powoduje zatrzymanie timera, a wpisanie 0 do TCNT0, to dokumentacja wyprowadzi Cię z błędu.


    Warto przeglądać czasami dokumentację ;-) Uświadomiłem sobie, że mam bład w programie, który działał więc nie zwracałem uwagi... Nie warto robić bezmyślnie CTRL+C, CTRL+V
  • #20 5917130
    vectra96
    Poziom 12  
    Problem rozwiązany ;]

    okazazło się iż w opcji projektu miałem wybrane domyśle urządzenie Atmega128!

    Dziękuję Wam za pomoc, jesteście wielcy!!!
REKLAMA