1 | // Ansteuerung eines HD44780 kompatiblen LCD im 4-Bit-Interfacemodus
|
2 | // http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial
|
3 | //
|
4 | // Die Pinbelegung ist über defines in lcd-routines.h einstellbar
|
5 |
|
6 | #include <avr/io.h>
|
7 | #include "lcd-routines.h"
|
8 | #include <util/delay.h>
|
9 |
|
10 |
|
11 | // sendet ein Datenbyte an das LCD
|
12 |
|
13 | void lcd_data(unsigned char temp1)
|
14 | {
|
15 | unsigned char temp2 = temp1;
|
16 |
|
17 | LCD_RS_PORT |= (1<<LCD_RS); // RS auf 1 setzen
|
18 |
|
19 | temp1 = temp1 >> 4;
|
20 | temp1 = temp1 & 0x0F;
|
21 |
|
22 | LCD_PORT_4 &= ~(1<<LCD_D4);
|
23 | LCD_PORT_5 &= ~(1<<LCD_D5);
|
24 | LCD_PORT_6 &= ~(1<<LCD_D6);
|
25 | LCD_PORT_7 &= ~(1<<LCD_D7);
|
26 |
|
27 | if(temp1 & 0x01) LCD_PORT_4 |=(1<<LCD_D4) ;// setzen
|
28 | if(temp1 & 0x02) LCD_PORT_5 |=(1<<LCD_D5) ;
|
29 | if(temp1 & 0x04) LCD_PORT_6 |=(1<<LCD_D6) ;
|
30 | if(temp1 & 0x08) LCD_PORT_7 |=(1<<LCD_D7) ;
|
31 | lcd_enable();
|
32 |
|
33 |
|
34 |
|
35 | temp2 = temp2 & 0x0F;
|
36 |
|
37 | LCD_PORT_4 &= ~(1<<LCD_D4);
|
38 | LCD_PORT_5 &= ~(1<<LCD_D5);
|
39 | LCD_PORT_6 &= ~(1<<LCD_D6);
|
40 | LCD_PORT_7 &= ~(1<<LCD_D7);
|
41 |
|
42 | if(temp2 & 0x01) LCD_PORT_4 |=(1<<LCD_D4) ;// setzen
|
43 | if(temp2 & 0x02) LCD_PORT_5 |=(1<<LCD_D5) ;
|
44 | if(temp2 & 0x04) LCD_PORT_6 |=(1<<LCD_D6) ;
|
45 | if(temp2 & 0x08) LCD_PORT_7 |=(1<<LCD_D7) ;
|
46 | lcd_enable();
|
47 |
|
48 |
|
49 | _delay_us(420);
|
50 | }
|
51 |
|
52 | // sendet einen Befehl an das LCD
|
53 |
|
54 | void lcd_command(unsigned char temp1)
|
55 | {
|
56 | unsigned char temp2 = temp1;
|
57 |
|
58 | LCD_RS_PORT &= ~(1<<LCD_RS); // RS auf 0 setzen
|
59 |
|
60 | temp1 = temp1 >> 4; // oberes Nibble holen
|
61 | temp1 = temp1 & 0x0F;
|
62 |
|
63 | LCD_PORT_4 &= ~(1<<LCD_D4);
|
64 | LCD_PORT_5 &= ~(1<<LCD_D5);
|
65 | LCD_PORT_6 &= ~(1<<LCD_D6);
|
66 | LCD_PORT_7 &= ~(1<<LCD_D7); // maskieren
|
67 |
|
68 | if(temp1 & 0x01) LCD_PORT_4 |=(1<<LCD_D4) ;// setzen
|
69 | if(temp1 & 0x02) LCD_PORT_5 |=(1<<LCD_D5) ;
|
70 | if(temp1 & 0x04) LCD_PORT_6 |=(1<<LCD_D6) ;
|
71 | if(temp1 & 0x08) LCD_PORT_7 |=(1<<LCD_D7) ;
|
72 | lcd_enable();
|
73 |
|
74 | temp2 = temp2 & 0x0F;
|
75 |
|
76 | LCD_PORT_4 &= ~(1<<LCD_D4);
|
77 | LCD_PORT_5 &= ~(1<<LCD_D5);
|
78 | LCD_PORT_6 &= ~(1<<LCD_D6);
|
79 | LCD_PORT_7 &= ~(1<<LCD_D7); // unteres Nibble holen und maskieren
|
80 |
|
81 | if(temp2 & 0x01) LCD_PORT_4 |=(1<<LCD_D4) ;// setzen
|
82 | if(temp2 & 0x02) LCD_PORT_5 |=(1<<LCD_D5) ;
|
83 | if(temp2 & 0x04) LCD_PORT_6 |=(1<<LCD_D6) ;
|
84 | if(temp2 & 0x08) LCD_PORT_7 |=(1<<LCD_D7) ;
|
85 | lcd_enable();
|
86 |
|
87 | _delay_us(420);
|
88 | }
|
89 |
|
90 | // erzeugt den Enable-Puls
|
91 |
|
92 | void lcd_enable(void)
|
93 | {
|
94 | // Bei Problemen ggf. Pause gemäß Datenblatt des LCD Controllers einfügen
|
95 | _delay_us(100);
|
96 | // http://www.mikrocontroller.net/topic/81974#685882
|
97 | LCD_EN1_PORT |= (1<<LCD_EN1);
|
98 |
|
99 |
|
100 | _delay_us(100); // kurze Pause
|
101 | // Bei Problemen ggf. Pause gemäß Datenblatt des LCD Controllers verlängern
|
102 | // http://www.mikrocontroller.net/topic/80900
|
103 | LCD_EN1_PORT &= ~(1<<LCD_EN1);
|
104 |
|
105 |
|
106 |
|
107 | }
|
108 | // Initialisierung:
|
109 | // Muss ganz am Anfang des Programms aufgerufen werden.
|
110 |
|
111 | void lcd_init(void)
|
112 | {
|
113 | _delay_ms(150);
|
114 | // Ports auf Ausgang schalten
|
115 | LCD_DDR_4 |=(1<<LCD_D4);
|
116 | LCD_DDR_5 |=(1<<LCD_D5);
|
117 | LCD_DDR_6 |=(1<<LCD_D6);
|
118 | LCD_DDR_7 |=(1<<LCD_D7);
|
119 | LCD_EN1_DDR |= (1<<LCD_EN1);
|
120 | LCD_RS_DDR |= (1<<LCD_RS);
|
121 |
|
122 | // muss 3mal hintereinander gesendet werden zur Initialisierung
|
123 |
|
124 | _delay_ms(150);
|
125 |
|
126 | LCD_PORT_4 |= (1<<LCD_D4);
|
127 | LCD_PORT_5 |= (1<<LCD_D5);
|
128 | LCD_PORT_6 &= ~(1<<LCD_D6);
|
129 | LCD_PORT_7 &= ~(1<<LCD_D7);
|
130 | LCD_RS_PORT &= ~(1<<LCD_RS); // RS auf 0
|
131 | _delay_ms(50);
|
132 | lcd_enable();
|
133 |
|
134 | _delay_ms(50);
|
135 | lcd_enable();
|
136 |
|
137 | _delay_ms(50);
|
138 | lcd_enable();
|
139 |
|
140 | _delay_ms(50);
|
141 |
|
142 | // 4 Bit Modus aktivieren
|
143 |
|
144 | LCD_PORT_4 &= ~(1<<LCD_D4);
|
145 | LCD_PORT_5 |= (1<<LCD_D5);
|
146 | LCD_PORT_6 &= ~(1<<LCD_D6);
|
147 | LCD_PORT_7 &= ~(1<<LCD_D7);
|
148 |
|
149 | lcd_enable();
|
150 | _delay_ms(1);
|
151 |
|
152 | // 4Bit / 2 Zeilen / 5x7
|
153 | lcd_command(0x28);
|
154 |
|
155 | // Display ein / Cursor aus / kein Blinken
|
156 | lcd_command(0x0C);
|
157 |
|
158 | // inkrement / kein Scrollen
|
159 | lcd_command(0x06);
|
160 |
|
161 | lcd_clear();
|
162 | }
|
163 |
|
164 | // Sendet den Befehl zur Löschung des Displays
|
165 |
|
166 | void lcd_clear(void)
|
167 | {
|
168 | lcd_command(CLEAR_DISPLAY);
|
169 | _delay_ms(50);
|
170 | }
|
171 |
|
172 | // Sendet den Befehl: Cursor Home
|
173 |
|
174 | void lcd_home(void)
|
175 | {
|
176 | lcd_command(CURSOR_HOME);
|
177 | _delay_ms(5);
|
178 | }
|
179 |
|
180 | // setzt den Cursor in Zeile y (1..4) Spalte x (0..15)
|
181 |
|
182 | void set_cursor(uint8_t x, uint8_t y)
|
183 | {
|
184 | uint8_t tmp;
|
185 |
|
186 | switch (y) {
|
187 | case 1: tmp=0x80+0x00+x; break; // 1. Zeile
|
188 | case 2: tmp=0x80+0x40+x; break; // 2. Zeile
|
189 | }
|
190 | lcd_command(tmp);
|
191 | }
|
192 |
|
193 | // Schreibt einen String auf das LCD
|
194 |
|
195 | void lcd_string( const char *data )
|
196 | {
|
197 | while( *data != '\0' )
|
198 | lcd_data( *data++ );
|
199 | }
|