AVR-kod kastar ingen interrupt. Varför?

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
mattswe
Inlägg: 159
Blev medlem: 20 augusti 2012, 13:27:51

AVR-kod kastar ingen interrupt. Varför?

Inlägg av mattswe »

Ok, AVR-specialister. Nedanstående kod verkar inte kasta något interrupt och jag begriper inte varför. Den är skriven i Atmel Studio 6 och exekveras i en ATtiny45.
På T0 (klockingången) har jag för tillfället anslutit en liten tangentbordsknapp som är hårdvarumässigt "avstudsad". Den signalen ser hur fin ut som helst på oscilloskopet (10uF, 10k och en Inv. Schmittrigger). Jag förväntar mig alltså att då jag tryckt på knappen 5 gånger ska led:en på PB1 tändas, men det händer ingenting.

Kod: Markera allt

#define F_CPU 8000000UL
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>

int main(void)
{
	DDRB |= (0 << PB2); // Pin PB2(T0) markeras som input (vilket är default)
	DDRB |= (1 << PB1); // Pin PB1 markeras som output
	PORTB |= (1 << PB2); // Aktiverar pullup-resistorn
	
	//Kontrollblink
	PORTB |= (1<<PB1);
	_delay_ms(500);
	PORTB &= (0<<PB1);

	cli(); // Stänger av globala interrupts (clear interrupts)
	
	TCCR0A = 0; // Sätter hela registret till 0	
	TCCR0B = 0;

	TCCR0B |= (1 << CS00); //Extern klocka på T0. Stigande flank.
	TCCR0B |= (1 << CS01); //Extern klocka på T0. Stigande flank.
	TCCR0B |= (1 << CS02); //Extern klocka på T0. Stigande flank.
	
	TCCR0A |= (0 << WGM00); // Mode CTC (Clear Timer on Compare Match Mode)
	TCCR0A |= (1 << WGM01); // Mode CTC
	TCCR0B |= (0 << WGM02); // Mode CTC

	OCR0A = 5; // Räknarens upplösning, TOP-värde.
	
	TIMSK = (1 << OCIE0A); // Aktiverar interrupt för TCNT0 = OCR0A (TOP-värdet är nått)
	
	sei(); // Slår på globala interrupts (set interrupts)

    while(1)
    {
    }
}

ISR(TIMER0_COMPA_vect)
{
	//Kontrollblink
	PORTB |= (1<<PB1);
}
bearing
Inlägg: 11669
Blev medlem: 2 mars 2006, 01:01:45
Ort: Ängelholm

Re: AVR-kod kastar ingen interrupt. Varför?

Inlägg av bearing »

Räknar räknaren nedåt?

Jag tror den räknar uppåt. Du ska alltså initiera med värdet -5, alternativt trycka 250 gånger.
sodjan
EF Sponsor
Inlägg: 43243
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: AVR-kod kastar ingen interrupt. Varför?

Inlägg av sodjan »

Det är väl en "compare" funktion?
När TCNT0 = OCR0A så bör interruptet utföras.
Jag vet inte varför det inte fungerar, men bara
som en kommentar till bearing... :-)
bearing
Inlägg: 11669
Blev medlem: 2 mars 2006, 01:01:45
Ort: Ängelholm

Re: AVR-kod kastar ingen interrupt. Varför?

Inlägg av bearing »

Aha, så klart.

Jag kan inte heller se något fel. Men, mattswe, ditt sätt att sätta bitarna ger inte alltid önskat resultat. T.ex. denna rad: PORTB &= (0<<PB1); - vilken AND-ar porten med 0, d.v.s. tar bort pull-up på ingången. Fast ifall ingången är ansluten till en digital utgång från en schmitt-trigger borde ju inte det spela någon roll.

Även TCCR0B |= (0 << WGM02); är tveksam kod, eftersom att det inte förändrar något att göra OR med 0. Men eftersom att du skrivit 0 till registrena innan, borde det inte innebära ett fel.

Om du vill ändra bitarna abc till 010 måste du göra såhär:

Kod: Markera allt

REGISTERX &= ~(1 << BITa);
REGISTERX |=  (1 << BITb);
REGISTERX &= ~(1 << BITc);
Alternativt sätta alla önskade bitar på en gång (utan varken AND eller OR):

Kod: Markera allt

REGISTERX = (0 << BITa) | (1 << BITb) | (0 << BITc);
Användarvisningsbild
Swech
EF Sponsor
Inlägg: 4743
Blev medlem: 6 november 2006, 21:43:35
Ort: Munkedal, Sverige (Sweden)
Kontakt:

Re: AVR-kod kastar ingen interrupt. Varför?

Inlägg av Swech »

Du sätter väl också inte själva räknaren till 0 vid start?
Om räknaren är > 5 så gör den ingen clear on compare förrän den slagit runt och
kommer till 5 igen

Swech
Bylin
Inlägg: 9
Blev medlem: 7 januari 2009, 22:33:52

Re: AVR-kod kastar ingen interrupt. Varför?

Inlägg av Bylin »

TCNT0 kommer att vara större än 5 innan interrupt för compare register A sätts.

Tänk på att TIMER0 blir aktiverad så fort någon av CS bitarna sätts. Eftersom CS00 först sätts så kommer räknaren att börja räkna där enligt CS00 mode. När CS01 sätts kommer räknaren att räkna enligt CS01 + CS00 mode osv. Det är inte fören CS02 sätts som räknaren kommer att stoppa och hamna i extern clock mode.

Därför så har räknaren redan räknat ett tag innan instruktionen "TCCR0A |= (1 << WGM01)" utförs.

Du kan nolla TIMER0 innan sei(); instruktionen eller sätta registervärdena samtidigt och inte behöva nolla TIMER0.

Pröva med denna kod:

Kod: Markera allt

OCR0A = 5;
TIMSK = (1 << OCIE0A);
TCCR0A = (1<<WGM01);
TCCR0B = (1<<CS00)+(1<<CS01)+(1<<CS02);
sei();

mattswe
Inlägg: 159
Blev medlem: 20 augusti 2012, 13:27:51

Re: AVR-kod kastar ingen interrupt. Varför?

Inlägg av mattswe »

Tack, när jag nollställer TCNT0 (eller använder Bylins kod) så fungerar det. Ett litet mysterium återstår dock. Jag måste trycka på knappen 6 gånger innan led:en tänds. Varför 6 och inte 5?!?
Men, mattswe, ditt sätt att sätta bitarna ger inte alltid önskat resultat.
Tack för denna anmärkning, ska tänka på det. Jag ska alltid skifta in en etta alltså, aldrig en nolla?
Även TCCR0B |= (0 << WGM02); är tveksam kod, eftersom att det inte förändrar något att göra OR med 0.
Jag förstår att detta inte har någon funktion, ville bara tydliggöra koden för mig själv, är tämligen grön på att programmera uC.
sodjan
EF Sponsor
Inlägg: 43243
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: AVR-kod kastar ingen interrupt. Varför?

Inlägg av sodjan »

> Jag måste trycka på knappen 6 gånger innan led:en tänds. Varför 6 och inte 5?!?

Jag vet inte mycket om AVR, men i databladet (kap 11.5 i DOC2586.PDF) står det:
"A match will set the Output Compare Flag (OCF0A or OCF0B) at the next timer clock cycle."

Fundera lite på vad "next timer clock" betyder just i ditt fall.
Timern "klockas" ju just från tryckknappen, eller hur?
mattswe
Inlägg: 159
Blev medlem: 20 augusti 2012, 13:27:51

Re: AVR-kod kastar ingen interrupt. Varför?

Inlägg av mattswe »

Kod: Markera allt

Jag vet inte mycket om AVR, men i databladet (kap 11.5 i DOC2586.PDF) står det:
"A match will set the Output Compare Flag (OCF0A or OCF0B) at the next timer clock cycle."
Ok, det förklarar ju saken. Jag har nog läst det men all databladets info är lite överväldigande än så länge.

Tack för hjälpen!
sodjan
EF Sponsor
Inlägg: 43243
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: AVR-kod kastar ingen interrupt. Varför?

Inlägg av sodjan »

Och "lösningen" är alltså, vadå? :-)
mattswe
Inlägg: 159
Blev medlem: 20 augusti 2012, 13:27:51

Re: AVR-kod kastar ingen interrupt. Varför?

Inlägg av mattswe »

Tja, lösningen var ju att nollställa TCNT0. Precis som du skrev så kastas interrupten vid "nästa klockcykel", alltså vid den sjätte pulsen, klockcykeln, från knappen. Nu ska jag byta ut knappen mot en "brusig" tachometersignal och mäta varvtal. :)
Neptunus
Inlägg: 41
Blev medlem: 3 september 2012, 08:54:59

Re: AVR-kod kastar ingen interrupt. Varför?

Inlägg av Neptunus »

Intressant svar på Sodjans fråga. Jag skulle nog använda fyra istället för fem för att tända upp dioden efter 5 knapptryck.

OCR0A = 4;
sodjan
EF Sponsor
Inlägg: 43243
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: AVR-kod kastar ingen interrupt. Varför?

Inlägg av sodjan »

> Tja, lösningen var ju att nollställa TCNT0.

Ja, lösningen på det *gamla* problemet, det du undrade över nu
var ju varför du måste trycka sex gånger. Och "lösningen" som jag
frågade efter är ju så klart den som Neptunus angav...
mattswe
Inlägg: 159
Blev medlem: 20 augusti 2012, 13:27:51

Re: AVR-kod kastar ingen interrupt. Varför?

Inlägg av mattswe »

Ok, jag förstår.
Skriv svar