1 | #include <avr/io.h>
|
2 | #define F_CPU 3686400UL
|
3 | #include <util/delay.h>
|
4 |
|
5 |
|
6 | #define LCD_RS PC0
|
7 | #define LCD_RW PC1
|
8 | #define LCD_EN PC2
|
9 | #define LCD_DATAPORT PORTD
|
10 | #define LCD_CTRLPORT PORTC
|
11 | #define LCD_DATADIR DDRD
|
12 | #define LCD_CTRLDIR DDRC
|
13 |
|
14 |
|
15 |
|
16 | ////////////////////////////////////////////////////////////////////////////////
|
17 | // LCD Ausführungszeiten (MS=Millisekunden, US=Mikrosekunden)
|
18 |
|
19 | #define LCD_BOOTUP_MS 15
|
20 | #define LCD_ENABLE_US 1
|
21 | #define LCD_WRITEDATA_US 46
|
22 | #define LCD_COMMAND_US 42
|
23 |
|
24 | #define LCD_SOFT_RESET_MS1 5
|
25 | #define LCD_SOFT_RESET_MS2 1
|
26 | #define LCD_SOFT_RESET_MS3 1
|
27 | #define LCD_SET_4BITMODE_MS 5
|
28 |
|
29 | #define LCD_CLEAR_DISPLAY_MS 2
|
30 | #define LCD_CURSOR_HOME_MS 2
|
31 |
|
32 | ////////////////////////////////////////////////////////////////////////////////
|
33 | // Zeilendefinitionen des verwendeten LCD
|
34 | // Die Einträge hier sollten für ein LCD mit einer Zeilenlänge von 16 Zeichen passen
|
35 | // Bei anderen Zeilenlängen müssen diese Einträge angepasst werden
|
36 |
|
37 | #define LCD_DDADR_LINE1 0x00
|
38 | #define LCD_DDADR_LINE2 0x40
|
39 | #define LCD_DDADR_LINE3 0x10
|
40 | #define LCD_DDADR_LINE4 0x50
|
41 |
|
42 | ////////////////////////////////////////////////////////////////////////////////
|
43 | // LCD Befehle und Argumente.
|
44 | // Zur Verwendung in lcd_command
|
45 |
|
46 | // Clear Display -------------- 0b00000001
|
47 | #define LCD_CLEAR_DISPLAY 0x01
|
48 |
|
49 | // Cursor Home ---------------- 0b0000001x
|
50 | #define LCD_CURSOR_HOME 0x02
|
51 |
|
52 | // Set Entry Mode ------------- 0b000001xx
|
53 | #define LCD_SET_ENTRY 0x04
|
54 |
|
55 | #define LCD_ENTRY_DECREASE 0x00
|
56 | #define LCD_ENTRY_INCREASE 0x02
|
57 | #define LCD_ENTRY_NOSHIFT 0x00
|
58 | #define LCD_ENTRY_SHIFT 0x01
|
59 |
|
60 | // Set Display ---------------- 0b00001xxx
|
61 | #define LCD_SET_DISPLAY 0x08
|
62 |
|
63 | #define LCD_DISPLAY_OFF 0x00
|
64 | #define LCD_DISPLAY_ON 0x04
|
65 | #define LCD_CURSOR_OFF 0x00
|
66 | #define LCD_CURSOR_ON 0x02
|
67 | #define LCD_BLINKING_OFF 0x00
|
68 | #define LCD_BLINKING_ON 0x01
|
69 |
|
70 | // Set Shift ------------------ 0b0001xxxx
|
71 | #define LCD_SET_SHIFT 0x10
|
72 |
|
73 | #define LCD_CURSOR_MOVE 0x00
|
74 | #define LCD_DISPLAY_SHIFT 0x08
|
75 | #define LCD_SHIFT_LEFT 0x00
|
76 | #define LCD_SHIFT_RIGHT 0x04
|
77 |
|
78 | // Set Function --------------- 0b001xxxxx
|
79 | #define LCD_SET_FUNCTION 0x20
|
80 |
|
81 | #define LCD_FUNCTION_4BIT 0x00
|
82 | #define LCD_FUNCTION_8BIT 0x10
|
83 | #define LCD_FUNCTION_1LINE 0x00
|
84 | #define LCD_FUNCTION_2LINE 0x08
|
85 | #define LCD_FUNCTION_5X7 0x00
|
86 | #define LCD_FUNCTION_5X10 0x04
|
87 |
|
88 | #define LCD_SOFT_RESET 0x30
|
89 |
|
90 | // Set CG RAM Address --------- 0b01xxxxxx (Character Generator RAM)
|
91 | #define LCD_SET_CGADR 0x40
|
92 |
|
93 | #define LCD_GC_CHAR0 0
|
94 | #define LCD_GC_CHAR1 1
|
95 | #define LCD_GC_CHAR2 2
|
96 | #define LCD_GC_CHAR3 3
|
97 | #define LCD_GC_CHAR4 4
|
98 | #define LCD_GC_CHAR5 5
|
99 | #define LCD_GC_CHAR6 6
|
100 | #define LCD_GC_CHAR7 7
|
101 |
|
102 | // Set DD RAM Address --------- 0b1xxxxxxx (Display Data RAM)
|
103 | #define LCD_SET_DDADR 0x80
|
104 |
|
105 | ////////////////////////////////////////////////////////////////////////////////
|
106 | // Initialisierung: muss ganz am Anfang des Programms aufgerufen werden.
|
107 | void lcd_init( void );
|
108 |
|
109 | ////////////////////////////////////////////////////////////////////////////////
|
110 | // LCD löschen
|
111 | void lcd_clear( void );
|
112 |
|
113 | ////////////////////////////////////////////////////////////////////////////////
|
114 | // Cursor in die 1. Zeile, 0-te Spalte
|
115 | void lcd_home( void );
|
116 |
|
117 | ////////////////////////////////////////////////////////////////////////////////
|
118 | // Cursor an eine beliebige Position
|
119 | void lcd_setcursor( unsigned char spalte, unsigned char zeile );
|
120 |
|
121 | ////////////////////////////////////////////////////////////////////////////////
|
122 | // Ausgabe eines einzelnen Zeichens an der aktuellen Cursorposition
|
123 | void lcd_data( unsigned char data );
|
124 |
|
125 | ////////////////////////////////////////////////////////////////////////////////
|
126 | // Ausgabe eines Strings an der aktuellen Cursorposition
|
127 | void lcd_string( const char *data );
|
128 |
|
129 | ////////////////////////////////////////////////////////////////////////////////
|
130 | // Ausgabe eines Kommandos an das LCD.
|
131 | void lcd_command( unsigned char data );
|
132 |
|
133 | ////////////////////////////////////////////////////////////////////////////////
|
134 | // Erzeugt einen Enable-Puls
|
135 | static void lcd_enable( void )
|
136 | {
|
137 | LCD_CTRLPORT |= (1<<LCD_EN); // Enable auf 1 setzen
|
138 | _delay_us( LCD_ENABLE_US ); // kurze Pause
|
139 | LCD_CTRLPORT &= ~(1<<LCD_EN); // Enable auf 0 setzen
|
140 | }
|
141 |
|
142 | ////////////////////////////////////////////////////////////////////////////////
|
143 | // Sendet eine 8-bit Ausgabeoperation an das LCD
|
144 | static void lcd_out8( unsigned char data )
|
145 | {
|
146 | LCD_DATAPORT = data;
|
147 | lcd_enable();
|
148 | }
|
149 |
|
150 | ////////////////////////////////////////////////////////////////////////////////
|
151 | // Initialisierung: muss ganz am Anfang des Programms aufgerufen werden.
|
152 | void lcd_init( void )
|
153 | {
|
154 | // verwendete Pins auf Ausgang schalten
|
155 | unsigned char pins = (1<<LCD_RW) | // R/W Leitung
|
156 | (1<<LCD_RS) | // R/S Leitung
|
157 | (1<<LCD_EN); // Enable Leitung
|
158 |
|
159 |
|
160 | LCD_CTRLDIR |= pins;
|
161 | LCD_CTRLPORT &= ~pins;
|
162 | LCD_DATADIR |= 0xFF;
|
163 | LCD_DATAPORT &= ~0xFF;
|
164 |
|
165 |
|
166 | // warten auf die Bereitschaft des LCD
|
167 | _delay_ms( LCD_BOOTUP_MS );
|
168 |
|
169 | // Soft-Reset muss 3mal hintereinander gesendet werden
|
170 | // zur Initialisierung
|
171 | lcd_out8( LCD_SOFT_RESET );
|
172 | _delay_ms( LCD_SOFT_RESET_MS1 );
|
173 |
|
174 | lcd_enable();
|
175 | _delay_ms( LCD_SOFT_RESET_MS2 );
|
176 |
|
177 | lcd_enable();
|
178 | _delay_ms( LCD_SOFT_RESET_MS3 );
|
179 |
|
180 | // 8-bit Modus / 2 Zeilen / 5x7
|
181 | lcd_command( LCD_SET_FUNCTION |
|
182 | LCD_FUNCTION_8BIT |
|
183 | LCD_FUNCTION_2LINE |
|
184 | LCD_FUNCTION_5X7 );
|
185 |
|
186 | // Display ein / Cursor aus / Blinken aus
|
187 | lcd_command( LCD_SET_DISPLAY |
|
188 | LCD_DISPLAY_ON |
|
189 | LCD_CURSOR_OFF |
|
190 | LCD_BLINKING_OFF);
|
191 |
|
192 | // Cursor inkrement / kein Scrollen
|
193 | lcd_command( LCD_SET_ENTRY |
|
194 | LCD_ENTRY_INCREASE |
|
195 | LCD_ENTRY_NOSHIFT );
|
196 |
|
197 | lcd_clear();
|
198 | }
|
199 |
|
200 | ////////////////////////////////////////////////////////////////////////////////
|
201 | // Sendet ein Datenbyte an das LCD
|
202 | void lcd_data( unsigned char data )
|
203 | {
|
204 |
|
205 | LCD_CTRLPORT |= (1<<LCD_RS); // RS auf 1 setzen
|
206 |
|
207 |
|
208 | lcd_out8( data );
|
209 | _delay_us( LCD_WRITEDATA_US );
|
210 | }
|
211 |
|
212 | ////////////////////////////////////////////////////////////////////////////////
|
213 | // Sendet einen Befehl an das LCD
|
214 | void lcd_command( unsigned char data )
|
215 | {
|
216 |
|
217 | LCD_CTRLPORT &= ~(1<<LCD_RS); // RS auf 0 setzen
|
218 |
|
219 | lcd_out8( data );
|
220 | _delay_us( LCD_COMMAND_US );
|
221 | }
|
222 |
|
223 | ////////////////////////////////////////////////////////////////////////////////
|
224 | // Sendet den Befehl zur Löschung des Displays
|
225 | void lcd_clear( void )
|
226 | {
|
227 | lcd_command( LCD_CLEAR_DISPLAY );
|
228 | _delay_ms( LCD_CLEAR_DISPLAY_MS );
|
229 | }
|
230 |
|
231 | ////////////////////////////////////////////////////////////////////////////////
|
232 | // Sendet den Befehl: Cursor Home
|
233 | void lcd_home( void )
|
234 | {
|
235 | lcd_command( LCD_CURSOR_HOME );
|
236 | _delay_ms( LCD_CURSOR_HOME_MS );
|
237 | }
|
238 |
|
239 | ////////////////////////////////////////////////////////////////////////////////
|
240 | // Setzt den Cursor in Spalte x (0..15) Zeile y (1..4)
|
241 |
|
242 | void lcd_setcursor( unsigned char x, unsigned char y )
|
243 | {
|
244 | unsigned char data;
|
245 |
|
246 | switch (y)
|
247 | {
|
248 | case 1: // 1. Zeile
|
249 | data = LCD_SET_DDADR + LCD_DDADR_LINE1 + x;
|
250 | break;
|
251 |
|
252 | case 2: // 2. Zeile
|
253 | data = LCD_SET_DDADR + LCD_DDADR_LINE2 + x;
|
254 | break;
|
255 |
|
256 | case 3: // 3. Zeile
|
257 | data = LCD_SET_DDADR + LCD_DDADR_LINE3 + x;
|
258 | break;
|
259 |
|
260 | case 4: // 4. Zeile
|
261 | data = LCD_SET_DDADR + LCD_DDADR_LINE4 + x;
|
262 | break;
|
263 |
|
264 | default:
|
265 | return; // für den Fall einer falschen Zeile
|
266 | }
|
267 |
|
268 | lcd_command( data );
|
269 | }
|
270 |
|
271 | ////////////////////////////////////////////////////////////////////////////////
|
272 | // Schreibt einen String auf das LCD
|
273 |
|
274 | void lcd_string( const char *data )
|
275 | {
|
276 | while( *data != '\0' )
|
277 | lcd_data( *data++ );
|
278 | }
|
279 |
|
280 | ////////////////////////////////////////////////////////////////////////////////
|
281 | // MAIN
|
282 | void main(void)
|
283 | {
|
284 | lcd_init();
|
285 |
|
286 | lcd_setcursor(0,1);
|
287 | lcd_string("Hallo");
|
288 | lcd_setcursor(0,2);
|
289 | lcd_string("Forum");
|
290 |
|
291 |
|
292 | while (1)
|
293 | {
|
294 |
|
295 | }
|
296 | }
|