-
Notifications
You must be signed in to change notification settings - Fork 0
/
lcd.c
312 lines (269 loc) · 7.56 KB
/
lcd.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
/*------------------------------------------------------------------------------
Copyright: Radig Ulrich mailto: mail@ulrichradig.de
Author: Radig Ulrich
Remarks:
known Problems: none
Version: 22.11.2007
Description: Programm zur Ansteuerung eines Standart LCD
(HD44870),(SED1278F) und kompatible
Addons : USE_LCD_4Bit wird zur Ansteuerung für Paraelle Ansteuerung benutzt (Ralf Figge)
------------------------------------------------------------------------------*/
#include "lcd.h"
#if USE_SER_LCD
#if USE_LCD_PORTC
//nix
#else
const char LINE_ADDRESS[] ={0x80,0xC0,0x90,0xD0}; //2 x 16;4 x 16 uvm.
//const char LINE_ADDRESS[] ={0x80,0xC0,0x94,0xD4}; //4 mal 20
volatile unsigned char back_light = 0;
//------------------------------------------------------------------------------
void lcd_init (void)
{
#if USE_LCD_4Bit
//Set Port Direction Register to Output for LCD Databus und LCD Steuerbus
LCD_Port_DDR = LCD_DataOutput+(1<<LCD_RS | 1<<LCD_RW );
// PORTB0+B3 auf Ausgabe schalten
DDRB |= 9;
#else
//Set Port Direction Register
DDR_LCD_DATA_ENABLE |= (1<<LCD_DATA_ENABLE);
DDR_LCD_CLOCK |= (1<<LCD_CLOCK);
DDR_LCD_DATA |= (1<<LCD_DATA);
PORT_LCD_DATA_ENABLE &= ~(1<<LCD_DATA_ENABLE);
#endif //USE_LCD_4Bit
//Wait a short Time after Power on
WAIT(10000);
for (unsigned char a=0;a<3;a++)
{
lcd_write (0x22,0); //Init in 4 Bit Mode
lcd_write (0x80,0); //Set DD-Ram Adresse = 0
}
#ifdef ONE_LINES
lcd_write (0x20,0); //1 Zeilen
#else
lcd_write (0x28,0); //mehrere Zeilen
#endif
lcd_write (0x0C,0); //Display On
// Hintergrundbeleuchtung an
// PORTB |= 8;
}
//------------------------------------------------------------------------------
void lcd_write (char data,char cd)
{
#if USE_LCD_4Bit
unsigned int timeout = 0;
//Wait until LCD is ready
while ((Read_LCD(0)&(1<<BUSYBIT)) > 0 && timeout++ < 500) {};
//Set Port Direction Register to Output for LCD Databus and LCD Controlbus
LCD_Port_DDR = LCD_DataOutput+(1<<LCD_RS | 1<<LCD_RW );
// PORTB0+B3 auf Ausgabe schalten
DDRB |= 9;
//Soll ins Steuer oder Datenregister geschrieben werden?
if (cd == 0)
{
LCD_Port_Write &=~ (1<<LCD_RS); //RS = 0 Steuerregister
}
else
{
LCD_Port_Write |= (1<<LCD_RS); //RS = 1 Dataregister
}
//Schreibsignal setzen
LCD_Port_Write &=~ (1<<LCD_RW);//Zum Schreiben RW-Pin = Low
//Schreiben der 1. 4Bit an das LCD Display
LCD_Port_Write = (LCD_Port_Write&0x0F) + (data&0xF0); //Write Nibbel MSB
//LCD_Port_Write |= (1<<LCD_E);
PORTB |= 1;
WAIT(200);
//LCD_Port_Write &=~ (1<<LCD_E);
PORTB &=~ 1;
//Schreiben der 2. 4Bit an das LCD Display
LCD_Port_Write = (LCD_Port_Write&0x0F) + ((data&0x0F)<<4); //Write Nibbel LSB
//LCD_Port_Write |= (1<<LCD_E);
PORTB |= 1;
WAIT(200);
//LCD_Port_Write &=~ (1<<LCD_E);
PORTB &=~ 1;
#else
WAIT(BUSY_WAIT);
unsigned char h_byte = 0;
unsigned char l_byte = 0;
//Soll ins Seuer oder Datenregister geschrieben werden?
if(cd)
{
h_byte |= (1<<LCD_RS_PIN);
l_byte |= (1<<LCD_RS_PIN);
}
if(back_light)
{
h_byte |= (1<<LCD_LIGHT_PIN);
l_byte |= (1<<LCD_LIGHT_PIN);
}
h_byte |= (data&0xF0)>>1; //Write Nibbel MSB
l_byte |= (data&0x0F)<<3; //Write Nibbel LSB
//Schreiben der 1. 4Bit an das LCD Display
shift_data_out(h_byte);
//Schreiben der 2. 4Bit an das LCD Display
shift_data_out(l_byte);
#endif //USE_LCD_4Bit
}
#if USE_LCD_4Bit
//------------------------------------------------------------------------------
char Read_LCD (char CD)
//------------------------------------------------------------------------------
{
char Data;
//Set Port Direction Register to Output for LCD Databus und LCD Steuerbus
LCD_Port_DDR = LCD_DataInput+(1<<LCD_RS | 1<<LCD_RW);
// PORTB0+B3 auf Ausgabe schalten
DDRB |= 9;
//Lesesignal setzen
LCD_Port_Write |= (1<<LCD_RW); //Zum Lesen RW-Pin = High
//Soll ins Seuer oder Datenregister geschrieben werden?
if (CD == 0)
{
LCD_Port_Write &=~ (1<<LCD_RS); //RS = 0 Steuerregister
}
else
{
LCD_Port_Write |= (1<<LCD_RS); //RS = 1 Dataregister
}
//LCD_Port_Write |= (1<<LCD_E);//Daten stehen an wenn Enable = High
PORTB |= 1;
WAIT(200);
Data = (LCD_Port_Read&0xF0); //Lesen des 1. Nibble (MSB)
//LCD_Port_Write &=~ (1<<LCD_E);
PORTB &=~ 1;
//LCD_Port_Write |= (1<<LCD_E);//Daten stehen an wenn Enable = High
PORTB |= 1;
WAIT(200);
Data += ((LCD_Port_Read&0xF0)>>4); //Lesen des 2. Nibble (LSB)
//LCD_Port_Write &=~ (1<<LCD_E);
PORTB &=~ 1;
return(Data);
}
#else
//------------------------------------------------------------------------------
void shift_data_out (char byte)
{
for (unsigned char a=8; a>0; a--)
{
if ( (byte & (1<<(a-1))) != 0)
{
PORT_LCD_DATA |= (1<<LCD_DATA); //Data PIN (High)
}
else
{
PORT_LCD_DATA &= ~(1<<LCD_DATA); //Data PIN (LOW)
}
PORT_LCD_CLOCK |= (1<<LCD_CLOCK); //Clock PIN (High)
NOP();
NOP();
PORT_LCD_CLOCK &= ~(1<<LCD_CLOCK); //Clock PIN (Low)
}
PORT_LCD_DATA_ENABLE |= (1<<LCD_DATA_ENABLE);
NOP();
NOP();
PORT_LCD_DATA_ENABLE &= ~(1<<LCD_DATA_ENABLE);
}
#endif //USE_LCD_4Bit
//------------------------------------------------------------------------------
void lcd_print_P (unsigned char zeile,unsigned char spalte,const char *Buffer,...)
{
va_list ap;
va_start (ap, Buffer);
int format_flag;
char str_buffer[10];
char str_null_buffer[10];
char move = 0;
char Base = 0;
int tmp = 0;
char by;
char *ptr;
//Berechnet Adresse für die Zeile und schreibt sie ins DD-Ram
zeile = LINE_ADDRESS[zeile];
zeile += spalte;
lcd_write(zeile,0);
//Ausgabe der Zeichen
for(;;)
{
by = pgm_read_byte(Buffer++);
if(by==0) break; // end of format string
if (by == '%')
{
by = pgm_read_byte(Buffer++);
if (isdigit(by)>0)
{
str_null_buffer[0] = by;
str_null_buffer[1] = '\0';
move = atoi(str_null_buffer);
by = pgm_read_byte(Buffer++);
}
switch (by)
{
case 's':
ptr = va_arg(ap,char *);
while(*ptr) {lcd_write(*ptr++,1); }
break;
case 'b':
Base = 2;
goto ConversionLoop;
case 'c':
//Int to char
format_flag = va_arg(ap,int);
lcd_write (format_flag++,1);
break;
case 'i':
Base = 10;
goto ConversionLoop;
case 'o':
Base = 8;
goto ConversionLoop;
case 'x':
Base = 16;
//****************************
ConversionLoop:
//****************************
itoa(va_arg(ap,int),str_buffer,Base);
int b=0;
while (str_buffer[b++] != 0){};
b--;
if (b<move)
{
move -=b;
for (tmp = 0;tmp<move;tmp++)
{
str_null_buffer[tmp] = '0';
}
//tmp ++;
str_null_buffer[tmp] = '\0';
strcat(str_null_buffer,str_buffer);
strcpy(str_buffer,str_null_buffer);
}
lcd_print_str (str_buffer);
move =0;
break;
}
}
else
{
lcd_write (by,1);
}
}
va_end(ap);
}
//------------------------------------------------------------------------------
void lcd_print_str (char *Buffer)
{
while (*Buffer != 0)
{
lcd_write (*Buffer++,1);
};
};
//------------------------------------------------------------------------------
void lcd_clear (void)
{
lcd_write (1,0); //Clear Display
lcd_write (0x80,0); //Set DD-Ram Adresse = 0
}
#endif
#endif