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.
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
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
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
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
voidrs232_putchar(charbuchstabe);
6
voidwait_ack(void);
7
charrs232_getchar(void);
8
9
volatilechara;
10
11
12
13
intmain(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
voidrs232_putchar(charbuchstabe)
72
{
73
while(!(UCSR1A&(1<<UDRE1)))
74
;
75
76
UDR1=buchstabe;
77
}
78
79
charrs232_getchar(void)
80
{
81
while(!(UCSR1A&(1<<RXC1)))
82
;
83
84
returnUDR1;
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
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
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
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
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
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
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
voidwait_ack(void)
5
{
6
characknowledge;
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
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
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:
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
>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]
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