Skocz do zawartości

Problem z obsługą przerwania Atmega328p (język C)


choco_amore

Pomocna odpowiedź

Cześć! Od pewnego czasu próbuję rozgryźć programowanie AVR w C. Napotkałem problem z obsługą przerwań, a dokładnie przerwanie od zmiany stanu pinu.

Z założenia program służy do generowania sygnału PWM do kontroli jasności świecenia dwóch  LED.

1. napięciem na A0 reguluje się świecenie LED podłączonego do portu nr 9.

2. napięciem na A1 reguluje się świecenie LED podłączonego do portu nr 10.

Wszystko działa poprawnie do momentu dodania do kodu obsługi przerwań. Diody przestają świecić, a dioda która powinna zmienić stan w momencie wywołania przerwania ledwo świeci i nie chce zmienić stanu niezależnie od tego czy na PB2 jest podany niski lub wysoki stan.  Mam wrażenie że coś ciągle wywołuje przerwania i dlatego reszta programu nie chce działać.

#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>


//obsluga przerwania od zmiany stanu PD2(zmiana PD7 gdy PD2 = 1)
ISR(PCINT2_vect)
{
    PORTD ^= (1<<PD7);
}


int main(void) {

    //ustawienie przerwania PCIE2=1 i PCINT18 =1 -> przerwanie od PD2
    PCICR |= (1<<PCIE2);
    PCMSK2 |= (1<<PCINT18);
    DDRD &= ~(1<<PD2); //ustawienie PD2 jako wejscia i podlaczenie rezystora podciągającego
    PORTD |= (1<<PD2);

    //ustawienie PD7 jako wyjscia i ustawienie jego stanu na 1
    DDRD |= (1<<PD7);
    PORTD |= (1 << PD7);

	//ustawienie PWM z timer1 - sygnal na dwie diody LED
	TCCR1A  = (1<<WGM11);
    TCCR1B  = (1<<WGM12)|(1<<WGM13);
    TCCR1B |= (1<<CS12) | (1<<CS10);  // prescaler=1024, pelen okres = 1 us             
    TCCR1A |= (1<<COM1A1) | (1<<COM1B1); // zeruje OC1A, OC1B przy rownosci z licznikiem TIMER1, ustawia dla wartosci TOP                
    ICR1 = 156; // pwm_freq = F_CPU/prescaler/ICR1  ---> 20 ms (50 Hz)                          
    OCR1A=16; // na wejsciu slabe swiecenie LED PB1 i PB2
    OCR1B=16;
    DDRB   |= (1<<PB1) | (1<<PB2);

    //ustawienie ADC na PC0 i PC1
   	ADMUX |= (1 << REFS0) | (1 << ADLAR); // AVCC jako napiecie odniesienia i odczyt tylko ADCH (left adjusted)
	ADCSRA |= (1 << ADPS2) |(1 << ADPS1) |(1 << ADPS0); //prescaler przetwornika ustawiony na 128	
	ADCSRA |= (1 << ADEN); // przetwornik wlaczony

    sei();

	while(1) 
{	
    //wybranie kanalu ADC, uruchomienie konwersji, ustawienie nowej wartosci OCR1A -> szerkosc PWM
	ADMUX &= ~(1<< MUX0);
	ADCSRA |= (1 << ADSC);
	while( ADCSRA & (1<<ADSC) );
	OCR1A = 8+ ADCH/8;

    //wybranie kanalu ADC, uruchomienie konwersji, ustawienie nowej wartosci OCR1A -> szerkosc PWM
	ADMUX |= (1 << MUX0);
	ADCSRA |= (1 << ADSC);
	while( ADCSRA & (1<<ADSC) );
	OCR1B = 8+ ADCH/8;

}
	return 0;
}

Proszę o pomoc w rozwikłaniu zagadki. Pozdrawiam. 😊

Link do komentarza
Share on other sites

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Anonim
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.

×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.