1 | // Ansteuerung eines HD44780 kompatiblen LCD im 4-Bit-Interfacemodus
|
2 | // http://www.mikrocontroller.net/articles/HD44780
|
3 | // http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/LCD-Ansteuerung
|
4 | //
|
5 | // Die Pinbelegung ist über defines in lcd-routines.h einstellbar
|
6 |
|
7 | #include <avr/io.h>
|
8 | #include "lcd-routines.h"
|
9 | #include <util/delay.h>
|
10 |
|
11 | ////////////////////////////////////////////////////////////////////////////////
|
12 | // Erzeugt einen Enable-Puls
|
13 | static void lcd_enable( void )
|
14 | {
|
15 | LCD_PORT |= (1<<LCD_EN); // Enable auf 1 setzen
|
16 | _delay_us( LCD_ENABLE_US ); // kurze Pause
|
17 | LCD_PORT &= ~(1<<LCD_EN); // Enable auf 0 setzen
|
18 | }
|
19 |
|
20 | ////////////////////////////////////////////////////////////////////////////////
|
21 | // Sendet eine 4-bit Ausgabeoperation an das LCD
|
22 | static void lcd_out( uint8_t data )
|
23 | {
|
24 | data &= 0xF0; // obere 4 Bit maskieren
|
25 |
|
26 | LCD_PORT &= ~(0xF0>>(4-LCD_DB)); // Maske löschen
|
27 | LCD_PORT |= (data>>(4-LCD_DB)); // Bits setzen
|
28 | lcd_enable();
|
29 | }
|
30 |
|
31 | ////////////////////////////////////////////////////////////////////////////////
|
32 | // Initialisierung: muss ganz am Anfang des Programms aufgerufen werden.
|
33 | void lcd_init( void )
|
34 | {
|
35 | // verwendete Pins auf Ausgang schalten
|
36 | uint8_t pins = (0x0F << LCD_DB) | // 4 Datenleitungen
|
37 | (1<<LCD_RS) | // R/S Leitung
|
38 | (1<<LCD_EN); // Enable Leitung
|
39 | LCD_DDR |= pins;
|
40 |
|
41 | // initial alle Ausgänge auf Null
|
42 |
|
43 | LCD_PORT &= ~pins;
|
44 |
|
45 | // warten auf die Bereitschaft des LCD
|
46 | _delay_ms( LCD_BOOTUP_MS );
|
47 |
|
48 | // Soft-Reset muss 3mal hintereinander gesendet werden zur Initialisierung
|
49 | lcd_out( LCD_SOFT_RESET );
|
50 | _delay_ms( LCD_SOFT_RESET_MS1 );
|
51 |
|
52 | lcd_enable();
|
53 | _delay_ms( LCD_SOFT_RESET_MS2 );
|
54 |
|
55 | lcd_enable();
|
56 | _delay_ms( LCD_SOFT_RESET_MS3 );
|
57 |
|
58 | // 4-bit Modus aktivieren
|
59 | lcd_out( LCD_SET_FUNCTION |
|
60 | LCD_FUNCTION_4BIT );
|
61 | _delay_ms( LCD_SET_4BITMODE_MS );
|
62 |
|
63 | // 4-bit Modus / 2 Zeilen / 5x7
|
64 | lcd_command( LCD_SET_FUNCTION |
|
65 | LCD_FUNCTION_4BIT |
|
66 | LCD_FUNCTION_2LINE |
|
67 | LCD_FUNCTION_5X7 );
|
68 |
|
69 | // Display ein / Cursor aus / Blinken aus
|
70 | lcd_command( LCD_SET_DISPLAY |
|
71 | LCD_DISPLAY_ON |
|
72 | LCD_CURSOR_OFF |
|
73 | LCD_BLINKING_OFF);
|
74 |
|
75 | // Cursor inkrement / kein Scrollen
|
76 | lcd_command( LCD_SET_ENTRY |
|
77 | LCD_ENTRY_INCREASE |
|
78 | LCD_ENTRY_NOSHIFT );
|
79 |
|
80 | lcd_clear();
|
81 | }
|
82 |
|
83 | ////////////////////////////////////////////////////////////////////////////////
|
84 | // Sendet ein Datenbyte an das LCD
|
85 | void lcd_data( uint8_t data )
|
86 | {
|
87 | LCD_PORT |= (1<<LCD_RS); // RS auf 1 setzen
|
88 |
|
89 | lcd_out( data ); // zuerst die oberen,
|
90 | lcd_out( data<<4 ); // dann die unteren 4 Bit senden
|
91 |
|
92 | _delay_us( LCD_WRITEDATA_US );
|
93 | }
|
94 |
|
95 | ////////////////////////////////////////////////////////////////////////////////
|
96 | ///Funktion für Umlaute
|
97 | void lcd_char( char c )
|
98 | {
|
99 | switch(c)
|
100 | {
|
101 | case 'ä' : c = 0xE1; break;
|
102 | case 'ö' : c = 0xEF; break;
|
103 | case 'ü' : c = 0xF5; break;
|
104 | case 'ß' : c = 0xE2; break;
|
105 | case '°' : c = 0xDF; break;
|
106 | case 'µ' : c = 0xE4; break;
|
107 | }
|
108 | }
|
109 | ////////////////////////////////////////////////////////////////////////////////
|
110 | // Sendet einen Befehl an das LCD
|
111 | void lcd_command( uint8_t data )
|
112 | {
|
113 | LCD_PORT &= ~(1<<LCD_RS); // RS auf 0 setzen
|
114 |
|
115 | lcd_out( data ); // zuerst die oberen,
|
116 | lcd_out( data<<4 ); // dann die unteren 4 Bit senden
|
117 |
|
118 | _delay_us( LCD_COMMAND_US );
|
119 | }
|
120 |
|
121 | ////////////////////////////////////////////////////////////////////////////////
|
122 | // Sendet den Befehl zur Löschung des Displays
|
123 | void lcd_clear( void )
|
124 | {
|
125 | lcd_command( LCD_CLEAR_DISPLAY );
|
126 | _delay_ms( LCD_CLEAR_DISPLAY_MS );
|
127 | }
|
128 |
|
129 | ////////////////////////////////////////////////////////////////////////////////
|
130 | // Sendet den Befehl: Cursor Home
|
131 | void lcd_home( void )
|
132 | {
|
133 | lcd_command( LCD_CURSOR_HOME );
|
134 | _delay_ms( LCD_CURSOR_HOME_MS );
|
135 | }
|
136 |
|
137 | ////////////////////////////////////////////////////////////////////////////////
|
138 | // Setzt den Cursor in Spalte x (0..15) Zeile y (1..4)
|
139 |
|
140 | void lcd_setcursor( uint8_t x, uint8_t y )
|
141 | {
|
142 | uint8_t data;
|
143 |
|
144 | switch (y)
|
145 | {
|
146 | case 1: // 1. Zeile
|
147 | data = LCD_SET_DDADR + LCD_DDADR_LINE1 + x;
|
148 | break;
|
149 |
|
150 | case 2: // 2. Zeile
|
151 | data = LCD_SET_DDADR + LCD_DDADR_LINE2 + x;
|
152 | break;
|
153 |
|
154 | case 3: // 3. Zeile
|
155 | data = LCD_SET_DDADR + LCD_DDADR_LINE3 + x;
|
156 | break;
|
157 |
|
158 | case 4: // 4. Zeile
|
159 | data = LCD_SET_DDADR + LCD_DDADR_LINE4 + x;
|
160 | break;
|
161 |
|
162 | default:
|
163 | return; // für den Fall einer falschen Zeile
|
164 | }
|
165 |
|
166 | lcd_command( data );
|
167 | }
|
168 |
|
169 | ////////////////////////////////////////////////////////////////////////////////
|
170 | // Schreibt einen String auf das LCD
|
171 |
|
172 | void lcd_string( const char *data )
|
173 | {
|
174 | while( *data != '\0' )
|
175 | lcd_data( *data++ );
|
176 | }
|
177 |
|
178 | ////////////////////////////////////////////////////////////////////////////////
|
179 | // Schreibt ein Zeichen in den Character Generator RAM
|
180 |
|
181 | void lcd_generatechar( uint8_t code, const uint8_t *data )
|
182 | {
|
183 | // Startposition des Zeichens einstellen
|
184 | lcd_command( LCD_SET_CGADR | (code<<3) );
|
185 |
|
186 | // Bitmuster übertragen
|
187 | for ( uint8_t i=0; i<8; i++ )
|
188 | {
|
189 | lcd_data( data[i] );
|
190 | }
|
191 | }
|