Sida 1 av 2

Timer0 på en Mega16 gör ingenting

Postat: 13 mars 2007, 19:44:30
av MicaelKarlsson
Jag har testat denna kod (för WinAVR) i min Mega16 som sitter i en STK500:

Kod: Markera allt

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

ISR(TIMER0_OVF_vect)
{
  PORTB ^= 0xFF;
  TCNT0=0;
}


int main ( void )
	{
	// Setup timer0
	TCCR0 = (1<<CS02)|(1<<CS00); 	//Timer clock = system clock/1024. 	
	TIMSK = 1;		 				//Enable Timer0 Overflow. Interrupt
	DDRB = 0xFF; 					//Set Port B as output.
	PORTB=0xFF;
	while (1)
		{
		asm volatile ("nop"::);
		}
	}
Det verkar som om timern startar i AVRStudio men det blir inte mycket blinkande.
Har stirrat mig blind på koden, vad är det för fel?
Har kikat på denna app-note: http://atmel.com/dyn/resources/prod_doc ... oc2505.pdf
Men inget funkar. :(

Postat: 13 mars 2007, 19:50:58
av Millox
Du vill nog använda |= istället för ^=. Du kommer annars att mata in 0x00 i registret hela tiden.

Postat: 13 mars 2007, 19:54:46
av Micke_s
Vad sägs om att slå på att interrupt kan hända, globala interruptflaggan?

Kod: Markera allt

 sei();  //i winavr.

Postat: 13 mars 2007, 20:32:34
av syltkaka
Urklipp ur "signal.h"

Kod: Markera allt

#warning "This header file is obsolete.  Use <avr/interrupt.h>."
#include <avr/interrupt.h>
Det är helt rätt att skriva '^=' om du vill att dem ska blinka.

EDIT: Tillägg

Postat: 14 mars 2007, 17:43:49
av MicaelKarlsson
Har ändrat i koden (se nedan) men med samma usla resultat. :(

Kod: Markera allt

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/delay.h>
#define bit_flip(p,m) ((p) ^= (m))
ISR(TIMER0_OVF_vect)
	{
	bit_flip(PORTB,1);  
	}


int main ( void )
	{
	// Setup timer0
	TCCR0 = (1<<CS02)|(1<<CS00); 	//Timer clock = system clock/1024.
	TIMSK =0x00;		 				//Enable Timer0 Overflow Interrupt.
	TCNT0=0;
	DDRB = 0xFF; 					//Set Port B as output		
	sei();
	while (1)
		{
		asm volatile ("nop"::);
		}
	}
Har kompilerat den för en Mega162 och Mega32 med samma usla resultat.

Någon som kan testa om koden fungerar?

Gjorde en test med följande i while(1)-loopen:

Kod: Markera allt

	//	_delay_us(150); //Bara för test.
	//	bit_flip(PORTB,1);
och den blinkar som den skall. Varför i hela fridens namn får jag inte igång timern? Vad är det jag missat?
Jag blir nog snart flintskallig :twisted:


EDIT

Kod: Markera allt

SIGNAL(TIMER0_OVF_vect)  //<---- Där var felet!!
{
  //PORTB ^= 0xFF;
  TCNT0=150;
  bit_flip(PORTB,1); 
}
Har hittat felet:
Kompilatorn fattade inte ISR men när jag gick över till SIGNAL gick det som smort! :D :D

Kanske dags att uppdatera! 8)

Postat: 14 mars 2007, 22:30:32
av syltkaka
Vilken version av WinAVR hade du då?

Känns konstigt att kombinationen av att använda interrupt.h och SIGNAL skulle fungera men uppenbarligen så fungerade det.

Postat: 15 mars 2007, 11:56:49
av MicaelKarlsson
Det är du inte ensam om syltkaka! Men SIGNAL finns med i interrupt.h

Kör (körde) med WinAVR-20060421, skall uppdatera i dag (15 mars)

Postat: 15 mars 2007, 12:06:40
av thepirateboy
Jag provade också koden och den hoppade aldrig in i interruptet. Jag kör senaste WinAVR (tror jag). Mycket märklig bugg...

Postat: 15 mars 2007, 12:12:56
av MicaelKarlsson
:? Mysko, skall uppdatera och se vad som händer. :pray:

Edit:
Uppdaterade WinAVR till 20070122 och då rasade AVRStudio 4.12 så efter en stunds uppdaterande så fungerar nu allt (tror jag) som det skall och följande kod blinkar fint.

Kod: Markera allt

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

#define bit_flip(p,m) ((p) ^= (m))


ISR(TIMER0_OVF_vect)
{  
  TCNT0=0;
  bit_flip(PORTB,1); 
}

int main ( void )
{
  // Setup timer0
  TIMSK |= (1 << TOIE0);  // Enable timer0 overflow interupt.
  TCCR0 |= (1 << CS00)|(1 << CS02); // CK/1024
  TCNT0 = 0;  // set timer counter to 0;
  sei();  //Enable interupts.
  DDRB = 0xFF;    // Configure PortB as output
  PORTB = 0xFF;
  while (1)
    {
      asm volatile ("nop"::);
    }
}
Så om ni får problem med att något inte fungerar som det skall så kan ni ta en titt i lss-filen.

Postat: 15 mars 2007, 17:44:16
av cykze
Varför har du "nop" i while-loopen? Den gör ju ingenting.

Postat: 15 mars 2007, 17:48:26
av MicaelKarlsson
Den bara "slank med". Som du säger, den gör ju inget så jag har inte fått ut tummen och raderat raden.

Postat: 15 mars 2007, 19:56:21
av sodjan
> Varför har du "nop" i while-loopen?

Jag vet inte hur det är i just *detta* fall, men många
kompilatorer plockar helt enkelt bort tomma loopar.
Att lägga en asm NOP där förhindrar det.

Postat: 16 mars 2007, 14:31:09
av MicaelKarlsson
sodjan: Har testat med och utan:

Kod: Markera allt

 asm volatile ("nop"::); 
Och du har rätt, se nedan:

Utan
asm NOP i while(1)

Kod: Markera allt

int main ( void )
	{
  de:	89 b7       	in	r24, 0x39	; 57
  e0:	81 64       	ori	r24, 0x41	; 65
  e2:	89 bf       	out	0x39, r24	; 57
	// Setup timer0
	TIMSK |= (1 << TOIE0);  // Enable timer0 overflow interupt.
	TCCR0 |= (1 << CS00); // CK/1 
  e4:	83 b7       	in	r24, 0x33	; 51
  e6:	81 60       	ori	r24, 0x01	; 1
  e8:	83 bf       	out	0x33, r24	; 51
	
	TCNT0= 0;  // set timer counter to 0;
  f0:	12 be       	out	0x32, r1	; 50
	
  sei();  //Enable interupts.
  f4:	78 94       	sei

  DDRB = 0xFF;    // Configure PortB as output
  f6:	8f ef       	ldi	r24, 0xFF	; 255
  f8:	87 bb       	out	0x17, r24	; 23

  PORTB = 0xFF;
  fa:	88 bb       	out	0x18, r24	; 24
  fc:	ff cf       	rjmp	.-2      	; 0xfc <main+0x1e>
och med asm volatile ("nop":: );

Kod: Markera allt


int main ( void )
	{
  de:	89 b7       	in	r24, 0x39	; 57
  e0:	81 64       	ori	r24, 0x41	; 65
  e2:	89 bf       	out	0x39, r24	; 57
	// Setup timer0
	TIMSK |= (1 << TOIE0);  // Enable timer0 overflow interupt.
	TCCR0 |= (1 << CS00); // CK/1
  e4:	83 b7       	in	r24, 0x33	; 51
  e6:	81 60       	ori	r24, 0x01	; 1
  e8:	83 bf       	out	0x33, r24	; 51
	TCCR2 |= (1 << CS22)|(1 << COM20); // CK/64 (1 << CS21)|
  ea:	85 b5       	in	r24, 0x25	; 37
  ec:	84 61       	ori	r24, 0x14	; 20
  ee:	85 bd       	out	0x25, r24	; 37

	TCNT0= 0;  // set timer counter to 0;
  f0:	12 be       	out	0x32, r1	; 50
  sei();  //Enable interupts.
  f4:	78 94       	sei

  DDRB = 0xFF;    // Configure PortB as output
  f6:	8f ef       	ldi	r24, 0xFF	; 255
  f8:	87 bb       	out	0x17, r24	; 23

  PORTB = 0xFF;
  fa:	88 bb       	out	0x18, r24	; 24

  while (1)
    {
      asm volatile ("nop"::);
  fc:	00 00       	nop
  fe:	fe cf       	rjmp	.-4      	; 0xfc <main+0x1e>
Som synes försvinner while(1) {} helt och hållet.

Kanske skall tillägga att kodsnuttarna är hämtade från .lss-filen som WinAVR skapar vid kompilering av C-koden.

Postat: 16 mars 2007, 14:49:14
av Micke_s
Den försvinner inte alls eller kan vara så att avr gcc lägger till en loop längst ner i main också.

Kod: Markera allt

  fc:   ff cf          rjmp   .-2         ; 0xfc <main+0x1e> 
loopar till sig själv hela tiden.

Postat: 16 mars 2007, 15:24:17
av syltkaka
Då är frågan hur det ser ut om man tar bort while-loopen helt och hållet.