Fundering kring en fuktion i C

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
Användarvisningsbild
Korken
Inlägg: 2230
Blev medlem: 3 februari 2006, 19:19:36
Ort: Luleå, Porsön

Fundering kring en fuktion i C

Inlägg av Korken »

Hej!

Jag sitter här och funderar...
Om jag gör en funktion i C som tar 1sec att gör allt i.
Om jag har den i mains while(1) kommer den då att vänta med att köra funktionen igen tills den första har kört klart eller kommer den att köra flera av den parallellt?

Exempel kod:

Kod: Markera allt

void testaren(void);

int main(void)
{	
    while(1)
	{
		testaren();
    }
	
	return 0;
}

void testaren(void)
{
	//Allt detta tar 1sec att utföra...
}
//Emil
Användarvisningsbild
Icecap
Inlägg: 26737
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Inlägg av Icecap »

Den kommer att köra funktionen och när funktionen är klar med sitt kommer programflödet att återgå till main.

Alltså kommer din exempelkod att utföra testaren(); gång efter gång efter gång....

Men aldrig sidlöpande.
sodjan
EF Sponsor
Inlägg: 43267
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

> kommer den då att vänta med att köra funktionen igen tills den första
> har kört klart eller kommer den att köra flera av den parallellt?

Ja och Nej.
Användarvisningsbild
Korken
Inlägg: 2230
Blev medlem: 3 februari 2006, 19:19:36
Ort: Luleå, Porsön

Inlägg av Korken »

Ok!

Tack för det snabba svaret!

//Emil
Användarvisningsbild
Korken
Inlägg: 2230
Blev medlem: 3 februari 2006, 19:19:36
Ort: Luleå, Porsön

Inlägg av Korken »

Som en liten följdfråga, om jag har en timer-interupt, kan jag köra 2st funktioner parallellt?
Om inte finns det något annat sätt att göra på?

Varför jag vill köra 2 funktioner parallellt är att jag har en Software PWM och en speciell räknare som båda måste hinna köras under en timer interupt.

Timern (CTC) är inställd men en compare på 50.

//Emil
cyr
Inlägg: 2712
Blev medlem: 27 maj 2003, 16:02:39
Ort: linköping
Kontakt:

Inlägg av cyr »

Kör den ena först och den andra sen?

Du kan inte bokstavligen köra två funktioner samtidigt utan att ha två processorer.
Användarvisningsbild
Korken
Inlägg: 2230
Blev medlem: 3 februari 2006, 19:19:36
Ort: Luleå, Porsön

Inlägg av Korken »

Ok, men jag är inte säker att båda hinner köra på en compare på 50.
Jag kan inte göra den större heller.

Hur räknar man ut hut många cycles det tar att utföra något?

//Emil
Användarvisningsbild
exile
EF Sponsor
Inlägg: 496
Blev medlem: 21 oktober 2005, 23:32:07

Inlägg av exile »

Du tittar på vad compilatorn spottar ut (.lss) och räknar hur lång tid det tar, alternativt att du kör den Debuger och "tar tid".....

En Software PWM kan göras kanska resurs snål, men det beror upplösning mm...

Klar det är lite enklare för oss hjälpa dej om talar om vad du tänker göra i stort ^^
Användarvisningsbild
Korken
Inlägg: 2230
Blev medlem: 3 februari 2006, 19:19:36
Ort: Luleå, Porsön

Inlägg av Korken »

Det stora jag gör är en skrivbords lampa som är gjord av en träkub med en bit plexiglasstav i med 3st RGB lysdioder i botten.
Och Software PWMen styr RGB och räknaren styr så att övergången mellan fägerna är dynamisk och inte hackig.

//Emil

Edit: Snabb CAD Bild
sodjan
EF Sponsor
Inlägg: 43267
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

Den snabbaste rutinen (d.v.s pwm-räknarna) körs av en rutin, lämpligen via
ett timer interrupt.

Den andra långsammare rutinen (färgbytet) kan antingen köras av samma
interrupt rutin (ha ett par extra räknare som styr när pwm paramaterarna
ska justeras). Eller (beroende på vilken processor du har, hur många
timers den har och vad du använder timers till för övrigt) via en "eget" timer
interrupt.

Det kan vara enklare att undvika störningar i pwm hanteringen genom
att hantera färgskiftena i samma rutin. Då har man garanti för att pwm
hanteringen kör med samma intervall hela tiden, även om interruptrutinen
ibland tar lite olika lång tid, vilket är OK så länge det är marginal
till nästa interrupt.

Du kan naturligtsvis aldrig kör två eller fler rutiner "samtidigt", annat än skenbart...

> Hur räknar man ut hut många cycles det tar att utföra något?

Men "räknar" normalt inte ut det.
Kör man assembler så använder man "stopwatch" i MPLAB/MPSIM.
Sen så trodde jag att man kör C för att *slippa* räkna cycler... :-)
Användarvisningsbild
$tiff
Inlägg: 4941
Blev medlem: 31 maj 2003, 19:47:52
Ort: Göteborg
Kontakt:

Inlägg av $tiff »

>> Korken

Detdär är det ju många här på forumet som lyckats med redan, däribland jag.
I ditt timeravbrott hanterar du semi-mjukvaru-PWMen. I huvudrutinen har du sedan "all tid i världen" att göra din färgskiftning, genom att modifiera variablerna som ditt PWM-avbrott läser ifrån.
Behöver du ytterligare "parallellitet" så behöver du fler avbrott eller en fiffig huvudloop om det inte är så noga med tiden.
Användarvisningsbild
Korken
Inlägg: 2230
Blev medlem: 3 februari 2006, 19:19:36
Ort: Luleå, Porsön

Inlägg av Korken »

Ok, såhär ser det ut nu.
Jag har en compare på 50 så jag har inte så många cykles på mig att göra detta.
Jag tor det räcker att göra dem efter varandra då dem är så små, men vad tror ni?
Jag måste kanske ändra compare till något lite större?

Kod: Markera allt

// Counts the RGB up and down with aprox 89steps/sec. So it takes aprox 3sec to go from 0-255.
// So it won't be a stepy convertion between colors.
void rgb_counter(void)
{
	static uint16_t counter = 0;
	
    if (counter > 600)
	{
		for (uint8_t i = 0; i < 3; i++)
		{
			if (rgb_compare[i] < rgb[i])
				rgb[i] - 1;
			else if (rgb_compare[i] > rgb[i])
				rgb[i] + 1;
		}
		
		counter = 0;
	}
	
	counter++;
}


// The Software PWM that controlls the Red, Green and Blue brightness and mix.
// Works at aprox. 200Hz.
void rgb_pwm(void)
{
    static uint8_t counter2 = 0;

    if (counter2 == 0)
        PORTB |= 0x07;

    for (uint8_t a = 0; a < 3; a++)
	{
        if (counter2 > rgb[a])
		{
            PORTB &= ~(1<<a);
		}
	}

    counter2++;
}
//Emil
Användarvisningsbild
exile
EF Sponsor
Inlägg: 496
Blev medlem: 21 oktober 2005, 23:32:07

Inlägg av exile »

He... är man långsam så är man ^^, men jag lägger upp exemplet i alla fall (kan vara roligt att kolla på)


Exempel

Kod: Markera allt

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

//globala variabler
unsigned char Count,PWM_R,PWM_G,PWM_B,state;

//
#define PORT_LED PORTB
#define DDR_LED DDRB
#define bit_R 0
#define bit_G 1
#define bit_B 2

#define s0 0
#define s1 1
#define s2 2


ISR(TIMER0_OVF_vect){
	//PWM
	unsigned char temp = PORT_LED & ~((1<<bit_R) | (1<<bit_G) | (1<<bit_B));
	if ( Count < PWM_R) temp |= (1<<bit_R);
	if ( Count < PWM_G) temp |= (1<<bit_G);
	if ( Count < PWM_B) temp |= (1<<bit_B);
	PORT_LED = temp;
	Count++;

	// Dimningen mellan De olika dioderna 
	if (Count == 0xff){
		if (state == s0){
			PWM_R++;
			PWM_G--;
			if (PWM_G == 0) state = s1;
		}
		if (state == s1){
			PWM_B++;
			PWM_R--;
			if (PWM_R == 0) state = s2;
		}
		if (state == s2){
			PWM_G++;
			PWM_B--;
			if (PWM_B == 0) state = s0;
		}
	}
}


void init_pwm(void){
	//
	PORT_LED &=  ~((1<<bit_R) | (1<<bit_G) | (1<<bit_B));
	DDR_LED = (1<<bit_R) | (1<<bit_G) | (1<<bit_B);
	Count = 0;
	TCCR0 = 1 << CS00;
	TIMSK = 1 << TOIE0;
}


int main (void){
	init_pwm();
	PWM_R = 0;
	PWM_G = 255;
	PWM_B = 0;
	state = s0;

	sei();
	for (;;){
		// Gör ingenting
	}
}

Jag ser att du använder en for-loop i pwm, den är ganska onödig då du bara har 3 st pwm-kanaler, det som är värre är att du använder shift till sammans med en variabel "PORTB &= ~(1<<a);" tyvär så kan AVR bara sifta 1 steg i taget vilket resulterar i att en loop skapas för att kunna sifta variabelt... Ta inte det här som kritik utan enkla tips på optimeringar ^^
Användarvisningsbild
Korken
Inlägg: 2230
Blev medlem: 3 februari 2006, 19:19:36
Ort: Luleå, Porsön

Inlägg av Korken »

Ok! Tack för tippsen!

Jag har gjort om lite.
Vad tror ni? Bättre/sämre?

Kod: Markera allt

// Counts the RGB up and down with aprox 89steps/sec. So it takes aprox 3sec to go from 0-255.
// So it won't be a stepy convertion between colors.
void rgb_counter(void)
{
	static uint16_t counter = 0;
	
    if (counter > 600)
	{
		if (rgb_compare[0] < rgb[0])
			rgb[0] - 1;
		else if (rgb_compare[0] > rgb[0])
			rgb[0] + 1;
		
		if (rgb_compare[1] < rgb[1])
			rgb[1] - 1;
		else if (rgb_compare[1] > rgb[1])
			rgb[1] + 1;

		if (rgb_compare[2] < rgb[2])
			rgb[2] - 1;
		else if (rgb_compare[2] > rgb[2])
			rgb[2] + 1;

		counter = 0;
	}
	
	counter++;
}


// The Software PWM that controlls the Red, Green and Blue brightness and mix.
// Works at aprox. 200Hz.
void rgb_pwm(void)
{
    static uint8_t counter2 = 0;

    if (counter2 == 0)
        PORTB |= 0x07;

    if (counter2 > rgb[0])
	{
        PORTB &= ~0x01;
	}
	
	if (counter2 > rgb[1])
	{
        PORTB &= ~0x02;
	}
	
	if (counter2 > rgb[2])
	{
        PORTB &= ~0x04;
	}

    counter2++;
}
//Emil
sodjan
EF Sponsor
Inlägg: 43267
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

Nu är jag helt lost här...

Är det PIC eller AVR det hela handlar om ????
Skriv svar