ATMega16 USART interupt?

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
Knoen
Inlägg: 103
Blev medlem: 11 oktober 2006, 08:50:57
Ort: Örebro

ATMega16 USART interupt?

Inlägg av Knoen »

Har försökt få usart interupt att fungera men utan att lyckas. Om jag kör den med Polling så fungerar allt fint. Men det verkar som om interupten inte vill fungera alls.

Så här har jag skrivit

Kod: Markera allt





int main()
{
	DDRB = 0xFF;
	USART_Init( MYUBRR );
	PORTB = 0b11111111;

	
	while( 1 )
	{
		  
	}
}

SIGNAL(SIG_UART_RECV)
{
		
		unsigned char data = UDR;
		if (data == '1' )
		{
			
		               if( PORTB == 0b11111111 )
				PORTB = 0b11111101;
			else
				PORTB = 0b11111111;

				return 0;
		}

		return 0;
}







void USART_Init( unsigned int ubrr )
{
	
	sbi(SREG,7); // Global interupt flag set
 	// interupt flag for USART send and receive
	sbi(UCSRB, 7); 
	sbi(UCSRB, 6);

	// Set baudrate
	UBRRL = 0x33; //set baud rate lo
 	UBRRH = 0x00; //set baud rate hi // 9600

	// enable receiver and transmitter
	UCSRB = (1<<RXEN)|(1<<TXEN);

	// Frame format 8 data, 2 stopbits
	UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0);

		// set RXC and TXC flags
}

unsigned char USART_Receive( void )
{
	//  Wait for data to be received 
	while ( !(UCSRA & (1<<RXC)) );

	//Get and return received data from buffer */
	return UDR;
}

void USART_Transmit( unsigned char data )
{

	// wait for emtpy send buffer
	while( !(UCSRA & (1<<UDRE)) );

	// put the data in the buffer, witch sends it
	UDR = data;
}

Tanken är att när den tar emot något så ska en lampa tändas på portb. Vad kan jag ha gjort för fel eftersom det inte fungerar alls?

Dessutom verkar jag inte kunna deklarera en SIGNAL funktion för usart Receive, då får jag ett felmeddelande från kompliatorn att det finns två :(
Användarvisningsbild
Stinrew
Inlägg: 954
Blev medlem: 20 augusti 2006, 03:14:41
Ort: Motala
Kontakt:

Inlägg av Stinrew »

Ursäkta en dum fråga, men börjar din C-fil med följande 3 rader:

#include <avr/io.h>
#include <avr/signal.h>
#include <avr/interrupt.h>

???

Som du skrivit din kod så kommer PORTB_1 bara att tändas om det decimala värdet på det som mottagits på serieporten är 1/0b00000001/0x01.
Vore det inte bättre med (data>0) i stället för (data == '1')??
Vet inte om du avsett ta emot tecknet "1", det decimala värdet för "1" är 49.
Användarvisningsbild
oJsan
EF Sponsor
Inlägg: 1541
Blev medlem: 11 november 2005, 21:36:51
Ort: Umeå
Kontakt:

Inlägg av oJsan »

Testa med ISR(UART_RX_vect) istället för SIGNAL(SIG_UART_RECV).
Se denna sida
SIGNAL är ersatt med ISR men ska (enligt länken) ha samma funktion. UART_RX_vect är det nya namnet för SIG_UART_RECV... så egentligen bör det inte göra någon skillnad, men eftersom din kompilator klagade så bör du testa.

För att vara säker på att du inte dribblar bort dig i if-satser så kan du se till att avbrottsrutinen endast ser ut såhär:

Kod: Markera allt

ISR(UART_RX_vect)
{
  unsigned char data = UDR;
  PORTB = 0b11111101;
  //return 0; ska inte behövas i en ISR.
}
Om utgången går låg har minst ETT avbrott körts.. om inte så nog UART-init knas.

Edit: Men vänta nu! Du har glömt att sätta RXCIE i UCSRB (borde definitivt vara lösningen på problemet!)
Användarvisningsbild
Stinrew
Inlägg: 954
Blev medlem: 20 augusti 2006, 03:14:41
Ort: Motala
Kontakt:

Inlägg av Stinrew »

Nej oJsan det har han inte!
sbi(UCSRB, 7);
Användarvisningsbild
björn
EF Sponsor
Inlägg: 2570
Blev medlem: 29 mars 2004, 23:09:55

Inlägg av björn »

Stinrew har redam sagt det men helt klart verkar felet vara att du endast gör något om du mottagit '1', har du testat överhuvudtaget att tec tända lysdioden direkt i interruptrutinen för att kolla om du kommer dit?

En annan sak är (som dock inte påverkar om du har bibliotek som stödjer alt en gammal ver av gcc) är att sbi() INTE stöds i gcc längre.
Användarvisningsbild
Stinrew
Inlägg: 954
Blev medlem: 20 augusti 2006, 03:14:41
Ort: Motala
Kontakt:

Inlägg av Stinrew »

Det stämmer, men GCC-kompilatorn är iaf bussig att ge error för cbi/sbi
Användarvisningsbild
björn
EF Sponsor
Inlägg: 2570
Blev medlem: 29 mars 2004, 23:09:55

Inlägg av björn »

Ja, det gör den. Jag skrev det mest som en påminelse så att man inte förlitar sig på ett skrivsätt som inte skall användas längre.
Användarvisningsbild
oJsan
EF Sponsor
Inlägg: 1541
Blev medlem: 11 november 2005, 21:36:51
Ort: Umeå
Kontakt:

Inlägg av oJsan »

Stinrew skrev:Nej oJsan det har han inte!
sbi(UCSRB, 7);
Jahapp, så enkelt var alltså inte... Jag skummade igenom koden och såg inget 'RXCIE' (resten av koden har ju fina register/bit-namn). Dessutom fanns texten "// set RXC and TXC flags " i slutet av rutinen, men ingen kod därunder...
Användarvisningsbild
Stinrew
Inlägg: 954
Blev medlem: 20 augusti 2006, 03:14:41
Ort: Motala
Kontakt:

Inlägg av Stinrew »

Nja, jag tror som jag sagt tidigare att felet är ännu enklare.
if (data == '1' )
Den här raden tror jag gör felet.
peter555
Inlägg: 6047
Blev medlem: 12 februari 2006, 10:02:22

Re: ATMega16 USART interupt?

Inlägg av peter555 »

Jag är ingen expert men jag håller själv på och pular med Mega16 nu.

Du gör först:

sbi(UCSRB, 7);
sbi(UCSRB, 6);

Kommer inte de bitarna att nollställas när du gör följande kommando ?

UCSRB = (1<<RXEN)|(1<<TXEN);

En annan fråga, finns det någon bra sammanställning över alla C kommandon ?
Användarvisningsbild
Stinrew
Inlägg: 954
Blev medlem: 20 augusti 2006, 03:14:41
Ort: Motala
Kontakt:

Inlägg av Stinrew »

Kommer inte de bitarna att nollställas när du gör följande kommando ?

UCSRB = (1<<RXEN)|(1<<TXEN);
Det är ingen fara, den kommandoraden shiftar bara in 1'or på RXEN och TXENs bit-positioner i UCSRB-registret(övriga bitpositioner i registret berörs inte).
En annan fråga, finns det någon bra sammanställning över alla C kommandon ?
Menar du för ANSI-C eller AVR-GCC??
peter555
Inlägg: 6047
Blev medlem: 12 februari 2006, 10:02:22

Inlägg av peter555 »

I min C bok står det att "vacated bits are filled with zero", jag hade tror jag problem med det så jag gör alltid:

REG = REG | (1<<bit)

Men det är mycket möjligt att det är onödigt.

Jag började att köra AVR-GCC men eftersom alla Atmels exempel är för IAR så har jag kört den därefter. Det kan vara intressant med båda versionerna. Boken jag har är mera för högnivåprogrammering och inte för maskinnära programmering
Knoen
Inlägg: 103
Blev medlem: 11 oktober 2006, 08:50:57
Ort: Örebro

Inlägg av Knoen »

peter555 -> japp du har rätt. Jag har hittat det felet också :), jag såg det av en slump när jag gick igenom programmet i simulator.

Stinrew -> ingen dum fråga alls. Det var nämligen det som var problemet. Jag hade glömt "signal.h" :vissla:


Nu fungerar det fint. :)

Men har upptäckt att jag har lite bekymmer med Timer0 istället.

Om jag förståt det rätt så innehåller registret TCCR0 CS00, CS01, CS02. Dessa tre bitar avgör vilken Prescale klockan ska ha?

Jag har räknat så här:

Min ATMega16 = 4Mhz. Om jag sätter CS00 = 1, CS01 = 0 och CS02 = 1 får jag en prescale = 1024.

Eftersom det en 8-bitars klocka så bör den ju "overflowa" vid 256. Timern räkar upp en gång på4Mhs / 1024 (= 3906) vanliga klockcykler. Rätt?

Vilket är en gång varje 1/4000000 * 3906 = 0,00097650 sekunder. Om jag uppdaterar en variabel med ett varje gång timern slår om (overflow) och när det nått 1024 så har det gått en sekund.

Har jag tänkt fel? Det är sent och jag borde verkligen sova lite :)

Problemet jag har att det går över en minut mellan omslagen (innan uppräknarvariablen når 1024). Om jag kör det i simulatorn och räknar klockcycklerna mellan varje overflow så tar det nästan 0,07 sekunder mellan overflows.

Vart har jag gjort bort mig i mitt resonemang?

lite kod:

Kod: Markera allt

#define ONE_SECOND 1024

int overflowCount;

SIGNAL(SIG_OVERFLOW0)
{

int main()
{
	overflowCount = 0;
	DDRB = 0xFF;
	USART_Init( MYUBRR );
	PORTB = 0b11111111;
	sbi( TIMSK, 0);
	sbi( TCCR0, 0);
	sbi( TCCR0, 2);
	while( 1 )
	{
  
	}
}

		
	overflowCount++;
	if(  overflowCount == ONE_SECOND )
		{
			if( PORTB == 0b11111111 )
				PORTB = 0b11111101;
			else
				PORTB = 0b11111111;

			overflowCount = 0;
		}
}
peter555
Inlägg: 6047
Blev medlem: 12 februari 2006, 10:02:22

Inlägg av peter555 »

Det borde bli 67 s, 4e6 / (1024*1024*256) =67.1 s

Edit: Fy på mig, man ska alltid göra en dimensionskontroll, det ska naturligtvis vara, (1024*1024*256) / 4e6 =67.1 s. Det blir 2 poängs avdrag på tentan
Senast redigerad av peter555 14 januari 2007, 12:06:57, redigerad totalt 1 gång.
Knoen
Inlägg: 103
Blev medlem: 11 oktober 2006, 08:50:57
Ort: Örebro

Inlägg av Knoen »

Hehe, du har rätt. Jag tänkter helt fel. Har lyckats fixa till det nu. Sova ett par timmar gjorde susen :)
Skriv svar