mikrocontroller.net

Forum: Compiler & IDEs Polling


Autor: Franz (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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ß

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

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

Autor: Franz (Gast)
Datum:

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

Autor: Welli (Gast)
Datum:

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

vielleicht so?

Autor: Franz (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ja das funktioniert!

danke!

Autor: Franz (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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ß

Autor: Welli (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: Franz (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

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

Bewertung
0 lesenswert
nicht 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.

Autor: Ulrich (Gast)
Datum:

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

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Welli (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: sch_michael (Gast)
Datum:

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

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

Bewertung
0 lesenswert
nicht 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).

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

Bewertung
0 lesenswert
nicht 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 :-)

Autor: Franz (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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ß

Autor: Marco S (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

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

Bewertung
0 lesenswert
nicht 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.

Autor: Franz (Gast)
Datum:

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

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

Bewertung
0 lesenswert
nicht 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.

Autor: Franz (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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!

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

Bewertung
0 lesenswert
nicht 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?

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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++)

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

Bewertung
0 lesenswert
nicht 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.

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

Bewertung
0 lesenswert
nicht 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.. .

Autor: Franz (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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!

Autor: Simon K. (simon) Benutzerseite
Datum:

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

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.