Sida 1 av 1

Problem med if-sats

Postat: 7 juni 2020, 17:08:51
av Glattnos
Vad är problemet här:

Kod: Markera allt

int x;

while (1) 
{
   if(x > 2)
   {
      PORTB ^= 1 << STEP_PIN; //Toggle STEP-pin
      x = 0;
   }
}
Borde det inte betyda att om värdet av x är större än 2 så ska if-koden köras?

Hela koden:

Kod: Markera allt

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

#define STEP_PIN 1

int x;

ISR (TIM0_OVF_vect) //Timer0 OverFlow vector
{
	x++;
}

int main(void)
{
    DDRB = (1<<DDB1)|(1<<DDB0); //Set pin 0(DIR) and 1(STEP) as outputs
	
	TCCR0B = (0<<CS02)|(1<<CS01)|(0<<CS00); //Start Timer0
	TIMSK0 = (1<<TOIE0); //TimerOverflowInterruptEnable
	
	sei(); //EnableGlobalInterrupt
	
    while (1) 
    {
		if(x > 2)
		{
			PORTB ^= 1 << STEP_PIN; //Toggle STEP-pin
			x = 0;
		}	
    }
}
x ökar med 1 varje gång timern ger overflow men den går aldrig in i if-koden och nollställer x :humm:

Re: Problem med if-sats

Postat: 7 juni 2020, 17:13:27
av Shimonu
X var inte definierad första gången det kördes

.

Re: Problem med if-sats

Postat: 7 juni 2020, 17:26:49
av Glattnos
Jag är inte helt med på hur du menar. Om man kollar på hela koden, borde inte det funka då?
I Atmel Studios simulator ser jag att x bara ökar och ökar men den hoppar över if-koden varje gång. Har kört koden på en uC också och det är samma resultat. Skriver jag "if(1)" så går den in och skapar en fyrkantsvåg ut :humm:

Re: Problem med if-sats

Postat: 7 juni 2020, 17:32:07
av metric
Ska det inte vara int x=0;
Annars kan väl x vara vad som helst från början?

Re: Problem med if-sats

Postat: 7 juni 2020, 17:33:56
av Swech
kompilatorn tycker att x inte ändrar sig.
Du pillar ju på den i en interrupt
Kan inte C men det är väl volatile eller liknande som X skall definieras som
Swech

Re: Problem med if-sats

Postat: 7 juni 2020, 17:34:37
av Glattnos
Absolut, så ska det ju vara!

Kod: Markera allt

volatile int x;

Re: Problem med if-sats

Postat: 7 juni 2020, 17:36:56
av kodar-holger
Du behöver volatile-deklarera x till att börja med. Optimeraren jobbar väldigt närsynt och ser att ingen gör något med x i main så den kan ta bort saker bäst den vill eftersom x aldrig kommer att bli >0. Och även om den inte tar bort saker kommer den nog att lägga den i ett register som din interruptrutin inte kommer åt. Volatile löser detta.

Sen vet du inte vad x är när programmet startar. Minnet kan innehålla vad som helst. Du måste alltså själv initialt sätta x till 0 (eller något annat värde), annars vet du inte vad som händer. Kanske är x 0, kanske 4711, kanske -2^32.

Re: Problem med if-sats

Postat: 7 juni 2020, 17:41:01
av Glattnos
Tackar för svaren :)
Att x inte gavs något värde var mest för att jag hade tagit bort det i felsöknings-syfte. Om x var någonting annat än 0,1 eller 2 vid programstart så skulle den ju ändå nollställas direkt :) Eller ja, kunde ju varit negativt tal också så helt rätt :)

Re: Problem med if-sats

Postat: 7 juni 2020, 19:29:06
av Mr Andersson
kodar-holger skrev:Sen vet du inte vad x är när programmet startar. Minnet kan innehålla vad som helst. Du måste alltså själv initialt sätta x till 0 (eller något annat värde), annars vet du inte vad som händer. Kanske är x 0, kanske 4711, kanske -2^32.
Hur många gånger har vi inte behandlat detta här på forumet?
Globala variabler är garanterade att initialiseras till 0.

Re: Problem med if-sats

Postat: 7 juni 2020, 19:30:26
av Icecap
Svaret är (som det redan står) att då x inkrementeras av en INTERRUPT-rutin måste deklareras som volatile.

Annars kommer optimeringen att anse att x inte ändras varför det optimeras bort.

Detta skriver jag för förtydliga förandra, det är ju en icke-ovanlig situation som uppstår lite då o då (fast då aldrig för mig :vissla:).

Re: Problem med if-sats

Postat: 7 juni 2020, 20:04:14
av Polyene
Utöver att x ska vara volatile så kommer du att få andra problem med koden som du nog inte tänkt på. Vad händer om interruptet sker på den rad som modifierar PORTB? Jo interruptet kommer att öka x, men sedan nollas x direkt när man återvänder från interruptet, så du tappar den ökningen.

Ett annat potentiellt problem är om int skulle vara större än ett dataord för processorn (beror på processor och kompilator), då riskerar man andra konstigheter.

Man brukar se till att stänga av interruptet i mainkoden under den tid man behandlar variabler som är gemensamma för main och interrupt, då undviker man båda dessa problem.

Re: Problem med if-sats

Postat: 7 juni 2020, 21:37:44
av Glattnos
Om interruptet händer på raden som modifierar PORTB så skulle x bli 4 och ska ändå nollställas eftersom det ska nollställas varje gång det blir över 2.

Det här med volatile brukar jag ju fråga ungefär en gång per år :)

Re: Problem med if-sats

Postat: 7 juni 2020, 23:09:06
av Polyene
Jag trodde nog att du ville att det skulle togglas på PORTB efter var tredje interrupt, men om x räknas upp till 4 och sen nollas så missar du ett interrupt så att det kommer att bli fyra interrupt mellan de två togglingarna. Men det kanske är så du vill ha det, även om det känns ovanligt?

Re: Problem med if-sats

Postat: 7 juni 2020, 23:54:09
av Glattnos
Precis så var det jag ville ha det, x var bara en räknare som kollades i programmet för att toggla när ett visst värde nåddes :) Egentligen så var det när x var över 150 men jag ändrade till 2 i felsöknings-syfte. Jag har gjort om nu så att det inte räknas utan istället togglar direkt i avbrottsrutinen och så har jag större prescaler på timern istället :)
Kör på en Attiny13 så det gäller att hålla nere kod-storleken :mrgreen: