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

Atmega8 - przerwania ADC zawieszają działanie portu D. Co poprawić?

antrykot 23 Sie 2007 18:34 1260 6
REKLAMA
  • #1 4208329
    antrykot
    Poziom 20  
    Posty: 470
    Pomógł: 27
    Ocena: 27
    Mam kawałek prostego kodziku. Gdy sei jest zakomentowane, diody mrugają (na porcie D), gdy włącze przerwania, na porcie D jest cały czas 0. Wygląda jak by proc sie zawieszał. Zapewne problem jest błachy i oczywisty, ale patrze w to już 2 dzień i nie moge znaleźć.
    Może ktoś powiedzieć co jest nie tak ?

    
    #define __AVR_ATmega8__
    #include "avr/io.h"
    #include <avr/interrupt.h>
    #include <avr/signal.h>
    
    
    #define FOSC 8000000// Clock Speed
    
    #define B0	1
    #define B1	2
    #define B2	4
    #define B3	8
    #define B4	16
    #define B5	32
    #define B6	64
    #define B7	128
    
    
    
    SIGNAL(SIG_ADC)
    {
        PORTD = B2;
    
    }
    
    void init_adc()
    {
    
    	ADMUX = 0   | ( 1 << REFS1 ) | ( 1 << REFS0 ) | ( 1 << ADLAR );     // chanel 0 active, Internal 2.56 Uref, right justified data.
    	ADCSRA = 0  | ( 1 << ADEN )  | /*( 1 << ADIF ) | */ ( 1 << ADIE ) |( 1 << ADFR ) | ( 1 << ADSC ) // adc enable, adc int flag, adc int enable,free run,start
    			 | ( 1 << ADPS2 ) | ( 1 << ADPS1 );          // adc prescaler 64 (125Khz / 8Mhz clock)
    
    
    //    sei();
    }
    
    
    int main ( void )
    {
    	long i = 0;
    	DDRD = 255;
    	PORTD = 0;
    
    	init_adc();
    
    	while ( 1 )
    	{
    		for ( i = 0; i < 94000; i++ )
    		{}
    		PORTD = 0xAA;
    		for ( i = 0; i < 94000; i++ )
    		{}
    		PORTD = 0x55;
    	}
    
    	return 0;
    }

    Procek - jak w temacie - mega8.
  • REKLAMA
  • Pomocny post
    #2 4208587
    bobbyAIR
    Poziom 20  
    Posty: 267
    Pomógł: 41
    Ocena: 6
    Nie wiesza się tylko nie zdążysz zobaczyć. ADC chodzi na tyle szybko, że instrukcje
    PORTD = 0xAA;
    PORTD = 0x55;
    Wykonują sie ale zaraz po nich wykonuje sie instrukcja
    PORTD = B2;
    i oko ludzkie tego nie wychwytuje
  • REKLAMA
  • #3 4208632
    antrykot
    Poziom 20  
    Posty: 470
    Pomógł: 27
    Ocena: 27
    Jednak sie zawiesza.
    Sprawdzałem oscyloskopem.
    Pozatym testowałem w ten sposób, że po prostu w przerwaniu włączałem diody, i wychodzi na to, że kod przerwania sie nigdy nie wykonuje.

    Nie wiem czy to przyczyna (za chwile będe sprawdzał), ale zrobiłem błąd w obsłudze przerwania, i gcc wywalił errora w funkcji test.c: In function `__vector_14':
    natomiast datasheet mówi o że vector15 jest od adc.
    Sprawdze w listingu asm.
  • REKLAMA
  • #4 4208694
    bobbyAIR
    Poziom 20  
    Posty: 267
    Pomógł: 41
    Ocena: 6
    Wiesz błąd dobrze jest zacytować jeśli się pojawia. Po drugie zamiast definiować procesor w pliku lepiej podać kompilatorowi na jaki procesor ma kompilować poprzez parametr -mmcu=atmega8. Po trzecie jeśli używasz interrupt.h to nie używaj już signal.h gdyż plik signal.h wygląda tak
    
    #ifndef _AVR_SIGNAL_H_
    #define _AVR_SIGNAL_H_
    
    #warning "This header file is obsolete.  Use <avr/interrupt.h>."
    #include <avr/interrupt.h>
    
    #endif /* _AVR_SIGNAL_H_ */
    

    Mi twoj kod kompiluje się porpawnie po zmianie nagłówka pliku ma
    
    #include "avr/io.h"
    #include <avr/interrupt.h>
    
    #define F_CPU 8000000// Clock Speed
     
     #define B0   1 
     #define B1   2 
     #define B2   4 
     #define B3   8 
     #define B4   16 
     #define B5   32 
     #define B6   64 
     #define B7   128 
     

    
    avr-gcc -g -O -mmcu=atmega8 -c main.c -o main.o
    avr-gcc -g -O -mmcu=atmega8 main.o -o main
    avr-strip main -o main-stripped
    avr-objcopy -O srec main-stripped main.srec
    rm main-stripped
    

    Pamiętaj też, że pliki takie jak util/delay.h oczekują makra F_CPU a nie FOSC
  • REKLAMA
  • #5 4209185
    antrykot
    Poziom 20  
    Posty: 470
    Pomógł: 27
    Ocena: 27
    Te FOSC było do jakiś obliczeń, w głównym programie (to jest tylko wyodrębniony problem dla testu)

    Błąd zrobiłem specjalnie, żeby zobaczyć nazwe funkcji, która kryje sie pod makrem SIGNAL, ale w kodzie ktory wkleiłem go oczywiście nie ma.

    Program sie kompiluje, ale problem jest taki, że nie działa. W pliku test.s, widze, że po wyjściu z obsługi przerwania jest ret, a nie reti, ale w sumie nie wykonuje sie to co jest w środku, więc nie wiem czy to ma jakiekolwiej znaczenie.
    Napisałem kawałek testu w ASM, i wszystko gra i buczy.

    Przytocze tutaj listing, wygenerowany przez gcc, może ktoś zauważy.

    Ręce mi już opadają. Spróbuje póżniej zassać nowe gcc, może to coś pomoże.
    Załączniki:
    • test.txt (2.57 KB) Musisz być zalogowany, aby pobrać ten załącznik.
  • Pomocny post
    #6 4209770
    BoskiDialer
    Poziom 34  
    Posty: 1530
    Pomógł: 353
    Ocena: 42
    1/ #include "avr/io.h" <- zdecydowanie powinno być <avr/io.h>
    2/ z tego co widać w "test.txt", nie ma tam żadnych funkcji odpowiedzialnych za przerwania (nazwy właśnie __vector_* [po rozwinieciu SIGNAL(x) przez preprocesor]), a skok do wektora przerwania, w którym brak funkcji przerwania powoduje skok do resetu (domyślna funkcja do wektorów to skok pod adres zerowy).
  • #7 4209809
    antrykot
    Poziom 20  
    Posty: 470
    Pomógł: 27
    Ocena: 27
    Tak, bo kombinowałem z ISR zamiast SIGNAL.
    Tak czy tak, patrzyłem na różne sposoby, i nie widać przerwania :/

    Inna sprawa to taka, że w C mogło by nie starczyć flasha, więc postanowilem napisać to w ASM i mieć świety spokój. Wcześniej po macoszemu traktowałem ten język, więc będe miał okazje pożądnie sie z nim zaznajomić i nabrać wprawy :)

Podsumowanie tematu

LABEL_AI_GENERATED
Dyskusja dotyczy problemu z mikrokontrolerem Atmega8, gdzie włączenie przerwań ADC powoduje zawieszanie się działania portu D, objawiające się brakiem migania diod. Przyczyną jest prawdopodobnie błędna obsługa przerwania ADC – funkcja przerwania nie jest wywoływana, co potwierdzono oscyloskopem. Wskazano, że użycie przestarzałego nagłówka zamiast może powodować problemy, a także że kompilator powinien być wywoływany z parametrem -mmcu=atmega8 zamiast definiowania procesora w kodzie. Zauważono, że makro SIGNAL może generować funkcję przerwania o niewłaściwej nazwie wektora (np. __vector_14 zamiast __vector_15 dla ADC), co skutkuje brakiem obsługi przerwania i resetem procesora. Rekomendowano stosowanie poprawnej definicji ISR oraz poprawne dołączanie nagłówków. Autor testował również kod w asemblerze, gdzie problem nie występował. Podsumowując, problem wynika z błędnej definicji i obsługi przerwania ADC w C oraz nieprawidłowego użycia nagłówków i kompilatora, co powoduje, że przerwanie nie jest wywoływane, a port D pozostaje w stanie niskim.
Podsumowanie AI na podstawie dyskusji. Może zawierać błędy.
REKLAMA