Forum: FPGA, VHDL & Co. HD44780 Ansteuerung


von Justus (Gast)


Lesenswert?

Guten Abend zusammen,
ich blicke schon seid ein paar Stunden auf meinen Code aber finde den 
Fehler nicht. Ich möchte ein HD44780 komp. LCD Controller ansteuern. Was 
ich in C schon des öfteren gemacht habe, lässt mich in VHDL irgendwie 
noch etwas stocken. Ich habe das Programm mit ISim simuliert und das 
sieht soweit eigentlich auch gut aus (habe einmal die LCD Init durch 
geschaut). Die Daten werden bei fallender Enable Flanke übernommen. 
Soweit ich mich noch erinnere, ist es ein gutes Zeichen, wenn erst die 
obere Zeile des (2*8) LCD Display geschwärzt ist und nach der Init beide 
Zeilen normal leer sind.

Aber nun genug der Worte, hier mein Code(abschnitt):
1
case LCD_STATE is
2
      
3
        when POWER_UP =>  ----------------------------------------------
4
                    -- 20ms abwarten (Displayreset)
5
                    
6
                    if (CLK_COUNT < (20000*FREQ)) then
7
                      CLK_COUNT := CLK_COUNT + 1;
8
                      LCD_STATE <= POWER_UP;
9
                    else
10
                      CLK_COUNT := 0;
11
                      LCD_RS <= '0';
12
                      LCD_RW <= '0';
13
                      LCD_STATE <= INIT;
14
                    end if;
15
        
16
        when INIT =>    ----------------------------------------------
17
                    -- Durchlaufen der Initialisierungssequenze
18
                    
19
                    CLK_COUNT := CLK_COUNT + 1;
20
                    
21
                    ----------------------------------------------
22
                    -- Interface auf 8 Bit setzten #1
23
                    
24
                    -- Zu Beginn 5ms warten
25
                    if (CLK_COUNT < (5000*FREQ)) then
26
                      LCD_DATA <= "0011";
27
                      LCD_E <= '1';
28
                      LCD_STATE <= INIT;
29
                      
30
                    -- weitere 50µs warten (fallende Flanke)
31
                    elsif (CLK_COUNT < (5050*FREQ)) then
32
                      LCD_E <= '0';
33
                      LCD_STATE <= INIT;
34
                    
35
                    ----------------------------------------------
36
                    -- Interface auf 8 Bit setzten #2
37
                    
38
                    -- weitere 5ms warten
39
                    elsif (CLK_COUNT < (10050*FREQ)) then
40
                      LCD_DATA <= "0011";
41
                      LCD_E <= '1';
42
                      LCD_STATE <= INIT;
43
                      
44
                    -- weitere 50µs warten (fallende Flanke)
45
                    elsif (CLK_COUNT < (10100*FREQ)) then
46
                      LCD_E <= '0';
47
                      LCD_STATE <= INIT;
48
49
                    ----------------------------------------------
50
                    -- Interface auf 8 Bit setzten #3
51
                    
52
                    -- weitere 100µs warten
53
                    elsif (CLK_COUNT < (10200*FREQ)) then
54
                      LCD_DATA <= "0011";
55
                      LCD_E <= '1';
56
                      LCD_STATE <= INIT;
57
                      
58
                    -- weitere 50µs warten (fallende Flanke)
59
                    elsif (CLK_COUNT < (10250*FREQ)) then
60
                      LCD_E <= '0';
61
                      LCD_STATE <= INIT;  
62
63
                    ----------------------------------------------
64
                    -- Interface auf 4 Bit setzten
65
66
                    -- weitere 100µs warten
67
                    elsif (CLK_COUNT < (10350*FREQ)) then
68
                      LCD_DATA <= "0010";
69
                      LCD_E <= '1';
70
                      LCD_STATE <= INIT;
71
                      
72
                    -- weitere 50µs warten (LCD_E wieder löschen)
73
                    elsif (CLK_COUNT < (10400*FREQ)) then
74
                      LCD_E <= '0';
75
                      LCD_STATE <= INIT;
76
                      
77
                    ----------------------------------------------
78
                    -- Function set: 2 Zeilig, 5*8 Punkt Matrix
79
80
                    -- weitere 100µs warten
81
                    elsif (CLK_COUNT < (10500*FREQ)) then
82
                      LCD_DATA <= "0010";
83
                      LCD_E <= '1';
84
                      LCD_STATE <= INIT;
85
                      
86
                    -- weitere 50µs warten (LCD_E wieder löschen)
87
                    elsif (CLK_COUNT < (10550*FREQ)) then
88
                      LCD_E <= '0';
89
                      LCD_STATE <= INIT;
90
                      
91
                    -- weitere 100µs warten
92
                    elsif (CLK_COUNT < (10650*FREQ)) then
93
                      LCD_DATA <= "1000";
94
                      LCD_E <= '1';
95
                      LCD_STATE <= INIT;
96
                      
97
                    -- weitere 50µs warten (fallende Flanke)
98
                    elsif (CLK_COUNT < (10700*FREQ)) then
99
                      LCD_E <= '0';
100
                      LCD_STATE <= INIT;
101
                    
102
                    ----------------------------------------------
103
                    -- Display ausschalten
104
                    
105
                    -- weitere 100µs warten
106
                    elsif (CLK_COUNT < (10800*FREQ)) then
107
                      LCD_DATA <= "0000";
108
                      LCD_E <= '1';
109
                      LCD_STATE <= INIT;
110
                      
111
                    -- weitere 50µs warten (fallende Flanke)
112
                    elsif (CLK_COUNT < (10850*FREQ)) then
113
                      LCD_E <= '0';
114
                      LCD_STATE <= INIT;
115
                      
116
                    -- weitere 100µs warten
117
                    elsif (CLK_COUNT < (10950*FREQ)) then
118
                      LCD_DATA <= "1000";
119
                      LCD_E <= '1';
120
                      LCD_STATE <= INIT;
121
                      
122
                    -- weitere 50µs warten (fallende Flanke)
123
                    elsif (CLK_COUNT < (11000*FREQ)) then
124
                      LCD_E <= '0';
125
                      LCD_STATE <= INIT;
126
                    
127
                    ----------------------------------------------
128
                    -- Displayinhalt löschen
129
                    
130
                    -- weitere 100µs warten
131
                    elsif (CLK_COUNT < (11100*FREQ)) then
132
                      LCD_DATA <= "0000";
133
                      LCD_E <= '1';
134
                      LCD_STATE <= INIT;
135
                      
136
                    -- weitere 50µs warten (fallende Flanke)
137
                    elsif (CLK_COUNT < (11150*FREQ)) then
138
                      LCD_E <= '0';
139
                      LCD_STATE <= INIT;
140
                      
141
                    -- weitere 100µs warten
142
                    elsif (CLK_COUNT < (11250*FREQ)) then
143
                      LCD_DATA <= "0001";
144
                      LCD_E <= '1';
145
                      LCD_STATE <= INIT;
146
                      
147
                    -- weitere 50µs warten (fallende Flanke)
148
                    elsif (CLK_COUNT < (11300*FREQ)) then
149
                      LCD_E <= '0';
150
                      LCD_STATE <= INIT;
151
                    
152
                    ----------------------------------------------
153
                    -- Kursor nach rechts wandernd, kein Displayshift
154
                    
155
                    -- weitere 100µs warten
156
                    elsif (CLK_COUNT < (11400*FREQ)) then
157
                      LCD_DATA <= "0000";
158
                      LCD_E <= '1';
159
                      LCD_STATE <= INIT;
160
                      
161
                    -- weitere 50µs warten (fallende Flanke)
162
                    elsif (CLK_COUNT < (11450*FREQ)) then
163
                      LCD_E <= '0';
164
                      LCD_STATE <= INIT;
165
                      
166
                    -- weitere 100µs warten
167
                    elsif (CLK_COUNT < (11550*FREQ)) then
168
                      LCD_DATA <= "0110";
169
                      LCD_E <= '1';
170
                      LCD_STATE <= INIT;
171
                      
172
                    -- weitere 50µs warten (fallende Flanke)
173
                    elsif (CLK_COUNT < (11600*FREQ)) then
174
                      LCD_E <= '0';
175
                      LCD_STATE <= INIT;
176
                    
177
                    ----------------------------------------------
178
                    -- Display anschalten
179
                    
180
                    -- weitere 100µs warten
181
                    elsif (CLK_COUNT < (11700*FREQ)) then
182
                      LCD_DATA <= "0000";
183
                      LCD_E <= '1';
184
                      LCD_STATE <= INIT;
185
                      
186
                    -- weitere 50µs warten (fallende Flanke)
187
                    elsif (CLK_COUNT < (11750*FREQ)) then
188
                      LCD_E <= '0';
189
                      LCD_STATE <= INIT;
190
                      
191
                    -- weitere 100µs warten
192
                    elsif (CLK_COUNT < (11850*FREQ)) then
193
                      LCD_DATA <= "1111";
194
                      LCD_E <= '1';
195
                      LCD_STATE <= INIT;
196
                      
197
                    -- weitere 50µs warten (fallende Flanke)
198
                    elsif (CLK_COUNT < (11900*FREQ)) then
199
                      LCD_E <= '0';
200
                      LCD_STATE <= INIT;
201
                    
202
                    ----------------------------------------------
203
          
204
                    else
205
                      CLK_COUNT := 0;
206
                      LCD_STATE <= IDLE;
207
                    end if;
208
                    
209
                    -- Initialisierung abgeschlossen
210
                    ----------------------------------------------
211
                    
212
        when LCD_WAIT =>  ----------------------------------------------
213
                    -- Warteschleife für 2ms (längster Befehl)
214
            
215
                    CLK_COUNT := CLK_COUNT + 1;
216
                    LCD_BUSY <= '1';
217
                    if (CLK_COUNT > (2100*FREQ)) then
218
                      LCD_STATE <= IDLE;
219
                    end if;
220
        
221
        when SEND =>    ----------------------------------------------
222
                    -- Enable Strobbe ausführen T=50µs + 50µs idle
223
                    
224
                    CLK_COUNT := CLK_COUNT + 1;
225
                    LCD_E <= '1';
226
                    LCD_BUSY <= '1';                    
227
                    if(CLK_COUNT > (50*FREQ)) then
228
                      LCD_E <= '0';
229
                    elsif (CLK_COUNT > (100*FREQ)) then
230
                      LCD_STATE <= LCD_WAIT;
231
                    end if;
232
            
233
        when IDLE =>    CLK_COUNT := 0;
234
                    LCD_BUSY <= '0';
235
                    LCD_STATE <= IDLE;
236
      
237
      end case;

Ich würde mich sehr freuen, wenn man jemand mit geübtem Auge einen Blick 
auf meinen Code werfen würde und bitte nicht zu kritisch, dass ist erst 
mein 3. Programm mit VHDL..

Viele Grüße

von Justus (Gast)


Lesenswert?

Was ich noch sagen wollte: Ich würde erwarten, dass nach der Init der 
Cursor als Block blinkend zu sehen ist, doch das Display bleibt einfach 
leer.

von Justus (Gast)


Lesenswert?

Das gibts doch nicht. Da schreibe ich diesen Beitrag hier und finde 
direkt danach den Fehler:

Ich habe dem Controller zu wenig Zeit zum Display Löschen Befehl 
spendiert!

Trotzdem vielen Dank :-)

von Duke Scarring (Gast)


Lesenswert?

Das ist wie beim Frisör. Einfach mal drüber reden hilft schon. :-)

Ansonsten ist eine HD44780-Ansteuerung in VHDL m.E. nicht wirklich 
elegant zu machen.

Bei mir sind es dann zwei FSM geworden. Eine State-Machine ist für den 
Low-Level-Zugriff (RESET1..3, SET_4BIT_MODE, LCD_COMMAND, LCD_DATA, 
LCD_CLEAR, LCD_HOME, READY).

Die zweite wartet jeweils, bis die erste READY ist und schaltet nach 
Bedarf in die benötigten States.

Alles in allem ist eine HD44780-Ansteuerung nicht unbedingt als Einstieg 
für den genneigten Anfänger zu empfehlen.

Duke

von Duke Scarring (Gast)


Lesenswert?

P.S.: Das nächte Mal bitte den vollständigen Code (mit Testbench!) in 
den Anhang. Dann können auch andere Deine Simulation nachvollziehen.

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.