Sida 1 av 2
Fundering kring en fuktion i C
Postat: 11 september 2006, 20:14:00
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
Postat: 11 september 2006, 20:47:45
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.
Postat: 11 september 2006, 20:48:28
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.
Postat: 11 september 2006, 21:02:30
av Korken
Ok!
Tack för det snabba svaret!
//Emil
Postat: 12 september 2006, 18:06:24
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
Postat: 12 september 2006, 18:50:12
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.
Postat: 12 september 2006, 19:03:05
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
Postat: 12 september 2006, 19:35:52
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 ^^
Postat: 12 september 2006, 19:56:44
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
Postat: 12 september 2006, 20:35:42
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...

Postat: 12 september 2006, 20:45:51
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.
Postat: 12 september 2006, 20:57:09
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
Postat: 12 september 2006, 21:26:24
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 ^^
Postat: 12 september 2006, 22:50:53
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
Postat: 12 september 2006, 23:43:02
av sodjan
Nu är jag helt lost här...
Är det PIC eller AVR det hela handlar om ????