Forum: Compiler & IDEs Polling


von Franz (Gast)


Lesenswert?

hallo,

ich versuche gerade über polling zu zählen wie oft ein signal an einem
port anliegt! wenn ein signal zum beispiel an portb0 anliegt müsste
doch pinb 1 sein oder irre ich mich da?

gruß

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Du irrst Dich nur dann nicht, wenn portb[1..7] null sind.

von Franz (Gast)


Lesenswert?

und wie kann ich in C auf nur das erste bit des pinb registers testen?

von Welli (Gast)


Lesenswert?

if (nPortValue & 0x01) { // nur 0-Bit abfragen
  myFunction();
}

vielleicht so?

von Franz (Gast)


Lesenswert?

ja das funktioniert!

danke!

von Franz (Gast)


Lesenswert?

wie kann ich denn da die genauigkeit raufschrauben? wenn das gleiche
signal über eine gewisse zeit reinkommt schwankt der zählerstand enorm!
woran liegt das und wie kann man das beheben??

gruß

von Welli (Gast)


Lesenswert?

Dann scheinst du, alles mögliche zu zählen, nur nicht dein Signal.
Hast du vielleicht an deinem Port einen Taster der ordentlich prellt?
Oder empfängst du andere Störsignale?

von johnny.m (Gast)


Lesenswert?

Wenn Du zählen willst, dann musst Du die Signalflanken zählen. Ich
vermute mal, dass Du gar nicht wartest, bis Dein Signaleingang wieder
auf null ist und deshalb jeden High-Pegel ein paar tausend mal
erfasst...

von Franz (Gast)


Lesenswert?

also ich zähl den counter folgendermaßen hoch:

cbi(DDRB, 0);
sbi(PORTB,0);
char neu = PINB;
if ( neu != alt)
{
  if ( !(neu & 1) )
        counter++;
}
alt = neu;
sbi(DDRB,0);

geht das so?

von Karl H. (kbuchegg)


Lesenswert?

Konfigurier den Port am Beginn des Programms und ändere
den dan nicht mehr. Wenn du den Pullup dazuschaltest, kannst
du abhängig davon wie die äussere Beschaltung aussieht ein
paar Schwingungen oder durch ein RC-Glied eine Verzögerung kriegen.
Wie auch immer: Wenn das Pgm hochfährt -> Ports und Pullups
konfigurieren. In der Interrupt-Funktion wertest du dann nur mehr
die Ereignisse aus und lässt die Konfiguration in Ruhe.

Zum Rest: Im Prinzip kannst du das so machen.
Ich wuerde es allerdings so schreiben:

   char neu = PINB & 0x01;

   /* Uebergang von 0 nach 1 ? Ja: Zaehlen */
   if( ( alt == 0 ) && ( neu != 0 ) )
     counter++;

   alt = neu;

Ich finde das kommt besser zum Ausdruck, welches Ereignis die
Zählung auslöst. Ist aber Geschmackssache.

von Ulrich (Gast)


Lesenswert?

[Verwirrungstiften]
Oder gleich so:
if( ( alt == 0 ) && ( neu != 0 ) && alt = neu )
     counter++;
Damit spart man sich eine Zeile ;-)
[/Verwirrungstiften]

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Am Ende sollte er glaub' ich sowieso besser einen Timerinterrupt
implementieren und in diesem seine Tasten abfragen und
entprellen.  Beispielcode für sowas gibt's reichlich.

von Welli (Gast)


Lesenswert?

@ulrich

[Verwirrungstiften]
Oder gleich so:
if( ( alt == 0 ) && ( neu != 0 ) && alt = neu )
     counter++;
Damit spart man sich eine Zeile ;-)
[/Verwirrungstiften


wobei alt = neu immer 1 ergibt

von sch_michael (Gast)


Lesenswert?

Ist ja auch so gedacht, halte ich persönlich aber für schlechten
Programmierstil, da unübersichtlich und nur schwer zu durchschauen.

von Karl H. (kbuchegg)


Lesenswert?

@Ulrich

Abgesehen vom offensichtlichen Tippfehler.
Wenn schon, dann:

if( ( alt != neu ) && ( alt == 0 ) && ( neu != 0 ) )
     counter++;

Viel Spass beim rausknobeln warum.
Tip: Es hat was mit der 'Short-Cut-Evaluation' zu tun
(Sorry, ich kenn das deutsche Wort dafür nicht).

von Karl H. (kbuchegg)


Lesenswert?

@Ulrich

[Mit der flachen Hand auf die Stirn klatschen]
Jetzt hab ich erst verstanden worauf du hinaus willst :-)
Solche Schweinereien hab ich mir schon vor Jahren abgewöhnt :-)

von Franz (Gast)


Lesenswert?

ich kann die ports aber von anfang an nicht konfigurieren und so lassen
weil das lcd alle ports belegt! ich muss sie also anschalten, gucken
und zählen und wieder abschalten! oder gibt es da doch eine elegantere
lösung? vielleicht die ports bei dem display deaktivieren?!

gruß

von Marco S (Gast)


Lesenswert?

if( ( alt == 0 ) && ( neu != 0 ) && alt = neu ) funktioniert auch nicht
sonderlich. Es wird versucht dem lvalue

(alt == 0) && (neu != 0) && alt

den Wert von neu zuzuweisen (Der = Operator hat hier die geringste
Priorität). Dazu müßte man den Ausdruck alt = neu in Klammern setzen.
Dann würde das logische && von links nach rechts ausgewertet und die
Zuweisung alt = neu nur erfolgen, wenn zuvor alt == 0 und neu != 0
logisch richtig waren. Damit spart man sich nicht nur eine Zeile ein,
sondern erzeugt auch ein ganz anderes Verhalten.

von Karl H. (kbuchegg)


Lesenswert?

> ich kann die ports aber von anfang an nicht konfigurieren

Dann machs wenigstens so:
Port konfigurieren
Timer initialisieren
Interrupts starten

und innerhalb der Interrupt Routine wertest du nur mehr
den Pin-Zustand aus. Aber lass um Gottes Willen während
der kompletten eigentlichen Messung die Portkonfiguration
in Ruhe.

> und so lassen weil das lcd alle ports belegt!

Keine gute Idee.

von Franz (Gast)


Lesenswert?

wie soll denn aber der interrupt ausgelöst werden wenn das lcd alle
ports belegt??

von Karl H. (kbuchegg)


Lesenswert?

Reden wir jetzt aneinander vorbei?
Was hat das eine mit dem anderen zu tun, ausser das das LCD
Port-Pins belegt und du aber einen Pin als Eingang zum
Abfragen brauchst.

Du hast dir doch einen Timer aufgesetzt, der in regelmaessigen
Zeitabständen einen Interrupt ausloest. Vom Auftreten eines
Interrupts bis zum Auftreten des nächsten Interrupts zählst
du mit wieviele 0-1 Übergänge an besagtem Eingangspin
auftreten.

von Franz (Gast)


Lesenswert?

nein ich zähle nicht mit dem timer! ich zähle in der mainloop! in dem
timer sende ich die daten an das lcd!

von Karl H. (kbuchegg)


Lesenswert?

Damit ich das richtig sehe:
  Den Timer, mit dem du eine stabile Zeitbasis hinkriegen
  könntest, nimmst du um damit Daten auf ein LCD zu schaufeln.

  Auf der anderen Seite benutzt du dort wo du eigentlich
  ein genaues Timing brauchen würdest eine Wald und Wiesen
  Schleife, die durch jeden dahergelaufenen Interrupt ab
  und an mal unterbrochen werden kann.

Und da wunderst du dich, dass die Zählerstände schwanken?

von Simon K. (simon) Benutzerseite


Lesenswert?

aha, und woher hast du die zeitbasis in der mainloop? die kann doch
unterbrochen werden durch interrupts und während dieser zeit wird dein
zählregister nicht mehr inkrementiert...

mit nem timer hast du ne stabile zeitachse (zB alle 1ms gibts 1
interrupt und 1 counter++)

von Karl H. (kbuchegg)


Lesenswert?

Vielleicht hab ich dich auch nur falsch verstanden.

Die Struktur sollte so aussehen:

In der Mainloop detektierst du ständig, ob am Eingang
ein 0-1 Übergang erkennbar ist.

Im Timer-Interrupt (der regelmässig aufgerufen wird), wird
der Zaehlerstand ausgewertet und wieder auf 0 gesetzt.
Natuerlich sollte die Timer-Interrupt-Funktion nicht allzu
lange dauern. Auf keinen Fall darf sie laenger als ein kompletter
0-1-0 Übergang sein. Die Ausgabe auf das LCD ist also nicht so toll
da drinnen. Die wuerde ich da komplett rausschmeissen.

main wuerde dann in etwa so aussehen (Achtung: Pseudo Code der
so ähnlich wie C aussieht).

  init_lcd()

  while( 1 )

    if( mode == 0 ) {
      counter = 0;
      mode = 1;
      Konfiguriere Eingang zum Aufnehmen der Pulse;
      starte_timer();
    }

    if( mode == 2 ) {     // mode ist vom Timer Interrupt auf 2
                          // gestellt worden, damit wird signalisiert
                          // das eine bestimmte Zeiteinheit abgelaufen
                          // ist.

      stoppe_timer();
      mode = 0;
      Konfiguriere Eingang wieder zurueck;
      counter auswerten und anzeigen;
    }

    if( mode == 1 ) {  // mode == 1 bedeutet dass zur Zeit gemessen
                       // wird.
      neu = ....
      ....
      if( ....
        counter++;
      alt = neu;
    }
  }

Und die Timer-Overflow Funktion hat nur noch eine Aufgabe:
Die globale Variable mode von 1 auf 2 zu setzen um der main-loop
anzuzeigen, dass die Zeit abgelaufen ist.

von Karl H. (kbuchegg)


Lesenswert?

Oops. Jetzt hab ich im letzten Posting während des Schreibens
2 Ideen zu einer einzigen vermanscht.
Ich würde es so machen, wie im 2.-ten Teil beschrieben.
Wenn du Frequenzen misst, dann ist die Zeitbasis der Messung
eines der wichtigsten Dinger. Ob das LCD nach 10 ms oder 11 ms
upgedatet wird, interessiert keine S.. .

von Franz (Gast)


Lesenswert?

ich habe aber keine schwankungen mehr! der zähler in der mainloop läuft
stabil! alle eine sekunde kommt ab und zu mal eine schwankung von 1!
aber das ist akzeptabel!
das senden im timer funktioniert auch problemlos!

danke für eure hilfe!

von Simon K. (simon) Benutzerseite


Lesenswert?

und, weißt du jetzt wieviel Zeit (t) ein Counter-zählerwert ist?

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.