Hallo, Ich will ein 4-Zeiliges Display mit der Artikelbezeichnung EA W164B-NLW ansteuern. Verkabelt etc ist schon alles, es funktioniert auch schon. Habe dazu eine Library die ich für 2 zeilige Displays verwende verwendet. Darum funktionieren auch nur die ersten 2 Zeilen des Displays. Habe schon probiert die Library auf 4 Zeilig umzumodifizieren, da aber meine C-Künste im Keller liegen funktionierts aber leider nicht. Die Koordinaten für den Curser werden im C-Code mit lcd_gotoxy(x,y) angegeben. y sind die Zeilen. Hier die Original-Library für 2-zeilige Displays:
1 | ///////////////////////////////////////////////////////////////////////////
|
2 | //// LCD_WSH.C ////
|
3 | //// Driver for common LCD modules ////
|
4 | //// ////
|
5 | //// lcd_init() Must be called before any other function. ////
|
6 | //// ////
|
7 | //// lcd_putc(c) Will display c on the next position of the LCD. ////
|
8 | //// The following have special meaning: ////
|
9 | //// \f Clear display ////
|
10 | //// \n Go to start of second line ////
|
11 | //// \b Move back one position ////
|
12 | //// ////
|
13 | //// lcd_gotoxy(x,y) Set write position on LCD (upper left is 1,1) ////
|
14 | //// ////
|
15 | //// lcd_getc(x,y) Returns character at position x,y on LCD ////
|
16 | //// ////
|
17 | //// lcd_set_CG(ChNum, *Buffer) Sets Custom-Graphics for User-Chars. ////
|
18 | //// ChNum: User-Char 0 .. 7 ////
|
19 | //// *Buffer: 8 Bytes Pixel-Data. details: see below! ////
|
20 | //// ////
|
21 | //// lcd_cursor(On, Blink) Cursor-Functionaliy details: see below! ////
|
22 | //// ////
|
23 | ///////////////////////////////////////////////////////////////////////////
|
24 | //// (C) Copyright 1996,2003 Custom Computer Services ////
|
25 | //// This source code may only be used by licensed users of the CCS C ////
|
26 | //// compiler. This source code may only be distributed to other ////
|
27 | //// licensed users of the CCS C compiler. No other use, reproduction ////
|
28 | //// or distribution is permitted without written permission. ////
|
29 | //// Derivative programs created using this software in object code ////
|
30 | //// form are not restricted in any way. ////
|
31 | ///////////////////////////////////////////////////////////////////////////
|
32 | //// History: ////
|
33 | //// 09-06-27 Martin Scharfetter: adapted for use of ////
|
34 | //// Werkschulheim Felbertal, Salzburg, AUSTRIA: ////
|
35 | //// 16F876, 18F2550+BootLoader + defining Custom-Graphics: ////
|
36 | //// added lcd_set_CG() for up to 8 defineable Pixel-Chars ////
|
37 | //// 09-06-28 Martin Scharfetter: added Cursor-Control lcd_cursor() ////
|
38 | ///////////////////////////////////////////////////////////////////////////
|
39 | |
40 | // As defined in the following structure the pin connection is as follows:
|
41 | // PIC LCD
|
42 | // D0 enable
|
43 | // D1 rs
|
44 | // D2 rw
|
45 | // D3 not connected
|
46 | // D4 D4
|
47 | // D5 D5
|
48 | // D6 D6
|
49 | // D7 D7
|
50 | //
|
51 | // LCD pins D0-D3 are not used and PIC D3 is not used.
|
52 | |
53 | |
54 | struct lcd_pin_map { // This structure is overlayed |
55 | BOOLEAN enable; // on to an I/O port to gain |
56 | BOOLEAN rs; // access to the LCD pins. |
57 | BOOLEAN rw; // The bits are allocated from |
58 | BOOLEAN unused; // low order up. ENABLE will |
59 | int data : 4; // be pin B0. |
60 | } lcd; |
61 | |
62 | |
63 | #if defined(__PCH__)
|
64 | #if defined use_portb_lcd
|
65 | #byte lcd = 0xF81 // This puts the entire structure
|
66 | #elif defined use_portc_lcd
|
67 | #byte lcd = 0xF82 // This puts the entire structure
|
68 | #elif defined use_portd_lcd
|
69 | #byte lcd = 0xF83 // This puts the entire structure
|
70 | #else
|
71 | #error Port for LCD not defined: use '#define use_portX_lcd' before including LCD_WSH.C (X=>Port: b, c or d)!
|
72 | #endif
|
73 | #else
|
74 | #if defined use_portb_lcd
|
75 | #byte lcd = 0x6 // on to port B (at address 6)
|
76 | #elif defined use_portc_lcd
|
77 | #byte lcd = 0x7 // on to port C (at address 7)
|
78 | #elif defined use_portd_lcd
|
79 | #byte lcd = 0x8 // on to port D (at address 8)
|
80 | #else
|
81 | #error Port for LCD not defined: use '#define use_portX_lcd' before including LCD_WSH.C (X=>Port: b, c or d)!
|
82 | #endif
|
83 | #endif
|
84 | |
85 | #if defined use_portb_lcd
|
86 | #define set_tris_lcd(x) set_tris_b(x)
|
87 | #elif defined use_portc_lcd
|
88 | #define set_tris_lcd(x) set_tris_c(x)
|
89 | #elif defined use_portd_lcd
|
90 | #define set_tris_lcd(x) set_tris_d(x)
|
91 | #endif
|
92 | |
93 | |
94 | |
95 | |
96 | #define lcd_type 2 // 0=5x7, 1=5x10, 2=2 lines
|
97 | #define lcd_line_two 0x40 // LCD RAM address for the second line
|
98 | |
99 | |
100 | BYTE const LCD_INIT_STRING[4] = {0x20 | (lcd_type << 2), 0xc, 1, 6}; |
101 | // These bytes need to be sent to the LCD
|
102 | // to start it up.
|
103 | |
104 | |
105 | // The following are used for setting
|
106 | // the I/O port direction register.
|
107 | |
108 | struct lcd_pin_map const LCD_WRITE = {0,0,0,0,0}; // For write mode all pins are out |
109 | struct lcd_pin_map const LCD_READ = {0,0,0,0,15}; // For read mode data pins are in |
110 | |
111 | |
112 | |
113 | BYTE lcd_read_byte() { |
114 | BYTE low,high; |
115 | set_tris_lcd(LCD_READ); |
116 | lcd.rw = 1; |
117 | delay_cycles(1); |
118 | lcd.enable = 1; |
119 | delay_cycles(1); |
120 | high = lcd.data; |
121 | lcd.enable = 0; |
122 | delay_cycles(1); |
123 | lcd.enable = 1; |
124 | delay_us(1); |
125 | low = lcd.data; |
126 | lcd.enable = 0; |
127 | set_tris_lcd(LCD_WRITE); |
128 | return( (high<<4) | low); |
129 | }
|
130 | |
131 | |
132 | void lcd_send_nibble( BYTE n ) { |
133 | lcd.data = n; |
134 | delay_cycles(1); |
135 | lcd.enable = 1; |
136 | delay_us(2); |
137 | lcd.enable = 0; |
138 | }
|
139 | |
140 | |
141 | void lcd_send_byte( BYTE address, BYTE n ) { |
142 | |
143 | lcd.rs = 0; |
144 | while ( bit_test(lcd_read_byte(),7) ) ; |
145 | lcd.rs = address; |
146 | delay_cycles(1); |
147 | lcd.rw = 0; |
148 | delay_cycles(1); |
149 | lcd.enable = 0; |
150 | lcd_send_nibble(n >> 4); |
151 | lcd_send_nibble(n & 0xf); |
152 | }
|
153 | |
154 | |
155 | |
156 | void lcd_init() { |
157 | BYTE i; |
158 | set_tris_lcd(LCD_WRITE); |
159 | lcd.rs = 0; |
160 | lcd.rw = 0; |
161 | lcd.enable = 0; |
162 | delay_ms(15); |
163 | for(i=1;i<=3;++i) { |
164 | lcd_send_nibble(3); |
165 | delay_ms(5); |
166 | }
|
167 | lcd_send_nibble(2); |
168 | for(i=0;i<=3;++i) |
169 | lcd_send_byte(0,LCD_INIT_STRING[i]); |
170 | }
|
171 | |
172 | |
173 | void lcd_gotoxy( BYTE x, BYTE y) { |
174 | BYTE address; |
175 | |
176 | if(y!=1) |
177 | address=lcd_line_two; |
178 | else
|
179 | address=0; |
180 | address+=x-1; |
181 | lcd_send_byte(0,0x80|address); |
182 | }
|
183 | |
184 | void lcd_putc( char c) { |
185 | switch (c) { |
186 | case '\f' : lcd_send_byte(0,1); |
187 | delay_ms(2); |
188 | break; |
189 | case '\n' : lcd_gotoxy(1,2); break; |
190 | case '\b' : lcd_send_byte(0,0x10); break; |
191 | default : lcd_send_byte(1,c); break; |
192 | }
|
193 | }
|
194 | |
195 | char lcd_getc( BYTE x, BYTE y) { |
196 | char value; |
197 | |
198 | lcd_gotoxy(x,y); |
199 | while ( bit_test(lcd_read_byte(),7) ); // wait until busy flag is low |
200 | lcd.rs=1; |
201 | value = lcd_read_byte(); |
202 | lcd.rs=0; |
203 | return(value); |
204 | }
|
205 | |
206 | /* lcd_set_CG() Set User-defineable Characters: Standard-Displays have up to 8 different Characters (max. 8x8=64 Byte, CG means Custom-Graphics)
|
207 | input: ChNum: Custom-Graphics Ram Address (0 .. 7), can be used e.g. by printf("%c", 0); for 1st CG or printf("\1"); for 2nd CG-Character
|
208 | Buffer: Address of a 8-Byte-Buffer containing the Pixel-Information: 1st Byte: Top Line (only 1st 5 Bits = Bit0..4 used)
|
209 | usage: unsigned char UserChar[8] = {0x00,0x00,0x00,0x1F,0x11,0x15,0x11,0x1F }; // 8 Bytes Pixel-Data: e.g. a square with a dot inside
|
210 | lcd_set_CG(3, UserChar); // set 4th CG-Ram to Pixel-Definition (8 user-defineable Characters possible (0 .. 7))
|
211 | printf(lcd_putc, "Hallo \3"); // printf 3rd char
|
212 | */
|
213 | void lcd_set_CG(BYTE ChNum, BYTE *Buffer) |
214 | {
|
215 | BYTE b; |
216 | lcd_send_byte(0, 0x40 | ((chnum & 0x07) << 3)); // Set CG-Address |
217 | for (b=0;b<=7;b++) |
218 | lcd_send_byte(1, Buffer[b ]); // Set 8 Bytes of Character-Data |
219 | }
|
220 | |
221 | /* lcd_cursor() Enable / Disable Cursor
|
222 | inputs: On: 1: enable Cursor: lower 5 Pixel (='Underline') at current Cursor-Pos is always on
|
223 | Blink: 1: Character at current Cursor-Pos blinks: all Pixels ON (5x8) alternate with current Character
|
224 | */
|
225 | void lcd_cursor(int1 On, int1 Blink) |
226 | {
|
227 | BYTE CursorCmd = 0x0C; // Display on/off control: 0x08, + Display always ON: 0x04 |
228 | if (Blink) |
229 | CursorCmd |= 0x01; // Character Blinks at Cursor-Pos |
230 | if (On) |
231 | CursorCmd |= 0x02; // Cursor ON |
232 | lcd_send_byte(0, CursorCmd); // Set Cursor-Command |
233 | }
|
Und hier meine Version die nicht funzt:
1 | ///////////////////////////////////////////////////////////////////////////
|
2 | //// LCD_WSH.C ////
|
3 | //// Driver for common LCD modules ////
|
4 | //// ////
|
5 | //// lcd_init() Must be called before any other function. ////
|
6 | //// ////
|
7 | //// lcd_putc(c) Will display c on the next position of the LCD. ////
|
8 | //// The following have special meaning: ////
|
9 | //// \f Clear display ////
|
10 | //// \n Go to start of second line ////
|
11 | //// \b Move back one position ////
|
12 | //// ////
|
13 | //// lcd_gotoxy(x,y) Set write position on LCD (upper left is 1,1) ////
|
14 | //// ////
|
15 | //// lcd_getc(x,y) Returns character at position x,y on LCD ////
|
16 | //// ////
|
17 | //// lcd_set_CG(ChNum, *Buffer) Sets Custom-Graphics for User-Chars. ////
|
18 | //// ChNum: User-Char 0 .. 7 ////
|
19 | //// *Buffer: 8 Bytes Pixel-Data. details: see below! ////
|
20 | //// ////
|
21 | //// lcd_cursor(On, Blink) Cursor-Functionaliy details: see below! ////
|
22 | //// ////
|
23 | ///////////////////////////////////////////////////////////////////////////
|
24 | //// (C) Copyright 1996,2003 Custom Computer Services ////
|
25 | //// This source code may only be used by licensed users of the CCS C ////
|
26 | //// compiler. This source code may only be distributed to other ////
|
27 | //// licensed users of the CCS C compiler. No other use, reproduction ////
|
28 | //// or distribution is permitted without written permission. ////
|
29 | //// Derivative programs created using this software in object code ////
|
30 | //// form are not restricted in any way. ////
|
31 | ///////////////////////////////////////////////////////////////////////////
|
32 | //// History: ////
|
33 | //// 09-06-27 Martin Scharfetter: adapted for use of ////
|
34 | //// Werkschulheim Felbertal, Salzburg, AUSTRIA: ////
|
35 | //// 16F876, 18F2550+BootLoader + defining Custom-Graphics: ////
|
36 | //// added lcd_set_CG() for up to 8 defineable Pixel-Chars ////
|
37 | //// 09-06-28 Martin Scharfetter: added Cursor-Control lcd_cursor() ////
|
38 | ///////////////////////////////////////////////////////////////////////////
|
39 | |
40 | // As defined in the following structure the pin connection is as follows:
|
41 | // PIC LCD
|
42 | // D0 enable
|
43 | // D1 rs
|
44 | // D2 rw
|
45 | // D3 not connected
|
46 | // D4 D4
|
47 | // D5 D5
|
48 | // D6 D6
|
49 | // D7 D7
|
50 | //
|
51 | // LCD pins D0-D3 are not used and PIC D3 is not used.
|
52 | |
53 | |
54 | struct lcd_pin_map { // This structure is overlayed |
55 | BOOLEAN enable; // on to an I/O port to gain |
56 | BOOLEAN rs; // access to the LCD pins. |
57 | BOOLEAN rw; // The bits are allocated from |
58 | BOOLEAN unused; // low order up. ENABLE will |
59 | int data : 4; // be pin B0. |
60 | } lcd; |
61 | |
62 | |
63 | #if defined(__PCH__)
|
64 | #if defined use_portb_lcd
|
65 | #byte lcd = 0xF81 // This puts the entire structure
|
66 | #elif defined use_portc_lcd
|
67 | #byte lcd = 0xF82 // This puts the entire structure
|
68 | #elif defined use_portd_lcd
|
69 | #byte lcd = 0xF83 // This puts the entire structure
|
70 | #else
|
71 | #error Port for LCD not defined: use '#define use_portX_lcd' before including LCD_WSH.C (X=>Port: b, c or d)!
|
72 | #endif
|
73 | #else
|
74 | #if defined use_portb_lcd
|
75 | #byte lcd = 0x6 // on to port B (at address 6)
|
76 | #elif defined use_portc_lcd
|
77 | #byte lcd = 0x7 // on to port C (at address 7)
|
78 | #elif defined use_portd_lcd
|
79 | #byte lcd = 0x8 // on to port D (at address 8)
|
80 | #else
|
81 | #error Port for LCD not defined: use '#define use_portX_lcd' before including LCD_WSH.C (X=>Port: b, c or d)!
|
82 | #endif
|
83 | #endif
|
84 | |
85 | #if defined use_portb_lcd
|
86 | #define set_tris_lcd(x) set_tris_b(x)
|
87 | #elif defined use_portc_lcd
|
88 | #define set_tris_lcd(x) set_tris_c(x)
|
89 | #elif defined use_portd_lcd
|
90 | #define set_tris_lcd(x) set_tris_d(x)
|
91 | #endif
|
92 | |
93 | |
94 | #define lcd_type 2 // 0=5x7, 1=5x10, 2=2 lines
|
95 | #define lcd_line_one 0x00 // LCD RAM address for the second line
|
96 | #define lcd_line_two 0x40 // LCD RAM address for the second line
|
97 | #define lcd_line_three 0x10 // LCD RAM address for the third line
|
98 | #define lcd_line_four 0x50 // LCD RAM address for the fourth line
|
99 | |
100 | |
101 | BYTE const LCD_INIT_STRING[4] = {0x20 | (lcd_type << 2), 0xc, 1, 6}; |
102 | // These bytes need to be sent to the LCD
|
103 | // to start it up.
|
104 | |
105 | |
106 | // The following are used for setting
|
107 | // the I/O port direction register.
|
108 | |
109 | struct lcd_pin_map const LCD_WRITE = {0,0,0,0,0}; // For write mode all pins are out |
110 | struct lcd_pin_map const LCD_READ = {0,0,0,0,15}; // For read mode data pins are in |
111 | |
112 | |
113 | |
114 | BYTE lcd_read_byte() { |
115 | BYTE low,high; |
116 | set_tris_lcd(LCD_READ); |
117 | lcd.rw = 1; |
118 | delay_cycles(1); |
119 | lcd.enable = 1; |
120 | delay_cycles(1); |
121 | high = lcd.data; |
122 | lcd.enable = 0; |
123 | delay_cycles(1); |
124 | lcd.enable = 1; |
125 | delay_us(1); |
126 | low = lcd.data; |
127 | lcd.enable = 0; |
128 | set_tris_lcd(LCD_WRITE); |
129 | return( (high<<4) | low); |
130 | }
|
131 | |
132 | |
133 | void lcd_send_nibble( BYTE n ) { |
134 | lcd.data = n; |
135 | delay_cycles(1); |
136 | lcd.enable = 1; |
137 | delay_us(2); |
138 | lcd.enable = 0; |
139 | }
|
140 | |
141 | |
142 | void lcd_send_byte( BYTE address, BYTE n ) { |
143 | |
144 | lcd.rs = 0; |
145 | while ( bit_test(lcd_read_byte(),7) ) ; |
146 | lcd.rs = address; |
147 | delay_cycles(1); |
148 | lcd.rw = 0; |
149 | delay_cycles(1); |
150 | lcd.enable = 0; |
151 | lcd_send_nibble(n >> 4); |
152 | lcd_send_nibble(n & 0xf); |
153 | }
|
154 | |
155 | |
156 | |
157 | void lcd_init() { |
158 | BYTE i; |
159 | set_tris_lcd(LCD_WRITE); |
160 | lcd.rs = 0; |
161 | lcd.rw = 0; |
162 | lcd.enable = 0; |
163 | delay_ms(15); |
164 | for(i=1;i<=3;++i) { |
165 | lcd_send_nibble(3); |
166 | delay_ms(5); |
167 | }
|
168 | lcd_send_nibble(2); |
169 | for(i=0;i<=3;++i) |
170 | lcd_send_byte(0,LCD_INIT_STRING[i]); |
171 | }
|
172 | |
173 | |
174 | void lcd_gotoxy( BYTE x, BYTE y) { |
175 | BYTE address; |
176 | |
177 | if(y=1) |
178 | address=lcd_line_one; |
179 | else if(y=2) |
180 | address=lcd_line_two; |
181 | else if(y=3) |
182 | address=lcd_line_three; |
183 | else if(y=4) |
184 | address=lcd_line_four; |
185 | else
|
186 | address=0; |
187 | address+=x-1; |
188 | lcd_send_byte(0,0x80|address); |
189 | }
|
190 | |
191 | void lcd_putc( char c) { |
192 | switch (c) { |
193 | case '\f' : lcd_send_byte(0,1); |
194 | delay_ms(2); |
195 | break; |
196 | case '\n' : lcd_gotoxy(1,2); break; |
197 | case '\b' : lcd_send_byte(0,0x10); break; |
198 | default : lcd_send_byte(1,c); break; |
199 | }
|
200 | }
|
201 | |
202 | char lcd_getc( BYTE x, BYTE y) { |
203 | char value; |
204 | |
205 | lcd_gotoxy(x,y); |
206 | while ( bit_test(lcd_read_byte(),7) ); // wait until busy flag is low |
207 | lcd.rs=1; |
208 | value = lcd_read_byte(); |
209 | lcd.rs=0; |
210 | return(value); |
211 | }
|
212 | |
213 | /* lcd_set_CG() Set User-defineable Characters: Standard-Displays have up to 8 different Characters (max. 8x8=64 Byte, CG means Custom-Graphics)
|
214 | input: ChNum: Custom-Graphics Ram Address (0 .. 7), can be used e.g. by printf("%c", 0); for 1st CG or printf("\1"); for 2nd CG-Character
|
215 | Buffer: Address of a 8-Byte-Buffer containing the Pixel-Information: 1st Byte: Top Line (only 1st 5 Bits = Bit0..4 used)
|
216 | usage: unsigned char UserChar[8] = {0x00,0x00,0x00,0x1F,0x11,0x15,0x11,0x1F }; // 8 Bytes Pixel-Data: e.g. a square with a dot inside
|
217 | lcd_set_CG(3, UserChar); // set 4th CG-Ram to Pixel-Definition (8 user-defineable Characters possible (0 .. 7))
|
218 | printf(lcd_putc, "Hallo \3"); // printf 3rd char
|
219 | */
|
220 | void lcd_set_CG(BYTE ChNum, BYTE *Buffer) |
221 | {
|
222 | BYTE b; |
223 | lcd_send_byte(0, 0x40 | ((chnum & 0x07) << 3)); // Set CG-Address |
224 | for (b=0;b<=7;b++) |
225 | lcd_send_byte(1, Buffer[b ]); // Set 8 Bytes of Character-Data |
226 | }
|
227 | |
228 | /* lcd_cursor() Enable / Disable Cursor
|
229 | inputs: On: 1: enable Cursor: lower 5 Pixel (='Underline') at current Cursor-Pos is always on
|
230 | Blink: 1: Character at current Cursor-Pos blinks: all Pixels ON (5x8) alternate with current Character
|
231 | */
|
232 | void lcd_cursor(int1 On, int1 Blink) |
233 | {
|
234 | BYTE CursorCmd = 0x0C; // Display on/off control: 0x08, + Display always ON: 0x04 |
235 | if (Blink) |
236 | CursorCmd |= 0x01; // Character Blinks at Cursor-Pos |
237 | if (On) |
238 | CursorCmd |= 0x02; // Cursor ON |
239 | lcd_send_byte(0, CursorCmd); // Set Cursor-Command |
240 | }
|
Die Adressen für die Zeilen des Displays sind laut Datenblatt für Zeile1 $00-$0F Zeile2 $40-$4F Zeile3 $10-$1F Zeile4 $50-$5F , was ich auch am Anfang für lcd_line_one, etc. definiert habe. Ich vermute dass in der Funktion lcd_gotoxy der Programmierfehler von mir liegt. Kann mir wer helfen? Danke! MfG Emanuel