Interrupt frågor AVR
Interrupt frågor AVR
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).
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.
Observera att koden inte gör något nyttigt.
(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
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;
}
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
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
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
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....
OK, skickar hela koden:
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
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: ändrat kod, men funkar inte
EDIT3: jag har testat med både SIGNAL o INTERRUPT
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
i interrupten, men det kom aldrig till datorn.
Ingenting skickas från avr till dator...
editerade lite.
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;
}
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.
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
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.