-
Notifications
You must be signed in to change notification settings - Fork 0
/
lcd.c
292 lines (244 loc) · 7.78 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
#include "lcd.h"
#include <xc.h>
#include "lcd_customization.h"
#include <libpic30.h>
#include "stringconversion.h"
// User specific definitions
// Definitions for LC display
#define LCD_POWER_UP_DELAY_MS 50 // Power up delay in ms
#define LCD_INIT_DELAY_MS 10 // Initialization steps delay in ms
#define LCD_COLS 16 // Display columns
#define LCD_ROWS 2 // Display rows
// Definitions for display modes and functions
#define LCD_CMD_MODE 0
#define LCD_DATA_MODE 1
#define LCD_INIT_MODE 2
#define LCD_CLR 1
#define LCD_HOME 2
#define LCD_DISP_ON 0x0C
#define LCD_FUNCTION_4BIT_1LINE 0x20
#define LCD_FUNCTION_4BIT_2LINES 0x28
#define LCD_FUNCTION_8BIT_1LINE 0x30
#define LCD_FUNCTION_8BIT_2LINES 0x38
void lcd_delay(void) // Do clock depending delay
{
__delay_us(100);
}
//-----------------------------------------------------------------------------
char LCD_ROW_TABLE[4] = // Display row addresses
{
0x80,
0xC0,
0x80 + LCD_COLS,
0xC0 + LCD_COLS
};
void lcd_init_shift_reg(uint8_t mode) // Clear shift-register, set E and RS
{
uint8_t n;
LCD_CLR_DATA(); // Clear data signal
lcd_delay();
// Clear all outputs of shift register
for (n = 7; n; n--)
{
LCD_SET_CLK();
lcd_delay();
LCD_CLR_CLK();
}
// Set high level for E at Q7
LCD_SET_DATA();
lcd_delay();
LCD_SET_CLK();
lcd_delay();
LCD_CLR_CLK();
// Set level for RS at Q6
if (mode == LCD_DATA_MODE)
{
LCD_SET_DATA();
}
else
{
LCD_CLR_DATA();
}
lcd_delay();
LCD_SET_CLK();
lcd_delay();
LCD_CLR_CLK();
}
//-----------------------------------------------------------------------------
void lcd_shift_nibble(uint8_t data) // Clock in 4 bits of data
{
uint8_t n, mask = 0x08;
for (n = 4; n; n--) // Do this for 4 databits
{
if (data & mask) // Set or reset data signal
{
LCD_SET_DATA();
}
else
{
LCD_CLR_DATA();
}
LCD_SET_CLK();
lcd_delay();
LCD_CLR_CLK();
mask >>= 1; // Shift right compare mask
}
// Clear data line, then do the last shift, Q7=1
LCD_CLR_DATA(); // Always clear data line before the last shift
LCD_SET_CLK();
lcd_delay();
LCD_CLR_CLK();
}
//-----------------------------------------------------------------------------
void lcd_shift_byte(uint8_t data,uint8_t mode) // Write command or data byte to display
{
lcd_init_shift_reg(mode); // Clear shift register, set RS and E
lcd_shift_nibble(data >> 4); // Shift high nibble first
// Now 6 bits are shifted, Q7=1 waiting for the data line to go high
// for a logical AND, thus a high at E to latch the data at Q5..Q2
LCD_SET_DATA();
lcd_delay();
// Do not write the low nibble if in LCD_INIT_MODE because
// the interface is in 8-bit mode at startup
if (mode != LCD_INIT_MODE)
{
lcd_init_shift_reg(mode); // Clear shift register, set RS and E
lcd_shift_nibble(data); // Shift low nibble last
// Now 6 bits are shifted, Q7=1 waiting for the data line to go high
// for a logical AND, thus a high at E to latch the data at Q5..Q2
LCD_SET_DATA();
lcd_delay();
}
LCD_CLR_DATA(); // Clear E always
lcd_delay();
}
//-----------------------------------------------------------------------------
void lcd_write_command(uint8_t command) // Write command byte to display
{
lcd_shift_byte(command,LCD_CMD_MODE); // Do serial byte transfer
}
//-----------------------------------------------------------------------------
void lcd_write_data(uint8_t data) // Write data byte to display
{
lcd_shift_byte(data,LCD_DATA_MODE); // Do serial byte transfer
}
//-----------------------------------------------------------------------------
// Function flags - Bit0 0: 5x7 Dots, 1: 5x10 Dots
// Bit1 0: 1 Row, 1: 2 Rows
// Bit2 0: 4-Bit interface, 1: 8-Bit interface
void lcd_function_mode(uint8_t function_mode) // Set display funktion mode
{
function_mode = ((function_mode & 7) << 2) + 0x20;
lcd_write_command(function_mode);
}
//-----------------------------------------------------------------------------
// Display flags - Bit0 0: blink cursor off, 1: blink cursor on
// Bit1 0: line cursor off, 1: line cursor on
// Bit2 0: display off, 1: display on
void lcd_display_mode(uint8_t display_mode) // Set display mode
{
display_mode = (display_mode & 7) + 0x08;
lcd_write_command(display_mode);
}
//-----------------------------------------------------------------------------
// Entry flags - Bit0 0: display shift off, 1: display shift on
// Bit1 0: decrement, 1: increment
void lcd_entry_mode(uint8_t entry_mode) // Set entry mode
{
entry_mode = (entry_mode & 3) + 0x04;
lcd_write_command(entry_mode);
}
//-----------------------------------------------------------------------------
void lcd_clear(void) // Clear display
{
lcd_write_command(LCD_CLR);
__delay_ms(4);
}
//-----------------------------------------------------------------------------
void lcd_home(void) // Set cursor to home position
{
lcd_write_command(LCD_HOME);
}
//-----------------------------------------------------------------------------
void lcd_goto_xy(uint8_t xpos,uint8_t ypos) // Set display cursor position
{
if (xpos < LCD_COLS && ypos < LCD_ROWS)
{
lcd_write_command(LCD_ROW_TABLE[ypos] + xpos);
}
}
//-----------------------------------------------------------------------------
void lcd_write_char(char chr) // Write character
{
lcd_write_data(chr);
}
//-----------------------------------------------------------------------------
void lcd_write_char_xy(uint8_t x,uint8_t y,char chr) // Write character at position
{
lcd_goto_xy(x,y);
lcd_write_data(chr);
}
//-----------------------------------------------------------------------------
void lcd_write_str(char* sp) // Write string
{
while (*sp)
{
lcd_write_data(*sp++);
}
}
//-----------------------------------------------------------------------------
void lcd_write_str_xy(uint8_t x,uint8_t y,char* sp) // Write string at position
{
lcd_goto_xy(x,y);
lcd_write_str(sp);
}
//-----------------------------------------------------------------------------
void lcd_init(void) // Initialize display
{
// Set clock- and data pin to low level
LCD_CLR_CLK();
LCD_CLR_DATA();
__delay_ms(LCD_POWER_UP_DELAY_MS); // Delay for power up time
// Start Initialization
// Only the high nibble ist transfered in LCD_INIT_MODE
lcd_shift_byte(LCD_FUNCTION_8BIT_1LINE,LCD_INIT_MODE);
__delay_ms(LCD_INIT_DELAY_MS);
lcd_shift_byte(LCD_FUNCTION_8BIT_1LINE,LCD_INIT_MODE);
__delay_ms(LCD_INIT_DELAY_MS);
lcd_shift_byte(LCD_FUNCTION_8BIT_1LINE,LCD_INIT_MODE);
__delay_ms(LCD_INIT_DELAY_MS);
lcd_shift_byte(LCD_FUNCTION_4BIT_1LINE,LCD_INIT_MODE);
__delay_ms(LCD_INIT_DELAY_MS);
// Display is in 4 bit I/O mode now
#if (LCD_ROWS > 1)
lcd_write_command(LCD_FUNCTION_4BIT_2LINES);
#else
lcd_write_command(LCD_FUNCTION_4BIT_1LINE);
#endif
__delay_ms(LCD_INIT_DELAY_MS);
lcd_write_command(LCD_DISP_ON);
__delay_ms(LCD_INIT_DELAY_MS);
lcd_write_command(LCD_CLR);
lcd_write_command(LCD_HOME);
__delay_ms(LCD_INIT_DELAY_MS);
}
void lcd_write_U8(char value,uint8_t digits) // Write unsigned 8-bit number
{
lcd_write_str(sc_S08_to_str(value,digits));
}
//-----------------------------------------------------------------------------
void lcd_write_U8_hex(char value) // Write hexdecimal 8-bit number
{
lcd_write_str(sc_U8_to_hex(value));
}
//-----------------------------------------------------------------------------
void lcd_write_U16(uint16_t value,uint8_t digits) // Write unsigned 16-bit number
{
lcd_write_str(sc_U16_to_str(value,digits));
}
//-----------------------------------------------------------------------------
void lcd_write_int_hex(uint16_t value) // Write hexdecimal 16-bit number
{
lcd_write_str(sc_U16_to_hex(value));
}
//-----------------------------------------------------------------------------