Forum: Mikrocontroller und Digitale Elektronik Anfängerfrage: Verhindern eine Funktion zu kopieren in C


von Attila C. (attila)


Angehängte Dateien:

Lesenswert?

Hallo!

Ich steh ein wenig auf dem Schlauch. Ich habe eine Funktion gebastelt 
die eine LED auf und abblendet. Die Geschwindigkeit des auf und 
abblendens ist jedesmal zufällig.

Nun möchte ich mehrere LEDs ansteuern und könnte dies durch 
kopieren,umbenennen und ändern des Ports in der Funktion erreichen. Das 
scheint mir nicht elegant zu sein.
Andererseits bereitet es mir Kopfzerbrechen das einiges an Parametern 
pro Aufruf der Funktion geändert wird.

Wie macht man sowas richtig?

von Mat (Gast)


Lesenswert?

Hallo,

du kannst einfach einen PORT und einen PIN übergeben, z.b. blink(PORTA, 
PA0)
bzw. in deinem Fall
PORTA |= blink(PA0);

gruß

von Attila C. (attila)


Lesenswert?

Hallo Mat,

ich glaube das wird der Sache nicht gerecht da ja alle LEDs 
unterschiedlich schnell auf und abblenden sollen.
Ich übergebe am Ende die Sache so:

blink[0]=blink0()
blink[1]=blink1()
.....
blink[7]

und danach:
Ausgabe=(blink0|blink1|blink2|.........|blink7)

von Chris (Gast)


Lesenswert?

sowas in der art ?
1
#define PWM_MAX 34
2
#define PWM_CHANNEL 8
3
#define PWM_DIR  (led_val[i]&128)
4
#define PWM_VAL  (led_val[i]&127)
5
6
char led_val[PWM_CHANNEL];
7
char led_dly[PWM_CHANNEL]
8
9
char blink0 (void)
10
{
11
  char i;      // temp general purpose variable
12
  static char pwm;
13
  int var;
14
  
15
  for(i=PWM_CHANNEL;i--;) {
16
    if(!led_dly[i]--)            //Bei Ablauf:
17
    {
18
    if (PWM_VAL==PWM_MAX)              //Zählrichtung bestimmen
19
      led_val[i]=PWM_MAX;
20
    else if (PWM_VAL==0)
21
      led_val[i]=128;
22
      
23
      PWM_DIR?led_dly[i]++:led_dly[i]--;        //Abhängig von der Richtung zählen
24
    led_dly[i]=rand()%200+1;        //Neue zufällige Länge für die Warteschleife
25
    }        
26
  }  
27
  
28
    if (pwm==44)          //Hier wird PWM generiert
29
    pwm=0;
30
    
31
    pwm=pwm+1;  
32
33
    var=0;
34
    for(i=PWM_CHANNEL;i--;) 
35
      if(pwm>PWM_VAL)  var|=1<<i;
36
37
  return var;
38
}

von Attila C. (attila)


Lesenswert?

Hallo Chris,

ich glaube nicht das es "sowas in der Art" ist. Meine Funktion generiert 
ja eine PWM. Da Du "for" Schleifen in deinem Vorschlag hast gehe ich 
davon aus das keine PWM generieren kannst. Ist das so richtig?

von Chris (Gast)


Lesenswert?

Das ist so falsch.
Deine Funktion generiert ein Bitpattern welches für ein PWM gebraucht 
werden kann, pwm wird damit selbst nicht generiert.
Der Forschlag ist im Prinzip dein Code, welcher einfach auf 8 leds 
erweitert wurde. Derzeit max 8 leds, wenn du das char blink0 in ein 
unsigned int blink0 änderst sind es dann max 16 leds. Wenn du mehr 
brauchst, auf long ändern sowie auch die Definition von var und du hast 
max 32 leds.
Weniger ist auch möglich, einfach die Konstante ändern.

von Chris (Gast)


Lesenswert?

Es hat sich jedoch beim Editieren ein Fehler eingeschlichen,
PWM_DIR?led_dly[i]++:led_dly[i]--;
muss
PWM_DIR?led_val[i]++:led_val[i]--;
heissen,
da ja x (val) gezählt wurde.

von Attila C. (attila)


Lesenswert?

Hallo Chris,

also ich versuche mal nachzuvollziehen was Du da Vorgeschlagen hast. Es 
werden da sicher noch Fragen auftauchen aber schonmal vielen Dank: Ist 
ja genug Stoff für einige Stunden ;-)

von Attila C. (attila)


Angehängte Dateien:

Lesenswert?

Ich hatte übrigens auch einen Fehler drinne und zwar bei der 
Neubestimmung der Auf und Abblendzeit.Nur der Vollständigkeit halber 
anbei der korrigierte Code.

von Chris (Gast)


Lesenswert?

Ich denke, es wäre einfacher einfach in HW auszutesten mit ein paar Leds
mehr am Port, dann versetehst du es sicher einfacher.

Ansonsten was ich nicht verstanden habe, wieso du bis 34 zählst und
den pwm bis 44, also ein fixed on-pwm von ca 22.7% immer an hast, aber
ich kenne auch nicht den zeitintervall von einem PWM zum anderen, 
vielleicht
entspricht eine Einheit auch ca 1/2 Stunde.
Sollte aber 44 nur ein Tippfehler sein, dann ändere bitte den Wert auf
PWM_MAX. So kannst du auch ev. später auf z.B. 100 ändern.

von Attila C. (attila)


Lesenswert?

Hallo Chris,

ich denke um deinen Code zu verstehen muss ich noch einige Kapitel in 
meinen C Büchern weiterarbeiten. Im Moment versuche ich nur 
nachzuvollziehen was Du im PWM Teil machst dabei stolpere ich im Moment 
über:

 #define PWM_VAL  (led_val[i]&127)

Mir scheint aber das Kapitel "Makros" das Richtige zu sein.

Ich habe das Ganze hier bereits mit 8 LEDs aufgebaut. Die hängen an 
einem 74HC595 (über SPI von einem ATmega8 gesteuert) und die erste LED 
macht was sie soll und , wie gesagt, wenn ich den ganzen Kram 8 mal 
kopieren würde, würden die anderen auch das tun was sie sollen. Aber das 
soll ja nicht Ziel der "Übung" sein ;-)

Die 44 sind kein Fehler. Wenn man noch mehr dimmt sieht man die 
einzelnen Helligkeitstufen und das ist nicht "schön" Wie man das löst 
ist sicherlich auch "Spass" für einige Nachmittage. Tipps nehme ich 
gerne an :-)

von Attila C. (attila)


Lesenswert?

Also ich rate jetzt mal ein wenig:

#define PWM_VAL  (led_val[i]&127)

Bedeutet das PWM_VAL "i" mal die Zeichenkette "led_val" denen wiederum 
jeweils der Wert "127" zugewiesen wird?

Und wie geht denn "i--" in einer for Schleife als Bedingung die dann 
auch noch keine Reinitialisierung enthält??? Was passiert denn da dann 
eigentlich?

von Chris (Gast)


Lesenswert?

Schreib rein was dir nicht klar ist und wieso, werde es dann erklären.

Ein define ist ein substitute, in der einfachsten Form ohne parameter
wie hier dient er hauptsächlich der Lesbarkeit des Quellcodes.

 #define PWM_VAL  (led_val[i]&127)

Ich habe die variable direction sowie x in eine einzige variable
zusammengesteckt, nähmlich led_val. Bit 7 ist direction und der Rest
ist x (von 0-127). Man hätte das auch mit Strukturen und Bitfeldern 
machen
können, bringt aber gewisse Probleme mit sich, welche man dann 
entsprechend
kontrollieren und beseitigen muss. Deshalb hatte ich hier einen 
einfacheren
Weg gewählt. Ist aber im Prinzip dasselbe wie
struct led_val_s {
  int val :7;
  int direction :1;
} led_val[8];

Dies nur am Rande.

PWM_VAL wird verwendet, um val, oder x in deinem Beispiel 
rauszubekommen,
wertebereich 0-127 . und PWM_DIR um die Direction rauszubekommen, 
wertebereich 128 oder 0 der einfachheit halber.

Eigentlich sollte es heissen, es werden die 7 bits ausmaskiert
 #define PWM_VAL  (led_val[i]&((1<<7)-1))
und
 #define PWM_DIR  (led_val[i]&(1<<7))

val&mask heisst hier value and mask, ein binäres and.
<< heisst shift left.

led_val[i] als Bit 0bDVVVVVVV , D=Dir V=val . Auf das reduziert sich 
das.

von Chris (Gast)


Lesenswert?

led_val ist ein Array aus PWM_CHANNEL Werten, also aus 8 in diesem
Beispiel

char led_var[PWM_CHANNEL]; // ist dasselbe als
char led_var[8];           // ein Array welches von led_var[0] bis 
led_var[7]
                           // zugegriffen wird, 8 variabeln insgesamt.

die variable i ist ein Zähler, welcher auch mit

char i ; // generic counter variable

initialisiert wird.

Das Makro oder die Define
 #define PWM_VAL  (led_val[i]&127)
wird im folgenden Code
 if (PWM_VAL==PWM_MAX)
durch
 if ((led_val[i]&127)==34)
ersetzt. Wenn du cpp bemühst, bekommst du das auch angezeigt.

Das For, PWM_CHANNEL ist dasselbe wie 8 und ein code wie dieser:
    for(i=PWM_CHANNEL;i--;) printf("i=%d\n",i);
->
    for(i=8;i--;) printf("i=%d\n",i);
=   produziert:
i=7
i=6
i=5
i=4
i=3
i=2
i=1
i=0

und wird insgesamt 8 mal durchlaufen.
Beim Vergleich i-- != 0 wird i nachher automatisch decrementiert.
Ansonsten könntest du auch schreiben,
    for(i=0;i<PWM_CHANNEL;i++)
gäbe denselben Effekt, nur die Richtung ist umgekehrt, von 0->max

von Attila C. (attila)


Lesenswert?

Chris,

wow! Respekt! Ich melde mich hier wieder sobald ich alles wirklich 
verstanden und vielleicht sogar umgesetzt habe. Vielen vielen Dank!

von Chris (Gast)


Lesenswert?

Hier nochmal der Code mit deinem Fehler behoben (rauf+runter gezählt).
1
#define PWM_CHANNEL 8
2
#define PWM_MAX   35
3
4
char blink0 (void)
5
{
6
static char val[PWM_CHANNEL];
7
static char dly[PWM_CHANNEL];
8
static char rnd[PWM_CHANNEL];
9
static char pwm;
10
11
  char i;      // temp general purpose variable
12
  int var;
13
  
14
  for(i=PWM_CHANNEL;i--;) 
15
    if(!dly[i]--)            //Bei Ablauf:
16
    {
17
      if (val[i]==0)
18
        dly[i]=rnd[i]=rand()%200+1;
19
      else if (val[i]==PWM_MAX)              //Zählrichtung bestimmen
20
        dly[i]=rnd[i],rnd[i]=0;
21
  
22
      rnd[i]?val[i]++:val[i]--;        //Abhängig von der Richtung zählen
23
    }        
24
25
  
26
    if (pwm==44)          //Hier wird PWM generiert
27
    pwm=0;
28
    
29
    pwm=pwm+1;  
30
31
    var=0;
32
    for(i=PWM_CHANNEL;i--;) 
33
      if(pwm>PWM_VAL)  var|=1<<i;
34
35
  return var;
36
}

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.