-
Notifications
You must be signed in to change notification settings - Fork 0
/
LCD_interface.h
261 lines (233 loc) · 7.21 KB
/
LCD_interface.h
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
#ifndef LCD_interface
#define LCD_interface
#ifndef F_CPU
#define F_CPU 16000000UL
#endif
#include "DIO_def.h"
#include "LCD_commands.h"
#include <util/delay.h>
#ifndef mode
#define mode 8 // 8-bits mode
#endif
#ifndef dataPort
#define dataPort D
#endif
#if dataPort == A
#define LCD_data_DDR DDRA_reg
#define LCD_data_PORT PORTA_reg
#define LCD_data_PIN PINA_reg
#elif dataPort == B
#define LCD_data_DDR DDRB_reg
#define LCD_data_PORT PORTB_reg
#define LCD_data_PIN PINB_reg
#elif dataPort == C
#define LCD_data_DDR DDRC_reg
#define LCD_data_PORT PORTC_reg
#define LCD_data_PIN PINC_reg
#elif dataPort == D
#define LCD_data_DDR DDRD_reg
#define LCD_data_PORT PORTD_reg
#define LCD_data_PIN PIND_reg
#endif
//
#ifndef controlPort
#define controlPort C
#endif
#if mode == 4 // 4-bits mode
#define controlPort dataPort
#endif
#if controlPort == dataPort && mode != 4 // 4-bits mode
#warning "for 8 bit registers and 8-bit mode, control port and data port cannot be the same !!!"
//#error "for 8 bit registers and 8-bit mode, control port and data port cannot be the same !!!"
#endif
#if controlPort == A
#define LCD_ctrl_DDR DDRA_reg
#define LCD_ctrl_PORT PORTA_reg
#define LCD_ctrl_PIN PINA_reg
#elif controlPort == B
#define LCD_ctrl_DDR DDRB_reg
#define LCD_ctrl_PORT PORTB_reg
#define LCD_ctrl_PIN PINB_reg
#elif controlPort == C
#define LCD_ctrl_DDR DDRC_reg
#define LCD_ctrl_PORT PORTC_reg
#define LCD_ctrl_PIN PINC_reg
#elif controlPort == D
#define LCD_ctrl_DDR DDRD_reg
#define LCD_ctrl_PORT PORTD_reg
#define LCD_ctrl_PIN PIND_reg
#endif
#define LCD_RS 0
#define LCD_RW 1
#define LCD_EN 2
/****************************************/
#ifndef lcdType
#define lcdType 162 // means 16X2
#endif
void lcdSendCommand (u8 CMD)
{
LCD_ctrl_PORT &= ~ (1<<LCD_RS); // RS = 0; dealing with commands
LCD_ctrl_PORT &= ~ (1<<LCD_RW); // RW = 0; writing
#if mode == 4
LCD_data_PORT = (LCD_data_PORT & 0x0f) | (CMD & 0xf0); // setting the first nibble to the first nibble of the CMD and all the second nibble is ones
#elif mode == 8
LCD_data_PORT = CMD; // sending command to the port
#endif
LCD_ctrl_PORT |= (1<<LCD_EN); // EN=1; appling high to low pulse
_delay_us(1); // actually it is 0.45 us
LCD_ctrl_PORT &= ~ (1<<LCD_EN); // EN=0;
if (CMD == lcdClear || CMD == lcdHome)
{
_delay_ms(2); // after clear or home commands we should wait about 2 ms
}
else
{
_delay_us(100); // from the data sheet we should wait 100 us after any command
}
#if mode == 4
LCD_data_PORT = (LCD_data_PORT & 0x0f) | (CMD <<4); // setting the second nibble to the second nibble of the CMD
LCD_ctrl_PORT |= (1<<LCD_EN); // EN=1; appling high to low pulse
_delay_us(1); // actually it is 0.45 us
LCD_ctrl_PORT &= ~ (1<<LCD_EN); // EN=0;
#endif
}
void lcdSendData (u8 data)
{
LCD_ctrl_PORT |= (1<<LCD_RS); // RS = 0; dealing with data
LCD_ctrl_PORT &= ~ (1<<LCD_RW); // RW = 0; writing
#if mode == 4
LCD_data_PORT = (LCD_data_PORT & 0x0f) | (data & 0xf0); // setting the first nibble to the first nibble of the data and all the second nibble is ones
#elif mode == 8
LCD_data_PORT = data; // sending data to the port
#endif
LCD_ctrl_PORT |= (1<<LCD_EN); // EN=1; appling high to low pulse
_delay_us(1); // actually it is 0.45 us
LCD_ctrl_PORT &= ~ (1<<LCD_EN); // EN=0;
_delay_us(100); // from the data sheet we should wait 100 us after any command
#if mode == 4
LCD_data_PORT = (LCD_data_PORT & 0x0f) | (data <<4); // setting the second nibble to the second nibble of the CMD
LCD_ctrl_PORT |= (1<<LCD_EN); // EN=1; appling high to low pulse
_delay_us(1); // actually it is 0.45 us
LCD_ctrl_PORT &= ~ (1<<LCD_EN); // EN=0;
#endif
}
void lcdInit()
{
LCD_data_PORT = 0xff; // LCD data port is output
LCD_ctrl_PORT = 0xff; // LCD control port is output
LCD_ctrl_PORT &= ~ (1<<LCD_EN); // LCD enable is low
_delay_ms(2); // waiting for the power to stabilize
#if mode == 4
// initialization codes for various types of LCDs
lcdSendCommand(0x33); // for the 4 bits mode
_delay_us(100); // after each command we should wait about 100 us
lcdSendCommand(0x32); // for the 4 bits mode
_delay_us(100); // after each command we should wait about 100 us
lcdSendCommand(0x28); // for the 4 bits mode
_delay_us(100); // after each command we should wait about 100 us
#elif mode == 8
lcdSendCommand(0x38); // for the 8 bits mode
_delay_us(100); // after each command we should wait about 100 us
#endif
lcdSendCommand(dispayOn_cursorBlinking); // MACRO from LCD_commands.h
_delay_us(100); // after each command we should wait about 100 us
lcdSendCommand(lcdClear); // MACRO from LCD_commands.h
_delay_ms(2); // after clear or home commands we should wait about 2 ms
lcdSendCommand(cursorToRight); // MACRO from LCD_commands.h, to right for writing in English!
_delay_us(100); // after each command we should wait about 100 us
}
void lcdReset ()
{
// clear the display and return the cursor to home
lcdSendCommand(lcdClear); // MACRO from LCD_commands.h
_delay_ms(2); // after clear or home commands we should wait about 2 ms
lcdSendCommand(lcdHome); // MACRO from LCD_commands.h
_delay_ms(2); // after clear or home commands we should wait about 2 ms
}
void lcdWritingIn (char language)
{
// choose the language to set the cursor direction
// cursor direction is to right by default
if (language=='a' || language=='A')
{
lcdReset();
lcdSendCommand(cursorToLeft); // MACRO from LCD_commands.h, to left for writing in Arabic!
_delay_us(100); // after each command we should wait about 100 us
}
else
{
lcdReset();
lcdSendCommand(cursorToRight); // MACRO from LCD_commands.h, to right for writing in English!
_delay_us(100); // after each command we should wait about 100 us
}
}
void lcdGotoRowCol(u8 y, u8 x)
{
// y for the row, x for the column
#if lcdType == 162
if (x<=0 || x>16)
return;
#elif lcdType == 201 || lcdType == 202 || lcdType == 204
if (x<=0 || x>20)
return;
#elif lcdType == 402 // means 40X2
if (x<=0 || x>40)
return;
#endif
switch (y)
{
case 1 : lcdSendCommand(0x80 + x-1); break;
#if lcdType == 162 || lcdType == 202 || lcdType == 204
case 2 : lcdSendCommand(0xC0 + x-1); break;
#endif
#if lcdType == 402
case 3 : lcdSendCommand(0x94 + x-1); break;
case 4 : lcdSendCommand(0xD4 + x-1);break;
#endif
default: break;
}
}
void lcdWriteChar(char chr)
{
lcdSendData(chr);
}
void lcdWritenum (u32 num)
{
/* the algorithm is as follows:
for n = 2023;
D0 = n % 10; --> 3
n /= 10; --> 202 int division
D1 = n % 10; --> 2
n /= 10; --> 20 int division
.
.
.
D3 D2 D1 D0 --> 2 0 2 3
*/
u8 numDigits=0;
u8 digits [10]; // for 'unsigned long' data types maximum number of digits for them is 10 digits --> 4'294'967'295
if (!num)
{
lcdWriteChar('0');
return;
}
while (num>0)
{
digits[numDigits++] = num % 10;
num/=10;
}
u8 i;
for (i=numDigits-1; i>=0; i--)
{
lcdWriteChar(digits[i]);
}
}
void lcdPrint(char* str)
{
u8 i=0;
while (str[i] !='\0')
{
lcdSendData(str[i++]);
}
}
#endif