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 | // Initialisierung: muss ganz am Anfang des Programms aufgerufen werden.
|
13 |
|
14 | void lcd_init(void)
|
15 | {
|
16 | // verwendete Pins auf Ausgang schalten
|
17 | uint8_t pins = (0x0F<<LCD_DB)|(1<<LCD_RS)|(1<<LCD_EN);
|
18 | LCD_DDR |= pins;
|
19 |
|
20 | // initial alle Ausgänge auf Null
|
21 | LCD_PORT &= ~pins;
|
22 |
|
23 | // warten auf die Bereitschaft des LCD
|
24 | _delay_ms(LCD_BOOTUP_MS);
|
25 |
|
26 | // Soft-Reset muss 3mal hintereinander gesendet werden zur Initialisierung
|
27 | lcd_out(LCD_SOFT_RESET);
|
28 | _delay_ms(LCD_SOFT_RESET_MS1);
|
29 |
|
30 | lcd_enable();
|
31 | _delay_ms(LCD_SOFT_RESET_MS2);
|
32 |
|
33 | lcd_enable();
|
34 | _delay_ms(LCD_SOFT_RESET_MS3);
|
35 |
|
36 | // 4-bit Modus aktivieren
|
37 | lcd_out(LCD_SET_FUNCTION|LCD_FUNCTION_4BIT);
|
38 | _delay_ms(LCD_SET_4BITMODE_MS);
|
39 |
|
40 | // 4-bit Modus / 2 Zeilen / 5x7
|
41 | lcd_command(LCD_SET_FUNCTION|LCD_FUNCTION_4BIT|LCD_FUNCTION_2LINE|LCD_FUNCTION_5X7);
|
42 |
|
43 | // Display ein / Cursor aus / Blinken aus
|
44 | lcd_command(LCD_SET_DISPLAY|LCD_DISPLAY_ON|LCD_CURSOR_OFF|LCD_BLINKING_OFF);
|
45 |
|
46 | // Cursor inkrement / kein Scrollen
|
47 | lcd_command(LCD_SET_ENTRY|LCD_ENTRY_INCREASE|LCD_ENTRY_NOSHIFT);
|
48 |
|
49 | lcd_clear();
|
50 | }
|
51 |
|
52 | ////////////////////////////////////////////////////////////////////////////////
|
53 | // Erzeugt einen Enable-Puls
|
54 |
|
55 | void lcd_enable(void)
|
56 | {
|
57 | LCD_PORT |= (1<<LCD_EN); // EN auf 1 setzen
|
58 | _delay_us(LCD_ENABLE_US); // kurze Pause
|
59 | LCD_PORT &= ~(1<<LCD_EN); // EN auf 0 setzen
|
60 | }
|
61 |
|
62 | ////////////////////////////////////////////////////////////////////////////////
|
63 | // Sendet eine 4-bit Ausgabeoperation an das LCD
|
64 |
|
65 | void lcd_out(uint8_t data)
|
66 | {
|
67 | data &= 0xF0; // obere 4 Bit maskieren
|
68 |
|
69 | LCD_PORT &= ~(0xF0>>(4-LCD_DB)); // Maske löschen
|
70 | LCD_PORT |= (data>>(4-LCD_DB)); // Bits setzen
|
71 | lcd_enable();
|
72 | }
|
73 |
|
74 | ////////////////////////////////////////////////////////////////////////////////
|
75 | // Sendet ein Datenbyte an das LCD
|
76 |
|
77 | void lcd_data(uint8_t data)
|
78 | {
|
79 | LCD_PORT |= (1<<LCD_RS); // RS auf 1 setzen
|
80 |
|
81 | lcd_out(data); // zuerst die oberen,
|
82 | lcd_out(data<<4); // dann die unteren 4 Bit senden
|
83 |
|
84 | _delay_us(LCD_WRITEDATA_US);
|
85 | }
|
86 |
|
87 | ////////////////////////////////////////////////////////////////////////////////
|
88 | // Sendet einen Befehl an das LCD
|
89 |
|
90 | void lcd_command(uint8_t data)
|
91 | {
|
92 | LCD_PORT &= ~(1<<LCD_RS); // RS auf 0 setzen
|
93 |
|
94 | lcd_out(data); // zuerst die oberen,
|
95 | lcd_out(data<<4); // dann die unteren 4 Bit senden
|
96 |
|
97 | _delay_us(LCD_COMMAND_US);
|
98 | }
|
99 |
|
100 | ////////////////////////////////////////////////////////////////////////////////
|
101 | // Sendet den Befehl zur Löschung des Displays
|
102 |
|
103 | void lcd_clear(void)
|
104 | {
|
105 | lcd_command(LCD_CLEAR_DISPLAY);
|
106 | _delay_ms(LCD_CLEAR_DISPLAY_MS);
|
107 | }
|
108 |
|
109 | ////////////////////////////////////////////////////////////////////////////////
|
110 | // Sendet den Befehl: Cursor Home
|
111 |
|
112 | void lcd_home(void)
|
113 | {
|
114 | lcd_command(LCD_CURSOR_HOME);
|
115 | _delay_ms(LCD_CURSOR_HOME_MS);
|
116 | }
|
117 |
|
118 | ////////////////////////////////////////////////////////////////////////////////
|
119 | // Setzt den Cursor in Zeile y (1..4) Spalte x (0..15)
|
120 |
|
121 | void lcd_setcursor(uint8_t x, uint8_t y)
|
122 | {
|
123 | uint8_t data;
|
124 |
|
125 | switch (y)
|
126 | {
|
127 | case 1: data=LCD_SET_DDADR|LCD_DDADR_LINE1|x; break; // 1. Zeile
|
128 | case 2: data=LCD_SET_DDADR|LCD_DDADR_LINE2|x; break; // 2. Zeile
|
129 | case 3: data=LCD_SET_DDADR|LCD_DDADR_LINE3|x; break; // 3. Zeile
|
130 | case 4: data=LCD_SET_DDADR|LCD_DDADR_LINE4|x; break; // 4. Zeile
|
131 | default: return; // für den Fall einer falschen Zeile
|
132 | }
|
133 | lcd_command(data);
|
134 | }
|
135 |
|
136 | ////////////////////////////////////////////////////////////////////////////////
|
137 | // Schreibt einen String auf das LCD
|
138 |
|
139 | void lcd_string(const char *data)
|
140 | {
|
141 | while(*data)
|
142 | {
|
143 | lcd_data(*data);
|
144 | data++;
|
145 | }
|
146 | }
|
147 |
|
148 | ////////////////////////////////////////////////////////////////////////////////
|
149 | // Schreibt ein Zeichen in den Character Generator RAM
|
150 |
|
151 | void lcd_generatechar(uint8_t code, const uint8_t *data)
|
152 | {
|
153 | // Startposition des Zeichens einstellen
|
154 | lcd_command(LCD_SET_CGADR|(code<<3));
|
155 |
|
156 | // Bitmuster übertragen
|
157 | for (uint8_t i=0; i<8; i++)
|
158 | {
|
159 | lcd_data(data[i]);
|
160 | }
|
161 | }
|