mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik "komische Zeichen" bei Verwendung von char[]


Autor: Frank (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hallo,

der Titel sagt vllt nicht direkt, um was es geht: also:
Mein Programm lässt einen tiny2313 über I²C einen Temperatursensor 
auslesen und die Werte auf Verlangen über serielle Schnittstelle an den 
Rechner senden. Damit der Speicher auch schön knapp wird geb' ich die 
Daten auch nochmal auf ein LCD aus.
Zum Problem:
Ich will einen Zähler (uint8_t oder char oder BYTE oder wasauchimmer) 
ausgeben. Codeschnipsel:
        char c[7];
  itoa(counter,c,10);
  uputs("counter at: ");
  lcd_puts("counter at: ");
  uputs(c);
  USART_Transmit('\n');
  lcd_puts(c);
  lcd_putc('\n');
Sobald der Codeblock nicht mehr auskommentiert ist, werden kryptische 
Zeichen über die RS232 gesendet, der µC resettet sich andauernd, 
reagiert nicht mehr richtig auf die Befehle(über RS232), ...
Das Verhalten tritt auch auf, wenn ich nach dem "sei();" in meiner 
main-Endlosschleife den Status von Tastern abfrage und auch erst dann, 
wenn ich auf diese Events reagiere.

Ich hoffe mal hier kann mir jemand helfen. Den so funktionierenden Code 
hänge ich an


Frank

Autor: Frank (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
hatte den quellcode vergessen ;)

Autor: Klugscheisser (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Man kriegt vielleicht noch ne Textverarbeitung im Interrupt unter... :-}

Sorry, aber das ist ein so häufiger Fehler: In Interrupts wird so 
schnell wie möglich, nur das ALLERNOTWENDIGSTE getan. Der Rest im 
Hauptprogramm. Dann klappts auch mit den Delays und anderen Interrupts 
die sich vielleicht in die Textverarbeitung drängeln wollen.

Autor: Klugscheisser (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
da fehlte der Ironie-Tag:
"die sich vielleicht in die Textverarbeitung drängeln wollen."

Sollte heissen, je kürzer der Interrupt, desto grösser die Chance, das 
keine verloren gehen.

Autor: Frank (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hm
gut, nur die Frage, wie komm ich aus der Interruptroutine raus?
Busy waiting will ich ja eigentlich durch die Interrupts umgehen - gut 
der µC hat nix besseres zu tun. Gibt's noch ne bessere möglichkeit?

Frank

Autor: Frank (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
update:

ich hab' statt den funktionsaufrufen in der Interruptroutine jetzt nur 
eine Variable verändert, die in der main-Schleife dauernd überprüft 
wird. Ändert sich der Wert der Variable wird die entsprechende Funktion 
aufgerufen.
Effekt: Kryptische Zeichen und die Funktionen werden nicht ausgeführt.

Gibt's hier nen Patentrezept für?

anbei wieder der Quellcode

Frank

Autor: Klugscheisser (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>nur die Frage, wie komm ich aus der Interruptroutine raus?
In C wird die Int-Routine verlassen, wenn das Funktionsende erreicht 
ist. Ein Return tuts auch. In Assembler ein "RTI".

>Busy waiting will ich ja eigentlich durch die Interrupts umgehen
Eben das ist ja einer der Vorteile von Interrupts, das Du kein 
Busy-Waiting brauchst.
Ich sagte ja auch nicht (wo schrieb ich denn das?) das Du auf Interrupts 
verzichten solltst. Ich schrieb vielmehr: "In Interrupts wird so
schnell wie möglich, nur das ALLERNOTWENDIGSTE getan".

Was genau ist Dir nicht klar?
Lies den Artikel unter http://www.mikrocontroller.net/articles/Interrupt
Dort findest Du simple Beispiele.

Also in Deinem Fall z.B.
volatile BYTE rcv_data, status, flag;
ISR(USART_RX_vect) {
    status = UCSRA;
    rcv_data = UDR;
    flag = true;
}

main {
   ...
   if (flag == true) {
      // das ganze Geraffel das vorher in Deinem Int stand
      flag = false;
   }
   ...
}

Ganz so, würde ich es nicht lassen, aber das wäre mal ein Ansatz. In 
Main, die Daten wegspeichern und flag gleich auf false setzen.

Im RX-Interrupt bietet sich z.B. ein Ringpuffer an.

Autor: Klugscheisser (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>ich hab' statt den funktionsaufrufen in der Interruptroutine jetzt nur
>eine Variable verändert, die in der main-Schleife dauernd überprüft
>wird.

Falschen Code gepostet?
Ich sehe im Interrupt immer noch einen ganzen Haufen Funktionsaufrufe.

Autor: Klugscheisser (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Gibt's hier nen Patentrezept für?
Modularen Aufbau. Entscheidung für Bottom-Up oder Top-Down Entwurf.
In dem Fall (wie oft) Bottom-Up. Einfache Funktionen zuerst. 
Testprogramm. Testen. Nächste Funktionen.

Autor: Frank (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
naja, die fehlerüberprüfung und das echo hab' ich gelassen, dachte die 
wären nicht so schlimm.
Jetzt aber mal alles auskommentiert -> funktioniert einwandfrei.

Vielen vielen Dank für die schnelle Hilfe zu so später Stunde.

Frank

Autor: Klugscheisser (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>naja, die fehlerüberprüfung und das echo hab' ich gelassen, dachte die
>wären nicht so schlimm.
>Jetzt aber mal alles auskommentiert -> funktioniert einwandfrei.
Hah! Hab's ja gleich gesagt. :-))))

>Vielen vielen Dank für die schnelle Hilfe zu so später Stunde.
Freut mich, das Du Dich bedankst. Viel Spass und Erfolg noch.

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Frank wrote:
> naja, die fehlerüberprüfung und das echo hab' ich gelassen, dachte die
> wären nicht so schlimm.
Denken kann Fehlen  :-/

Sowas hat in einer Interrupt-Routine überhaupt gar nix zu suchen:
:
    lcd_puts("\nerror");
    RED;
    if( status & (1 << FE) ){
      lcd_puts(" fe\n");
    }if( status & (1 << DOR) ){
      lcd_puts(" dor\n");
    }if( status & (1 << UPE) ){
      lcd_puts(" pe\n");
    }return;
    }
  lcd_putc(rcv_data);
:
Weißt du, was lcd_puts() wie macht? Nein? Dann hat diese Funktion im 
Interrupt nichts verloren. In die Interruptroutine kommt nur 
handverlesener, bekannter Code.

Autor: Frank (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
gut, habe verstanden.

Jetzt geht mir aber der Speicherplatz aus.
entweder switch braucht zu viel, oder ich muss an anderer Stelle sparen.

lässt sich die pfleury-lcd-lib irgendwo noch verkleinern bzw gibt s 
sonst noch beliebte Fallen?
(so in richtung: BYTE verwenden, für nen schalter sind 7 bit zu viel)


nochmal Danke für die Mühe

Frank

Autor: Klugscheisser (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Welcher Speicher geht Dir aus? RAM, Flash oder beides?

Durch das verschieben des Codes aus dem Int irgendwo andershin sollte 
sich die Codegrösse nicht (wesentlich) ändern?

Autor: Frank (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

mir geht vor allem der Programmspeicher aus - von 2k hab ich ohne 
LCDAusgabe noch ca 1.5k übrig. Meine Frage jetzt also ist, welche 
Codekonstrukte man tunlichst vermeiden sollte. z.B. kostet mich
a++; a%=10
deutlich mehr als
a = a<10 ? a+1 : 0

Was wäre ein Testlauf ohne einen Fehler, mit dem ich wieder zum Thema 
zurückkomme. Diesmal gibt's komische Zeichen, nur weil ich mich 
erdreiste einen Ausgangspin ein- oder auszuschalten. In der 
RX-Interrupt-routine wird nur noch (leider mit switch) ein char 
verändert.
DDRB |= (1 << PB6 ); // Ausgang definieren
...
PORTB |= (1<<PB6); // Ausgang einschalten
...
PORTB &= ~(1<<PB6); // Ausgang ausschalten
Wenn jemand Rat weiß . . .

tia

Frank

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.