www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Display Probleme


Autor: Goldi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo

ich Probleme mit einem Display.

Zuerst habe ich versucht eine Linie mit blauem Hintergrund auszugeben.
Das hat funktioniert.

Jetzt versuche ich Buchstaben auszugeben die in einem Interrupt 
verändert werden.

Die Probleme sind jetzt dass kurze Zeit nur ein blauer Hintergrund 
angezeigt wird dann wird ein grüner Hintergrund angezeigt, der blaue 
Hintergrund wird mit einem grauen vermischt und ganz kurze Zeit zeigt es 
mir den blauen Hintergrund mit dem Buchstaben an.


Was kann da das Problem sein.

Es ist ein at90 und beim Display ist ein Goldelox Prozessor.
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>

void rs232_putchar (char buchstabe);

volatile char a;



int main(void)
{
  DDRC= 0x04;
  PORTC= 0x04;
  DDRB= 0xFF;
  PORTB = 0xFE;

  CLKPR = 0x80; 
  CLKPR = 0x00;

  UCSR1B = (1<<TXEN1);
  UCSR1C = (0<<USBS1) | (3<<UCSZ10);
  UBRR1 = 25;

  
  TCCR1B= (1<<WGM12) | (4<<CS10) ;
  TIMSK1= (1<<OCIE1A) | (1<<TOIE1);
  OCR1A = 31250;


  _delay_ms(1000);

    rs232_putchar(0x55); //Uart

    rs232_putchar(0x45); //Display löschen



    a='a';

    sei();
  
  while(1)
  {
    rs232_putchar(0x42); //blauer Hintergrund
    rs232_putchar(0x00);
    rs232_putchar(0x1F);

    rs232_putchar(0x45); //Display löschen


    rs232_putchar(0x74); //a als char ausgeben
    rs232_putchar(a);
    rs232_putchar(0x2F);
    rs232_putchar(0x8F);
    rs232_putchar(0xFF);
    rs232_putchar(0xFF);
    rs232_putchar(0x04);
    rs232_putchar(0x02);

  }
}


void rs232_putchar (char buchstabe)
{
  while ( !( UCSR1A & (1<<UDRE1)) )
  ;

  UDR1 = buchstabe;
}


ISR (TIMER1_COMPA_vect)
{

  a++;
  
    if(a == 'z')
    {
      a='a';
    }
}

MfG

Autor: Goldi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dieses Display macht mich noch wahnsinnig.

Kann mir jemand sagen was das bedeutet.

Debugger: 'Break at line projekt.c:60' has been disabled. Unable to bind 
line 60 in file "projekt.c" to a program memory address.
Debugger: 'Break at line projekt.c:247' has been disabled.
Debugger: 'Break at line projekt.c:215' has been disabled.


MfG

Autor: Goldi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was ich vergessen habe zu fragen.

Ist es normal bei einem OLED Display dass man immer am Anfang der 
"while(1)" Schleife den Bildschirm löscht.

Habe einen Strich gezeichnet und nach einiger Zeit kommen eine Menge von 
anderen Strichen irgendwo am Display

Autor: Sascha Weber (sascha-w)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

na mit deiner while(1) löschts't du ja ständig dein Display und baus't 
alles neu auf und das im ms Bereich - wenig sinnvoll. Warte lieber bis a 
sich ändert und führe dann den Inhalt der Schleife aus.

Sascha

Autor: Goldi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich weiß dass es immer wieder gelöscht wird. Das Problem ist dass sich 
andauernd irgendwelche Stricherl quer durch das Display bilden. Deswegen 
habe ich es immer gelöscht. Mein Problem ist jetzt noch dass das 
Interrupt regelmäßig ausgeführt wird (Led blinken) aber der sich nicht 
ändert. Zumindest lange Zeit.


#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>

void rs232_putchar (char buchstabe);
void wait_ack(void);
char rs232_getchar(void);

volatile char a;



int main(void)
{
  DDRC= 0x04;
  PORTC= 0x04;
  DDRB= 0xFF;
  PORTB = 0xFE;

  CLKPR = 0x80; 
  CLKPR = 0x00;

  UCSR1B = (1<<TXEN1) | (1<<RXEN1);
  UCSR1C = (0<<USBS1) | (3<<UCSZ10);

   UBRR1H = (25>>8);
   UBRR1L = 25;

  TCCR1B= (1<<WGM12) | (4<<CS10) ;
  TIMSK1= (1<<OCIE1A) | (1<<TOIE1);
  OCR1A = 31250;

  _delay_ms(400);

  rs232_putchar(0x55);

  rs232_putchar(0x45); //Bildschirm löschen


    a='a';

    sei();

  rs232_putchar(0x45);
  
  while(1)
  {



    //rs232_putchar(0x45); //Display löschen

    rs232_putchar(0x42); //blauer Hintergrund
    rs232_putchar(0x00);
    rs232_putchar(0x1F);
    

    rs232_putchar(0x4C); //Querstrich ausgeben
    rs232_putchar(0x00);
    rs232_putchar(0x00);
    rs232_putchar(0x5F);
    rs232_putchar(0x3F);
    rs232_putchar(0xFF);
    rs232_putchar(0xFF);
  //  wait_ack();

  }
}


void rs232_putchar (char buchstabe)
{
  while ( !( UCSR1A & (1<<UDRE1)) )
  ;

  UDR1 = buchstabe;
}

char rs232_getchar(void)
{
  while ( !(UCSR1A & (1<<RXC1)) )
  ;

  return UDR1;
}


ISR (TIMER1_COMPA_vect)
{
  rs232_putchar(0x45);
//  wait_ack();

  a++;
  
    if(a == 'z')
    {
      a='a';
    }

    PORTB=~PORTB;    

    rs232_putchar(0x74); //a als char ausgeben, position, farbe, größe 
    rs232_putchar(a);
    rs232_putchar(0x15);
    rs232_putchar(0x18);
    rs232_putchar(0xFF);
    rs232_putchar(0xFF);
    rs232_putchar(0x04);
    rs232_putchar(0x02);
    //wait_ack();

}


/*
void wait_ack(void)
{
  char acknowledge;
  
  do
  {
    acknowledge = rs232_getchar();
  }
  while (acknowledge != 0x06);
}*/

Autor: Sascha Weber (sascha-w)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
kannst du nicht die Einstellungen wie "blauer Hintergrund" genau 1x 
machen!
Kommt das Display mit dem kontinuierlichen Datenstrom mit dem du es in 
deiner while Schleife bombardierst zurecht??
Würde mich nicht wundern, wenn es einige Befehle verschluckt, und 
dadurch irgendwelchen Mist anzeigt.

Sascha

Autor: Goldi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Habe schon blauer Hintergrund vor die while(1)-Schleife gestellt.

Habe schon versucht zwischen jeden Befehl ein wait_ack zu stellen. Das 
Display schickt 0x06 an den uC wenn die Befehle erfolgreich empfangen 
wurden. In diesem Fall zeigt es mir nur einen blauen Hintergrund an.

Wenn ich aber nur am Ende der Befehlskette ein wait_ack stelle, zeigt es 
mir hin und wieder was an aber es ist länger nur ein blauer Hintergrund 
oder sogar eine andere Farbe.

Das Problem ist dass es nicht einmal Mist anzeigt sondern fast immer nur 
einen einfärbigen Hintergrund.

Denke nicht dass es an der Schaltung liegen kann da es manchmal was 
anzeigt.

Danke für die Hilfe, wünsche übrigens fröhliche Weihnachten

MfG

Autor: Sascha Weber (sascha-w)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hast du mal ein Datenblatt des Displays ?

Sascha

Autor: Goldi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: Sascha Weber (sascha-w)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
also das Wait ACK solltest du schon nach jeder Befehlssequenz ausführen, 
allerdings nicht ewig, falls dein Display ein NACK 0x15 zurückgibt. 
Kannst ja zum Test die Rückmeldungen parallel an einen Computer leiten.

Sascha

Autor: Goldi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe jetzt überall ein wait_ack wieder eingefügt. Es zeigt mir noch 
immer nur einen blauen Bildschirm an wo die Farbe manchmal dünkler und 
wieder heller wird.

Ist die Zeile so richtig. Die while-Schleife soll wiederholt werden wenn 
acknowledge nicht 0x06 bzw. 0x15 ist

do
  {
         //
  }
  while ( !( (acknowledge == 0x06) || (acknowledge == 0x15) ));


Autor: Sascha Weber (sascha-w)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
na das ist doch Unsinn Schleife wenn "NICHT 0x06 ODER 0x15" 0x15 ist 
doch "NICHT 0x06".

was heist jetzt 'überall' ?

Ich denke so sollte es aussehen ...

rs232_putchar(0x42); //blauer Hintergrund
rs232_putchar(0x00);
rs232_putchar(0x1F);
wait_ack();

rs232_putchar(0x4C); //Querstrich ausgeben
rs232_putchar(0x00);
rs232_putchar(0x00);
rs232_putchar(0x5F);
rs232_putchar(0x3F);
rs232_putchar(0xFF);
rs232_putchar(0xFF);
wait_ack();

--
benutze doch mal PortB, an dem du was zum anzeigen anschließen kannst 
und mache folgendes:
PORTB=0
//blauer Hintergrund
wait_ack()
PORTB=1
//Querstrich
wait_ack()
PORTB=2
//Textzeichen ausgeben
wait_ack()
PORTB=3

dann siehtst du ob er irgendwo hängen bleibt

führst du die Befehle immernoch ständig in einer Schleife aus ?
Mit den put_char in der Main-Schleife und den Ausgaben innerhalb der ISR 
erfolgt doch eine Mischung der gesendeten Daten - entweder nur in Main 
ODER der ISR senden!

Sascha

Autor: Goldi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke!


>na das ist doch Unsinn Schleife wenn "NICHT 0x06 ODER 0x15" 0x15 ist
>doch "NICHT 0x06".

Habe es eh gemerkt und ausgebessert jedoch muss man 0x15 ganz weglassen.


Das wait_ack(), gehört das hinter jedes rs232_putchar() oder ganz am 
Ende der Funktionsbefehle?
Das Display schickt es nach jedem emfangen Hex ein ACK oder ganz am 
Ende?


>führst du die Befehle immernoch ständig in einer Schleife aus ?
>Mit den put_char in der Main-Schleife und den Ausgaben innerhalb der ISR
>erfolgt doch eine Mischung der gesendeten Daten - entweder nur in Main
>ODER der ISR senden!

Ich habe alle möglichen Varianten ausprobiert. Habe jetzt alles in Main 
eingegeben da sonst ein schwarzer Hintergrund kommt.

So halbert funktioniert es jetzt. Bleibt nur hin und wieder hängen.

Ich würde jetzt gerne einen Timer machen der nach 10ms die Funktion 
abbricht. Der Timer soll aber nur zählen wenn er in der do-while 
Schleife ist => nicht regelmäßig einen Interrupt ausführen.

Wie könnte ich das machen?

TCCR0A = (2 << WGM00) //CTC
TCCR0B = (5 << CS00)  //Prescaler

void wait_ack(void)
{
  char acknowledge;
         
        //Timer soll anfangen zu zählen

  PORTB|= 0x08;
  
  do
  {
                //Wenn der Timer 10ms erreicht soll er in der do-while Schleife einen "break" machen
    acknowledge = rs232_getchar();  
  }
  while (acknowledge != 0x06); 

        //TCNT auf 0 setzen und TCNT stoppen.

  PORTB &= 0xF7;
}


Autor: Sascha Weber (sascha-w)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

also wie ich das Datenblatt verstanden habe kommt das ACK immer nach der 
erfolgreichen Verarbeitung eines Befehls, wenn der Befehl eben das 
senden von 6 Byte erfordert, dann kommt die Rückmeldung erst nachdem die 
6Byte beim Display eingegangen sind und erfolgreich verarbeitet wurden.

Wenn's hängen bleibt heist das du bekommst kein ACK (0x06), aber dann 
doch wenigstens ein NACK (0x15). Um sicher zu gehen, das auch alles 
korrekt dargestellt wird müsstest du eine Befelssequenz senden - 
anschließend auf ein eingehendes Byte warten - ist es ein ACK dann 
weiter im Programm, sonst die Befehlssequenz erneut senden.

Mit deinem Timeout solltest du schon in GetChar anfangen, denn wenn kein 
Byte kommt wartet er ja dort schon ewig.

etwa so ...

char wait_ack(void)
{
  int timeout = 50;  //maximal 50ms warten

  while ( (!(UCSR1A & (1<<RXC1)) && timeout > 0 ) {
     timeout--;
     delayms(1);
  }
  if (timeout==0) return 0;
  return UDR1;
}

die Zeiten müsste man an das Display anpassen, aber im Datenblatt hab 
ich darüber nichts gelesen - glaube ich.

wenn das Display die Befehle des öfteren missversteht müsstest du jede 
Sequenz so ...

do {
 //Befehlsbyte 1 senden
 //Befehlsbyte 2 senden
 //Befehlsbyte 3 senden
 //Befehlsbyte 4 senden
 //....
} while (wait_ack != 0x06);

... einkapseln, um sicherzustellen das alles richtig dargestellt wird.


Sascha

Autor: Goldi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke, das Bsp. sieht sehr gut aus. Es bleibt beim getchar hängen.

Ich nehme mir wahrscheinlich dein Bsp.. Habe aber versucht ein eigenes 
zu schreiben.

Nebenbei würde mich interessieren ob man mit einem Interrupt eine 
do-while Schleife abbrechen kann.

So ähnlich:

TCCR0A = (2<<WGM00);
OCR0A = 78;
TCCR0B = (5<<CS00);

ISR (TIMER0_COMPA_vect)
{
  break;
}

void wait_ack(void)
{
  char acknowledge;
  int i;

  i=0;


  PORTB|= 0x08;

  
  TCCR0B = (5<<CS00);

  do
  {

    
PORTB&= 0x7F;
    acknowledge = rs232_getchar();  
PORTB |= 0x80;  
  
  }
  while (acknowledge != 0x06); 

  TCCR0B = (0<<CS00);
  TCNT0 = 0x00;
  
  PORTB &= 0xF7;
}

Autor: Sascha Weber (sascha-w)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
so nicht, du musst schon eine Globale Variable in der ISR auf einen 
bestimmten Wert setzen, die du in deiner Schleife abfragst.

Zu dem Zweck einen INT zu nehmen halte ich aber für wenig sinnvoll, denn 
ich denke mal wenn die Ausgabe hängt muss das Hauptprogramm eh warten.

Sascha

Autor: Goldi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Zu dem Zweck einen INT zu nehmen halte ich aber für wenig sinnvoll, denn
>ich denke mal wenn die Ausgabe hängt muss das Hauptprogramm eh warten.

Wie meinst du das?


Hast du eine Idee wo sich das Programm immer aufhängt. Ich finde es 
komisch dass nicht mehr einmal das Interrupt ausgeführt wird.


Die Idee war, wenn das Programm ins getchar() kommt soll der Timer0 als 
Stoppuhr eingeschaltet werden. Wenn die Zeit vorbei ist soll das 
Programm das getchar() und die do{}while; Schleife im wait_ack() 
abbrechen.

[c]volatile int interrupt;

char rs232_getchar(void)
{

  while ( (!(UCSR1A & (1<<RXC1))) && (interrupt==0))
  ;

  return UDR1;
}



ISR (TIMER1_COMPA_vect)
{
  rs232_putchar(0x45);
  wait_ack();

        PORTB ^= (1<<PB0);

  a++;

    if(a == 9)
    {
      a=0;
    }

    umgewandelt= a + '0';
}

ISR (TIMER0_COMPA_vect)
{
  interrupt=1;

        PORTB ^= (1<<PB4);
}


void wait_ack(void)
{
  char acknowledge;

  PORTB|= 0x40;

  interrupt=0;

  TCCR0B = (5<<CS00);

  do
  {
                PORTB |= 0x80;

    acknowledge = rs232_getchar();

                PORTB&= 0x7F;
  }
  while ((acknowledge != 0x06)) && (interrupt!=0));

  interrupt=0;

  TCCR0B = (0<<CS00);
  TCNT0 = 0x00;

  PORTB &= 0xBF;
}[c]

Autor: Sascha Weber (sascha-w)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Goldi schrieb:
>>Zu dem Zweck einen INT zu nehmen halte ich aber für wenig sinnvoll, denn
>>ich denke mal wenn die Ausgabe hängt muss das Hauptprogramm eh warten.
>
> Wie meinst du das?
wenn du schon in einer Endlosschleife wartest, bis ein Signal vom Timer 
kommt, dann macht dein Programm doch in der Zwischenzeit sowiso nichts 
anderes. Also würde es auch ein Delay und ein Zähler tun.

> Hast du eine Idee wo sich das Programm immer aufhängt. Ich finde es
> komisch dass nicht mehr einmal das Interrupt ausgeführt wird.
was ist denn die letzte Meldung von PortB ??

>
> Die Idee war, wenn das Programm ins getchar() kommt soll der Timer0 als
> Stoppuhr eingeschaltet werden. Wenn die Zeit vorbei ist soll das
> Programm das getchar() und die do{}while; Schleife im wait_ack()
> abbrechen.
zur ACK-Abfrage mehrmals getChar aufzurufen ist doch eigentlich Unsinn, 
das Display schickt entweder:
 kein Byte     - Befehl unvollständig, es wartet weiter
 EIN Byte 0x06 - Befehl verarbeitet
 EIN Byte 0x15 - Befehl unbekannt
d.h. wenn beim 1. Aufruf von getChar ein Byte zurück kommt, und das ist 
nicht 0x06, dann kommt auch nichts weiter nach bis du den nächsten 
Befehl gesendet hast.
Die Funktion ist nicht mit der Busy-Bit-Abfrage der gebräuchlichen LCD's 
zu verwechseln, bei denen du immer den aktuellen Wert abholen mußt. Und 
das solange bis das Display fertig ist.

deshalb siehe mein Beispiel, eine begrenzte Zeit auf EIN Byte warten.

Sascha

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.