Skocz do zawartości

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


Pomocna odpowiedź

Napisano

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. 😊

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...