Sida 1 av 1
Exempelkod i C för interupts efterlyses (AVR)
Postat: 7 november 2005, 21:12:34
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.
Postat: 7 november 2005, 22:25:29
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.
Postat: 8 november 2005, 00:41:45
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
{
}
}
Postat: 8 november 2005, 07:43:26
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
Postat: 11 november 2005, 12:37:48
av vlad
Mycket väl kommenterad kod det där...
Postat: 11 november 2005, 14:58:34
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.
Postat: 11 november 2005, 16:41:12
av PaNiC
Nu har jag lagt till lite kommentarer. Fråga om det är något mer.
Postat: 11 november 2005, 23:52:25
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
Postat: 12 november 2005, 00:05:26
av sodjan
Kör ni samma C kompilator ?
Postat: 12 november 2005, 00:45:07
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

.
Postat: 12 november 2005, 00:47:48
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.
Postat: 12 november 2005, 13:23:24
av speakman
Okej, jag kör avr-gcc 3.4.3 under Linux.
Mvh
speakman
Postat: 15 november 2005, 17:56:04
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á:
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
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
Postat: 16 november 2005, 17:44:41
av Daniel
Jag tackar och bockar för en mkt bra beskrivning rickeboy! Precis vad jag behövde.