Forum: Mikrocontroller und Digitale Elektronik String über UART an LCD


von Christoph (Gast)


Lesenswert?

Moin moin zusammen,

ich arbeite momentan daran, ein 16x2 LCD an meinem ATmega8A zu benutzen.
Ich bin mit der Initialisierung des LCDs bereits fertig und habe auch 
schon Text, welcher mit .db abgespeichert ist, anzeigen lassen.

Da ich nun aber den Text mit meinem myAVR Workpad per UART-Schnittstelle 
ändern möchte und .db nur konstant ist, frage ich mich, wie ich einen 
ankommenden String in mein SRAM speichere und diesen dann im Nachhinein 
an das LCD schicken kann.

Aufgrund dessen, dass ich nicht jedes Zeichen einzeln verschicken 
möchte, habe ich mir eine Funktion mittels der Zeigerregister gebaut:
1
;Einen konstanten Text aus dem Flash Speicher ausgeben. Der Text wird mit einer 0 beendet
2
string:
3
           push  temp1
4
5
string_1:
6
           lpm   temp1, Z+
7
           cpi   temp1, 0
8
           breq  string_2
9
       
10
           rcall  lcd_data
11
           rjmp  string_1
12
13
string_2:
14
           pop   temp1
15
           ret


Den Text habe ich bisher mit einer 0 beendet.

Liebe Grüße

Christoph

von Karl B. (gustav)


Lesenswert?

Hi,
Stichworte:
arbeite mit UART mit Interrupt und definiere einen Ringpuffer.

ciao
gustav

von Stefan F. (Gast)


Lesenswert?

Du musst die UART Schnittstelle initialisieren und mittels ISR die 
empfangenen Bytes in einen Puffer ablegen. Außerhalb der ISR sendest du 
den Pufferinhalt dann an das Display.

Damit du während der Ausgabe weitere Zeichen empfangen kannst (falls das 
gewollt ist), solltest du entweder einen Ringpuffer benutzen, oder zwei 
Puffer immer abwechselnd.

von Karl B. (gustav)


Angehängte Dateien:

Lesenswert?

Hi,
so in etwa:

ciao
gustav

von Christoph (Gast)


Lesenswert?

Danke erstmals für die super schnellen Antworten :D
(damit hätte ich nicht gerechnet)

Ich habe jetzt im SRAM ein paar bytes mit :
1
.dseg
2
3
text: .byte 20
4
5
.eseg

reserviert.

Dank Gustav habe ich auch bereits die Ladefunktion soweit ich es 
beurteilen kann richtig umgesetzt:
1
receive:
2
  warten:
3
    SBIS UCSRA,RXC ; Prüfen ob was im Empfang ist
4
  rjmp warten
5
6
  lds r22,UDR
7
  st Y+, r22
8
9
  rcall funktionkommtnoch
10
11
reti

Jetzt stellt sich mir die Frage auf, wie ich die Zeichen nun lade. Ich 
habe ja zuvor die Zeigeregister benutzt um das Ende des Strings mit der 
0 zu finden. Kann ich diese Methode auch hier wieder anwenden? Und aus 
mir unerklärlichen Gründen musste der Text bzw. die Adresse 2mal in die 
Zeigeregister geladen werden. Ist das hier auch so?

von Karl B. (gustav)


Angehängte Dateien:

Lesenswert?

Hi,
schau mal drüber.
Ist aber nicht sauber.
Aufgabe:
Gleichzeitig Uhrzeit und unten auf Zeile 2 Message via Rs232 , wenn sie 
kommt, auf LCD.
Man kann nicht gleichzeitig auf dieselben Adressen Schreib- und 
Lesezugriff machen. Das ist im Proggi nicht beachtet worden.
Trotzdem mal gucken. Vielleicht bringt Dich das auf eine Idee.

ciao
gustav

von Christoph (Gast)


Lesenswert?

Karl B. schrieb:
> schau mal drüber.

Vielen Dank für dein Codebeispiel...Da bin ich doch aber leider viel zu 
neu in Assembler um das zu verstehen... Ich hab es mir länger angeguckt 
und versucht über meine Funktion auszugeben.

Funktioniert nur wie erwartet nicht :D
1
string:
2
           push  temp1
3
       ldi r22,0
4
5
string_1:
6
       inc r22
7
           ld    temp1, Y+
8
           cpi   r22, 80
9
           breq  string_2
10
       
11
           rcall  lcd_data
12
           rjmp  string_1
13
14
string_2:
15
           pop   temp1
16
           ret
17
18
receive:
19
  push temp1
20
21
  warten:
22
  SBIS UCSRA,RXC ; Prüfen ob was im Empfang ist
23
  rjmp warten
24
25
  in temp1,UDR
26
  st Y+, temp1
27
  rcall string
28
29
  pop temp1
30
31
reti

von S. Landolt (Gast)


Lesenswert?

Einige Gedanken:

Zu verschwinden und nach vier Tagen ohne Erklärung wiederzukommen, ist 
unfair gegenüber denjenigen, die hier nach bestem Wissen versuchen zu 
helfen.

Offenbar wurde weder die Verwendung von Indexregistern noch das Konzept 
des Interrupts verstanden. Also würde ich erstmal ohne dieses arbeiten: 
ein Zeichen vom UART einlesen und auf das LCD ausgeben. Erst dann den 
UART-Interrupt benutzen, immer noch mit einem einzigen Zeichen. Dann 
vielleicht eine zwischengespeicherte Zeichenkette, als Schlußkennung, 
analog zu dieser '0', ein spezielles Zeichen, '!' oder ähnliches. Erst 
wenn das läuft (und vor allem verstanden ist), kann man den Ringpuffer 
in Angriff nehmen.

von c-hater (Gast)


Lesenswert?

S. Landolt schrieb:

> Offenbar wurde weder die Verwendung von Indexregistern noch das Konzept
> des Interrupts verstanden.

Ich würde sagen: er hat garnix verstanden (und will, wie alle diese 
unsäglichen C&P-"Programmierer" auch garnichts verstehen). Das ist ganz 
klar sinnlos zusammenkopierter Code.

Und was er tatsächlich will, ist: dass wir ihm sein Programm schreiben.

von Christoph (Gast)


Lesenswert?

S. Landolt schrieb:
> Zu verschwinden und nach vier Tagen ohne Erklärung wiederzukommen

Bei allem Respekt, aber ich muss nun wirklich nicht darlegen, dass ich 
momentan meinen Internetanbieter wechsele und somit kein Internet hatte. 
Es ist wirklich nett, dass hier Hilfe angeboten wird. Jedoch ist es für 
keinen User eine Pflicht sofort Rede und Antwort stehen zu müssen. Also 
bitte verzeih mir, dass ich nicht direkt antworten konnte.

S. Landolt schrieb:
> Offenbar wurde weder die Verwendung von Indexregistern noch das Konzept
> des Interrupts verstanden

Teils teils. Ich bin mir bewusst wie ein Interrupt funktioniert und 
frage mich, aus welchen Gründen du daran zweifelst. Bei den 
Indexregistern kann ich dir zustimmen.

c-hater schrieb:
> und will, wie alle diese
> unsäglichen C&P-"Programmierer" auch gar nichts verstehen

Finde ich tatsächlich echt schade, dass man gleich als "Neuling" so 
abgestempelt wird, nur weil man nicht gleich komplettes Verständnis 
gegenüber einem Thema hat. Wie erwähnt, bin ich noch recht neu in 
Assembler und kenne mich deshalb auch wenig aus. Es ist also nicht 
notwendig jemanden anhand seines Wissens zu beurteilen. Schlussendlich 
habe ich ja nun nicht geschrieben, dass ich Assembler nicht verstehen 
will und keine Motivation dazu hätte.

c-hater schrieb:
> Und was er tatsächlich will, ist: dass wir ihm sein Programm schreiben.

Einspruch...Das hab ich zu keinem Moment gefordert/erfragt. Mir war nur 
anfangs unklar, mit welcher Methodik meine Idee umzusetzen ist.

Ich hoffe, dass meine Antwort nicht negativ angekommen ist, da dies 
wirklich nicht intentioniert ist.

Liebe Grüße

Christoph

von S. Landolt (Gast)


Lesenswert?

zu Punkt 1:
Ich halte es nach wie vor für schlechten Stil; Sie werden es vielleicht 
besser verstehen, wenn Sie selbst einmal soweit sind, anderen helfen zu 
können.

zu Punkt 2:
Die Ursache für den Receive-Interrupt ist RXC - in der ISR nochmals zu 
"Prüfen ob was im Empfang ist", und das in einer Warteschleife, ist 
sinnlos.
  Aus dem Datenblatt: "The RXC Flag can be used to generate a Receive 
Complete interrupt ..."

Und auch ich "hoffe, dass meine Antwort nicht negativ angekommen ist"; 
ich helfe gerne, packen wir's an.

von Karl B. (gustav)


Angehängte Dateien:

Lesenswert?

Hi,
also Polling und Interrupt sind doch nicht gleichzeitig nötig.
Doppelt gemoppelt oder stören sich sogar gegenseitig.
Das jetzt noch einmal ausführlicher zu erläutern, wäre hier zu viel.
Nur ein paar Stichworte in den Bildchen.


ciao
gustav

: Bearbeitet durch User
von S. Landolt (Gast)


Lesenswert?

an Karl B.:

Wozu cli und sei zu Beginn bzw. Ende der ISR?
Welchem Zweck dient die UDRE-Abfrage innerhalb der RXC-ISR?
0x0009 als URXCaddr bei einem ATmega8A?

von Pandur S. (jetztnicht)


Lesenswert?

Also, wenn die UART Routine dann geht, haben wir den String in einem 
Buffer.
Von dort wird er per Timer, zB alle 10ms ein Zeichen geschrieben.

Ich wuerd kontinuierlich den gesammten Inhalt des festen Buffers per 
Timer ins Display kopieren.

Ich mach das schon seit Jahren so.

von W.S. (Gast)


Lesenswert?

Christoph schrieb:
> ...frage ich mich, wie ich einen
> ankommenden String in mein SRAM speichere und diesen dann im Nachhinein
> an das LCD schicken kann.
>
> Aufgrund dessen, dass ich nicht jedes Zeichen einzeln verschicken
> möchte, habe ich mir...

Bedenke, daß ein UART eine Schnittstelle ist für asynchronen Betrieb. 
Dort hast du es mit einzelnen Zeichen zu tun, die du auch einzeln 
auswerten solltest.

Nun, die eigentliche Ausgabe deiner Textzeichen auf das LCD scheint ja 
gelöst zu sein. Was da bleibt, ist einfach nur eine simple 
Empfangsroutine, die am UART guckt, ob da ein Zeichen eingetrudelt ist 
oder nicht. Und wenn eines da ist, dann brauchst du es ja im Prinzip nur 
zum LCD auszugeben.

Allerdings sollte diese Empfangsroutine ein paar Sonderzeichen verstehen 
und separat behandeln.
Als da wären:
- Schreibzeiger auf eine bestimmte Position stellen, z.B. Anfang der 1. 
Zeile oder de 2. Zeile oder irgendwo mittendrin
- Display komplett ablöschen
- Zeile von aktueller Position bis Zeilenende ablöschen
- eventuell Blinken oder Cursor-Strich einstellen

Für so eine einfache Anwendung brauchst du keinen Interrupt-Betrieb, da 
reicht simples Pollen aus. Die LCD-Ausgabe ist da allemal schnell genug, 
um kein Zeichen zu verpassen.

W.S.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Christoph schrieb:
> ändern möchte und .db nur konstant ist, frage ich mich, wie ich einen
> ankommenden String in mein SRAM speichere und diesen dann im Nachhinein
> an das LCD schicken kann.

Hier:
1
Main:
2
           rcall GetStr
3
           rcall lcd_data
4
           rjmp  Main
5
6
GetStr:
7
           ldi   zl, low(text)
8
           ldi   zh, high(text)
9
           push  zl
10
           push  zh
11
           push  temp1
12
13
Wt4Char:
14
           sbis  UCSRA, RXC
15
           rjmp  Wt4Char
16
           in    temp1, UDR
17
           st    Z+, temp1
18
           cpi   temp1, 0x0D
19
           brne  Wt4Char
20
21
           clr   temp1
22
           st    -Z, temp1
23
           pop   temp1
24
           pop   zh
25
           pop   zl
26
           ret
27
28
.dseg
29
text: .byte 20

 Irgendein Text über UART eingeben, mit CR(0x0D) abschliessen - das
 kann man z.B. bei HTerm sehr einfach einstellen.

: Bearbeitet durch User
von Karl B. (gustav)


Angehängte Dateien:

Lesenswert?

Hi,
Das Beispielproggi. war für einen ATMEGA8515 gedacht.
Diente als Denkanstoß.

Schau mal hier:

http://ww1.microchip.com/downloads/en/DeviceDoc/en590320.pdf

Die targetspezifischen Einstellungen könntest Du im Analogieverfahren 
herausfinden.

Trotzdem möchte ich noch auf Deine Fragen kurz eingehen:

S. Landolt schrieb:
> Wozu cli und sei zu Beginn bzw. Ende der ISR?

Weil noch ein anderer Interrupt zeitkritisch dazwischenfunken könnte.
Im konkreten Falle alle Hundertselsekunde ein Timer-Interrupt.
Schau mal auf das Video.
Ja,
quasi gleichzeitig Ausgabe der vom Decoder gelieferten Zeit
sowohl auf LCD als auch über Teraterm via RS232/V24.
Wobei bei der RS232-Ausgabe die Nullen und Einsen des Zeitzeichensignals 
optisch dargestellt werden sollten, um besser herausfinden zu können, 
wann der Decoder etwas an Bitfehlern produziert. Bzw. der Empfänger 
falsche Bits liefert. So habe ich auch herausgefunden, dass ein 
systematischer Fehler vorlag. Immer bestimmte Bits waren falsch. Immer 
an derselben Stelle.
Konnte im Programm dann entsprechend abgeändert werden.

Die Begriffe cli und sei werden Dir noch öfter begegnen. Z.B. Bei 
"atomic"
Zugriffen,-bei SRAM-Zugriffen, oder bei EEPROM-Zugriffen.
Immer da, wo ein Interrupt mit der nachfolgenden Routine eine Aktion, 
die nicht unterbrochen werden darf, stören würde.

S. Landolt schrieb:
> Welchem Zweck dient die UDRE-Abfrage innerhalb der RXC-ISR?

Gucken, ob der Puffer schon wieder für neue Aufgaben bereit ist. 
Empfangsfertigmeldung. Wenn nicht, wird auch nicht irgendetwas, was 
gerade im Puffer steht, auf die Ausgabe gegeben. Der Vorgang nimmt ja 
auch ein bisschen Zeit in Anspruch. Dann wird bisweilen noch ein 
Frame-Error-Flag abgefragt. Muss man nicht, kann man aber.

S. Landolt schrieb:
> 0x0009 als URXCaddr bei einem ATmega8A?

Das soll der Interruptvektor voll ausformuliert sein. Das hat mehr 
didaktische Gründe. Und deutet darauf hin, dass bei verschiedenen 
Targets das auch durchaus 'mal anders sein kann. Und deswegen 
"portierte" Programme nicht laufen.
Ist vielleicht zuviel an Redundanz am Anfang. Aber mir hat das geholfen, 
die Sachen dann besser zu verstehen. Es empfiehlt sich, erst später 
Dinge wegzulassen, die man für überflüssig hält.

ciao
gustav

: Bearbeitet durch User
von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Karl B. schrieb:
> S. Landolt schrieb:
>> Wozu cli und sei zu Beginn bzw. Ende der ISR?
>
> Weil noch ein anderer Interrupt zeitkritisch dazwischenfunken könnte.

 Kann passieren, natürlich.
 Nur wird (bei AVR) das gerade laufende Interrupt erst bis zum Ende
 bzw. reti abgearbeitet.
 Also, total überflüssig und das hat Landolt gemeint.

Karl B. schrieb:
> Schau mal auf das Video.
> Ja,
> quasi gleichzeitig Ausgabe der vom Decoder gelieferten Zeit
> sowohl auf LCD als auch über Teraterm via RS232/V24.

 Ich kann nur auf ein schwarzes Bildschirm schauen.

Karl B. schrieb:
> Die Begriffe cli und sei werden Dir noch öfter begegnen. Z.B. Bei
> "atomic" Zugriffen,-bei SRAM-Zugriffen, oder bei EEPROM-Zugriffen.

 Aber bestimmt NICHT in einer AVR-ISR.

Karl B. schrieb:
> S. Landolt schrieb:
>> 0x0009 als URXCaddr bei einem ATmega8A?
>
> Das soll der Interruptvektor voll ausformuliert sein. Das hat mehr
> didaktische Gründe.

 Didaktisch?
 Bei URXC Interrupt auf OVF0addr springen?

Karl B. schrieb:
> Ist vielleicht zuviel an Redundanz am Anfang. Aber mir hat das geholfen,
> die Sachen dann besser zu verstehen.

 Bist du ganz sicher, die Sachen auch richtig verstanden zu haben?

: Bearbeitet durch User
von S. Landolt (Gast)


Lesenswert?

an Karl B.:

Marc V. hat zwar schon einiges klargestellt, aber ich denke, ich sollte 
auch antworten:

> ... Interrupt zeitkritisch dazwischenfunken ...
Aus dem Datenblatt: "When an interrupt occurs, the Global Interrupt 
Enable I-bit is cleared and all interrupts are disabled."

In der Empfangsroutine abzufragen, ob der Sendepuffer leer ist, ergibt 
für mich erstmal keinen Sinn - haben Sie hierzu eine konkrete Anwendung?

Statt (dem falschen) ".org  0x0009" bevorzuge ich ".org URXCaddr".

von S. Landolt (Gast)


Lesenswert?

PS:

Wir reden hier vom ATmega8A und seiner Großfamilie.

Die megaAVR® 0-series, zum Beispiel, hat ein aufwändigeres 
Interruptsystem, dort gilt "... Global Interrupt Enable bit (I) in the 
CPU Status register (CPU.SREG). This bit is not cleared when an 
interrupt is acknowledged."

von W.S. (Gast)


Lesenswert?

S. Landolt schrieb:
> In der Empfangsroutine abzufragen, ob der Sendepuffer leer ist, ergibt
> für mich erstmal keinen Sinn - haben Sie hierzu eine konkrete Anwendung?

Had dein Chip getrennte Interrupts für Rx voll und Tx leer? Oder 
erzeugen die denselben Interrupt?

W.S.

von Karl B. (gustav)


Angehängte Dateien:

Lesenswert?

Marc V. schrieb:
> Bei URXC Interrupt auf OVF0addr springen?

Meine Güte,
hab mich beim Kopieren in der Zeile vertan.
Das kann jedem mal passieren.
Sollte doch nur ein "Schnipsel" sein.

Aber die passende richtige Kopie oben,
Ja, ist für den ATMEGA8515.

Marc V. schrieb:
> Bist du ganz sicher, die Sachen auch richtig verstanden zu haben?

In der besagten ISR ist ein "cli" und "sei" drin.

Der Programmabschnitt wird auch von anderen so verwendet,
denke, schaden kann es nicht. Obwohl das vorerst irgendwie unlogisch 
ist,
wenn eine Interruptstreviceroutine ausgeführt wird, läuft die erst 
einmal durch. Egal was sonst noch passiert.

ciao
gustav

: Bearbeitet durch User
von Joachim B. (jar)


Lesenswert?

W.S. schrieb:
> Had dein Chip

Landolt ist nicht der TO

der TO schrieb:

Christoph schrieb:
> ich arbeite momentan daran, ein 16x2 LCD an meinem ATmega8A

und da gilt

https://www.mikrocontroller.net/articles/AVR-Tutorial:_Interrupts#INT0.2C_INT1_und_die_zugeh.C3.B6rigen_Register

W.S. schrieb:
> Had dein Chip getrennte Interrupts für Rx voll und Tx leer?

ja

W.S. schrieb:
> erzeugen die denselben Interrupt?

nein

Interruptname
USART_TX   USART-Sendung abgeschlossen
USART_RX   USART-Empfang abgeschlossen
USART_UDRE   USART-Datenregister leer

von S. Landolt (Gast)


Lesenswert?

W.S. schrieb:
> Had dein Chip getrennte Interrupts für Rx voll und Tx leer? Oder
> erzeugen die denselben Interrupt?

Ich bin nicht sicher, ob ich die Frage richtig verstanden habe, ich 
versuche mal als Antwort:
1
.equ  URXCaddr  = 0x000b  ; USART, Rx Complete
2
.equ  UDREaddr  = 0x000c  ; USART Data Register Empty
3
.equ  UTXCaddr  = 0x000d  ; USART, Tx Complete
"The UDRE Flag indicates if the transmit buffer (UDR) is ready to 
receive new data. If UDRE is one, the buffer is empty, and therefore 
ready to be written."

von Karl B. (gustav)


Lesenswert?

Hi,
schau mal in die def.incs.
Da ist mir offensichtlich noch ein Lapsus drunter weggelaufen.

Der 8515 hat ADC und dann Ende.
der 8535 hat die Liste versetzt, so dass tatsächlich der Overflow dabei 
rauskommt.

Oder noch besser AT90S8515
da sind wir auf dem richtigen Dampfer.

Wie gesagt,
das sind die Tücken.
Liste korrigieren tu ich jetzt aber nicht, da das Prob. ja jetzt
auch klar ist und entsprechend richtig geproggt werden kann.

ciao
gustav

: Bearbeitet durch User
von S. Landolt (Gast)


Lesenswert?

PS an W.S.:

Falls die doppelte Bedeutung von UDR unklar sein sollte:
"The USART Transmit Data Buffer Register and USART Receive Data Buffer 
Registers share the same I/O address referred to as USART Data Register 
or UDR. The Transmit Data Buffer Register (TXB) will be the destination 
for data written to the UDR Register location. Reading the UDR Register 
location will return the contents of the Receive Data Buffer Register 
(RXB)."

von Carl D. (jcw2)


Lesenswert?

S. Landolt schrieb:
> an Karl B.:
>
> Wozu cli und sei zu Beginn bzw. Ende der ISR?
> Welchem Zweck dient die UDRE-Abfrage innerhalb der RXC-ISR?
> 0x0009 als URXCaddr bei einem ATmega8A?

Sicher ist sicher. Der HW ist nicht zu trauen, denn die hat sicher nicht 
das DB gelesen. Gut wenn man alles unter Kontrolle hat.

Oder so ;-)

von Karl B. (gustav)


Lesenswert?

Hi,
ATmega8A

welche def. inc ganz genau?

ciao
gustav

von S. Landolt (Gast)


Lesenswert?

Karl B. schrieb:
> Der 8515 hat ADC und dann Ende.

?
Genau dieser hat doch keinen ADC.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Carl D. schrieb:
> Sicher ist sicher. Der HW ist nicht zu trauen, denn die hat sicher nicht
> das DB gelesen. Gut wenn man alles unter Kontrolle hat.

 Genau.
 Nur manchmal tut HW so, als ob.
 Das sind dann die schlimmsten Fälle überhaupt, weil man den Fehler bei
 sich selbst suchen muss und das ist so etwas von unwahrscheinlich...

: Bearbeitet durch User
von Karl B. (gustav)


Lesenswert?

S. Landolt schrieb:
> Genau dieser hat doch keinen ADC.

Vergiss es,

wir sind mittlerweile da:

Christoph schrieb:
> meinem ATmega8A

Karl B. schrieb:
> Hi,
> ATmega8A
>
> welche def. inc ganz genau?

Erst diese Angabe, dann sehen wir weiter. Alles andere ist nicht 
zielführend.

Marc V. schrieb:
> Nur manchmal tut HW so, als ob.

In den Atmel Docus sind bei Revisions manchmal Dinge einfach unkritisch 
per copy and paste von anderen übernommen worden.
Wenn man das dann nachprüft, merkt man, dass da was nicht stimmen kann.
Insbesondere gilt das für Programmbeispiele.
Beitrag "Fehler in ATMEL ATMega32U2 Doku 7799"

ciao
gustav

: Bearbeitet durch User
von S. Landolt (Gast)


Lesenswert?

> welche def. inc ganz genau?

?-?
Es spielt doch keine Rolle, ob m8Adef.inc oder m8def.inc, es handelt 
sich um dieselbe Signatur.

von Christoph (Gast)


Lesenswert?

Also ich habe jetzt den Interrupt so konfiguriert:
1
receive:
2
cli
3
SBI PORTC,3
4
  push temp1
5
  clr r27         ;XH auf 0
6
  ldi r26, 0x0060 ;Anfang des SRAMs beladen = XL
7
  in temp1,UDR
8
  st X+, temp1
9
  out UDR,temp1
10
  rcall senden     ;Feedback, was gesendet wurde
11
  pop temp1
12
  sei
13
reti

An C3 ist eine LED die auslöst, wenn der Interrupt geladen wurde.
1
stop:
2
IN r20,  PINC
3
ANDI r20,0b00100000
4
CPI  r20,0b00000000
5
BREQ umschalten
6
LDS r22,0x0060
7
CPI r22, 0b00000000
8
BREQ stop
9
rjmp string

Hier habe ich mein Schleifenprogramm, welches einen Taster überprüft, 
und bei Betätigung das LCD an/aus schaltet. Danach habe ich nach meinem 
Verständnis versucht zu gucken, ob ein Text im Text im SRAM steht. 
Sollte dort einer stehen, müsste an der Speicherzelle ja etwas ungleich 
0 sein.

1
string:
2
           push  temp1
3
       ldi r22,0
4
5
string_1:
6
       ldi r26, 0x0060
7
       inc r22
8
           ld    temp1, X+
9
           cpi   r22, 80
10
           breq  string_2
11
       
12
           rcall  lcd_data
13
           rjmp  string_1
14
15
string_2:
16
           pop   temp1
17
           ret

Und hier habe ich versucht, die Speicherzeile 0x0060 und folgende Zellen 
mit Post-Increment auszulesen und einzeln an das LCD zu senden. Leider 
sehe ich an dieser Stelle die Buchstaben alle doppelt und dreifach.

Mir ist bewusst, dass es bestimmt eine schönere Lösung für versiertere 
Programmierer gibt, jedoch spiegelt dies ungefähr mein Verständnis, wie 
der SRAM funktioniert. Vielleicht könntet ihr mir hier unter die Arme 
greifen, da mir langsam die Ideen ausgehen, wie dies zu lösen ist.

von Uwe (Gast)


Lesenswert?

Hi,
>string_1:
>       ldi r26, 0x0060
>       inc r22

>      rjmp  string_1

Auf welchen Wert denkst du wird R27(XH) geladen?
>Leider sehe ich an dieser Stelle die Buchstaben alle doppelt und dreifach.
Ev. solltest du X mal in Ruhe lassen.

von Niklas W. (niklas_w)


Lesenswert?

Uwe schrieb:
> Auf welchen Wert denkst du wird R27(XH) geladen?

Ich habe es ja im Interrupt auf 0 gesetzt...

Uwe schrieb:
> Ev. solltest du X mal in Ruhe lassen.

Hab die Funktion mit X mal weggelassen. Aber dann weiß mein LD ja gar 
nicht, welcher Speicherzelle er laden soll.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Niklas W. schrieb:
> Hab die Funktion mit X mal weggelassen. Aber dann weiß mein LD ja gar
> nicht, welcher Speicherzelle er laden soll.

 Mir scheint, du weisst ja gar nicht was du willst...

 Ich habe dir ein funktionierndes Beispiel geschickt weil du einen
 String anstatt aus Flash aus RAM anzeigen wolltest.

 Du weisst ja nicht einmal wie man mit Registerpaaren richtig
 umgeht, aber jetzt willst du auf einmal Taster, Interrupts usw. in
 "deinem" Programm haben...

 Gerade als Anfänger sollte man alles so einfach wie nur möglich halten.

von Niklas W. (niklas_w)


Lesenswert?

Taster und Interrupt funktionieren ja super.

Marc V. schrieb:
> Du weisst ja nicht einmal wie man mit Registerpaaren richtig
>  umgeht

Ich brauche doch bei 0x0060 nur das untere Register. Da kann doch das 
obere bei 0 bleiben, oder nicht?

Marc V. schrieb:
> Gerade als Anfänger sollte man alles so einfach wie nur möglich halten.

Im Grunde ist es eine Schulaufgabe und ich hab bereits bestimmte 
Kriterien erfüllt. Die Initialisierung klappt und meine Tasterlogik 
auch. Die Indexregister zeigen doch auf die Speicherzellen, wo jeweils 
ein Zeichen im SRAM gespeichert ist. Verstehe ich das falsch?

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Niklas W. schrieb:
> auch. Die Indexregister zeigen doch auf die Speicherzellen, wo jeweils
> ein Zeichen im SRAM gespeichert ist. Verstehe ich das falsch?

 Ja.
 0x60 ist eine feste Adresse, welche sich zwar im RAM befindet, aber
 welcher Lehrer hat dir gesagt, dass das so richtig ist?
 Ich habe dir doch gezeigt wie man das richtig macht.
1
           ldi   xl, low(text)
2
           ldi   xh, high(text)
 Damit kann sich der text an einer beliebigen Adresse im RAM befinden.
 Und wer sagt dir, dass der obere Register 0 enthält?

Christoph schrieb:
> Sollte dort einer stehen, müsste an der Speicherzelle ja etwas ungleich
> 0 sein.
1
 
2
string:
3
        push  temp1      ;* Warum nur temp1 und nicht auch r22 und X-Reg?
4
        ldi r22,0
5
 
6
string_1:
7
        ldi r26, 0x0060  ;* Du setzst den Index wieder und wieder und wieder auf 0x60
8
        inc r22
9
        ld    temp1, X+  ;* Deswegen nützt dir dieses Post increment überhaupt nix
10
        cpi   r22, 80    ;* Wieso 80, sollte das nicht auf Null geprüft werden, anstatt auf Länge?
11
        breq  string_2
12
 
13
        rcall  lcd_data
14
        rjmp  string_1   ;* Und dann wunderst du dich, dass immer dieselben Zeichen angezeigt werden?
15
 
16
string_2:
17
        pop   temp1
18
        ret

: Bearbeitet durch User
von Niklas W. (niklas_w)


Lesenswert?

Aber wenn ich es doch irgendwo im SRAM abspeichere, also bei text: , 
dann weiß ich doch gar nicht ab wann der Index anfangen soll... Es tut 
mir wirklich leid, wenn ich mich gerade doof stelle...


Edit:

Ok jetzt denke ich es verstanden zu haben...
1
string:
2
           push  temp1
3
       push zl
4
       push zh
5
       ldi r22,0
6
       ldi   zl, low(text)
7
           ldi   zh, high(text)
8
9
string_1:
10
       
11
       inc r22
12
           ld    temp1, Z+
13
           cpi   r22, 0
14
           breq  string_2
15
       
16
           rcall  lcd_data
17
           rjmp  string_1
18
19
string_2:
20
           pop   temp1
21
       pop zl
22
       pop zh
23
           ret

1
receive:
2
cli
3
SBI PORTC,3
4
5
6
    push  zl
7
    push  zh
8
    ldi   zl, low(text)
9
    ldi   zh, high(text)
10
    push  temp1
11
12
  warten:
13
    sbis  UCSRA, RXC
14
    rjmp  warten
15
    in    temp1, UDR
16
    st    Z+, temp1
17
  out UDR,temp1
18
  rcall senden
19
    cpi   temp1, 0x0D
20
    brne  warten
21
22
  clr   temp1
23
    st    -Z, temp1
24
  pop   temp1
25
    pop   zh
26
    pop   zl
27
  sei
28
reti

Hab es so umgesetzt...Klappt aber irgendwie nicht

: Bearbeitet durch User
von Joachim B. (jar)


Lesenswert?

Niklas W. schrieb:
> Hab es so umgesetzt...Klappt aber irgendwie nicht

du brauchst ein load indirect und increment

https://www.microchip.com/webdoc/avrassembler/avrassembler.wb_LD.html

dein reservierter Speicher für die Daten ist ja wenn ich das alles 
richtig verfolgt hatte:

Christoph schrieb:
> Ich habe jetzt im SRAM ein paar bytes mit :
> .dseg
>
> text: .byte 20
>
> reserviert.

text ist die Adresse vom Speicher genauerweise vom ersten Byte also Byte 
0 bis zu text +19 wegen 20 Byte (falls sich nichts in dne letzten Jahren 
geändert hat (aber ich komme vom 6502 der nur einen Adressraum kannte)

also musst du irgendwo den post increment machen

https://www.microchip.com/webdoc/avrassembler/avrassembler.wb_LD.html
The X pointer register can either be left unchanged by the operation, or 
it can be post-incremented or pre-decremented.

Ich bin da nicht sattelfest beim AVR aber einiges gilt noch immer, siehe 
ASM Befehle AVR.

Niklas W. schrieb:
> Aber wenn ich es doch irgendwo im SRAM abspeichere, also bei text: ,
> dann weiß ich doch gar nicht ab wann der Index anfangen soll...

? der Index fängt da an wo der ASM den text hinlegt, wie lang er ist 
hast du festgelegt und wo dein Indexzeiger aktuall steht musst du wissen 
wenn du ein increment machst, also schön mitzählen!

von Niklas W. (niklas_w)


Lesenswert?

Joachim B. schrieb:
> der Index fängt da an wo der ASM den text hinlegt, wie lang er ist
> hast du festgelegt und wo dein Indexzeiger aktuall steht musst du wissen
> wenn du ein increment machst, also schön mitzählen!

Da ich ihn ja hier:
1
string:
2
           push  temp1
3
     push zl
4
     push zh
5
     ldi r22,0
6
           ldi   zl, low(text)
7
           ldi   zh, high(text)
8
9
string_1:
10
       
11
       inc r22
12
           ld    temp1, Z+
13
           cpi   r22, 0
14
           breq  string_2
15
       
16
           rcall  lcd_data
17
           rjmp  string_1
18
19
string_2:
20
           pop   temp1
21
       pop zl
22
       pop zh
23
           ret

neu reinlade und danach immer inkrementiere müsste das doch passen

von Joachim B. (jar)


Lesenswert?

Niklas W. schrieb:
> müsste das doch passen

ja müsste aber....

Niklas W. schrieb:
> ...Klappt aber irgendwie nicht

finde den Fehler!

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Niklas W. schrieb:
> Ok jetzt denke ich es verstanden zu haben...

 Nein.
 Die Reihenfolge deiner push und pop Befehle stimmt nicht, es wird
 LIFO benutzt, heisst letzter rein geht als erster raus.

 push temp1
 push zl
 push zh
...
...
 pop  zh
 pop  zl
 pop  temp1

von Joachim B. (jar)


Lesenswert?

Marc V. schrieb:
> Die Reihenfolge deiner push und pop Befehle stimmt nicht, es wird
>  LIFO benutzt, heisst letzter rein geht als erster raus.

top! +1 von mir
ich wusste irgendwas sah merkwürdig aus, aber ich bin zulange raus!

: Bearbeitet durch User
von Niklas W. (niklas_w)


Lesenswert?

Marc V. schrieb:
> Nein.
>  Die Reihenfolge deiner push und pop Befehle stimmt nicht, es wird
>  LIFO benutzt, heisst letzter rein geht als erster raus.

Oh stimmt ganz vergessen... Jetzt wirds langsam immer peinlicher ._.

1
receive:
2
cli
3
SBI PORTC,3
4
5
6
  push temp1
7
  push zl
8
  push zh
9
    ldi   zl, low(text)
10
    ldi   zh, high(text)
11
12
13
  warten:
14
    sbis  UCSRA, RXC
15
    rjmp  warten
16
    in    temp1, UDR
17
    st    Z+, temp1
18
  out UDR,temp1
19
  rcall senden
20
    cpi   temp1, 0x0D            ;<------ funktioniert nicht
21
    brne  warten
22
23
  clr   temp1
24
    st    -Z, temp1
25
  pop  zh
26
  pop  zl
27
  pop  temp1
28
  rcall string
29
  sei
30
reti


Mein Vergleich in der Interruptfunktion will aber auch iwie nicht...Ich 
prüfe doch auf Carriage Return...Wenn ich den Vergleich auskommentiere, 
dann wird das ganze LCD einfach dunkel

von Joachim B. (jar)


Lesenswert?

mach mal kleinere Schritte

Niklas W. schrieb:
> Wenn ich den Vergleich auskommentiere,
> dann wird das ganze LCD einfach dunkel

welches LCD?

du schickst über USART raus

bist du sicher das deine 20 Byte nicht überlaufen?
was ist mit NL, manche wollen CR & NL manche nur NL
Dein "String" sollte trotzdem NULL terminiert sein und der Pointer nie 
größer text + 19 sein!

vor allem WAS schickst du raus? evtl. ESC Sequenzen? oder nicht 
druckbare Zeichen?

: Bearbeitet durch User
von Niklas W. (niklas_w)


Lesenswert?

Joachim B. schrieb:
> welches LCD?

Ein 16x2 LCD...

Joachim B. schrieb:
> du schickst über USART raus

Ja ich schicke einfach nochmal raus, was ich gesendet habe, um ein 
Feedback zu bekommen, dass es überhaupt geklappt hat.

Joachim B. schrieb:
> bist du sicher das deine 20 Byte nicht überlaufen?

Momentan schicke ich das Wort Moin...Das sollte passen.

Joachim B. schrieb:
> Dein "String" sollte trotzdem NULL terminiert sein und der Pointer nie
> größer text + 19 sein!

Wenn ich mehr Bytes reserviere macht es keinen Unterschied....Er bleibt 
bei dem Vergleich und geht gar nicht in die Stringfunktion

von Joachim B. (jar)


Lesenswert?

Niklas W. schrieb:
> Momentan schicke ich das Wort Moin...Das sollte passen.

und wieso dann

Niklas W. schrieb:
> ...Ich
> prüfe doch auf Carriage Return...

wenn du es nicht mitschickst?

Niklas W. schrieb:
> rcall senden
>     cpi   temp1, 0x0D            ;<------ funktioniert nicht
>     brne  warten

deine Texte bleiben unverständlich!

: Bearbeitet durch User
von Niklas W. (niklas_w)


Lesenswert?

Joachim B. schrieb:
> wenn du es nicht mitschickst?

Sollte ich dann \r schicken oder wie versteht der Assembler das?

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Niklas W. schrieb:
1
  in    temp1, UDR
2
  st    Z+, temp1
3
  out   UDR,temp1
4
  rcall senden
5
  cpi   temp1, 0x0D            ;<- und du bist sicher, dass temp1 immer noch denselben Wert hat?
6
  brne  warten

 Wie sieht deine Routine "senden" aus?

 Irgendwie macht das keinen Spass.
 Wenn ich ein Puzzle haben will, dann kaufe ich mir eins.

 Sende doch alles, dann kann man mehr sagen, so ist es nur raten...

von Joachim B. (jar)


Lesenswert?

Niklas W. schrieb:
> Sollte ich dann \r schicken oder wie versteht der Assembler das?

oder nur 13d oder 0Dh

: Bearbeitet durch User
von Niklas W. (niklas_w)


Angehängte Dateien:

Lesenswert?

Joachim B. schrieb:
> oder nur 13d oder 0D

So?

von Niklas W. (niklas_w)


Lesenswert?

Ah ok...Wenn ich das als Zahl mitschicke klappt es....Aber dann wird das 
LCD einfach dunkel und zeigt nix mehr.

von Joachim B. (jar)


Lesenswert?

Marc V. schrieb:
> Irgendwie macht das keinen Spass.
>  Wenn ich ein Puzzle haben will, dann kaufe ich mir eins.

+1

wenn immer nur Bruchstüke kommen verliert man den Überblick und die Lust 
zu helfen!

immer vor und zurückscrollen hält mein Mausrad nicht aus und es gibt 
eine Codeansicht die hier besser geeignet wäre!

: Bearbeitet durch User
von Niklas W. (niklas_w)


Lesenswert?

Joachim B. schrieb:
> wenn immer nur Bruchstüke kommen verliert man den Überblick und die Lust
> zu helfen!
>
> immer vor und zurückscrollen hällt mein Mausrad nicht aus und es gibt
> eine Codeansicht die hier besser geeignet wäre!

Tut mir wirklich leid und ich bin sehr dankbar für die Hilfe, die mir 
hier zuteil wird. Ich konnte es jetzt an das LCD übertragen und es 
funktioniert problemlos. Leider schreibt es noch nicht in die zweite 
Zeile aber das werde ich denke ich iwie mit dem Control Command für die 
RAM-Adresse hinbekommen...Denke ich

Wirklich vielen Dank für die Hilfe

von Niklas W. (niklas_w)


Lesenswert?

Irgendwie war da was beim myAVR Workpad falsch...Nachdem es gecrashed 
ist und ich es neugestartet habe, hat es einwandfrei funktioniert.

von Karl B. (gustav)


Lesenswert?

Wie man an diesem Thread hier sieht,
hat es überhaupt keinen Sinn, irgendetwas an Hilfestellung zu leisten,
ohne dass man sich vom Kenntnisstand des Fragenden überzeugt hat.

Was ich verlange, bevor ich hier weitermache:
Ein sauber aufgeführes Programmbeispiel.

Seite 33

http://avr-asm-download.de/beginner_de.pdf

ciao
gustav

: Bearbeitet durch User
Beitrag #6116133 wurde vom Autor gelöscht.
von W.S. (Gast)


Lesenswert?

S. Landolt schrieb:
> PS an W.S.:
>
> Falls die doppelte Bedeutung von UDR unklar sein sollte:

Also, die Ur-Frage war ja, ob man sich in der ISR auch um den 
umgekehrten Datenstrom kümmern müßte. Mit den Atmels befasse ich mich 
NICHT, deswegen die vorsichtige Frage. Bei vielen Cortexen (wie z.B. 
den hier beliebten STM32) gibt es nur einen Interrupt-Handler für beide 
Richtungen. Deshalb muß der sich auch um Rx und Tx kümmern.




Joggel E. schrieb:
> Also, wenn die UART Routine dann geht, haben wir den String in einem
> Buffer.
> Von dort wird er per Timer, zB alle 10ms ein Zeichen geschrieben.
>
> Ich wuerd kontinuierlich den gesammten Inhalt des festen Buffers per
> Timer ins Display kopieren.

So eine Strategie halte ich für ausgesprochen schlecht durchdacht. 
Immerhin kommen an einem UART irgendwelche Zeichen in lockerer Folge der 
Reihe nach an - und es ist genug Zeit zwischen 2 Zeichen, um jedes 
einzeln verwerten zu können, OHNE diese zuvor in irgend einem String 
zwischenspeichern zu müssen.

Wozu also einen Timer benützen? Wozu all die Zeichen zwischenspeichern? 
Es reicht doch wohl aus, wenn selbige auf dem Display zu lesen sind.


Eigentlich geht das doch sehr einfach:
1. Man definiere sich ein paar Sonderzeichen für Positionierungen etc:
0xE0..0xFF = Schreibposition auf Zeichen 0..15 in Zeile 1 setzen
0xC0..0xDF = Schreibposition auf Zeichen 0..15 in Zeile 2 setzen
0x03 = Clear bis Zeilenende
.. und bei Bedarf noch weitere Steuerzeichen.

2. Und beim Empfang eines Zeichens:

 C = LiesZeichenAusUART
 if C>=0xE0
 then Setze Schreibzeiger auf Zeile 0, Stelle C-0xE0, exit;

 if C>=0xC0
 then Setze Schreibzeiger auf Zeile 1, Stelle C-0xE0, exit;

 if C = 3 then
 { merke Schreibzeiger in Rettvariable;
   while Schreibzeiger noch in Zeile do
     { Gib ' ' an LCD aus;
       Inkrementiere Schreibzeiger;
     }
  Restauriere Schreibzeiger von Rettvariable;
  exit
 }

 Gib C an LCD aus;
 exit
 ende;

So, das mal quasi symbolisch hingeschrieben. Das braucht lediglich je 
ein Byte für C, Schreibzeiger und Rettvariable.

W.S.

von Joachim B. (jar)


Lesenswert?

W.S. schrieb:
> So eine Strategie halte ich für ausgesprochen schlecht durchdacht.
> Immerhin kommen an einem UART irgendwelche Zeichen in lockerer Folge der
> Reihe nach an - und es ist genug Zeit zwischen 2 Zeichen, um jedes
> einzeln verwerten zu können,

stimme zu

W.S. schrieb:
> Wozu also einen Timer benützen?

weil es keinen Sinn hat zu oft Zeichen auf ein LCD zu schreiben, wer 
soll das in 10ms lesen?

W.S. schrieb:
> Wozu all die Zeichen zwischenspeichern?

weil man im RAM Zeichen, wenn neue Daten kommen, schneller überschreiben 
kann als auf dem Display und wer im 10ms Timer IRQ (z.B. 
Tastenentprellung) einen counter hochzählt, ich bis 25 und somit alle 
250ms den LCD Text aktualisiert, hat weniger Flimmern auf dem LCD und 
bremst den µC weniger aus und es bleibt mehr Zeit und Takte für andere 
Routinen übrig.

: Bearbeitet durch User
von W.S. (Gast)


Lesenswert?

Joachim B. schrieb:
> weil es keinen Sinn hat zu oft Zeichen auf ein LCD zu schreiben, wer
> soll das in 10ms lesen?

Und wieso sollte man das Zeichen überhaupt mehrfach auf's LCD schreiben? 
Einmal genügt doch vollkommen, lesbarer wird's auch bei mehrfachem 
Schreiben nicht.

Und worum handelt es sich denn TATSÄCHLICH??

Also
1. Mit einem ATmega Zeichen vom UART auf's LCD schreiben

2. Zeichen von anderen Teilen der Firmware im ATmega auf's LCD 
schreiben?

3. Beides, also Zeichen von der Firmware und vom UART gemischt auf's LCD 
schreiben?

Eigentlich hat der TO jetzt genug Tips gekriegt, um klar zu kommen. 
Alles Weitere sollte jetzt seine Angelegenheit sein.

W.S.

von Uwe (Gast)


Lesenswert?

Hi,
also ich habe für das LCD immer einen Puffer. Da kann man dann auch mal 
prüfen wo denn die Zeichen hingehören. Ein 2x16 hat ja auch einen 
Zeichenspeicher von 2x40, ok nicht alle aber viele. Man hat auch die 
Möglichkeit mal Sonderzeichen zu nutzen. ($EF = ö)
Übrigens wenn man wissen will ob der Puffer voll ist(20 Zeichen) kann 
man auch mit

.dseg
.org 0x60
text: .byte 20

st    Z+, temp1
CPI  Zl,(low(text)+20)

prüfen und dann die Zeile komplett ausgeben.

Übrigens:
>     ldi r22,0
>           ldi   zl, low(text)
>           ldi   zh, high(text)

>string_1:

>       inc r22
>           ld    temp1, Z+
>           cpi   r22, 0
>           breq  string_2
>           rcall  lcd_data
>           rjmp  string_1
zählt bis 256!

Viel Erfolg, Uwe

von Joachim B. (jar)


Lesenswert?

W.S. schrieb:
> Und wieso sollte man das Zeichen überhaupt mehrfach auf's LCD schreiben?

was genau verstehst du an

Joachim B. schrieb:
> wenn neue Daten kommen
Joachim B. schrieb:
> den LCD Text aktualisiert

nicht?

ich erkläre dir es gerne gaaaanz laaaangsaaaam

z.B. eintrudelner neuer Text oder Telegramm kommt schneller als man 
lesen kann, was tun genauso schnell ausgeben wie er kommt?
1. sinnlos

Den Text stehen lassen bis man hätte lesen können?
2. bringt nicht unbedingt wichtige News, die dann weg sind, ebenfalls 
sinnlos!

3. beste Methode die mir gefällt, letzten neusten Text im RAM 
zwischenspeichern und wieder ans LCD schicken wenn die Wartezeit z.B. 
250ms  (oder nach Belieben) um ist

Ich mache 250ms damit eine fortlaufende Uhr soft läuft und nicht holpert 
denn nicht immer erfolgt die LCD Ausgabe zum Sekundenwechsel.

Will man z.B. eine Ubat überwachen reicht natürlich alle Sekunde
Will man die aktuellen Börsenwerte anzeigen braucht man zum Lesen wohl 
mehr Zeit.

Wenn du allerdings eine Methode kennst im Standard LCD nur die 
relevanten  mittelsten Zeichen zu tauschen von Ubat = 5,1V zu Ubat = 
4,9V würde man noch weniger Zeichen neu schreiben, kann einen 
Zeitvorteil bringen, aber im Interesse der Einfachheit würde ich die 
ganze Zeile neu schreiben.

: Bearbeitet durch User
von W.S. (Gast)


Lesenswert?

Joachim B. schrieb:
> ich erkläre dir es gerne gaaaanz laaaangsaaaam

Das war überhaupt keine Erklärung. Ich zitiere dich nochmal:

> weil es keinen Sinn hat zu oft Zeichen auf ein LCD zu schreiben, wer
> soll das in 10ms lesen?

Und von dem 10 ms Timer hat du und nicht ich geschrieben.

Also: Wenn Zeichen vom UART hereinkommen, dann sind die ja wohl dazu 
gedacht, um laut Eröffnungpost auf dem LCD angezeigt zu werden. ODER?

Also kann man sie auch gleich beim Empfang anzeigen.

Und wenn jemand so unsäglich DOOF ist, das alte Testament in voller 
Länge ohne Pausen auf einem 2 zeiligen LCD anzeigen zu wollen, dann ist 
er selber dran schuld, daß er vor lauter Datenrauschen nix lesen kann.

Joachim B. schrieb:
> Wenn du allerdings eine Methode kennst im Standard LCD nur die
> relevanten  mittelsten Zeichen zu tauschen

Da ist doch ne völlig übliche Sache: einfach den Schreibzeiger im LCD 
auf die gewünschte Position stellen und dann die Zeichen schreiben. Ist 
genau dasselbe wie das Stellen des Schreibzeigers auf Zeile 1 oder 2 
(oder 3 oder 4 bei vierzeiligen Typen).

W.S.

von Joachim B. (jar)


Lesenswert?

W.S. schrieb:
> einfach den Schreibzeiger im LCD
> auf die gewünschte Position stellen und dann die Zeichen schreiben

du denkst zu einfach!

Ich habe LCD die eben nicht alte Pixel löschen wenn neue Pixel an 
anderer Stelle geschrieben werden!

Bevor man nun pixelweise löscht und davor erst mal feststellt welche 
Pixel noch stehen (die LCD können auch nicht ausgelesen werden und ein 
pixelgenaues Schattenram halte ich für oversized) schreibe ich doch 
lieber komplett neu mit löschen vorher (bei Bedarf)

W.S. schrieb:
> Und wenn jemand so unsäglich DOOF ist, das alte Testament in voller
> Länge ohne Pausen auf einem 2 zeiligen LCD anzeigen zu wollen, dann ist
> er selber dran schuld

OK du hast Recht, deine Begründung ist für alle die Beste.

Ich muss dir ja nicht folgen und auch kein anderer mir :)

Jeder darf mit jedem Tempo alles aufs LCD zaubern ob lesbar oder nicht 
ist ja egal.

von W.S. (Gast)


Lesenswert?

Joachim B. schrieb:
> Ich habe LCD die eben nicht alte Pixel löschen wenn neue Pixel an
> anderer Stelle geschrieben werden!

Soso. Das ist ja auch normal, daß ein GRAFISCHES Display nicht "alte" 
Pixel löscht, wenn an eine andere Stelle was geschrieben wird. Wäre ja 
noch schöner!!!

Aber hier haben wir:

Christoph schrieb:
> ich arbeite momentan daran, ein 16x2 LCD an meinem ATmega8A zu benutzen.

Und das ist ein alphanumerisches Display mit 2 Zeilen zu je 16 
Textzeichen.

Dort gibt es keine "alten" Pixel, sondern es gibt dort drinnen einen RAM 
für die Textzeichen und die kann man dadurch sehen, daß ein Pixelmuster 
aus dem ebenfalls enthaltenen Zeichen-ROM an der zuständigen Stelle 
dargestellt wird.

Wenn man so ein Textzeichen überschreibt, dann ändert sich damit auch 
dessen Darstellung. Da braucht man garnix zu löschen.

Klaro?

W.S.

von Joachim B. (jar)


Lesenswert?

W.S. schrieb:
> W.S.

du hast ja soooo Recht, es ist ermüdend und nun hast du deinen Willen.
Ob das dem TO mehr half als alles vorher?
Auch ohne dich kam der TO der Lösung näher, hier ungefähr:
Beitrag "Re: String über UART an LCD"

von Mw E. (Firma: fritzler-avr.de) (fritzler)


Lesenswert?

@Joachim B
Du weist doch, dass W.S. hier nur rumnervt und keine Ahnung vom 
Programmieren hat und dazu Ansichten aus den 80ern.
Das Problem ist nur, dass er jetzt auch schon anfängt Forennutzer aktiv 
zu vergraulen.

von Joachim B. (jar)


Lesenswert?

Mw E. schrieb:
> W.S.

ich meine mich dunkel an gute Beiträge von ihm erinnern zu können, muss 
aber sehr lange her sein, vielleicht irre ich mich auch.

von c-hater (Gast)


Lesenswert?

Joachim B. schrieb:

> ich meine mich dunkel an gute Beiträge von ihm erinnern zu können, muss
> aber sehr lange her sein, vielleicht irre ich mich auch.

Egal, was in der Vergangenheit war, im konkreten Fall hat er einfach mal 
nur Recht. Es ging tatsächlich nur um ein doofes Textdisplay. Der Exkurs 
Richtung (funktional beschränkter) Grafikdisplays war vollkommen 
überflüssig und NULL hilfreich für den TO, weil der eben ein solches 
nicht verwendet und auch nicht verwenden will.

Und all der Bratz bezüglich Updaterate usw. war auch vollkommen 
überflüssig, denn es geht ja ganz offensichtlich um die Übertragung und 
Anzeige einzelner, manuell erzeugter Strings.

Die kann man natürlich einfach live Zeichen für Zeichen auf das Display 
schreiben, wenn die Baudrate hinreichend gering ist. Wenn nicht, muss 
man den String halt buffern und schreibt ihn nach Eintreffen des 
Ende-Zeichens auf das Display.

Das Problem des TO ist einfach nur, dass er keinen Plan entwickeln kann, 
auch nur eins der beiden Konzepte umzusetzen. Von den Kompetenzmängeln 
bei der Beherrschung seines Werkzeugs ist das erstmal noch völlig 
unabhängig, deswegen lasse ich seine Ausrede mit den mangelnden 
Assemblerkenntnissen auch nicht gelten. Er würde das auch in C oder 
irgendeiner anderen Sprache nicht umgesetzt bekommen, weil er einfach 
nicht weiss, was er da eigentlich tut...

von Mw E. (Firma: fritzler-avr.de) (fritzler)


Lesenswert?

Joachim B. schrieb:
> ich meine mich dunkel an gute Beiträge von ihm erinnern zu können, muss
> aber sehr lange her sein, vielleicht irre ich mich auch.

Wenn dem so ist würde ich wirklich gerne mal wissen was dann 
zwischenzeitlich schiefgelaufen ist :/

von Joachim B. (jar)


Lesenswert?

c-hater schrieb:
> Es ging tatsächlich nur um ein doofes Textdisplay.

beim TO im ersten Beitrag ja, aber nicht lt. Titel und es soll ja auch 
andere LCD geben.
Ich für meinen Teil habe mich recht schnell vom doofen Text LCD 
verabschiedet.

c-hater schrieb:
> Das Problem des TO ist einfach nur, dass er keinen Plan entwickeln kann,
> auch nur eins der beiden Konzepte umzusetzen.

das sah zumindest eine Weile so aus, aber er kam ja voran, wie er 
weitermacht liegt bei ihm.

Der kleine Ausflug zurück zu ASM hat mir aber trotzdem Spass gemacht, 
manches ändert sich nie: load & increment obgleich die mnemonics nun 
anders heissen.

aus ldi load & increment wurde ldi load immediate

aber das kann man ja neu lernen.

von Karl B. (gustav)


Angehängte Dateien:

Lesenswert?

Hi,
die HD 44780 LCDs nehmen einem die meiste Arbeit schon ab.
Bei der Initialisierung des LCD kann man unter anderem auch einen 
Automatismus bei der Darstellung der Zeichen festlegen. Man braucht 
nicht extra pro Charakter einen Befehl zur Positionierung machen, wenn 
ein fortlaufender Text dargestellt werden soll. Kann man schon, muss man 
nicht.
Auch, wenn Zeichen vom UART kommen. Wie im Beispielfilmchen.
Die "normale" Einstellung ist, dass nach jedem ausgegebenen Zeichen der 
Cursor um eine Position nach rechts rückt, das wird dann beim Init in 
der Doku als Adressenincrement bezeichnet. Es gibt auch ein 
Adressendecrement.
Und Shift. Gesamten Inhalt des Display-RAMS schieben. Und Cursor nicht 
darstellen trotz Increment/Decrement. Und mehr -> Doku.

ciao
gustav

: Bearbeitet durch User
von Stefan F. (Gast)


Lesenswert?

Karl B. schrieb:
> Und Shift. Gesamten Inhalt des Display-RAMS schieben.

Du meinst vermutlich den Befehl, der das "Fenster" horizontal über dem 
RAM verschiebt. Wann braucht man das?

Ich hätte lieber einen Befehl, der Text nach oben scrollt. Den gibt's 
leider nicht.

von Karl B. (gustav)


Angehängte Dateien:

Lesenswert?

Stefan ⛄ F. schrieb:
> Wann braucht man das?

Hi,
selten.
Das wird besser anders gelöst.
Zum Beispiel ein Messgeräteprogramm.
Legende konstant und Messwerte dann "variabel", wenn Stellenzahl 
überschritten 12,34  Dann 23,45  es sollen 4  bzw. mit Komma 5 Stellen 
bleiben.
Manche Programme wechseln sogar innerhalb des laufenden Programms noch 
einmal und initialisieren LCD entsprechend neu.

Da kann man viel "rumbasteln."
Und die Befehlsbezeichnungen können ganz schön missverständlich sein.
Wenn man vom Effekt ausgeht.
Zwar no shift.
aber im Folgebefehl dann doch "shift".
Na ja. Dabla genau lesen und ausprobieren.
;....
;Entry Mode/Shift Set:
;
cbi  daten,    0
ldi  temp,    0x06   ;Cursor "increment/increase"
;        ;Displayinhalt wird nicht ;geschoben "no shift"
rcall  kommando
rcall  verzoegerung3
cbi  daten,    0
ldi  temp,    0x1C  ;Display rechts schieben
rcall  kommando
;...
Siehe Video, was dabei rauskommt.

ciao
gustav

: Bearbeitet durch User
von Karl B. (gustav)


Angehängte Dateien:

Lesenswert?

Hi,
auf Seite 40 im Dabla steht's noch ausführlicher.

ciao
gustav

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.