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 | LCD_PORT &= ~pins;
|
43 |
|
44 | // warten auf die Bereitschaft des LCD
|
45 | _delay_ms( LCD_BOOTUP_MS );
|
46 |
|
47 | // Soft-Reset muss 3mal hintereinander gesendet werden zur Initialisierung
|
48 | lcd_out(LCD_SOFT_RESET );
|
49 | _delay_ms( LCD_SOFT_RESET_MS1 );
|
50 |
|
51 | lcd_enable();
|
52 | _delay_ms( LCD_SOFT_RESET_MS2 );
|
53 |
|
54 | lcd_enable();
|
55 | _delay_ms( LCD_SOFT_RESET_MS3 );
|
56 |
|
57 | lcd_out(LCD_SOFT_SET);
|
58 | _delay_ms(1);
|
59 |
|
60 | lcd_out(LCD_SET_DISPLAY |
|
61 | LCD_DISPLAY_OFF);
|
62 | _delay_ms(1);
|
63 |
|
64 | lcd_clear();
|
65 |
|
66 | lcd_out(LCD_SET_ENTRY |
|
67 | LCD_ENTRY_INCREASE);
|
68 | _delay_ms(1);
|
69 | /********************INIT DONE********************************************/
|
70 |
|
71 | // 4-bit Modus aktivieren
|
72 | lcd_out( LCD_SET_FUNCTION |
|
73 | LCD_FUNCTION_4BIT );
|
74 | _delay_ms( LCD_SET_4BITMODE_MS );
|
75 |
|
76 | // 4-bit Modus / 2 Zeilen / 5x7
|
77 | lcd_command( LCD_SET_FUNCTION |
|
78 | LCD_FUNCTION_4BIT |
|
79 | LCD_FUNCTION_2LINE |
|
80 | LCD_FUNCTION_5X7 );
|
81 |
|
82 | // Display ein / Cursor aus / Blinken aus
|
83 | lcd_command( LCD_SET_DISPLAY |
|
84 | LCD_DISPLAY_ON |
|
85 | LCD_CURSOR_ON |
|
86 | LCD_BLINKING_ON);
|
87 |
|
88 | // Cursor inkrement / kein Scrollen
|
89 | lcd_command( LCD_SET_ENTRY |
|
90 | LCD_ENTRY_INCREASE |
|
91 | LCD_ENTRY_NOSHIFT );
|
92 | lcd_clear();
|
93 | }
|
94 |
|
95 | ////////////////////////////////////////////////////////////////////////////////
|
96 | // Sendet ein Datenbyte an das LCD
|
97 | void lcd_data( uint8_t data )
|
98 | {
|
99 | LCD_PORT |= (1<<LCD_RS); // RS auf 1 setzen
|
100 |
|
101 | lcd_out( data ); // zuerst die oberen,
|
102 | lcd_out( data<<4 ); // dann die unteren 4 Bit senden
|
103 |
|
104 | _delay_us( LCD_WRITEDATA_US );
|
105 | }
|
106 |
|
107 | ////////////////////////////////////////////////////////////////////////////////
|
108 | // Sendet einen Befehl an das LCD
|
109 | void lcd_command( uint8_t data )
|
110 | {
|
111 | LCD_PORT &= ~(1<<LCD_RS); // RS auf 0 setzen
|
112 |
|
113 | lcd_out( data ); // zuerst die oberen,
|
114 | lcd_out( data<<4 ); // dann die unteren 4 Bit senden
|
115 |
|
116 | _delay_us( LCD_COMMAND_US );
|
117 | }
|
118 |
|
119 | ////////////////////////////////////////////////////////////////////////////////
|
120 | // Sendet den Befehl zur Löschung des Displays
|
121 | void lcd_clear( void )
|
122 | {
|
123 | lcd_command( LCD_CLEAR_DISPLAY );
|
124 | _delay_ms( LCD_CLEAR_DISPLAY_MS );
|
125 | }
|
126 |
|
127 | ////////////////////////////////////////////////////////////////////////////////
|
128 | // Sendet den Befehl: Cursor Home
|
129 | void lcd_home( void )
|
130 | {
|
131 | lcd_command( LCD_CURSOR_HOME );
|
132 | _delay_ms( LCD_CURSOR_HOME_MS );
|
133 | }
|
134 |
|
135 | ////////////////////////////////////////////////////////////////////////////////
|
136 | // Setzt den Cursor in Spalte x (0..15) Zeile y (1..4)
|
137 |
|
138 | void lcd_setcursor( uint8_t x, uint8_t y )
|
139 | {
|
140 | uint8_t data;
|
141 |
|
142 | switch (y)
|
143 | {
|
144 | case 1: // 1. Zeile
|
145 | data = LCD_SET_DDADR + LCD_DDADR_LINE1 + x;
|
146 | break;
|
147 |
|
148 | case 2: // 2. Zeile
|
149 | data = LCD_SET_DDADR + LCD_DDADR_LINE2 + x;
|
150 | break;
|
151 |
|
152 | case 3: // 3. Zeile
|
153 | data = LCD_SET_DDADR + LCD_DDADR_LINE3 + x;
|
154 | break;
|
155 |
|
156 | case 4: // 4. Zeile
|
157 | data = LCD_SET_DDADR + LCD_DDADR_LINE4 + x;
|
158 | break;
|
159 |
|
160 | default:
|
161 | return; // für den Fall einer falschen Zeile
|
162 | }
|
163 |
|
164 | lcd_command( data );
|
165 | }
|
166 |
|
167 | ////////////////////////////////////////////////////////////////////////////////
|
168 | // Schreibt einen String auf das LCD
|
169 |
|
170 | void lcd_string( const char *data )
|
171 | {
|
172 | while( *data != '\0' )
|
173 | lcd_data( *data++ );
|
174 | }
|
175 |
|
176 | ////////////////////////////////////////////////////////////////////////////////
|
177 | // Schreibt ein Zeichen in den Character Generator RAM
|
178 |
|
179 | void lcd_generatechar( uint8_t code, const uint8_t *data )
|
180 | {
|
181 | // Startposition des Zeichens einstellen
|
182 | lcd_command( LCD_SET_CGADR | (code<<3) );
|
183 |
|
184 | // Bitmuster übertragen
|
185 | for ( uint8_t i=0; i<8; i++ )
|
186 | {
|
187 | lcd_data( data[i] );
|
188 | }
|
189 | }
|