Forum: Mikrocontroller und Digitale Elektronik Display Probleme


von Goldi (Gast)


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.
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include <util/delay.h>
4
5
void rs232_putchar (char buchstabe);
6
7
volatile char a;
8
9
10
11
int main(void)
12
{
13
  DDRC= 0x04;
14
  PORTC= 0x04;
15
  DDRB= 0xFF;
16
  PORTB = 0xFE;
17
18
  CLKPR = 0x80; 
19
  CLKPR = 0x00;
20
21
  UCSR1B = (1<<TXEN1);
22
  UCSR1C = (0<<USBS1) | (3<<UCSZ10);
23
  UBRR1 = 25;
24
25
  
26
  TCCR1B= (1<<WGM12) | (4<<CS10) ;
27
  TIMSK1= (1<<OCIE1A) | (1<<TOIE1);
28
  OCR1A = 31250;
29
30
31
  _delay_ms(1000);
32
33
    rs232_putchar(0x55); //Uart
34
35
    rs232_putchar(0x45); //Display löschen
36
37
38
39
    a='a';
40
41
    sei();
42
  
43
  while(1)
44
  {
45
    rs232_putchar(0x42); //blauer Hintergrund
46
    rs232_putchar(0x00);
47
    rs232_putchar(0x1F);
48
49
    rs232_putchar(0x45); //Display löschen
50
51
52
    rs232_putchar(0x74); //a als char ausgeben
53
    rs232_putchar(a);
54
    rs232_putchar(0x2F);
55
    rs232_putchar(0x8F);
56
    rs232_putchar(0xFF);
57
    rs232_putchar(0xFF);
58
    rs232_putchar(0x04);
59
    rs232_putchar(0x02);
60
61
  }
62
}
63
64
65
void rs232_putchar (char buchstabe)
66
{
67
  while ( !( UCSR1A & (1<<UDRE1)) )
68
  ;
69
70
  UDR1 = buchstabe;
71
}
72
73
74
ISR (TIMER1_COMPA_vect)
75
{
76
77
  a++;
78
  
79
    if(a == 'z')
80
    {
81
      a='a';
82
    }
83
}

MfG

von Goldi (Gast)


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

von Goldi (Gast)


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

von Sascha W. (sascha-w)


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

von Goldi (Gast)


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.


1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include <util/delay.h>
4
5
void rs232_putchar (char buchstabe);
6
void wait_ack(void);
7
char rs232_getchar(void);
8
9
volatile char a;
10
11
12
13
int main(void)
14
{
15
  DDRC= 0x04;
16
  PORTC= 0x04;
17
  DDRB= 0xFF;
18
  PORTB = 0xFE;
19
20
  CLKPR = 0x80; 
21
  CLKPR = 0x00;
22
23
  UCSR1B = (1<<TXEN1) | (1<<RXEN1);
24
  UCSR1C = (0<<USBS1) | (3<<UCSZ10);
25
26
   UBRR1H = (25>>8);
27
   UBRR1L = 25;
28
29
  TCCR1B= (1<<WGM12) | (4<<CS10) ;
30
  TIMSK1= (1<<OCIE1A) | (1<<TOIE1);
31
  OCR1A = 31250;
32
33
  _delay_ms(400);
34
35
  rs232_putchar(0x55);
36
37
  rs232_putchar(0x45); //Bildschirm löschen
38
39
40
    a='a';
41
42
    sei();
43
44
  rs232_putchar(0x45);
45
  
46
  while(1)
47
  {
48
49
50
51
    //rs232_putchar(0x45); //Display löschen
52
53
    rs232_putchar(0x42); //blauer Hintergrund
54
    rs232_putchar(0x00);
55
    rs232_putchar(0x1F);
56
    
57
58
    rs232_putchar(0x4C); //Querstrich ausgeben
59
    rs232_putchar(0x00);
60
    rs232_putchar(0x00);
61
    rs232_putchar(0x5F);
62
    rs232_putchar(0x3F);
63
    rs232_putchar(0xFF);
64
    rs232_putchar(0xFF);
65
  //  wait_ack();
66
67
  }
68
}
69
70
71
void rs232_putchar (char buchstabe)
72
{
73
  while ( !( UCSR1A & (1<<UDRE1)) )
74
  ;
75
76
  UDR1 = buchstabe;
77
}
78
79
char rs232_getchar(void)
80
{
81
  while ( !(UCSR1A & (1<<RXC1)) )
82
  ;
83
84
  return UDR1;
85
}
86
87
88
ISR (TIMER1_COMPA_vect)
89
{
90
  rs232_putchar(0x45);
91
//  wait_ack();
92
93
  a++;
94
  
95
    if(a == 'z')
96
    {
97
      a='a';
98
    }
99
100
    PORTB=~PORTB;    
101
102
    rs232_putchar(0x74); //a als char ausgeben, position, farbe, größe 
103
    rs232_putchar(a);
104
    rs232_putchar(0x15);
105
    rs232_putchar(0x18);
106
    rs232_putchar(0xFF);
107
    rs232_putchar(0xFF);
108
    rs232_putchar(0x04);
109
    rs232_putchar(0x02);
110
    //wait_ack();
111
112
}
113
114
115
/*
116
void wait_ack(void)
117
{
118
  char acknowledge;
119
  
120
  do
121
  {
122
    acknowledge = rs232_getchar();
123
  }
124
  while (acknowledge != 0x06);
125
}*/

von Sascha W. (sascha-w)


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

von Goldi (Gast)


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

von Sascha W. (sascha-w)


Lesenswert?

hast du mal ein Datenblatt des Displays ?

Sascha

von Goldi (Gast)


Lesenswert?


von Sascha W. (sascha-w)


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

von Goldi (Gast)


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

1
do
2
  {
3
         //
4
  }
5
  while ( !( (acknowledge == 0x06) || (acknowledge == 0x15) ));

von Sascha W. (sascha-w)


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

von Goldi (Gast)


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?
1
TCCR0A = (2 << WGM00) //CTC
2
TCCR0B = (5 << CS00)  //Prescaler
3
4
void wait_ack(void)
5
{
6
  char acknowledge;
7
         
8
        //Timer soll anfangen zu zählen
9
10
  PORTB|= 0x08;
11
  
12
  do
13
  {
14
                //Wenn der Timer 10ms erreicht soll er in der do-while Schleife einen "break" machen
15
    acknowledge = rs232_getchar();  
16
  }
17
  while (acknowledge != 0x06); 
18
19
        //TCNT auf 0 setzen und TCNT stoppen.
20
21
  PORTB &= 0xF7;
22
}

von Sascha W. (sascha-w)


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

von Goldi (Gast)


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:
1
TCCR0A = (2<<WGM00);
2
OCR0A = 78;
3
TCCR0B = (5<<CS00);
4
5
ISR (TIMER0_COMPA_vect)
6
{
7
  break;
8
}
9
10
void wait_ack(void)
11
{
12
  char acknowledge;
13
  int i;
14
15
  i=0;
16
17
18
  PORTB|= 0x08;
19
20
  
21
  TCCR0B = (5<<CS00);
22
23
  do
24
  {
25
26
    
27
PORTB&= 0x7F;
28
    acknowledge = rs232_getchar();  
29
PORTB |= 0x80;  
30
  
31
  }
32
  while (acknowledge != 0x06); 
33
34
  TCCR0B = (0<<CS00);
35
  TCNT0 = 0x00;
36
  
37
  PORTB &= 0xF7;
38
}

von Sascha W. (sascha-w)


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

von Goldi (Gast)


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]

von Sascha W. (sascha-w)


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

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.