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