mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Alternative zu Printf in Interrupt


Autor: Benno (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo

Kann mir bitte jemand helfen.
Ich gebe in einer Interruptroutine daten aus (von einem ADC). Momentan
mit Printf, das dauert aber zu lange. die Routine sollte  nicht länger
als 1ms dauern da ich eine Sampelrate von 1000Hz anstrebe.
Gibt es eine Alternative?? ich hab was von Flags gelesen. Davon hab ich
keinen Plan. Wie geht das??

Ich verwende einen PIC16F777 mit CCS Compiler

Autor: Dirk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

eine alternative waere es deine Daten in einen Ringbuffer zulegen und
in der Mainroutine dann auf die USART Schnittstelle zugeben. Die
Funktion zur Ausgabe muesstest du selber programmieren.


Gruß,

Dirk

Autor: Benno (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi Dirk,

Das klingt kompliziert!! Als schnittstelle verwende ich ein RS232. Geht
das damit auch?
Hast Du einen Beispielcode für das legen auf den Ringbuffer? Ich hab
davon noch nie gehört, bin erst seit ein paar monaten am
Programmieren.
Vielen dank für Deine schnelle Hilfe!!

Gruß Benno

Autor: Hagen Re (hagen)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das problem dürfte hier nichtmal die RS232 Software sein, die meisten
arbeiten intern schon mit Ringbuffern. Eher vermute ich das die
String-Formatierungen in printf() das zeitliche Problem darstellen.

Also entweder ganz darauf verzichten und dein RS232 protokoll auf ein
binäres Protokoll ohne Formatierungen umstellen. Dazu benötigst du
natürlich auf PC Seite eine eigene Software zum Empfang der Daten.

Oder aber die Formatierung deiner Werte ausserhalb der ISR machen und
dann senden. Unter Umständen kostet das aber eben soviel Zeit das mehr
Daten schneller reinkommen als du formatieren und raussenden kannst.

Gruß Hagen

Autor: Tom (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wieviel du senden kannst hängt natürlich zunächst mal von der Baudrate
ab. Bei 9600 Baud ist das gerade mal 1 Zeichen in einer ms. Selbst wenn
du auf 115200 Baud gehst, dann kannst du max. 11 Zeichen in dieser Zeit
senden. (1 Zeichen = 10 Bit bei 8N1)
Somit ist wahrscheinlich die serielle Schnittstelle die Bremse und gar
nicht printf().

Gruss

Autor: Wolfram (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Gibt es eine Alternative?? ich hab was von Flags gelesen. Davon hab
ich
>keinen Plan. Wie geht das??

dein Programm sollte so aussehen

interruptroutine
{
lege Wert in Puffer
}

Hauptprogramm
1.sind werte im Puffer?
wenn ja:übernimm Werte und gib sie aus evt. mit printf
zu 1.

mit Flags regelst du den Zugriff auf den Puffer. Es dürfen nicht beide
(Interrupt und Hauptprogramm) auf den Puffer gleichzeitig zugreifen.
Das einfachste ist die Interrupts, während deines Zugriffs auf den
Puffer aus dem Hauptprogramm zu verbieten.
Da der Puffer von 2 unabhängigen routinen benutzt wird mußt du dies dem
Compiler mitteilen. In C würdest du dies mit volatile tun.

Autor: Michi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
"Es dürfen nicht beide (Interrupt und Hauptprogramm) auf den Puffer
gleichzeitig zugreifen.
Das einfachste ist die Interrupts, während deines Zugriffs auf den
Puffer aus dem Hauptprogramm zu verbieten.
Da der Puffer von 2 unabhängigen routinen benutzt wird mußt du dies
dem
Compiler mitteilen. In C würdest du dies mit volatile tun."


Häh?
Wieso muss man den Interrupt im Hauptprogramm sperren?
Das ist ja die lausigste Lösung. Das geht auch anders.

Autor: Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Man muß nur einen Ringpuffer aufbauen, auf den zwei Zeiger zeigen:
Ein Schreibzeiger und Lesezeiger. Der Schreibzeiger wird in der ISR
erhöht und der Lesezeiger in Hauptprogramm.
An die Speicherstelle des Schreibzeigers wird der ADC-Wert durch die
ISR geschrieben. Im Hauptprogramm werden dann solange die Werte über
die RS232 gesendet, bis der Lesezeiger den Schreibzeiger eingeholt hat.
Allerdings könnte es nach Toms Berechnung vorkommen, dass eher der
Schreibzeiger den Lesezeiger "überrundet". (ich hab die Berechnung
nicht weiter nachvollzogen/überprüft.)

Autor: Benno (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das mit dem Ringpuffer bringt mir glaube ich nichts.
die zeit des lesens hängt ja von der übertragung ab. Wenn ich das
wieder mit pintf mache wird das ganze ja auch nicht schneller. Ich hab
keine Pausen für das Verbieten des Interrupts eingeplant. Ich brauche
kontinuierlich einen ADC-Wert pro ms, also muß das interrupt auch jede
ms ausgelößt werden. Oder denke ich da falsch?

Gruß Benno

Autor: Tom (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Da denkst du richtig.
Wenn dein Controller eh nichts anderes macht ausser ADC-Werte einlesen
und über die serielle Schnittstelle ausgeben, dann gewinnst du durch
einen Ringpuffer gar nichts. Das erzeugt dann eher noch mehr Overhead.
Somit musst du dir überlegen wie viele Zeichen du ausgeben kannst, bis
der nächste Interrupt kommt. Werden nicht allzu viele sein (s.o.).
Vielleicht macht es ja Sinn die Werte direkt zu senden und nicht erst
mittels printf() nach ASCII zu wandeln. Dann muss halt ein Programm auf
der anderen Seite die Werte in ein lesbares Format bringen.
Sollte dich wirklich nur der printf() ausbremsen, musst du eben deine
eigene Ausgaberoutine schreiben, einen ADC-Wert nach ASCII zu
konvertieren geth mit relativ wenig Aufwand.

Gruss

Autor: Christian (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Benno: Was macht denn das printf? Nur eine Wandlung von einem Wert in
desses ASCII-Darstellung mit irgendeinem Radix? Dann solltest Du Dir
mal die Funktionen itoa(...) bzw. ltoa(...) ansehen, die sind schneller
als printf. Oder eben die Konvertierung eben selber programmieren, z.B.
für Radix 16 (Hexadezimalsystem) geht das sehr effizient.

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.