Forum: Mikrocontroller und Digitale Elektronik Suche hilfe für einen blutigen Anfänger


von Dennis Brücke (Gast)


Lesenswert?

Hi @all,

ich habe eigendlich folgendes Problem ich habe zum allerersten mal
Kontakt mit MC´s und habe mir von rowald.de das Testboard gebaut und
mir ein LCD Display gekauft, ok text habe ich schon hinbekommen. Jetzt
hab ich mal Probiert eine Tastenabfrage mit einzubauen.

Sprich:
 Taste 1 lässt den Text einblenden
 Taste 2 Bildschirm Löschen.

Schalte ich den MC an Funktioniert Taste 1 ok dann Taste 2...
aber leide bekomme ich nach dem LCD-Clearen keinen Text mehr wenn ich
dir Taste 1 Drücke... :( ich finde den Fehler einfach nicht...

Nun möchte ich euch in dieser Community mal bitten meinen Source
anzuschauen, und mir evtl. tips geben worauf ich achten sollte und
evtl. wo ich Grundlegende fehler gemacht habe, nicht das ich mir beim
lernen gleich gravierende Fehler aneigne.

Gruß Dennis

Source:
-----------------------------------------------------------------
.include "m8def.inc"

init:
      ldi r21, HIGH(ramend)      ; Stackpointer Init
      out sph, r21
      ldi r21, LOW(ramend)
      out spl, r21

      ldi zh, HIGH(text*2)      ; Z-Pointer init
      ldi zl, low(text*2)

      ldi r16, 0b00011100        ; PD2,3,4 Ausgang
      out ddrd, r16
      ldi r16, 0b00001111        ; PC0,1,2,3 Ausgang
      out ddrc, r16

      ldi r16, 0b11010000
      out portd, r16          ; Setze PD4 auf HIGH

main:
      rcall lcd_init          ; LCD-Initalisieren
      rcall lcd_clear          ; LCD-Clearen

loop:
      sbis pind, 6
      rcall print

      sbis pind, 7
      rcall lcd_clear



      rjmp loop            ; Dauer schleife

print:    lpm                ; Daten aus FlashROM lesen (Z-Pointer)
      tst R0              ; Teste ob 0
      breq print_end          ; Wenn TEST = Wahr dann zu ...
      mov r16, r0            ; Kopiere Inhalt von R0 (lpm) in r16
      rcall lcd_data          ; Gebe r16 auf LCD aus
      adiw ZL,1            ; Erhöhe Z-Pointer Startpunkt um 1
      rcall delay1s          ; Pause
      rcall delay1s          ; Pause
      rjmp print            ; Und wieder von vorne
print_end:
      ret            ; Springe in die Endlosschleife

lcd_init:
           ldi  r18,50            ; 50x delay 5ms
powerupwait:
           rcall  delay5ms        ; Pause von 5ms
           dec  r18              ; Decrement r18 -1
           brne  powerupwait          ; und das so lange bis r18 = 0

       ldi r16, 0b00000011            ; Init vom LCD (Siehe Datenblatt)
           out PORTC, r16          ; PORTC Setzen
           rcall lcd_enable               ; LCD Enable
           rcall delay5ms          ; Pause 5ms
           rcall lcd_enable               ; LCD Enable
           rcall delay5ms          ; Pause 5ms
           rcall lcd_enable               ; LCD Enable
           rcall delay5ms          ; Pause 5ms

       ldi r16, 0b00000010            ; LCD 4bit-Modus einstellen (Siehe
Datenblatt)
           out PORTC, r16          ; PORTC Setzen
           rcall lcd_enable          ; LCD Enable
           rcall delay5ms          ; Pause 5ms

           ldi r16, 0b00101000            ;noch was einstellen...
           rcall lcd_command

           ldi r16, 0b00001111            ;...nochwas...
           rcall lcd_command

           ldi r16, 0b00000100            ;endlich fertig
           rcall lcd_command
           ret

lcd_data:
           sbi portd, 2            ; LCD Modus auf Daten
       mov r17, r16            ; Kopiere r16 in r17
           swap r16              ; Tausche
           andi r16, 0b00001111
           out PORTC, r16
           rcall lcd_enable
           andi r17, 0b00001111
           out PORTC, r17
           rcall lcd_enable
           rcall delay50us
           cbi portd, 2
       ret

lcd_command:                            ;wie lcd_data, nur ohne RS zu
setzen
           mov r17, r16
           swap r16
           andi r16, 0b00001111
           out PORTC, r16
           rcall lcd_enable
           andi r17, 0b00001111
           out PORTC, r17
           rcall lcd_enable
           rcall delay50us
           ret

lcd_clear:
           ldi r16, 0b00000001   ;Display löschen
           rcall lcd_command
           rcall delay5ms
           ret

lcd_enable:
      sbi PORTD, 4
      nop
      nop
      nop
      cbi PORTD, 4
      ret


delay50us:                              ;50us Pause
           ldi  r16, $42
delay50us_:dec  r16
           brne delay50us_
           ret

delay5ms:                               ;5ms Pause
           ldi  r16, $21
WGLOOP0:   ldi  r17, $C9
WGLOOP1:   dec  r17
           brne WGLOOP1
           dec  r16
           brne WGLOOP0
           ret                          ;wieder zurück

delay1s:                               ;5ms Pause
           ldi  r16, $ff
delay1s1:   ldi  r17, $ff
delay1s2:   dec  r17
           brne delay1s2
           dec  r16
           brne delay1s1
           ret                          ;wieder zurück

text:
.db "a",0

von Johannes Raschke (Gast)


Lesenswert?

Das Programm sieht ja schon mal nicht schlecht aus.
In der print - routine wird allerdings das Z-Register verändert,
deshalb mußt Du das wieder auf den Anfang des Strings setzen, wenn Du
den nochmal ausgeben möchtest!

Viele Grüße

Johannes

von Johannes Raschke (Gast)


Lesenswert?

Und noch etwas:
in der print - Routine erhöhst Du ZL immer um eines. Was aber, wenn der
String zufällig über das Ende des "segments" hinausgeht (z.b. 0x01fa
bis 0x0201)? Du solltest also das ganze Z-Registerpaar um 1 erhöhen,
dafür gibt's einen eigenen Befehl.
Ich habe hier auch schonmal meine eigene print_disp routine
veröffentlicht, kannste  über die Suchfunktion finden.

cheeorio


Johannes

von Dennis Brücke (Gast)


Lesenswert?

Patsch.... da hab ich gar nicht drauf geachtet...
Danke Dir ;)

Vieleicht kannst Du mir noch helfen, bevor ich groß suche Habe noch
folgende fragen:

- Wie spreche ich in form von z.b. print routine die 2. Zeile an ?
- Wie kann man Text in Form einer Laufschrift abarbeiten lassen...
  right in left out z.b.

---------------------------------------------------------------------
>print:    lpm                ; Daten aus FlashROM lesen (Z-Pointer)
>      tst R0              ; Teste ob 0
>      breq print_end          ; Wenn TEST = Wahr dann zu ...
>      mov r16, r0            ; Kopiere Inhalt von R0 (lpm) in r16
>      rcall lcd_data          ; Gebe r16 auf LCD aus
>      adiw ZL,1            ; Erhöhe Z-Pointer Startpunkt um 1
*      rcall delay1s          ; Pause
*      rcall delay1s          ; Pause
>      rjmp print            ; Und wieder von vorne
>print_end:
>      ret            ; Springe in die Endlosschleife
---------------------------------------------------------------------

Gibt es evtl. noch eine bessere möglichkeit, den Text delayed
auszugeben, anstatt gleich eine übergroße delay schleife ?

Gruß Dennis

von crazy horse (Gast)


Lesenswert?

keine Ahnung, wie es in Bascom geht, mit CV kann mn die Cursorposition,
also die aktuelle Schreibmarke mit
lcd_gotoxy(x,y);
setzen.
Was ähnliches müsste es auch in Bascom geben.

von Johannes Raschke (Gast)


Lesenswert?

Die 2.Zeile beginnt an einer Speicheradresse, deren Wert im Datenblatt
des Displays steht. Wenn Du die erste Zeile vollschreibst, kommst Du
also irgendwan in einer anderen Zeile heraus (z.B. der zweiten bei
einem zweizeiligen Display).
Üblicherweise benutzt man den Befehl set_DDRAM_address, um den Cursor
zu positionieren (mit lcd_command).
Laufschrift, hm. Bei kurzen Texten in den Speicherbereich hinter den
angezeigten Zeichen schreiben und die Display_shift commands
(Datenblatt) benutzen. Bei sehr langen Strings ist sicherlich ein
bißchen mehr Arbeit nötig, da kann ich Dir aus dem Stehgreif auch
nichts sagen.

Eine andere Möglichkeit für delays sind die Timer, mit denen ich
allerdings noch nicht gearbeitet habe. Hier im Tutorial und in der
Codesammlung gibt's aber Beispiele und Erklärungen dazu.

Viele Grüße

Johannes

von Dennis Brücke (Gast)


Lesenswert?

@Johannes:

Danke Dir trotzdem,
habe jetzt meinen ADIW ZL,1 auf ADIW ZH:ZL,1 erweitert -> funktioniert
das das Z-Registerbetrifft überlege ich grad wie ich diesen
zurücksetze... :(

evtl. PUSH ZH:ZL und am ENDE POP ZH:ZL ?

@Crazy:

Wie kommst Du auf Bascom ? ist doch alles ASM ! ;)

Habe mich genau 10 Minuten mit Bascom beschäftigt...
5 Min zum Installieren 2 Min zum Test und dann 3 Min zum
deinstallieren... lol

Erzeugt mir einfach einen zu großen Code im AVR um genau das
gleiche in Bascom zu machen wie diesen einfach string mit
Tastensteuerung auszugeben benötige ich in Bascom schon fast 450
blöcke... ASM bin ich bei 105...

Muss ja nicht gleich den AVR zuhauen... wer weis, wann ich die routinen
noch mal brauche ;)

Gruß @all von Dennis

P.S.: ist ein Super Forum hier sehr schnelle Antworten, SUPER TEAM ;)
      Auch wenn ich PHPbb vorziehe als Board... ;)

von crazy horse (Gast)


Lesenswert?

stimmt - nimms als black out nach einer langen Nacht :-)

von Johannes Raschke (Gast)


Lesenswert?

Kannst doch einfach

  ldi zh, HIGH(text*2)      ; Z-Pointer init
  ldi zl, low(text*2)

mit in die Schleife schreiben, muß ja zum Testen nicht elegant sein...
Die ZH und ZL müßte man schätzungsweise getrennt pushen bzw.
"poppen".

von Dennis Brücke (Gast)


Lesenswert?

Werd´s gleich mal testen ;)
Danke Dir.

Gruß Dennis

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.