Interrupt frågor AVR

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
Användarvisningsbild
björn
EF Sponsor
Inlägg: 2570
Blev medlem: 29 mars 2004, 23:09:55

Interrupt frågor AVR

Inlägg av björn »

tjena, nu var det dags för frågestund igen....
Jag hade tänkt köra ett interrupt på min atmega16 när den får data på uarten, men då kom jag fram till att jag fattar överhuvudtaget inte hur man använder interrupt.
Jag har läst i databladet och en del i WinAVR's manual, men jag är inte med på hur man skall koda det.

Finns det något mer på nätet man kan läsa? Programkod skulle vara inressant, men isåfall lätta exempel(för att sätta mig in i hur andra tänker och behöver tar tid).
Senast redigerad av björn 25 juli 2005, 17:35:49, redigerad totalt 3 gånger.
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

Besvarar kanske inte dina frågor, men...

Varför inte ange "AVR" i trådens "subject", så att vi/jag som inte jobber med AVR inte behöver öppna den i onödan ??? (Allat tar tid när man kör modem...)
Användarvisningsbild
björn
EF Sponsor
Inlägg: 2570
Blev medlem: 29 mars 2004, 23:09:55

Inlägg av björn »

Fixat, så nu slipper di klicka i onödan.
Användarvisningsbild
cykze
EF Sponsor
Inlägg: 1539
Blev medlem: 8 april 2004, 10:40:28
Ort: Uppsala

Inlägg av cykze »

Observera att koden inte gör något nyttigt.

Kod: Markera allt

#include <avr/io.h>

#define FOSC 1000000 //clock
#define BAUD 4800 //baudrate
#define MYUBRR FOSC/16/BAUD-1

volatile uint8_t senaste_vardet; // volatile eftersom variabeln används innefrån en interrupt-rutin. 

// Anropas när U(S)ART:en har tagit emot ett tecken
SIGNAL (SIG_USART_RECV)
{
    senaste_vardet = UDR;
}

int main()
{
    UBRRH = (unsigned char)(MYUBRR>>8);
    UBRRL = (unsigned char)MYUBRR;

    UCSRB = _BV(RXCIE) | _BV(RXEN) | _BV(TXEN); // RXCIE anger att vi vill att en interrupts ska inträffa när det finns något nytt att läsa

    sei(); // Slår på "huvudströmbrytaren" för interrupts

    while (1)
    {
    // gör ingenting
    }

    return 0;
}
(Tog lite kod från din andra tråd.)

Det finns en del saker man måste tänka på när man använder interrupts. Här är några,

* Se till att innehållet i interruptrutinen tar så kort tid som möjligt att köra igenom.
* Använd nyckelordet 'volatile' för globala variabler som både interruptrutiner och "den vanliga koden" använder. Annars kan det hända att betydelsefull kod optimeras bort på ett eller annat sätt.
* Tänk på att en interrupt kan inträffa i alla möjliga ställen i programkoden. Läser du t ex in ett 16-bitarsvärde som ligger som en global variabel och det inträffar en interrupt som ändrar i den 16-bitarsvariabeln har du problem.

De är nog de viktigaste iaf.

edit: ubrr -> MYUBRR
frejo
Inlägg: 496
Blev medlem: 21 april 2004, 21:43:01
Ort: Linköping

Inlägg av frejo »

Vill du va säker på att en viss kod inte avbryts av interruptet så skriv cli() ovanför för att stänga av och sen sei() efteråt.

Hur alla olika interrupt definieras finns beskrivet i AVRLibC manualen.
Användarvisningsbild
björn
EF Sponsor
Inlägg: 2570
Blev medlem: 29 mars 2004, 23:09:55

Inlägg av björn »

tack, då var det inte så svårt som jag trodde.
Men jag fastnar som vanligt ändå...

Skall man inte kunna göra såhär då för att eka tillbaka det som kommer in på usarten bara?Jag vet att det inte är en snygg lösning men det borde väl funka?

SIGNAL (SIG_USART_RECV)
{
senaste_vardet = UDR;
while ( !(UCSRA & (1<<UDRE)) )
; /* Wait for empty transmit buffer */
UDR = senaste_vardet; /* Start transmittion */
}

Jag får bara tillbaka 00
Användarvisningsbild
erixon
Inlägg: 380
Blev medlem: 27 augusti 2003, 10:21:58

Inlägg av erixon »

Du får gärna skicka med hela koden och använda "

Kod: Markera allt

" tagarna, rent spontat så tycker jag att det bör fungera dock behöver du inte while () efter som avr kan skicka lika snabt som den tar imot...
Men som sagt... det är oftast lättare och hjälpa om man kan se "hela" koden då felet kan vara på helt annat ställe en vad man tror....
Användarvisningsbild
björn
EF Sponsor
Inlägg: 2570
Blev medlem: 29 mars 2004, 23:09:55

Inlägg av björn »

OK, skickar hela koden:

Kod: Markera allt

#include <avr/io.h>
#include <avr/interrupt.h>
#define FOSC 1000000 //clock
#define BAUD 4800 //baudrate
#define MYUBRR ((FOSC/16)/BAUD-1)
void USART_init (unsigned int);
volatile uint8_t senaste_vardet; 

void USART_init (unsigned int ubrr){
	/*set budrate*/
	UBRRH = (unsigned char)(ubrr>>8);
	UBRRL = (unsigned char)ubrr;
	/*Enable receiver and transmitter*/
	UCSRB = _BV(RXCIE) | _BV(RXEN) | _BV(TXEN);
	/*set frameformat : 8 databits 1 stop bits*/
	//UCSRC = (1<<URSEL) |(1<<USBS) | (3<<UCSZ0);

}


INTERRUPT (SIG_USART_RECV)
{
     senaste_vardet = UDR;
      UDR=senast_vardet;
}


int main (void){

         USART_init (MYUBRR);
         sei();
              for (;;){
                       // Gör ingenting
}
}



 
EDIT: Jag såg att jag missat lite, återkommer med ny kod
EDIT: ändrat kod, men funkar inte
EDIT3: jag har testat med både SIGNAL o INTERRUPT
Användarvisningsbild
cykze
EF Sponsor
Inlägg: 1539
Blev medlem: 8 april 2004, 10:40:28
Ort: Uppsala

Inlägg av cykze »

Det ska vara,
SIGNAL (SIG_USART_RECV)
inte,
INTERRUPT (SIG_USART_RECV)

INTERRUPT ska du vara _extremt_ försiktig med då den tillåter att interrupts interruptar interrupts!

Fast det är inte säkert att det är det som ställer till det i det här fallet.

Tar AVR:en emot rätt värde?

edit: (såg din edit3)
Användarvisningsbild
björn
EF Sponsor
Inlägg: 2570
Blev medlem: 29 mars 2004, 23:09:55

Inlägg av björn »

Ok, jag läste något om det med signal med. men jag testade båda...
Jag tror inte att avren kommer in i interrupten överhuvudtaget för jag testade att lägga in

Kod: Markera allt

 

INTERRUPT (SIG_USART_RECV)
{
UDR = 0xff
     //senaste_vardet = UDR;
      //UDR=senast_vardet;
} 


i interrupten, men det kom aldrig till datorn.
Ingenting skickas från avr till dator...

editerade lite.
Senast redigerad av björn 24 juli 2005, 18:49:44, redigerad totalt 2 gånger.
frejo
Inlägg: 496
Blev medlem: 21 april 2004, 21:43:01
Ort: Linköping

Inlägg av frejo »

Har sett kod där det står
senaste_vardet = inb(UDR);

vet inte om det gör nån skillnad...

vill du säkert se om den kommer in i interrupten eller ej så lägg en pinne hög i interruptrutinen och mät på den eller sätt en led där. Brukar alltid ha med en led ur felsökningsynpunkt.

Vet inte vad som skiljer UCSRB och UCR men i avrlib används:

// enable RxD/TxD and interrupts
outb(UCR, BV(RXCIE)|BV(TXCIE)|BV(RXEN)|BV(TXEN));

http://hubbard.engr.scu.edu/embedded/av ... ource.html

edit:
inget skiljer dom, hitta denna rad i uart.h
#define UCR UCSRB
Senast redigerad av frejo 24 juli 2005, 18:54:14, redigerad totalt 1 gång.
Användarvisningsbild
björn
EF Sponsor
Inlägg: 2570
Blev medlem: 29 mars 2004, 23:09:55

Inlägg av björn »

ok, skall lägga på en led. inb() funkade inte i kompileringen " undefined reference to `inb' "
Användarvisningsbild
speakman
Inlägg: 4838
Blev medlem: 18 augusti 2004, 23:03:32
Ort: Ånge

Inlägg av speakman »

Det kanske inte har nån betydelse för just ditt problem, men lägg märke till att det står "senaste_vardet" på ena stället, och "senast_vardet" på andra. ;)

Mvh
speakman
Användarvisningsbild
björn
EF Sponsor
Inlägg: 2570
Blev medlem: 29 mars 2004, 23:09:55

Inlägg av björn »

hehe, jo det märkte jag när jag kompilerade....
frejo
Inlägg: 496
Blev medlem: 21 april 2004, 21:43:01
Ort: Linköping

Inlägg av frejo »

Ett annat alternativ kan ju va att ta ett färdigt exempel från AVRLib för att se om hårdvaran fungerar som den ska och sen gå vidare med sin egen kod.
Skriv svar