mikrocontroller.net

Forum: Compiler & IDEs Lektor für C-Programm gesucht


Autor: Michael Z. (zellm)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich stelle hier mal ein Programm online, das ich geschrieben habe.

Da ich mit meinen C-Kenntnissen noch ziemlich am Anfang stehe, hoffe ich 
auf diese Art und weise ein Paar Hinweise oder Tipps und Tricks zu 
erfahren.

Ich danke vorab jedem, der sich die mühe macht diese (ca. 120) Zeilen 
anzuschauen und mir ein Feedback dazu gibt.

Gruß an alle.
Michael

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich mache mal den Anfang

In deinem Code kommt ziemlich oft PB1 etc vor. Als Kommentar hast du 
dazugeschrieben, was sich dahinter verbirgt.

zb hier
  DDRB |=   (1<<PB0) | (1<<PB1) | (1<<PB2) | (1<<PB3) | (1<<PB4) | (1<<PB5) | (1<<PB6) | (1<<PB7);  // Ausg�nge
//        Hupe  Klappe_auf  Klappe_zu  BlinkLampe  Lampe    Lampe    Lampe    Lampe

Das ist schon mal nicht so schlecht, aber das kann man noch besser 
machen. Setze dir immer das Ziel, deinen Code so zu schreiben, dass du 
Kommentare dieser Art nicht brauchst.

In deinem Fall geht das ganz leicht
#define HUPE         PB0
#define KLAPPE_AUF   PB1
#define KLAPPE_ZU    PB2
#define BLINK_LAMPE  PB3
....



....
  DDRB |=   (1<<HUPE) | (1<<KLAPPE_AUF) | (1<<KLAPPE_ZU) | (1<<BLINK_LAMPE) ....

oder zb dann auch hier
ISR (TIMER2_COMP_vect)
{
  overflows++;  // Interruptz�hler um 1 inkrementieren
  blinktimer++;  // Z�hler f�r Blinkfrequenz um 1 inkrementieren

  if (PINC & (1<<REMOTE_START))
    start ++;
  else
    start = 0;

  if (PINC & (1<<REMOTE_RESET))
    reset ++;
  else
    reset = 0;

  if (moop != 0) {
    if (blinktimer >= fBlinklampe) {  // Blinkgeschwindigkeit einstellen
      PORTB ^= (1<<BLINK_LAMPE);
      blinktimer = 0;  // Z�hler zur�cksetzen
    }
  }
  if (moop != 0) {  // Ausgabe von Akustischem Signal wenn moop ungleich 0
    moop--;  // moop um 1 dekrementieren
    PORTB |= (1<<HUPE) | (1<<KLAPPE_AUF);  // Hupe ein
  }
  else {  // Ausschalten des Signales wenn Z�hler auf 0 Zur�ckgelaufen
    PORTB &= ~ ((1<<HUPE) | (1<<KLAPPE_AUF));  // Hupe aus
  }

  if (overflows == 20) {  // Steuerung des Sekundenz�hlers
    Sekunde++;  // Wert des Sekundenz�hlers um 1 inkrementieren
    overflows = 0;  // Interruptz�hler zur�cksetzen
  }
}

Dadurch gewinnt der Code an Qualität, weil du nicht lange überlegen 
musst, was denn jetzt an PB1 angeschlossen ist. Der Code sagt es dir, 
bzw. umgekehrt: Du schaltest nicht mehr PB1, du schaltest die HUPE und 
der Compiler weiß, dass die an PB1 angeschlossen ist.
Die Kommentare sind dann auch überflüssig, weil alles was es dazu zu 
sagen gibt, im Code steht. Im schlimmsten Fall ist der Kommentar einfach 
nur falsch, wie zb hier
ISR (TIMER2_COMP_vect) {
  overflows++;  // Interruptz�hler um 1 inkrementieren
  blinktimer++;  // Z�hler f�r Blinkfrequenz um 1 inkrementieren
  if (PINC & (1<<PINC0)) {  // Abfrage Start signal von Fernbedinung
    start ++;
  }
  else {
    start = 0;
  }
  if (PINC & (1<<PC1)) {  // Abfrage Start signal von Fernbedinung
    reset ++;
  }
  else {
    reset = 0;
  }

Ist dir aufgefallen, dass im Kommentar in 2 Fällen behauptet wird, dass 
hier von der Fernsteuerung das Start Signal kommt.

Und jetzt vergleiche mit
  if (PINC & (1<<REMOTE_START))
    start ++;
  else
    start = 0;

  if (PINC & (1<<REMOTE_RESET))
    reset ++;
  else
    reset = 0;

Da braucht es keinen Kommentar, damit ich dasselbe herauslesen kann. 
Nur: Da hier der Code sein eigener Kommentar ist, kann er auch nicht 
falsch sein.

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
if (PINC & (1<<PINC0)) {  // Abfrage Start signal von Fernbedinung
    start ++;
  }
...
if (PINC & (1<<PC1)) {  // Abfrage Start signal von Fernbedinung
    reset ++;
  }
Ist das beabsichtigt?
if (moop != 0) {
    if (blinktimer >= fBlinklampe) {  // Blinkgeschwindigkeit einstellen
      PORTB ^= (1<<PB3);  // Signal an PB3 invertieren
      blinktimer = 0;  // Z�hler zur�cksetzen
    }
  }
  if (moop != 0) {  // Ausgabe von Akustischem Signal wenn moop ungleich 0
    moop--;  // moop um 1 dekrementieren
    PORTB |= (1<<PB0) | (1<<PB1);  // Hupe ein
  }
Daraus könnte man evtl. eine einzige If-Schlaufe machen..

Das sind die beiden Dinge, die mir beim Überfliegen grade so ins Auge 
stachen. Mehr Zeit hab ich leider momentan nicht..

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Daraus könnte man evtl. eine einzige If-Schlaufe machen..

Eine was?!

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Rufus t. Firefly (rufus) (Moderator) wrote:
> > Daraus könnte man evtl. eine einzige If-Schlaufe machen..
> Eine was?!
If-Abfrage, sorry ^^

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
    if ((Sekunde == 10) && (overflows == 0)) {
      moop = 9;  // Signal "Ende der Zeit zum Fahrzeug ziehen" veranlassen
    }
    if ((Sekunde == 15) && (overflows == 0)) {
      PORTB |=  (1<<PB4);  // Lampe1 aus
    }
    if ((Sekunde == 30) && (overflows == 0)) {
 ....

Diese ganze Sequenz ist nicht sehr schön.
Aber zumindest solltest du den Prozessor etwas entlasten (da geht es bei 
dir noch nicht um Performance sondern dass du dich daran gewöhnst)
    if ((Sekunde == 10) && (overflows == 0)) {
      moop = 9;  // Signal "Ende der Zeit zum Fahrzeug ziehen" veranlassen
    }
    else if ((Sekunde == 15) && (overflows == 0)) {
      PORTB |=  (1<<PB4);  // Lampe1 aus
    }
    else if ((Sekunde == 30) && (overflows == 0)) {
....

Wenn Sekunde gleich 10 war (und Overflows gleich 0 ), dann ist völlig 
klar, dass Sekunde nicht auch noch 15 sein kann, oder 30 oder was auch 
immer


Die Abfrage auf overflows == 0 solltest du vorziehen und damit die 
einzelnen if einfacher machen

   ...

   if( overflows == 0 ) {

     if( Sekunde == 10 )
      moop = 9;  // Signal "Ende der Zeit zum Fahrzeug ziehen" veranlassen

     else if( Sekunde == 15 )
       PORTB |=  (1<<LAMPE_1);  // Lampe1 aus

     else if( Sekunde == 30 )
       PORTB |= (1<<LAMPE_2);  // Lampe2 aus

     else if( Sekunde == 45 )
       PORTB |= (1<<LAMPE_3);  // Lampe3 aus

     else if( Sekunde == 60 )
       PORTB |= (1<<LAMPE_4);  // Lampe4 aus

    ...

Je einfacher du den jeweiligen Bedingungsteil gestalten kannst, desto 
weniger Möglichkeiten gibt es, dort einen Fehler zu machen.

Du merkst vielleicht auch, dass ich kein Verfechter der 'überall muss 
eine {} sein'-Schule bin. Für mich ist es wichtiger, dass die einzelnen 
else-if Fälle einen optischen Block bilden. Wenn da nur eine Anweisung 
steht UND wenn ich sbolut sicher sein kann, dass da auch nie irgendetwas 
anderes stehen wird, dann lass ich die {} auch gerne weg.

Autor: ... ... (docean) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
dann noch das Sekunde==x durch ein case ersetzen und schon ist es 
hübsch..

Autor: der mechatroniker (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Variablenbenennung würd mir spontan einfallen:
volatile uint8_t reset = 0;    // Ob gestartet werden soll oder nicht...
Der Variablenname sagt erst mal gar nix aus, außer dass es was mit dem 
Reset zu tun hat. Der Kommentar ist doppelt falsch, benutzt wird die 
Variable offensichtlich als Zähler zum Entprellen (und nicht als Flag 
"ob oder nicht") des Reset-Tasters (und nicht des Start-Tasters). Warum 
dann nicht
volatile uint8_t cntResetDebounce = 0;
ohne Kommentar? Dann kann der Kommentar auch nicht mehr falsch sein 
(Prinzip wurde bei den Portpins schon erläutert)

Für die Variable "start" gilt entsprechendes...

Autor: der mechatroniker (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kleine Zwischenbemerkung: Ich finds gut, dass sich Anfänger Gedanken um 
die Qualität ihres Codes machen. Gibts selten ;-)

Würdest du dein Beispiel zur Verfügung stellen, dass wir ein Tutorial 
"Sauber C codieren" oder so draus machen?

Autor: Michael Z. (zellm)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wow... !!!

Ich bin absolut Überwältigt von der rießen Resonaz auf meine Anfrage.

Ein richtig großes

DD       A     NN   N  K  K  EEEEE
D D     A A    N N  N  K K   E
D  D   A   A   N  N N  KK    EEE
D D   AAAAAAA  N   NN  K K   E
DD   A       A N    N  K  K  EEEEE

an alle!

@ Karl heinz Buchegger: Extra Dank für die gute Erklärung!

@ der mechatroniker: Ich verstehe noch nicht ganz wie du das mit dem 
Tutorial meinst. Aber dagegen habe ich nichts.

Es wird wohl eine kleine Weile dauern alle Anregungen umzusetzen, aber 
Ihr werdet dann von mir lesen.

Gruß Michael

Autor: Michael Z. (zellm)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe mal eben noch den Hinweis mit dem CASE aufgenommen...

Könnte das in etwa so passen?
switch (Sekunde) {
   case 10: moop = 9; break;
   case 15: PORTB |=  (1<<LAMPE_0); break;
   case 30: PORTB |= (1<<LAMPE_1); break;
   //usw...
}

Autor: P. S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
der mechatroniker schrieb:

>
volatile uint8_t cntResetDebounce = 0;

Die Abkuerzerei stoert nicht nur den Lesefluss, in diesem Fall kann es 
auch noch leicht als anstoessig interpretiert werden...

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Michael Zeller schrieb:
> Ich habe mal eben noch den Hinweis mit dem CASE aufgenommen...
>
> Könnte das in etwa so passen?
>
>
switch (Sekunde) {
>    case 10: moop = 9; break;
>    case 15: PORTB |=  (1<<LAMPE_0); break;
>    case 30: PORTB |= (1<<LAMPE_1); break;
>    //usw...
> }

Ja  genau.

Der ganze Abschnitt, der sich im Original über viele Zeilen hingezogen 
hat, müsste jetzt deutlich kürzer sein ohne dadurch kryptisch zu wirken. 
Das ist gut so, denn viele Probleme in der Programmierung enstehen 
dadurch dass wir Menschen den Code nicht mehr überblicken können. Viele 
Programmierer benutzen so was wie eine Faustregel: Wenn der Inhalt einer 
Funktion nicht mehr auf eine Bildschirmseite passt, ist es Zeit darüber 
nachzudenken, ihn entweder zu kompremieren oder in mehrere Funktionen 
aufzuteilen.

Autor: Michael Z. (zellm)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich habe eure Vorschläge mal so gut ich es verstanden habe umgesetzt.

Ich freue mich auf eure Kritik und weitere Anregungen.

Gruß Michael

PS: Das Programm befindet sich im Anhang ;-)

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das hier
        case 170: PORTD |= fBlinklampe = 15; break;  // Blinklampe 15/20 /s blinken lassen
        case 175: PORTD |= fBlinklampe = 10; break;  // Blinklampe 10/20 /s blinken lassen
        case 177: PORTD |= fBlinklampe = 5; break;  // Blinklampe 5/20 /s blinken lassen
        case 179: PORTD |= fBlinklampe = 2; break;  // Blinklampe 2/20 /s blinken lassen

sieht .... ungewöhnlich aus
Es entspricht auch nicht dem, was im Originalprogramm an der 
entsprechenden Stelle passierte :-)

Autor: Michael Z. (zellm)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Oh... Verd*** ;-)

Hier die Korrekte Version

Danke!

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nächster Punkt:
Du hast noch einige konstante Werte in deinem Programm.

zb.
Dass deine ISR 20 mal in der Sekunde aufgerufen wird, hab ich nur 
rausgefunden, indem ich den restlichen Sourcecode studiert habe.

Frage: Kann ich das leicht ändern?
Wie ist das, wenn der Prozessor nicht mit 4Mhz sondern mit 8Mhz 
betrieben wird? Was muss dann alles im Programm geändert werden? (Ziel 
ist es: Ich ändere nur eine Zahl, F_CPU, und alles andere passt sich von 
alleine an!)

Wie kommen die hier
  OCR2 = 194;          // Vergleichswert 194 einstellen => 20,03 Hz
zustande?

Was ist, wenn ich die Dauer des Hupsignals länger oder kürzer machen 
möchte? Wo muss ich dann drehen? Wie kommen die Zahlenwerte dort 
zustande?

Schön wäre es, wenn am Anfang des Programms ein paar #define wären, mit 
denen ich das einfach anpassen kann.

machst du zb
#define F_CPU            4000000   // darf nicht höher als 5.2 Mhz sein
#define TIME_RESOLUTION  20        // 20 ISR Aufrufe in der Sekunde

dann kannst du
    OCR2 = ( F_CPU / 1024 / TIME_RESOLUTION ) - 1;

schreiben und der Compiler rechnet dir den Wert aus. Da das alles 
konstante Zahlenwerte sind, wird das wirklich vom Compiler berechnet und 
nciht zur Laufzeit des Programmes. Das kostet dir also nichts, ausser 
ein bischen Tipparbeit. Aber du kannst F_CPU und TIME_RESOLUTION an 
einer Stelle ändern und damit das gewünschte veranlassen. Natürlich 
musst du dann noch:
 if (overflows == TIME_RESOLUTION) {  // Steuerung des Sekundenz�hlers
    Sekunde++;  // Wert des Sekundenz�hlers um 1 inkrementieren
    overflows = 0;  // Interruptz�hler zur�cksetzen
  }

ändern, aber das Ziel ist erreicht: Jemand der einen 1Mhz Quarz 
einsetzen will, kann das tun. Er ändert einfach F_CPU und fertig. Die 
Variable Sekunde wird nach wie vor im Sekundentakt (zumindest genau 
genug) hochgezählt.

Kannst du auch dafür
        case 170: fBlinklampe = 15; break;  // Blinklampe 15/20 /s blinken lassen
        case 175: fBlinklampe = 10; break;  // Blinklampe 10/20 /s blinken lassen
        case 177: fBlinklampe = 5; break;  // Blinklampe 5/20 /s blinken lassen
        case 179: fBlinklampe = 2; break;  // 

arithmetische Ausdrücke finden, so dass sich der Zahlenwert aus dem Rest 
und einer vorgegebenen Zeit (oder Frequenz) ergibt? Selbiges für die 
Dauer des Hupsignals.

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
if (!(PINC & (1<<START))) {
    StartDebounce ++;
  }
Theoretisch könntest du noch all diese Vergleiche in Definitionen 
packen, aber das ist dann eher noch Kosmetik als etwas anderes.

Also bei den Definitionen käme dann noch ein:
#define  RUN_START_DEBOUNCE  ((PINC&0x01) == 0x00)
Dann würde die If-Abfrage lauten:
if(RUN_START_DEBOUNCE){ StartDebounce++; }

Mir hilft es, da ich dann auf den ersten Blick sehe, in welcher 
Beziehung dieses START-Bit nun genutzt wird, gerade das '!' zu Beginn 
des Vergleichs wird manchmal sehr gerne übersehen. Die Benennung bleibt 
natürlich dir selbst überlassen, wie es für dich am eindeutigsten ist.
Aber jeder nach seinem Geschmack :)

Autor: der mechatroniker (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Peter: Ich steh gerade auf dem Schlauch: Was kann an meiner Variablen 
cntResetDebounce als anstößig interpretiert werden?

(abgesehen davon, dass das Abkürzen von Namensbestandteilen, die ständig 
vorkommen -- cnt für counter, id für identifier, ix für index usw. -- 
m.E. nicht den Lesefluss stört, sondern im Gegenteil dafür sorgt, dass 
man sprechende Variablennamen vergeben kann, ohne dass diese allzu lang 
werden; aber da gehen die Geschmäcker wohl auseinander).

Ich wollte gerade noch einen Punkt anmerken, aber ich sehe, das wurde 
schon umgesetzt (das abenteuerliche "Einfangen" des Programmablaufs am 
Ende wurde durch Rücksetzen der Variablen "lauft" ersetzt).

Autor: Michael Z. (zellm)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Karl heinz Buchegger

entspricht das erhoffte Ergebniss in etwa folgendem? :
fBlinklampe = (20*(1/gewueschte_Frequenz)); break;  // Blinklampe mi x Hz blinken lassen

bzw.
fBlinklampe = (10*(1/gewueschte_Frequenz)); break;  // Blinklampe mi x Hz blinken lassen
Da ich ja die lampe in der Angegebenen Frequenz toggle also die 
blinkfrequenz nur halb so groß ist.


Falls das noch nicht passt brauche ich noch nen kleinen Schups runter 
von dem Schlauch auf dem ich gerade stehe...

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Michael Zeller schrieb:
> @ Karl heinz Buchegger
>
> entspricht das erhoffte Ergebniss in etwa folgendem? :
>
fBlinklampe = (20*(1/gewueschte_Frequenz)); break;  // Blinklampe mi
> x Hz blinken lassen
>
> bzw.
>
fBlinklampe = (10*(1/gewueschte_Frequenz)); break;  // Blinklampe mi
> x Hz blinken lassen
> Da ich ja die lampe in der Angegebenen Frequenz toggle also die
> blinkfrequenz nur halb so groß ist.
>
>

Sieht nicht schlecht aus.

Autor: Michael Z. (zellm)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
OK. Ich habe das Programm nun nochmal etwas umgerührt...

Bin gespannt es heute Nachmittag auf der Test-Hardware (STK600) mal 
probelaufen zu lassen.

Falls noch jemand eine gute Idee hat dar natülich weiterhin kritik geübt 
werden!

Gruß Michael

Autor: Michael Z. (zellm)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,

ich habe nun wie angekündigt das Programm mal etwas getestet.
Die besagten tests verliefen sogar (zumindest relativ) erfolgreich, was 
ich bestimmt nicht zuletzt Eurer(!) Hilfe zu verdanken habe.

Dafür nochmal ein herzliches Dankeschön!

Natürlich habe ich noch den ein oder Anderen Denkfehler aufgedeckt und 
auch ein Paar leichtsinnsfehler beheben müssen...
(copy & paste ist so ne sache ;-)

Dabei sind mir einige Fragen gekommen die ich hiermit einfach mal in die 
Runde werfe, wer sich denen annehmen möchte darf das gerne tun. ;-)

1. Ich habe recht viel Code in meiner ISR. Ist dagegen etwas 
einzuwenden? Bzw. macht es aus irgendwelchen Gründen sinn da etwas zu 
verändern?

2. Würde es sinn machen Teile des Programmes in Subroutinen zu 
verwandeln und diese dann in der Mainloop nurnoch aufzurufen?

3. Gibt es noch andere Dinge die zu einem (anständigen) C-Programm 
gehören die ich momentan vergessen habe, oder die mir nicht bekannt 
sind.

Gruß an alle

Michael

Autor: P. S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Michael Zeller schrieb:

> 1. Ich habe recht viel Code in meiner ISR. Ist dagegen etwas
> einzuwenden? Bzw. macht es aus irgendwelchen Gründen sinn da etwas zu
> verändern?

Du kannst das so lange machen, wie du willst - solange du dir sicher 
bist, dass die ISR fertig ist, bevor sie wieder aufgerufen wird.

> 2. Würde es sinn machen Teile des Programmes in Subroutinen zu
> verwandeln und diese dann in der Mainloop nurnoch aufzurufen?

Wichtig: Eine Funktion sollte immer einen Sinn ergeben. Hilfsfunktionen 
mit 10+ Parametern die irgendeinen Zwischenschritt machen, der nur in 
einem bestimmten Kontext einen Sinn ergibt, sollte man vermeiden.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Michael Zeller schrieb:

> 1. Ich habe recht viel Code in meiner ISR.

Halb so wild.
Das sieht nur soviel aus. Dein Programm nimmt fast überall eine von 2 
Alternativen. Natürlich müssen beide Alternativen in der ISR stehen, 
aber abgearbeitet wird ja immer nur 1 Zweig davon.

> Ist dagegen etwas
> einzuwenden? Bzw. macht es aus irgendwelchen Gründen sinn da etwas zu
> verändern?

Das hier würde ich verändern
   ....

   ......    (Blinktimer >= ((INTERRUPTS_PER_SECOND/2)*(1/Frequenz_Blinklampe)))) 

Die Berechnung muss ja nicht jedesmal gemacht werden, verändert sich ja 
so gut wie nie (aus Sicht des µC)

Ich würde das so machen:

(BTW: Bist du sicher, dass du 1 / Frequenz_Blinklampe berechnet haben 
willst. Das sind alles ganze Zahlen. Da kommt immer 0 heraus. Manchmal 
ist es hilfreich ein bischen Mathe einzusetzen :-)

#define SLOW_BLINK    4
#define FAST_BLINK   12

uint16_t CalcTimerTicks( uint16_t Frequenz )
{
  uint16_t ticks;

  if( Frequenz == 0 )
    return 0;

  ticks = INTERRUPTS_PER_SECOND / ( 2 * Frequenz );

  if( ticks == 0 )  // nur um sicher zu gehen
    return 1;
  
  return ticks;
}

ISR (TIMER2_COMP_vect) {
  ....
  if ((Lauft != 0) && (Blinktimer >= Blinkticks)) {
  ....

int main()
{
   ...

       case 170: Blinkticks = CalcTimerTicks( SLOW_BLINK ); break;
       case 175: Blinkticks = CalcTimerTicks( FAST_BLINK ); break;


Autor: Michael Z. (zellm)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ohh... ,

dass das ja alles ganze Zahlen sein müssen hab ich total verpennt. :-X
(schande über mich)

@ Karl heinz Buchegger:
Danke für den guten Tipp.

Ich werde mal versuchen den umzusetzen.

Eine Frage dazu habe ich aber noch:

Die Blinkfrequenz kann nicht größer 500Hz sein da sonst das Ergebniss 
von
  ticks = INTERRUPTS_PER_SECOND / ( 2 * Frequenz );
0 sein wird.

Also wird dieser Unerlaubte Zustand durch
  if( ticks == 0 )  // nur um sicher zu gehen
    return 1; 
abgefangen, indem dann einfach immer 1 zurückgegeben wird.
Also der kleinst mögliche Zeitintervall.

...
Hmm...
Eigendlich wollte ich fragen wozu
  if( ticks == 0 )  // nur um sicher zu gehen
    return 1; 
gut sein soll... :-D

hat sich wohl gerade erledigt... :-)

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Michael Zeller schrieb:
> Die Blinkfrequenz kann nicht größer 500Hz sein da sonst das Ergebniss
> von
>
  ticks = INTERRUPTS_PER_SECOND / ( 2 * Frequenz );
> 0 sein wird.
>
> Also wird dieser Unerlaubte Zustand durch
>
  if( ticks == 0 )  // nur um sicher zu gehen
>     return 1; 
> abgefangen, indem dann einfach immer 1 zurückgegeben wird.
> Also der kleinst mögliche Zeitintervall.

Und damit die größte mögliche Frequenz.
Bei dir spielt das keine Rolle, den den Unterschied zwischen 200Hz und 
800Hz kann niemand sehen :-)

Das ist die ganze Idee dahinter.

Ein weiterer Nutzeffekt:
Man könnte die Variable Blinkticks damit gleichzeitig als Schalter 
fungieren lassen.
Ist Blinkticks gleich 0, dann ist das Blinken ausgeschaltet
Ist es ungleich 0, dann ist es eingeschaltet und gibt die 'Frequenz' an.

Autor: Michael Z. (zellm)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo alle zusammen,

im Anhang findet Ihr den (warscheinlich) Finalen- Stand des Programms.

Ich habe das Programm ausführlich auf meinem STK600 getestet und bin mit 
der Funktion sehr zufrieden.
Und das verdanke ich zu einem erheblichen Teil eurer kompetenten Hilfe.

Dafür nochmal ein Herzlichens Dankeschön (Ihr seid klasse)!

Um nun das erlernte nicht gleich wieder zu vergessen steht auch schon 
das nächste Projekt ins Haus... :-)
Ich werde dazu mal etwas Brain-Storming betreiben und schauen was so 
dabei herauskommt.

Abschließende Frage: falls ich zum nächsten Programm eure Hilfe 
nocheimal notwendig haben sollte ;-) , neuer Thread oder den bestehenden 
vortsetzen?
(die Überschrift des bestehenden würde ja noch stimmen)

schönen Gruß an alle

Michael

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Michael Zeller schrieb:

> Abschließende Frage: falls ich zum nächsten Programm eure Hilfe
> nocheimal notwendig haben sollte ;-) , neuer Thread oder den bestehenden
> vortsetzen?


Neues Programm -> Neuer Thread.

Autor: ... ... (docean) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
#ifndef F_CPU
#define F_CPU 4000000  // darf nicht höher als 5.2 MHz sein
#endif

besser ist
#ifndef F_CPU
#warning F_CPU nicht definiert, setze es jetzt auf 4000000
#define F_CPU 4000000  // darf nicht höher als 5.2 MHz sein
#endif

So bekommt man eine Warnung wenn man F_CPU vergisst einzustellen (im 
makefile z.B.)

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.