Forum: Mikrocontroller und Digitale Elektronik STK500 & LCD was mache ich falsch?


von Andreas Brede (Gast)


Lesenswert?

Hallo Leute,

ich habe mir ein STK500 zugelegt und ein LCD Display daran
angeschlossen Infos zum Display liegen unter
http://www.lcd-module.de/deu/pdf/doma/dip162-d.pdf vor. Ich habe diesen
sourecode benuzt:

;***************************************************************
;Programm LCD.ASM
;Das Programm demonstriert, wie man eine LCD-Anzeige mit
;16 Zeichen x 2 Zeilen an einen AT90S2313 anschliessen
;es wird vorausgesetzt, dass die Anzeige einen HD44780 oder
;kompatiblen Controller verwendet.
;AT90S2313 mit 4 MHz Takt
;***************************************************************

.device  AT90S2313
.include "2313def.inc"      ;muss im selben
          ;Verzeichnis stehen


;Definition der Steuerleitungen
.equ    E  = PD0    ;E an Pin PD0
.equ    RW  = PD1    ;RW an Pin PD1
.equ    RS  = PD2    ;RS an Pin PD2
;.equ    LCD_cntr = PORTD  ;PORTD ist Kontroll-Port
;.equ    LCD_data = PORTB  ;PORTB ist Daten-Port
.equ    BF  = PB7    ;Busy flag


;LCD Befehle
.equ    clear_LCD  = 0b00000001  ;loesche Anzeige
.equ    home_LCD  = 0b00000010  ;return home
.equ    set_LCD    = 0b00111000  ;8 bits,2 Zeilen,5x7dots
.equ    LCD_on    = 0b00001110  ;schalte LCD ein
.equ    entry_mode  = 0b00000110  ;setze Cursor


;Variablendefinition

.def    zeichen  = r0    ;Zeichen aus der Tabelle
.def    buffer  = r16    ;RX/TX Daten von/zu LCD
.def    counter  = r17    ;Zaehler fuer den Text
.def    temp  = r18


.CSEG
.ORG    0x00                ; Programm beginnt bei 0
    rjmp  main    ; Starte Hauptprogramm

;**************************************************************
; Subroutine init
; Initialisiere PORTD
;**************************************************************

init:    ldi     temp,0b11111111  ;PORTD ist Ausgang
    out  DDRD,temp
    cbi  PORTD,E    ;E initialisieren
    cbi  PORTD,RS
    cbi  PORTD,RW
    ret



;***************************************************************
; Subroutine busy_flag
; Diese Routine testet, ob die LCD-Anzeige bereit ist, einen
; neuen Befehl oder weitere Daten zu empfangen.
;***************************************************************

busy_flag:  ldi  temp,0b00000000  ;PORTB ist Eingang
    out  DDRB,temp
                cbi  PORTD,RS  ;Befehl wird gesendet
                sbi  PORTD,RW  ;setze LCD in Lesemodus
                sbi  PORTD,E    ;spreche LCD an
    nop
    nop
                sbic  PINB,BF    ;LCD bereit?
                rjmp  busy_flag       ;nein, wiederhole
                cbi  PORTD,E    ;disable LCD
                ret                     ;LCD bereit


;***************************************************************
; Subroutine write_data
; Diese Routine sendet Daten zur LCD-Anzeige.
; Die Daten muessen im Register buffer uebergeben werden.
;***************************************************************

write_data:  rcall  busy_flag  ;LCD bereit?
                ldi  temp,0b11111111  ;PORTB ist Ausgang
    out  DDRB,temp
                sbi  PORTD,RS  ;Daten werden gesendet
                cbi  PORTD,RW  ;LCD in Schreibmodus
    sbi  PORTD,E    ;spreche LCD an
                out  PORTB,buffer  ;sende Daten
                cbi  PORTD,E    ;disable LCD
                ret


;***************************************************************
; Subroutine write_instr
; Diese Routine sendet Befehle zur LCD-Anzeige.
; Der Befehl muss im Register buffer uebergeben werden.
;***************************************************************

write_instr:  rcall  busy_flag  ;LCD bereit?
                ldi  temp,0b11111111  ;RB ist Ausgang
    out  DDRB,temp
                cbi  PORTD,RS  ;Befehl wird gesendet
                cbi  PORTD,RW  ;LCD in Schreibmodus
    sbi  PORTD,E    ;spreche LCD an
                out  PORTB,buffer  ;sende Befehl
                cbi  PORTD,E    ;disable LCD
                ret


;***************************************************************
; Hauptprogramm
; Schreibt "AT90S2313" in die erste Zeile und "LCD-Routine"
; in die zweite Zeile des LCDs.
;***************************************************************

main:    ldi  temp,RAMEND    ; setze Stack-Pointer
    out  SPL,temp    ; an das SRAM-Ende

    rcall  init      ; PORTD initialisieren

    ldi  buffer,set_LCD    ;setze LCD Funktion
    rcall  write_instr

    ldi  buffer,LCD_on    ;schalte LCD ein
    rcall  write_instr

    ldi  buffer,clear_LCD  ;loesche Anzeige
    rcall  write_instr

    ldi  buffer,entry_mode  ;Eingabemodus
    rcall  write_instr


;Holt den Text 'AT90S2313' aus der Tabelle und schreibt diesen in
;die erste Zeile der Anzeige

    ldi  counter,9    ;Zeichenzaehler
    ldi  ZL,LOW(Tabelle1*2)  ;Low-Zeiger auf Tabellenanfang
    ldi  ZH,HIGH(Tabelle1*2)  ;High-Zeiger auf Tabellenanfang
loop_msg1:  lpm        ;hole Zeichen aus Tabelle
    mov  buffer,zeichen    ;Zeichen uebergeben
    rcall  write_data        ;schreibe Zeichen in LCD
                inc  ZL
    brcc   no_carry1
    inc  ZH
no_carry1:      dec     counter                 ;alle Zeichen
gesendet?
                brne  loop_msg1    ;Nein! Sende naechstes Zeichen

;Holt den Text 'LCD-Routine' aus der Tabelle und schreibt diesen
;in die zweite Zeile der Anzeige

    ldi  buffer,0b11000000  ;LCD-Startadresse 2.Zeile
    rcall  write_instr    ;sende Befehl
    ldi  counter,11    ;Zeichenzaehler
    ldi  ZL,LOW(Tabelle2*2)  ;Low-Zeiger auf Tabellenanfang
    ldi  ZH,HIGH(Tabelle2*2)  ;High-Zeiger auf Tabellenanfang
loop_msg2:  lpm        ;hole Zeichen aus Tabelle
    mov  buffer,zeichen    ;Zeichen uebergeben
    rcall  write_data        ;schreibe Zeichen in LCD
    adiw    ZL,1                    ;16-Bit Zeiger erhoehen
no_carry2:  dec  counter      ;alle Zeichen gesendet?
                brne  loop_msg2    ;Nein! Sende naechstes Zeichen



;Endlosschleife. AVR zuruecksetzen, um Programm erneut zu starten

loop:    rjmp  loop


;Tabelle 1 mit dem Text "AT90S2313", der in die 1.Zeile geschrieben
;werden soll

Tabelle1:  .DB "AT90S2313"


;Tabelle 2 mit dem Text "LCD-Routine", der in die 2.Zeile
geschrieben
;werden soll

Tabelle2:  .DB "LCD-Routine"

Angeschlossen habe ich das ganze wie folgt am STK500

Port D
PD0 = E
PD1 = R/W
PD2 = RS

Port B
PB0 = D0
PB1 = D1
PB2 = D2
PB3 = D3
PB4 = D4
PB5 = D5
PB6 = D6
PB7 = D7
GND = VSS + C
VTG = VDD + (28ohm + A)
An Vee habe ich zusätzlich einen 10kOhm Trimmer zwichen VCC + VSS
geschaltet.

Da ich zum ersten mal mit mikrocontrollern arbeite hab ich wenig
erfahrung damit! Mein Problem ist das ich keine Ausgabe am lcd bekomme.
Bin mir auch nicht sicher ob ich den AT0S2321 überhaupt programiert
habe. Folgendes hatte ich gemacht. Programm AVR-Studio mit Soure code
geöffnet. Im menü STK500 device auf 90S2313 eingestellt programming
Mode Parallel/high volltage serial, hab ihn mit der Hex datei gefüttert
und programm ausgeführt. Zu den Zeitpunkt war folgendes im STK500
gesteckt. brücke von Prog Data auf PortB und von Prog CTRL auf PortD,
ich habe dabei keine Fehler erhalten im Show fenster waren alle
ausgeführten Befehle ok. Ich denke der programm modus sollte so beendet
sein?!? Trozalledem bekomme ich keine Ausgabe!

Ich hoffe das mir jemand dabei helfen kann da es sich ja sicher nur um
eine kleinigkeit handeln müsste denke ich!

Mfg A. brede

von Tobi (Gast)


Lesenswert?

ohne jetzt direkt auf dein problem einzugehen:
warum benutzt du kein isp??
warum versuchst du nicht erstmal die leds am stk500 anzusteuern, dann
kannst du dir auch sicher sein, dass das programmieren und alles klappt

von Rahul (Gast)


Lesenswert?

Auf was taktest du das STK500?
4MHz (laut Programm-Kommentar) werden da schwer realisierbar sein.
Meins kann maximal 3,68MHz.
Naja, dadurch wäre es aber nur langsamer, was dem LCD eigentlich egal
sein sollte.
Tobi hat schon den richtigen Ansatz aufgezeigt:
Lern den Controller und das Board erst mal etwas näher kennen indem du
die vorhandenen LEDs und Taster betust.
Mit der High-Voltage-Programmierung kann man eigentlich nichts falsch
machen, und es gibt auch ein paar Controller, die sich nicht sofort vom
Werk aus per ISP programmieren lassen (meine Erfahrung: ATmega162).
Probier doch einfach mal solche Sachen aus, wie Taster byteweise
einlesen und byteweise auf LEDs ausgeben. Damit kann man immer ganz gut
sehen, ob der Chip richtig funktioniert.
Vielleicht hast du ja auch was bei den Fuses nicht richtig
eingestellt.

Gruß Rahul

von Bernd (Gast)


Lesenswert?

Wenn ich meine Proggis debuge, dann baue ich zum Testen am Ende der
Routine die ich mir vornehme ein bissel Code ein, der eine LED
anschaltet und den Controller stoppt.

So kann man den Code Schrittweise testen und schauen ob es so tut wie
man denkt.

Oder man benutzt den Simulator im AVR Studio. Allerdings mache ich es
mal so und mal so.

Ist eben eine Geschmacksfrage. :-)

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.