Sida 1 av 3

Interrupt frågor AVR

Postat: 24 juli 2005, 12:45:03
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).

Postat: 24 juli 2005, 13:33:37
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...)

Postat: 24 juli 2005, 13:46:55
av björn
Fixat, så nu slipper di klicka i onödan.

Postat: 24 juli 2005, 13:57:56
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

Postat: 24 juli 2005, 14:34:39
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.

Postat: 24 juli 2005, 15:57:46
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

Postat: 24 juli 2005, 17:48:17
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....

Postat: 24 juli 2005, 18:10:27
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

Postat: 24 juli 2005, 18:40:46
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)

Postat: 24 juli 2005, 18:47:20
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.

Postat: 24 juli 2005, 18:48:23
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

Postat: 24 juli 2005, 18:52:52
av björn
ok, skall lägga på en led. inb() funkade inte i kompileringen " undefined reference to `inb' "

Postat: 24 juli 2005, 18:52:58
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

Postat: 24 juli 2005, 19:00:01
av björn
hehe, jo det märkte jag när jag kompilerade....

Postat: 24 juli 2005, 19:06:55
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.