Forum: Mikrocontroller und Digitale Elektronik 4 Bit Initialisierung PIC16F628A


von Tobias S. (tobias-sch)


Angehängte Dateien:

Lesenswert?

Hallo werte Gemeinde,

ich mache schon seit 7 Tagen an meinem Problem herum und es löst sich 
einfach nicht. In der Suchfunktion habe ich leider keinen Quellcode 
gefunden, der so prähistorisch ist wie mein eigener.

Ich habe das Display

ANAG Vision AV 1610

an den PIC 16F628A

angeschlossen wie im Quellcode zu lesen ist. Leider funktioniert die 
Initialisierung aus welchen Gründen auch immer nicht. Die Anschlüsse des 
Displays sind korrekt mit dem PIC verbunden und haben auch Kontakt. Ich 
hab das Ganze auch schon mit dem MPLab Simulator durchgespielt und die 
ausgehenden Signale sollten zur Initialisierungsvorschrift passen.

Lasse ich die Initialisierung durchlaufen, dann stehen danach immer noch 
schwarze Kästchen auf der einen Displayhälfte( obwohl es ja eigentlich 
danach aus sein sollte).
Bei einer busy check Abfrage nach der Initialisierung bleibt es im 
Unterprogramm busy check hängen (habe ich mit Prüf-LED herausgefunden). 
DB7 muss also entweder beim Einlesen dauerhaft auf high sein oder mein 
Unterprogramm busy_check hat einen Fehler.

 Fragen:

Um das busy Flag auszulesen, wie gehe ich da vor?

klar ist mir: R/W auf high, RS auf low

1. Enable? lese ich DB7 aus während enable auf high ist oder nachdem ich 
Enable getoggelt habe?

2. Ich habe längere Pausezeiten zwischen den Initialisierungsschritten, 
ist das erlaubt?

3. Lasse ich die nicht verwendeten Pins am LCD offen oder ziehe sie auf 
Masse?

4. Ist mein Function Set richtig gesetzt? Im Datenblatt zum Anag steht N 
anscheinend nicht für die Anzahl der Displaylines sondern für die 
Auflösung der Zeichen, wofür steht dann F?


Fragen über Fragen :-P
Vielen Dank für Eure Antworten und schöne Weihnachten!

Quellcode
1
;===================================
2
; Portdefinitionen
3
;===================================
4
5
#define Taster_1    PORTA, 0        ;
6
#define Taster_2    PORTA, 1        ;
7
#define LED_1      PORTA, 7        ;
8
#define LCD_E      PORTA, 4        ;
9
#define LCD_RW      PORTA, 3        ;
10
#define LCD_RS      PORTB, 5        ;
11
#define LCD_D4      PORTB, 0        ;
12
#define LCD_D5      PORTB, 1        ;
13
#define LCD_D6      PORTB, 2        ;
14
#define LCD_D7      PORTB, 3        ;
15
16
....
17
....
18
....
19
20
;===================================
21
; Display initialisieren
22
;===================================
23
24
  _wait d'300000'                    ; warte 0,3 s
25
  bcf LCD_RW                        ; 8 Bit Initialisierung
26
  bcf LCD_RS                        ;
27
  bsf LCD_D4                        ;
28
  bsf LCD_D5                        ;
29
  nop                            ;
30
  bsf LCD_E                        ;
31
  nop                            ;
32
  nop                            ;
33
  bcf LCD_E                        ;  
34
  nop
35
  bcf LCD_D4                        ;
36
  bcf LCD_D5                        ;
37
  _wait d'1000'                      ; warte 1 ms
38
  
39
  bsf LCD_D4                        ; 8 Bit Initialisierung
40
  bsf LCD_D5                        ;
41
  nop                            ; 
42
  bsf LCD_E                        ;
43
  nop                            ;
44
  nop                            ;
45
  bcf LCD_E                        ;
46
  nop  
47
  bcf LCD_D4                        ;
48
  bcf LCD_D5                        ;
49
  
50
  _wait d'1000'                      ; warte 1 ms
51
  bsf LCD_D4                        ; 8 Bit Initialisierung
52
  bsf LCD_D5                        ;
53
  nop                            ;
54
  bsf LCD_E                        ;
55
  nop                            ;
56
  nop                            ;
57
  bcf LCD_E                        ;
58
  nop  
59
  bcf LCD_D4                        ;
60
  bcf LCD_D5                        ;
61
  nop
62
  _wait d'1800'                      ; warte 1,8 ms
63
  
64
; 4 Bit Initialisierung
65
  
66
67
  bsf LCD_D5                        ;
68
  nop                            ;
69
  bsf LCD_E                        ;
70
  nop                            ;
71
  nop                            ;
72
  bcf LCD_E                        ;
73
  nop  
74
  bcf LCD_D5                        ;
75
  nop
76
  _wait d'1800'                      ; warte 1,8 ms
77
78
; ab hier muss mit Zerlegung der 8 Bit gearbeitet werden
79
                                ; 
80
  movlw b'00101000'                    ; Function set, 2 zeilig und 5x7
81
  call write_ins                      ;
82
  nop                            ;
83
84
85
  _wait d'1800'                      ; warte 1,8 ms
86
  
87
  movlw b'00001000'                    ; Display aus
88
  call write_ins                      ;
89
  nop                            ;
90
  _wait d'1800'                      ; warte 1,8 ms
91
  
92
  movlw b'00000001'                    ; Display löschen
93
  call write_ins                      ;
94
  nop                            ;
95
  _wait d'1800'                      ; warte 1,8 ms
96
  
97
  
98
  movlw b'00000110'                    ; Entry Mode Set, cursor nach rechts, shift aus
99
  call write_ins                      ;
100
  nop                            ;
101
  _wait d'1800'                      ; warte 1,8 ms
102
  movlw b'00001111'                    ; Display einschalten, Cursor ein und Zeichen blinkt an Cursorstelle
103
  call write_ins                      ;
104
  nop                            ;
105
  
106
  ....
107
  ....
108
  ....
109
110
;================================================================================================
111
; Unterprogramme
112
;================================================================================================
113
114
busy_check
115
  
116
  _BANK_1                          ;
117
  movlw b'00001000'                    ;PortB 3 als Eingang definieren
118
  movwf TRISB                        ;
119
  _BANK_0
120
  bcf LCD_RS                        ; setze LCD_RW und LCD_RS auf low
121
  bsf LCD_RW                        ; um busy flag auszulesen
122
  
123
  loopb
124
    bcf LCD_E    
125
    nop
126
    nop
127
    bsf LCD_E                        ; Enable setzen
128
    btfsc LCD_D7                      ; ist busy Flag nicht gesetzt?
129
    goto loopb                        ; doch, zurück zu loopb
130
    bcf LCD_E                        ; nein, nicht mehr, Enable löschen
131
    _BANK_1                          ;
132
    clrf TRISB                        ;  alle B Ports sind wieder Ausgänge
133
    _BANK_0                          ;
134
    _wait d'21'                        ; warte 21 us
135
  return                            ; zurück ins Programm
136
137
  write_ins
138
    movwf 0x25                        ; Wert in Reg 25 speichern
139
    movwf 0x26                        ; Wert in Reg 26 speichern
140
    swapf 0x25, 0                      ; 4 obere Bits mit 4 unteren vertauschen
141
    andlw b'00001111'                    ; 4 "neue" obere Bits maskieren
142
    movwf PORTB                        ; 4 "alte" obere Bits an PortB ausgeben
143
    bcf LCD_RS                        ; lösche LCD_RS und LCD_RW
144
    bcf LCD_RW                        ; um in die Befehlsübertragung zu gelangen
145
    nop                            ; warte
146
    bsf LCD_E                        ; Übertragung starten
147
    nop                            ;  warte
148
    nop                            ;  warte
149
    bcf LCD_E                        ; Übertragung beenden
150
    nop                            ; warte
151
    _wait d'1800'
152
    movf 0x26, 0                      ; ursprüngliches Byte in W laden
153
    andlw b'00001111'                    ; 4 "alte" obere Bits maskieren
154
    movwf PORTB                        ; 4 "alte" untere Bits an PORTB ausgeben
155
    nop                            ; warte
156
    bsf LCD_E                        ; Übertragung starten
157
    nop                            ;
158
    nop                            ;
159
    bcf LCD_E                        ;
160
    nop                            ;
161
    clrf PORTB                        ; Bits in PORTB löschen
162
    return                          ; zurück ins Hauptprogramm
163
164
  write_data
165
    movwf 0x27                        ; Wert in Reg 27 speichern
166
    movwf 0x28                        ; Wert in Reg 28 speichern
167
    bsf LCD_RS                        ; setze LCD_RS und lösche LCD_RW um in 
168
    bcf LCD_RW                        ; Datenübertragung zu gelangen
169
    swapf 0x27, 0                      ; 4 obere Bits mit 4 unteren vertauschen
170
    andlw b'00001111'                    ; 4 "neue" obere Bits maskieren
171
    iorwf PORTB, 1                      ; 4 "alte" obere Bits an PortB ausgeben
172
    nop                            ; warte
173
    bsf LCD_E                        ; Übertragung starten
174
    nop                            ; warte
175
    bcf LCD_E                        ; warte
176
    nop                            ; warte
177
    
178
    movf 0x28, 0                      ; ursprüngliches Byte wiederherstellen, Byte in W-Register lassen
179
    andlw b'00001111'                    ; 4 "alte" obere Bits maskieren
180
    iorwf PORTB, 1                      ; 4 "alte" untere Bits an PORTB ausgeben
181
    nop                            ; warte
182
    bsf LCD_E                        ; Übertragung starten
183
    nop                            ; warte
184
    nop                            ; warte
185
    bcf LCD_E                        ; Übertragung beenden
186
    nop                            ; warte
187
    clrf PORTB                        ; Bits in PORTB löschen
188
    bcf LCD_RS                        ; lösche LCD_RS  
189
    bcf LCD_RW                        ; und LCD_RW wieder
190
    return                          ; zurück ins Hauptprogramm

von c-hater (Gast)


Lesenswert?

Tobias S. schrieb:

> Um das busy Flag auszulesen, wie gehe ich da vor?
>
> klar ist mir: R/W auf high, RS auf low
>
> 1. Enable? lese ich DB7 aus während enable auf high ist oder nachdem ich
> Enable getoggelt habe?

Während enable auf high ist, aber nicht zu früh, nachdem es auf high 
gegangen ist. Es gibt eine Mindestzeit, die zu warten ist. Nur bei 
hinreichend langsamem Controller und/oder hinreichend ineffizienter 
Sprache/Programmierung darf man diese Zeit ignorieren.

> 2. Ich habe längere Pausezeiten zwischen den Initialisierungsschritten,
> ist das erlaubt?

Ja. Du kannst alles beliebig langsam abfackeln. Sehr praktisch, um 
erstmal die Korrektheit der Ansteuerung und der Verdrahtung zu testen. 
Geht's mit grosszügigen Delays, ist soweit alles in Ordnung, bis auf das 
Timing.

> 3. Lasse ich die nicht verwendeten Pins am LCD offen oder ziehe sie auf
> Masse?

Für die eigentliche Funktion ist das völlig egal. Schlimmstenfalls hast 
du einen geringfügig höheren Stromverbrauch als nötig.

von Tobias S. (tobias-sch)


Lesenswert?

Vielen Dank für die schnelle Antwort!

Jetzt ist nur noch offen, weshalb die Initialisierung offensichtlich 
fehl schlägt :-P

von Stefan (Gast)


Lesenswert?

Versuch doch mal einen Quellcode, der
für einen HD44780 geschrieben ist.
Die beiden Controller sind kompatible.

von Kenner (Gast)


Lesenswert?

Es kann viele Ursachen haben, Da muss man alles nochmal durch-checken.
Versuch ohne busy_check, mit einer warte-pause sollte ea auch gehen.

Das ist ein Beispiel:

-- output low nibble in value to the HD44780
procedure HD44780_IO( byte in value ) is
   hd44780_4_E  = high      -- enable
   hd44780_4_D  = value     -- put value on the data lines
   hd44780_4_E  = low       -- disable
   delay_100uS(2)         -- enough for the simple operations
end procedure

-- output the instruction byte in value to the HD44780
procedure HD44780_instruction( byte in value ) is
   hd44780_4_DI = low       -- select instruction
   HD44780_IO( value >> 4 ) -- output high nibble
--   delay_100uS( 10 )        -- required delay
   HD44780_IO( value )      -- output low nibble
   delay_100uS( 10 )        -- required delay
end procedure

procedure HD44780_setup is
   HD44780_instruction( 0b_0000_1000 ) -- display off
   delay_100uS( 10 )
   HD44780_instruction( 0b_0000_0001 ) -- clear display
   delay_1mS( 2 )
   HD44780_instruction( 0b_0000_0010 ) -- cursor home
   delay_1mS( 2 )
   HD44780_instruction( 0b_0000_0110 ) -- entry, autoincrement, no shift
   delay_100uS( 10 )
   HD44780_instruction( 0b_0000_1100 ) -- display on, cursor off, blink 
off
   delay_100uS( 10 )
end procedure


-- initialisation  for LCD
procedure lcd_init is

 _hd44780_4_init             -- IO pin initialisation for 4 bit

 delay_10mS( 5 )            -- gives the HD44780 time to wake up
 hd44780_4_DI = low          -- select instructions
 HD44780_IO( 0x03 )       -- sync one
 delay_1mS( 5 )            -- extra delay
 HD44780_IO( 0x03 )       -- and one more
 delay_100uS( 5 )            -- extra delay
 HD44780_IO( 0x03 )       -- end yet another
 delay_100uS( 5 )            -- extra delay
 HD44780_IO( 0x02 )       -- init to 4-bit mode
 delay_100uS( 5 )
 HD44780_instruction( 0b_0010_1000 )  -- two lines, 5x7 font
   delay_100uS( 5 )
 HD44780_setup
end procedure

von Tobias S. (tobias-sch)


Lesenswert?

Ohne busy check arbeite ich im Moment auch. Ich bin am überlegen, ob ich 
mit dem Tauschen der oberen mit den unteren Nibbles im 4 Bit-Modus einen 
Fehler mache. Aber soweit ich weiß muss das obere Nibble zuerst 
übertragen werden und da ich die Pins 0 bis 3 von Port B verwende, 
müsste es ja richtig sein, die Nibbles zu vertauschen und dann zuerst 
das higher Nibble an die Ausgänge 0 bis 3 zu legen.

@Stefan:
Sofern ich einen Initialisierungscode in ASM finde, ziehe ich das 
durchaus in Erwägung, da ich am Anfang meiner Programmierfähigkeiten 
bin, kenne ich mich leider nicht mit C aus. Sobald der Display mit 
meinem ASM Code läuft, möchte ich mich aber in C einarbeiten.

von Noch einer (Gast)


Lesenswert?

Pic16 Assembler und HD44780. Da hat wohl jeder von uns die Beispiele von 
Sprut übernommen.

http://www.sprut.de/electronic/pic/programm/lcd.htm

von Stefan (Gast)


Lesenswert?

Dann such doch im Internet danach.
Gibt doch jedemenge Seiten davon.

Hier ein Beispiel: http://www.ekenrooi.net/lcd/lcd2.shtml

von Kenner (Gast)


Lesenswert?

Ja, es ist wichtig wo die daten-lines angeschlossen sind, am oberen 
nibble oder unteren. Die Initialiesirung muss dann entsprechend 
angepasst werden.

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.