Exempelkod i C för interupts efterlyses (AVR)

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
Daniel
Inlägg: 19
Blev medlem: 24 september 2005, 16:56:50
Ort: Göteborg

Exempelkod i C för interupts efterlyses (AVR)

Inlägg av Daniel »

Jag vill lära mig använda interupts och det hade varit kanon om någon har ett bra exempel på detta i C-kod för AVR, t.ex för att "polla" en knapp.
Användarvisningsbild
karlstedt
EF Sponsor
Inlägg: 966
Blev medlem: 14 oktober 2003, 16:55:23
Ort: Lund
Kontakt:

Inlägg av karlstedt »

Jag skulle vilja säga att om du kan C redan är databladen det bästa sättet att lära sig använda interrupt.
Användarvisningsbild
PaNiC
Inlägg: 2610
Blev medlem: 15 augusti 2003, 22:16:15
Ort: Skånelandet

Inlägg av PaNiC »

Polla via en timer då antar jag?

Det här är koden till min nixieklocka som gör bland annat just detta.

Kod: Markera allt

#include "avr/io.h" 
#include "inttypes.h" 
#include "avr/interrupt.h" 
#include "avr/signal.h" 
#include "string.h" 
#include "stdio.h" 

#define clock = 2000000 

	unsigned char secs = 0; 
	unsigned char tsecs = 0; 
	unsigned char mins = 0; 
	unsigned char tmins = 0; 
	unsigned char hrs = 0; 
	unsigned char thrs = 0; 

void delay1() //helt vanlig delayfunktion
	{ 
	unsigned char delayvar1; 
	delayvar1 = 255; 
	while(delayvar1 != 0) 
		{ 
		delayvar1--; 
		} 
	} 

void setup() //fixar till så saker fungerar
	{ 
	DDRA = 0xFF; //PORTA-C outputs
	DDRB = 0xFF; 
	DDRC = 0xFF; 
	DDRD = 0b00011100; //PORTD bit 2-4 outputs
	OCR1A = 31250; //Sätter output compare-register A till 31250, timer1 prescalas även med 64 som gör att interrupt sker en gång i sekunden.
	TCCR1B = (3<<CS10)|(1<<CTC1); //(CK/64) //tre skiftat till CS10 som sätter prescaler till 64 och 1 skiftat till CTC1 som nollställer räknaren vid compare match
	PORTA = 0x00; 
	PORTB = 0x00; 
	PORTC = 0x00; 
	TIMSK = (1<<OCIE1A); //Timer interrupt mask register sätts till att interrupt ska ske vid output compare match 1A
	sei(); //Sätter igång interrupts
	} 




SIGNAL(SIG_OUTPUT_COMPARE1A) //Interrupthandler för output compare 1A
	{ 
	if ((PIND&0x02) == 0)
		{
		hrs++;
		if ((thrs == 2)&&(hrs == 4)) 
			{ 
			hrs = 0; 
			thrs = 0; 
			} 
		}
	if ((PIND&0x01) == 0)
		{
		mins++;
		}
	secs++; 
	if ((secs == 10)) 
		{ 
		secs = 0; 
		tsecs++; 
		} 
	if ((tsecs == 6)) 
		{ 
		tsecs = 0; 
		mins++; 
		} 
	if ((mins == 10)) 
		{ 
		mins = 0; 
		tmins++; 
		} 
	if ((tmins == 6)) 
		{ 
		tmins = 0; 
		hrs++; 
		} 
	if ((hrs == 10)) 
		{ 
		hrs = 0; 
		thrs++; 
		} 
	if ((thrs == 2)&&(hrs == 4)) 
		{ 
		secs = 0; 
		tsecs = 0; 
		mins = 0; 
		tmins = 0; 
		hrs = 0; 
		thrs = 0; 
		} 
	PORTA = ((secs)|(tsecs<<4)); 
	PORTB = ((mins)|(tmins<<4)); 
	PORTC = ((hrs)|(thrs<<4)); 
	} 


int main(void) //Mainloop
	{ 
	setup(); 
	for(;;) //Loop forever
		{ 

		} 
	} 
Senast redigerad av PaNiC 11 november 2005, 16:40:45, redigerad totalt 1 gång.
Användarvisningsbild
speakman
Inlägg: 4838
Blev medlem: 18 augusti 2004, 23:03:32
Ort: Ånge

Inlägg av speakman »

Sedan är frågan lite dubbeltydlig; pollning brukar innebära att man just _inte_ använder interrupt, utan frågar av, i det här fallet, knappen kontinuerligt i huvudloopen.

Mvh
speakman
vlad
Inlägg: 119
Blev medlem: 13 februari 2005, 16:28:47

Inlägg av vlad »

Mycket väl kommenterad kod det där...
Daniel
Inlägg: 19
Blev medlem: 24 september 2005, 16:56:50
Ort: Göteborg

Inlägg av Daniel »

Databladen kanske är det bästa sättet att lära sig interrupts men om man vill lära sig något nytt brukar jag föredra att kika på ett exempel först och titta nogrannare i databladen sen. Tack PaNiC för koden, men som sagt lite kommentarer hade inte skadat.
Användarvisningsbild
PaNiC
Inlägg: 2610
Blev medlem: 15 augusti 2003, 22:16:15
Ort: Skånelandet

Inlägg av PaNiC »

Nu har jag lagt till lite kommentarer. Fråga om det är något mer.
Användarvisningsbild
speakman
Inlägg: 4838
Blev medlem: 18 augusti 2004, 23:03:32
Ort: Ånge

Inlägg av speakman »

Funkar verkligen "DDRD = 0b00011100;" ?
Jag får "invalid suffix "b10111111" on integer constant" om jag försöker mig på det...

Mvh
speakman
sodjan
EF Sponsor
Inlägg: 43247
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

Kör ni samma C kompilator ?
Användarvisningsbild
PaNiC
Inlägg: 2610
Blev medlem: 15 augusti 2003, 22:16:15
Ort: Skånelandet

Inlägg av PaNiC »

Jaså får du det?
Jodå den raden fungerar och har fungerat hela tiden.

Jag kör WinAVR-pluginen till AVRStudio. Rekommenderas varmt :).
Användarvisningsbild
cykze
EF Sponsor
Inlägg: 1539
Blev medlem: 8 april 2004, 10:40:28
Ort: Uppsala

Inlägg av cykze »

Att ange binära tal på det där viset har fungerat för mig förut, men inte längre. Jag tror att det beror på vilken version av avr-gcc man kör.
Användarvisningsbild
speakman
Inlägg: 4838
Blev medlem: 18 augusti 2004, 23:03:32
Ort: Ånge

Inlägg av speakman »

Okej, jag kör avr-gcc 3.4.3 under Linux.

Mvh
speakman
Användarvisningsbild
rickeboy
Inlägg: 678
Blev medlem: 13 augusti 2003, 09:12:17
Ort: Göteborg / Karlskrona
Kontakt:

Inlägg av rickeboy »

Tycker inte ngn har gett dig ngn direkt grund att stå på så här tänkte jag fylla i med det jag anser vara bra att kunna om interrupts samt vart du ska titta om du funderar lite när du väl sitter där och programmerar...

Det man kan konstatera är att det är lite olika beroende på vilken kompilator du använder också... jag förklarar för AVR-GCC...
http://www.nongnu.org/avr-libc/
http://www.nongnu.org/avr-libc/user-manual/index.html


Först och främst så har du din main-loop alá:

Kod: Markera allt

int main(void) {

//Tjolla hoppsan sig!

}
För att sedan fixa ngt interrupt måste du fixa en interrupt-handler dvs en rutin micron hoppar till om ett interrupt sker... det vi då direkt konstaterar är att det finns två olika interrupts handlers att välja mellan nämligen

Kod: Markera allt

SIGNAL()
och
INTERRUPT()
För att använda dessa måste vi även inkludera filen signal.h

Vad är det nu för skillnad? Jo... nämligen prioriteten... dvs om det får ske andra sorters interrupts när du väl är inne i en interrupts handler för ett annat interrupt.

Vad för sorts interrupt är det vi vill ha? Dags att kolla i listan! http://www.nongnu.org/avr-libc/user-man ... rupts.html

T ex för att ta hand om det externa interruptet 0 måste vi alltså skriva ngt i stil med detta:

Kod: Markera allt

//INKLUDERA NÖDVÄNDIGA FILER!
#include bla bla
#include <signal.h>

SIGNAL(SIG_INTERRUPT0)
{
    //Säg hej!
}

int main (void) {

sei();

}
sei(); Gör så att vi globalt enablar interrupts!

Jaja... sry... hinner inte skriva mer nu...
en bit av en förklaring som förhoppningsvis hjälper...
Det man ska tänka på i interrupts är att inte ha loopar som kan ta en evighet etc... interrupt handler ska vara snabb och snärtig!

//rickeboy
Daniel
Inlägg: 19
Blev medlem: 24 september 2005, 16:56:50
Ort: Göteborg

Inlägg av Daniel »

Jag tackar och bockar för en mkt bra beskrivning rickeboy! Precis vad jag behövde.
Skriv svar