Forum: Mikrocontroller und Digitale Elektronik DOG-M mit ATmega8 in Assembler ansteuern


von Tobi (Gast)


Lesenswert?

Hallo
Ich möchte ein 2-zeiliges DOG-M Display in Assembler ansteuern. Ich 
lasse es im 4 Bit Modus an Port D laufen. Leider geschiet auf dem 
Display garnichts. Das Datenblatt zum Display ist hier: 
http://www.lcd-module.de/deu/pdf/doma/dog-m.pdf und hier ist mein Code:
Wär nett wenn jemand wüsste was ich falsch gemacht hab!!

;+----------------------------------------------------------------------
;| Title           : Ansteuerung für einen DOGM-Textdisplay
;+----------------------------------------------------------------------
;| Funktion        : gibt ;-) auf dem Display aus
;| Schaltung       : DOGM 2x16 an portb im 4 bit Modus (wie LCD-Add-On)
;+----------------------------------------------------------------------
;| Prozessor       : ATmega8
;| Takt            : 3,6864 MHz
;| Sprache         : Assembler
;| Datum           : heute
;| Version         : 1.0
;| Autor           : Tobias Frintz
;+----------------------------------------------------------------------
.include  "AVR.H"
;----------------------------------------------------------------------- 
-
;Reset and Interrupt vector             ;VNr.  Beschreibung
  rjmp  main  ;1   POWER ON RESET
  reti    ;2   Int0-Interrupt
  reti    ;3   Int1-Interrupt
  reti    ;4   TC2 Compare Match
  reti    ;5   TC2 Overflow
  reti    ;6   TC1 Capture
  reti    ;7   TC1 Compare Match A
  reti    ;8   TC1 Compare Match B
  reti    ;9   TC1 Overflow
  reti    ;10  TC0 Overflow
  reti    ;11  SPI, STC Serial Transfer Complete
  reti    ;12  UART Rx Complete
  reti    ;13  UART Data Register Empty
  reti    ;14  UART Tx Complete
  reti    ;15  ADC Conversion Complete
  reti    ;16  EEPROM Ready
  reti    ;17  Analog Comparator
  reti    ;18  TWI (I²C) Serial Interface
  reti    ;19  Store Program Memory Ready
;----------------------------------------------------------------------- 
-
;Start, Power ON, Reset
main:  ldi  r16,lo8(RAMEND)
  out  SPL,r16
  ldi  r16,hi8(RAMEND)
  out  SPH,r16
  rcall  LCD_init
  rcall  LCD_clear
;----------------------------------------------------------------------- 
-
mainloop:  wdr
  rcall  wait5ms
  ldi  r16,'H'
  rcall  LCD_data
  ldi  r16,'y'
  rcall  LCD_data
  ldi  r16,'!'
  rcall  LCD_data
  rcall  LCD_home
  rjmp  mainloop
;----------------------------------------------------------------------- 
-
LCD_data:  ldi  r18,0b00000100
  rjmp  LCD_out
;----------------------------------------------------------------------- 
-
LCD_cmd:  ldi  r18,0b00000000
LCD_out:  mov  r17,r16
  swap  r17
  andi  r16,0b11110000
  or  r16,r18
  andi  r17,0b11110000
  or  r17,r18
  out  PORTD,r16
  rcall  LCD_enable
  rcall  wait5ms
  ret
;----------------------------------------------------------------------- 
-
LCD_enable:  sbi  PORTD,3  ;Enable high
  nop    ;kurtz warten
  nop
  nop
  cbi  PORTD,3  ;Enable low
  ret
;----------------------------------------------------------------------- 
-
LCD_clear:  ldi  r16,0b00000001  ;Display löschen
  rcall  LCD_cmd
  rcall  wait5ms
  ret
;----------------------------------------------------------------------- 
-
LCD_home:  ldi  r16,0b00000010
  rcall  LCD_cmd
  rcall  wait5ms
  ret
;----------------------------------------------------------------------- 
-
LCD_off:  ldi  r16,0b00001000
  rcall  LCD_cmd
  rcall  wait5ms
  ret
;----------------------------------------------------------------------- 
-
LCD_on:  ldi  r16,0b00001110
  rcall  wait5ms
  ret
;----------------------------------------------------------------------- 
-
LCD_line1:  ldi  r16,0b10000000  ;DRAM auf 0x00
  rcall  LCD_cmd
  rcall  wait5ms
  ret
;----------------------------------------------------------------------- 
-
LCD_line2:  ldi  r16,0b11000000  ;DRAM auf 0x40
  rcall  LCD_cmd
  rcall  wait5ms
  ret
;----------------------------------------------------------------------- 
-
wait5ms:  push  r24  ;r24 retten
  push  r25  ;r25 retten
  ldi  r25,50  ;für 1ms = 10
loop1:  ldi  r24,123
loop2:  dec  r24
  brne  loop2  ;Solange nicht NULL
  dec  r25  ;Zähler 2 -1
  brne  loop1  ;Solange nicht NULL
  dec  r16  ;Zähler1 -1
  brne  loop1  ;Solange nicht NULL
  pop  r25  ;r25 wiederherstellen
  pop  r24  ;r24 wiederherstellen
  ret    ;Rücksprung
;----------------------------------------------------------------------- 
-

LCD_init:  sbi  DDRD,1
  sbi  DDRD,2
  sbi  DDRD,3
  sbi  DDRD,4
  sbi  DDRD,5
  sbi  DDRD,6
  sbi  DDRD,7
  cbi  PORTD,2
  ; warten bis Powerup
  ldi  r18,10
powerup:  rcall  wait5ms
  dec  r18
  brne  powerup  ;min. 30 millisec
  ;sende init 1
  ldi  r16,0b00100000
  out  PORTD,r16
  rcall  LCD_enable
  rcall  wait5ms  ;Zeit zum umschalten lassen
  ldi  r16,0b00101001  ;Funktion Set
  rcall  LCD_cmd
  ldi  r16,0b00011100  ;Bias Set
  rcall  LCD_cmd
  ldi  r16,0b01010010  ;Power Control
  rcall  LCD_cmd
  ldi  r16,0b01101001  ;Follower Control
  rcall  LCD_cmd
  ldi  r16,0b01110100  ;Contrast Set
  rcall  LCD_cmd
  ldi  r16,0b00001111  ;Display on
  rcall  LCD_cmd
  ldi  r16,0b00000001  ;Clear Display
  rcall  LCD_cmd
  ldi  r16,0b00000110  ;Entry Mode Set
  rcall  LCD_cmd
  ret
;----------------------------------------------------------------------- 
-

von Uwe N. (ulegan)


Lesenswert?

Dein lcd_cmd solltest du nochmal überdenken. Irgendwie veroderst du da 
die oberen mit den unteren 4 Bit und gibst sie gemeinsam aus. Du 
müsstest im 4-Bit Modus die beiden Teile nacheinander ausgeben, jewils 
mit einem eigenen Enable-Impuls. Zuerst die obere, dann die untere 
Hälfte.
Ungefähr so:
1
LCD_data:  ldi  r18,0b00000100
2
  rjmp  LCD_out
3
;------------------------------------------------------------------------
4
LCD_cmd:  ldi  r18,0b00000000
5
LCD_out:  mov  r17,r16
6
  swap  r17
7
  andi  r16,0b11110000
8
  or  r16,r18
9
  out  PORTD,r16
10
  rcall  LCD_enable
11
12
  andi  r17,0b11110000
13
  or  r17,r18
14
  out  PORTD,r16
15
  rcall  LCD_enable
16
  rcall  wait5ms
17
  ret

von Tobi (Gast)


Lesenswert?

Hi

Danke für die Antwort. hast natürlich recht gehabt (war ein 
abschreibfehler) Das Problem ist nur der Display geht immer noch nicht. 
Ich glaube das in der lcd-init, powerup noch ein Fehler ist.

Tobi

PS: Ich habe die Displaybeleuchtung einmal vor lcd_init angeschalten (im 
main) und einmal dannach. Nur davor gehen die LEDs an, des heißt dass 
programm hängt sich in der init, powerup auf oder? !?

von Uwe N. (ulegan)


Lesenswert?

In wait5ms hat sich ein r16 eingeschlichen, das brauchts nicht. Ich habs 
nicht ausgerechnet, aber diese Routine dürfte mit r16 unerwartet lange 
dauern...
Eigentlich ist das auch die einzige Stelle, wo sich das Programm 
aufhängen kann. Sonst gibts ja keine Schleifen.
1
wait5ms:  push  r24  ;r24 retten
2
  push  r25  ;r25 retten
3
  ldi  r25,50  ;für 1ms = 10
4
loop1:  ldi  r24,123
5
6
loop2:  dec  r24
7
  brne  loop2  ;Solange nicht NULL   etwa (50*(123*3+4))/3686400s =5ms
8
9
  dec  r25  ;Zähler 2 -1
10
  brne  loop1  ;Solange nicht NULL
11
;  dec  r16  ;Zähler1 -1
12
;  brne  loop1  ;Solange nicht NULL
13
  pop  r25  ;r25 wiederherstellen
14
  pop  r24  ;r24 wiederherstellen
15
  ret    ;Rücksprung

Dann fehlt laut Datenblatt hier was:
1
  ldi  r16,0b01110100  ;Contrast Set
2
  rcall  LCD_cmd
3
;<--
4
  ldi  r16,0b00111000  ;Zurück zur Instruction table 0
5
  rcall  LCD_cmd
6
;-->
7
  ldi  r16,0b00001111  ;Display on
8
  rcall  LCD_cmd

Ich hab mich auch verschrieben, beim zweiten out muss es natürlich r17 
heissen.

von Tobi (Gast)


Lesenswert?

>Ich hab mich auch verschrieben, beim zweiten out muss es natürlich r17
>heissen.
hm. des versteh ich jetzt nicht
1. wo ist das zweite out?!?
2. und warum r17 ?!? das Register wird doch nur bei lcd_out benutzt

von Visitor (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Tobi,

ich habe mich für die Initialisierung an dem Datenblattt des 
ST7036-Controllers orientiert (Bsp. S 42)

von Tobi (Gast)


Lesenswert?

>ldi  r16,0b00111000  ;Zurück zur Instruction table 0

Man tut ja Funktionsset 2 mal Senden:

-am Anfang zur einstellung von 4/8Bit, Table, Dotmatrix, Lines usw...
-Was ich nicht versteh beim zweitenmal sendet man es ja nur um zum Table 
1 zu kommen. Muss man dann die anderen vorhergesendeten Einstellungen 
nochmalsenden oder nicht?!?

So?      0b00101000
Oder so? 0b00100000

von Uwe N. (ulegan)


Lesenswert?

>2. und warum r17 ?!? das Register wird doch nur bei lcd_out benutzt

Ich meinte dieses hier:
1
LCD_data:  ldi  r18,0b00000100
2
  rjmp  LCD_out
3
;------------------------------------------------------------------------
4
LCD_cmd:  ldi  r18,0b00000000
5
LCD_out:  mov  r17,r16
6
  swap  r17
7
  andi  r16,0b11110000
8
  or  r16,r18
9
  out  PORTD,r16
10
  rcall  LCD_enable
11
12
  andi  r17,0b11110000
13
  or  r17,r18
14
  out  PORTD,r17    ; hier r17 nicht r16
15
  rcall  LCD_enable
16
  rcall  wait5ms
17
  ret

>ldi  r16,0b00111000  ;Zurück zur Instruction table 0

Das muss wohl nicht unbedingt sein.

Problematisch ist das Umschalten vom 8- in den 4-Bit Modus.
In http://www.lcd-module.de/eng/pdf/zubehoer/st7036.pdf
steht ein Beispiel für 8051

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.