www.mikrocontroller.net

Forum: Compiler & IDEs LCD - Ausgabefehler


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

Bewertung
0 lesenswert
nicht lesenswert
Hallo Forum

Habe ein Problem mit der LCD - Ausgabe.
Kurze Fehlerbeschreibung:
Gebe an das Display in Zeile1 'Satellite Tracking' und in Zeile2 
'System' aus. Beide Strings habe ich in die Mitte des LCD positioniert.
Nach 5 sec soll ein anderer Text ausgegeben werden und nach weiteren 5 
sec ein weiterer Text. Danach soll wieder Text Nr.1 ausgegeben werden.
Da das LCD nach dem Umschalten auf den nächsten Text einzelne Buchstaben 
des vorigen Textes ausgab, begann ich mit der Fehlersuche.
Ich veränderte den Code so, dass immer nur Text 1 ausgegeben werden 
soll. Nachdem ich den Code an den µC übertragen hatte, bestand immer 
noch das Problem. In Zeile2 stand kurz nach der Übertragung nicht mehr 
'System', sondern 'SystemSysem'. Nach weiteren 5 sec werden wieder 
andere Zeichen übertragen.

Verwende als Routinen den LCD Code vom Tutorial.
Programmiere mit AVR Studio und WinAVR 20090313

Hier ein Kleiner Ausschnitt des Codes:

ISR(TIMER0_COMP_vect){

  
  Zaehler++;
  if(Zaehler == 625){
    
    if(dddd == 1){
      .
      .
      .
    }

    if(dddd == 2){
          
      lcd_clear();
      //LCD_Ausgabe++;       // zur Fehlerbegrenzung
                             // auskommentiert
      Zaehler = 0;
      if(LCD_Ausgabe == 4){

        LCD_Ausgabe = 1;
        
      }
      asdf = 1;
    }
  }
}




int main(void){

        .
        .
        .

  TIMSK |= (1<<OCIE0);

  DDRC = 0xff;
  PORTC = 0xFF;
  sei();

  lcd_init();

  TCCR0 |= (1<<WGM01);
  OCR0 = 249;
  Uebertragung1 = 1;
  LCD_Ausgabe = 1;
        gh = 1;
  
  while(1){

    if(Uebertragung1 == 1){
      
      dddd = 2;
      
      if(LCD_Ausgabe == 1){

        set_cursor(1,1);
        lcd_string("Satellite Tracking");  
        set_cursor(7,2);
        lcd_string("System");
        //set_cursor(5,1);
        if(gh == 1){

          TCCR0 |= (1<<CS02);
          gh = 0;
        }
      }

      if(LCD_Ausgabe == 2){

        set_cursor(1,1);
        lcd_string("aaaaaaaaaaaaaaaaaaa");  
        set_cursor(7,2);
        lcd_string("bbbbbbbbbbbbb");
      }

      if(LCD_Ausgabe == 3){

        set_cursor(1,1);
        lcd_string("ccccccccccccccccccc");  
        set_cursor(7,2);
        lcd_string("dddddddddddddddd");
      }
    }

      .
      .
      .


Weiß leider nicht wo der Fehler liegt.
Es kann sich nur um einen kleinen Fehler handeln, da das Programm (außer 
das LCD) an sich funktioniert.


Weiters bekomme ich immer ein Warning.
> passing argument 1 of 'strtok' discards qualifiers from pointer target type


Wo liegt hier das Problem?

Danke für eure Hilfe.

Autor: Εrnst B✶ (ernst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Welcher AVR?
Evtl zu wenig Ram => Stacküberlauf?
oder F_CPU falsch gesetzt => LCD-Wartezeiten zu kurz => set_cursor 
funktioniert nicht?

> passing argument 1 of 'strtok' discards qualifiers from pointer target type

strtok mag einen char * als source-string, keinen volatile unsigned char 
*...
Richtige typen verwenden oder mit cast compiler zum schweigen bringen.

Autor: Christian (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Verwende einen ATmegs32, hab also noch ausreichend Ressourcen.
F_CPU kann nicht falsch gesetzt sein, da alle anderen Programme damit 
einwandfrei funktionierten.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du mußt Dich schon entscheiden, wo Du das LCD benutzt, im Main oder im 
Interrupt.
Beides zusammen geht nicht!

Und Interrupt ist definitiv der falsche Platz, wenn Du auch mal größere 
Programme schreiben willst.
Das LCD ist nämlich ein sehr langsames Gerät, versaut Dir also die 
Interrupt-Response.


Peter

Autor: Christian (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Peter

Danke für den Tipp.
Hab statt lcd_clear(); eine Variabe gesetzt und das LCD im main 
gelöscht.
Jetzt funktioniert es ohne Probleme. Sind solche Hilfsvariablen die 
beste Lösung für LCD-Befehle, die in der ISR gebraucht werden?

In der Interrupt - Routine habe ich unter if(dddd == 1) noch ein 
lcd_clear();. Dieser Befehl scheint dem Programm nichts auszumachen, 
erst bei zwei LCD-Befehlen arbeitet der µC nicht korrekt. Sollte ich das 
noch vorhandene lcd_clear(); aus der Routine auch entvernen?
Warum funktioniert die Verwendung im main und im Interrupt zusammen 
nicht?
Danke für Deine Bemühungen.

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

Bewertung
0 lesenswert
nicht lesenswert
Christian schrieb:

> Jetzt funktioniert es ohne Probleme. Sind solche Hilfsvariablen die
> beste Lösung für LCD-Befehle, die in der ISR gebraucht werden?

Im Grunde ja.
Man nennt die Dinger 'Jobflags'.
Sie zeigen der Hauptschleife an, dass ein Job zu erledigen ist, bei dir 
das löschen eines LCD.

Aber im Grunde hast du trotzdem immer noch einen falschen Ansatz.
Die ISR soll sich nämlich im Grunde überhaupt nicht um das LCD kümmern.
Die ISR macht eine Modusumschaltung. Dein LCD geht vom Modus "Ausgabe 1 
anzeigen" über in den Modus "Ausgabe 2 anzeigen". Und die Hauptschleife 
entscheidet, was dazu alles notwendig ist.

> In der Interrupt - Routine habe ich unter if(dddd == 1) noch ein
> lcd_clear();. Dieser Befehl scheint dem Programm nichts auszumachen,
> erst bei zwei LCD-Befehlen arbeitet der µC nicht korrekt. Sollte ich das
> noch vorhandene lcd_clear(); aus der Routine auch entvernen?

Ja. Schmeiss es raus. Und wechsle deine Sichtweise der Dinge. Die ISR 
geht es überhaupt nichts an, dass da ein LCD existiert (siehe oben mit 
den Modi)

> Warum funktioniert die Verwendung im main und im Interrupt zusammen
> nicht?

Weil du nicht darauf achtest, welche Anweisungen in der Hauptschleife 
unterbrichen werden, wenn der Interrupt kommt.

Du hast momentan eine gemeinsam genutzte Resource, die aus mehreren 
Threads angesprochen wird.
Stell dir einen Drucker vor und 2 Threads. Der 2.te Thread kann den 
ersten jederzeit unterbrechen.
So, jetzt versucht der 1.te Thread eine Ausgabe am Drucker zu machen. Er 
will "Willkommen" dort hinschreiben. Also fängt er an:
W hinmalen
i hinmalen
l hinmalen
l hinmalen

und jetzt schlägt der 2.te Thread zu und gibt seinerseits etwas auf dem 
Drucker aus: "Hallo"
H hinmalen
a hinmalen
l hinmalen
l hinmalen
o hinmalen

der 2. Thread hat seinen Job erledigt und die Kontrolle geht zum 1.ten 
Thread zurück. Der wurde bei der Ausgabe unterbrochen und macht dort 
weiter wo er unterbrichen wurde. Also malt er weiter
k hinmalen
o hinmalen
...

Auf dem Druckerpapier steht dann: WillHallokommen

So. jetzt kanns natürlich noch dicker kommen. Was ich so lapidar als 
'hinmalen' bezeichnet habe, sind in Wirklichkeit ja auch Aktionen, die 
eine gewisse Zeit dauern und in sich wieder aus vielen Aktionen 
bestehen. Je nachdem, wo genau der 2-te Thread den ersten unterbricht, 
kann da alles mögliche entstehen. Von "der eine Thread hat den Cursor an 
die Position 10 geschickt, der andere ändert ihm das 'unter dem Arsch'" 
bis hin zu "der eine Thread schaltet die Portpins so wie er sie braucht, 
die ihm der andere gleich wieder anders umschaltet".

Autor: Christian (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> Aber im Grunde hast du trotzdem immer noch einen falschen Ansatz.
> Die ISR soll sich nämlich im Grunde überhaupt nicht um das LCD kümmern.
> Die ISR macht eine Modusumschaltung. Dein LCD geht vom Modus "Ausgabe 1
> anzeigen" über in den Modus "Ausgabe 2 anzeigen". Und die Hauptschleife
> entscheidet, was dazu alles notwendig ist.

Ok! Habe verstanden, dass sich die ISR nicht um das LCD kümmern soll. 
Trotzdem entscheidet die ISR durch diese Jobflags was zu tun ist. In 
meinem Programm kümmert sie sich um das LCD.
Wo ist der falsche Ansatz, wenn meine ISR durch setzen von Variablen dem 
main mitteilt, dass es im darauffolgenden Durchlauf das LCD löschen 
soll?

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.