Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Issues with driving 16x2 LCD

Status
Not open for further replies.

baileychic

Advanced Member level 3
Joined
Aug 2, 2017
Messages
728
Helped
56
Reputation
112
Reaction score
57
Trophy points
28
Activity points
7,033
I am having issues driving a 16x2 LCD.

Find the attached PDF. I have to write code for that LCD.

I am trying 4-bit mode.

Here is my code. All I get is black boxes on line 1. Line 2 is blank.

I ran LED blink and it runs fine and perfect.


Code C - [expand]
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
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
#define _XTAL_FREQ 4000000UL
 
// PIC18F4520 Configuration Bit Settings
 
// 'C' source line config statements
 
// CONFIG1H
#pragma config OSC = XT         // Oscillator Selection bits (XT oscillator)
#pragma config FCMEN = ON       // Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor enabled)
#pragma config IESO = OFF       // Internal/External Oscillator Switchover bit (Oscillator Switchover mode disabled)
 
// CONFIG2L
#pragma config PWRT = ON        // Power-up Timer Enable bit (PWRT enabled)
#pragma config BOREN = ON       // Brown-out Reset Enable bits (Brown-out Reset enabled and controlled by software (SBOREN is enabled))
#pragma config BORV = 2         // Brown Out Reset Voltage bits ()
 
// CONFIG2H
#pragma config WDT = OFF        // Watchdog Timer Enable bit (WDT disabled (control is placed on the SWDTEN bit))
#pragma config WDTPS = 1024     // Watchdog Timer Postscale Select bits (1:1024)
 
// CONFIG3H
#pragma config CCP2MX = PORTC   // CCP2 MUX bit (CCP2 input/output is multiplexed with RC1)
#pragma config PBADEN = OFF     // PORTB A/D Enable bit (PORTB<4:0> pins are configured as digital I/O on Reset)
#pragma config LPT1OSC = OFF    // Low-Power Timer1 Oscillator Enable bit (Timer1 configured for higher power operation)
#pragma config MCLRE = ON       // MCLR Pin Enable bit (MCLR pin enabled; RE3 input pin disabled)
 
// CONFIG4L
#pragma config STVREN = ON      // Stack Full/Underflow Reset Enable bit (Stack full/underflow will cause Reset)
#pragma config LVP = OFF        // Single-Supply ICSP Enable bit (Single-Supply ICSP disabled)
#pragma config XINST = OFF      // Extended Instruction Set Enable bit (Instruction set extension and Indexed Addressing mode disabled (Legacy mode))
 
// CONFIG5L
#pragma config CP0 = OFF        // Code Protection bit (Block 0 (000800-001FFFh) not code-protected)
#pragma config CP1 = OFF        // Code Protection bit (Block 1 (002000-003FFFh) not code-protected)
#pragma config CP2 = OFF        // Code Protection bit (Block 2 (004000-005FFFh) not code-protected)
#pragma config CP3 = OFF        // Code Protection bit (Block 3 (006000-007FFFh) not code-protected)
 
// CONFIG5H
#pragma config CPB = OFF        // Boot Block Code Protection bit (Boot block (000000-0007FFh) not code-protected)
#pragma config CPD = OFF        // Data EEPROM Code Protection bit (Data EEPROM not code-protected)
 
// CONFIG6L
#pragma config WRT0 = OFF       // Write Protection bit (Block 0 (000800-001FFFh) not write-protected)
#pragma config WRT1 = OFF       // Write Protection bit (Block 1 (002000-003FFFh) not write-protected)
#pragma config WRT2 = OFF       // Write Protection bit (Block 2 (004000-005FFFh) not write-protected)
#pragma config WRT3 = OFF       // Write Protection bit (Block 3 (006000-007FFFh) not write-protected)
 
// CONFIG6H
#pragma config WRTC = OFF       // Configuration Register Write Protection bit (Configuration registers (300000-3000FFh) not write-protected)
#pragma config WRTB = OFF       // Boot Block Write Protection bit (Boot block (000000-0007FFh) not write-protected)
#pragma config WRTD = OFF       // Data EEPROM Write Protection bit (Data EEPROM not write-protected)
 
// CONFIG7L
#pragma config EBTR0 = OFF      // Table Read Protection bit (Block 0 (000800-001FFFh) not protected from table reads executed in other blocks)
#pragma config EBTR1 = OFF      // Table Read Protection bit (Block 1 (002000-003FFFh) not protected from table reads executed in other blocks)
#pragma config EBTR2 = OFF      // Table Read Protection bit (Block 2 (004000-005FFFh) not protected from table reads executed in other blocks)
#pragma config EBTR3 = OFF      // Table Read Protection bit (Block 3 (006000-007FFFh) not protected from table reads executed in other blocks)
 
// CONFIG7H
#pragma config EBTRB = OFF      // Boot Block Table Read Protection bit (Boot block (000000-0007FFh) not protected from table reads executed in other blocks)
 
// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.
 
#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
 
#define _LCD_FIRST_ROW          0x80     //Move cursor to the 1st row
#define _LCD_SECOND_ROW         0xC0     //Move cursor to the 2nd row
#define _LCD_THIRD_ROW          0x94     //Move cursor to the 3rd row
#define _LCD_FOURTH_ROW         0xD4     //Move cursor to the 4th row
#define _LCD_CLEAR              0x01     //Clear display
#define _LCD_RETURN_HOME        0x02     //Return cursor to home position, returns a 
                                         //shifted display to its original position.
                                         //Display data RAM is unaffected.
#define _LCD_CURSOR_OFF         0x0C     //Turn off cursor
#define _LCD_UNDERLINE_ON       0x0E     //Underline cursor on
#define _LCD_BLINK_CURSOR_ON    0x0F     //Blink cursor on
#define _LCD_MOVE_CURSOR_LEFT   0x10     //Move cursor left without changing 
                                         //display data RAM
#define _LCD_MOVE_CURSOR_RIGHT  0x14     //Move cursor right without changing 
                                         //display data RAM
#define _LCD_TURN_ON            0x0C     //Turn Lcd display on
#define _LCD_TURN_OFF           0x08     //Turn Lcd display off
#define _LCD_SHIFT_LEFT         0x18     //Shift display left without changing 
                                         //display data RAM
#define _LCD_SHIFT_RIGHT        0x1E     //Shift display right without changing 
                                         //display data RAM
 
#define LCD_RS LATCbits.LATC0
#define LCD_EN LATCbits.LATC3
#define LCD_D4 LATCbits.LATC4
#define LCD_D5 LATCbits.LATC5
#define LCD_D6 LATCbits.LATC6
#define LCD_D7 LATCbits.LATC7
 
#define LCD_RS_Direction TRISCbits.TRISC0
#define LCD_EN_Direction TRISCbits.TRISC3
#define LCD_D4_Direction TRISCbits.TRISC4
#define LCD_D5_Direction TRISCbits.TRISC5
#define LCD_D6_Direction TRISCbits.TRISC6
#define LCD_D7_Direction TRISCbits.TRISC7
 
#define EN_DELAY 500
#define LCD_STROBE {LCD_EN = 1; __delay_us(EN_DELAY); LCD_EN = 0; __delay_us(EN_DELAY);};
 
#define LED_North LATAbits.LATA0
#define LED_East  LATAbits.LATA1
#define LED_West  LATAbits.LATA2
#define LED_South LATAbits.LATA3
 
const char txt1[] = "Project-1";
const char txt2[] = "Dam Gate Control";
 
char txt[32];
 
// copy const to ram string
char * CopyConst2Ram(char *dest, const char *src){
    char *d;
    d = dest;
 
    while(*src) {
       *dest++ = *src++;
    }
   
    return d;
}
 
void LCD_Cmd(char out_char) { 
    LCD_RS = 0;
    
    LCD_EN = 1;  
    LCD_D4 = (out_char & 0x10)?1:0;
    LCD_D5 = (out_char & 0x20)?1:0;
    LCD_D6 = (out_char & 0x40)?1:0;
    LCD_D7 = (out_char & 0x80)?1:0;
    //LCD_STROBE
    __delay_us(EN_DELAY);
    LCD_EN = 0;
  
    LCD_EN = 1;  
    LCD_D4 = (out_char & 0x01)?1:0;
    LCD_D5 = (out_char & 0x02)?1:0;
    LCD_D6 = (out_char & 0x04)?1:0;
    LCD_D7 = (out_char & 0x08)?1:0;
     __delay_us(EN_DELAY);
    LCD_EN = 0;
    //LCD_STROBE
 
    if(out_char == 0x01)__delay_ms(2);
}
 
void LCD_Chr(char row, char column, char out_char) { 
   /* 
   switch(row){ 
        case 1:
        LCD_Cmd(0x00 + (column - 1));
        break;
        case 2:
        LCD_Cmd(0x40 + (column - 1));
        break;
        case 3:
        LCD_Cmd(0x54 + (column - 1));
        break;
        case 4:
        LCD_Cmd(0x68 + (column - 1));
        break;
    }
   */
    
   switch(row){ 
    case 1:
        LCD_Cmd(0x80 + (column - 1));
        break;
        case 2:
        LCD_Cmd(0xC0 + (column - 1));
        break;
        case 3:
        LCD_Cmd(0x94 + (column - 1));
        break;
        case 4:
        LCD_Cmd(0xD4 + (column - 1));
        break;
     }
     
    LCD_RS = 1;
    /*  
    LCD_D4 = (out_char & 0x10)?1:0;
    LCD_D5 = (out_char & 0x20)?1:0;
    LCD_D6 = (out_char & 0x40)?1:0;
    LCD_D7 = (out_char & 0x80)?1:0;
    LCD_STROBE
 
    LCD_D4 = (out_char & 0x01)?1:0;
    LCD_D5 = (out_char & 0x02)?1:0;
    LCD_D6 = (out_char & 0x04)?1:0;
    LCD_D7 = (out_char & 0x08)?1:0;
    LCD_EN = 1;
    LCD_STROBE
    */
   
     LCD_EN = 1;  
    LCD_D4 = (out_char & 0x10)?1:0;
    LCD_D5 = (out_char & 0x20)?1:0;
    LCD_D6 = (out_char & 0x40)?1:0;
    LCD_D7 = (out_char & 0x80)?1:0;
    //LCD_STROBE
    __delay_us(EN_DELAY);
    LCD_EN = 0;
  
    LCD_EN = 1;  
    LCD_D4 = (out_char & 0x01)?1:0;
    LCD_D5 = (out_char & 0x02)?1:0;
    LCD_D6 = (out_char & 0x04)?1:0;
    LCD_D7 = (out_char & 0x08)?1:0;
     __delay_us(EN_DELAY);
    LCD_EN = 0;
    //LCD_STROBE 
}
 
void LCD_Chr_Cp(char out_char) { 
    LCD_RS = 1;
    /*
    LCD_D4 = (out_char & 0x10)?1:0;
    LCD_D5 = (out_char & 0x20)?1:0;
    LCD_D6 = (out_char & 0x40)?1:0;
    LCD_D7 = (out_char & 0x80)?1:0;
    LCD_STROBE
 
    LCD_D4 = (out_char & 0x01)?1:0;
    LCD_D5 = (out_char & 0x02)?1:0;
    LCD_D6 = (out_char & 0x04)?1:0;
    LCD_D7 = (out_char & 0x08)?1:0;
    LCD_EN = 1;
    LCD_STROBE
   */
   
    LCD_EN = 1;  
    LCD_D4 = (out_char & 0x10)?1:0;
    LCD_D5 = (out_char & 0x20)?1:0;
    LCD_D6 = (out_char & 0x40)?1:0;
    LCD_D7 = (out_char & 0x80)?1:0;
    //LCD_STROBE
    __delay_us(EN_DELAY);
    LCD_EN = 0;
  
    LCD_EN = 1;  
    LCD_D4 = (out_char & 0x01)?1:0;
    LCD_D5 = (out_char & 0x02)?1:0;
    LCD_D6 = (out_char & 0x04)?1:0;
    LCD_D7 = (out_char & 0x08)?1:0;
     __delay_us(EN_DELAY);
    LCD_EN = 0;
    //LCD_STROBE
} 
 
void LCD_Init() { 
    __delay_ms(200);
 
    LCD_RS_Direction = 0;
    LCD_EN_Direction = 0;
    LCD_D4_Direction = 0;
    LCD_D5_Direction = 0;
    LCD_D6_Direction = 0;
    LCD_D7_Direction = 0;
 
    LCD_RS = 0;
    LCD_EN = 0;
    LCD_D4 = 0;
    LCD_D5 = 0;
    LCD_D6 = 0;
    LCD_D7 = 0;    
    
    __delay_ms(60);
 
    LCD_D4 = 1;
    LCD_D5 = 1;
    LCD_D6 = 0;
    LCD_D7 = 0;
 
    LCD_STROBE
 
    __delay_ms(60);
 
    LCD_D4 = 1;
    LCD_D5 = 1;
    LCD_D6 = 0;
    LCD_D7 = 0;
 
    LCD_STROBE
 
    __delay_ms(60);
 
    LCD_D4 = 1;
    LCD_D5 = 1;
    LCD_D6 = 0;
    LCD_D7 = 0;
 
    LCD_STROBE
 
    __delay_ms(60);
 
    LCD_D4 = 0;
    LCD_D5 = 1;
    LCD_D6 = 0;
    LCD_D7 = 0;
 
    LCD_STROBE
 
    __delay_ms(20);
 
    LCD_Cmd(0x28);
    LCD_Cmd(0x06);
}
 
void LCD_Out(char row, char col, char *text) {
    while(*text)
         LCD_Chr(row, col++, *text++);
}
 
void LCD_Out_Cp(char *text) {
    while(*text)
         LCD_Chr_Cp(*text++);
}
 
int main(int argc, char** argv) {
    // Write your code here
    CMCON = 0x07;
    ADCON1 = 0x0F;
           
    TRISA = 0x30;
    TRISC = 0x00;
    
    LCD_Init();
    LCD_Cmd(_LCD_CURSOR_OFF);
    LCD_Cmd(_LCD_CLEAR);
    
    LCD_Out(1,1,CopyConst2Ram(txt,txt1));
    LCD_Out(2,1,CopyConst2Ram(txt,txt2));
    
   while(1) {
       LED_North = ~LED_North;
      __delay_ms(500);
   }
   
   return (EXIT_SUCCESS);
}

 

Attachments

  • LCD(2).pdf
    696.1 KB · Views: 98

You have a lot of duplicate code in there making it more difficult to read.

Note that writing commands and data to the LCD only differ by the level on the RS pin so you can combine the two routines quite easily. You probably don't need the 'copyConst2Ram' routine either.

Try writing a single routine, lets call it "Write2LCD(char Type, char Time, char Data)" where 'Type' is either 1 or 0 to specify whether data or a command is intended, 'T' is the delay after the transfer because some commands take longer than others and 'Data' is the actual payload. Then you can use something like:
Write2LCD(Cmd,10,Byte);
with everything in it. You can wrap the function in a loop to send complete strings.

Also note that if the design uses fixed wiring, you don't need all the bit to pin translation code, that would eliminate about 20% of your program in one step!

Brian.
 
The the LCD.pdf mentions about 8-bit interface. I need to use 4-bit interface.

My code works fine in Proteus but not on the hardware.

ON hardware all I get is black boxes on first line of LCD and 2nd line is clear.

In my code, ignore all commented codes. Just consider non-commented codes and reply.
 

You delay 500 us but only 500 ns is necessary.

You should probably also have the delay after setting LCD_EN = 0
In several places you set LCD_EN = 1 again with no delay.
 
Certainly it's a timing issue but your code is still much longer than needed. All those "LCD_D4 = (out_char & 0x10)?1:0;" and similar statements are to allow for the LCD to be driven from mixed ports, as you are driving the LCD only from one port you can do it much simpler by OR'ing and shifting the bits.

Consider:
high 4 bits of data to LCD = byte & 0xF0;
low 4 bits of data to LCD = (byte << 4); // may need to '& 0xF0' with the result, depends on the compiler.

Many of your "#defines" are duplicates or ignored later in the code too.

Brian.
 

Attachments

  • WhatsApp Image 2020-02-12 at 10.04.17 AM.jpeg
    WhatsApp Image 2020-02-12 at 10.04.17 AM.jpeg
    141.2 KB · Views: 100
  • WhatsApp Image 2020-02-12 at 10.06.56 AM.jpeg
    WhatsApp Image 2020-02-12 at 10.06.56 AM.jpeg
    106.6 KB · Views: 100
  • WhatsApp Image 2020-02-12 at 10.07.05 AM.jpeg
    WhatsApp Image 2020-02-12 at 10.07.05 AM.jpeg
    131.9 KB · Views: 102
  • WhatsApp Image 2020-02-12 at 10.07.22 AM.jpeg
    WhatsApp Image 2020-02-12 at 10.07.22 AM.jpeg
    134.4 KB · Views: 100
  • WhatsApp Image 2020-02-12 at 10.12.27 AM.jpeg
    WhatsApp Image 2020-02-12 at 10.12.27 AM.jpeg
    145.7 KB · Views: 102

Hi,

What about the RW signal of the LCD? How did you connect it?

Klaus
 
On the board, the Vss, Vo (Contrast adjust) and RW pins are shorted and grounded. They are hardwired.

This is my new code and it still has the same issue as before.

The new LCD code is also working fine in Proteus.

4 MHz Crystal on board.

ICD3 with external power is used for dumping the code to PIC on board.

Code:
#define _XTAL_FREQ 4000000UL

// PIC18F4520 Configuration Bit Settings

// 'C' source line config statements

// CONFIG1H
#pragma config OSC = XT         // Oscillator Selection bits (HS oscillator)
#pragma config FCMEN = OFF      // Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor disabled)
#pragma config IESO = OFF       // Internal/External Oscillator Switchover bit (Oscillator Switchover mode disabled)

// CONFIG2L
#pragma config PWRT = ON        // Power-up Timer Enable bit (PWRT enabled)
#pragma config BOREN = SBORDIS  // Brown-out Reset Enable bits (Brown-out Reset enabled in hardware only (SBOREN is disabled))
#pragma config BORV = 3         // Brown Out Reset Voltage bits (Minimum setting)

// CONFIG2H
#pragma config WDT = OFF        // Watchdog Timer Enable bit (WDT disabled (control is placed on the SWDTEN bit))
#pragma config WDTPS = 32768    // Watchdog Timer Postscale Select bits (1:32768)

// CONFIG3H
#pragma config CCP2MX = PORTC   // CCP2 MUX bit (CCP2 input/output is multiplexed with RC1)
#pragma config PBADEN = OFF     // PORTB A/D Enable bit (PORTB<4:0> pins are configured as digital I/O on Reset)
#pragma config LPT1OSC = OFF    // Low-Power Timer1 Oscillator Enable bit (Timer1 configured for higher power operation)
#pragma config MCLRE = ON       // MCLR Pin Enable bit (MCLR pin enabled; RE3 input pin disabled)

// CONFIG4L
#pragma config STVREN = ON      // Stack Full/Underflow Reset Enable bit (Stack full/underflow will cause Reset)
#pragma config LVP = OFF         // Single-Supply ICSP Enable bit (Single-Supply ICSP enabled)
#pragma config XINST = OFF      // Extended Instruction Set Enable bit (Instruction set extension and Indexed Addressing mode disabled (Legacy mode))

// CONFIG5L
#pragma config CP0 = OFF        // Code Protection bit (Block 0 (000800-001FFFh) not code-protected)
#pragma config CP1 = OFF        // Code Protection bit (Block 1 (002000-003FFFh) not code-protected)
#pragma config CP2 = OFF        // Code Protection bit (Block 2 (004000-005FFFh) not code-protected)
#pragma config CP3 = OFF        // Code Protection bit (Block 3 (006000-007FFFh) not code-protected)

// CONFIG5H
#pragma config CPB = OFF        // Boot Block Code Protection bit (Boot block (000000-0007FFh) not code-protected)
#pragma config CPD = OFF        // Data EEPROM Code Protection bit (Data EEPROM not code-protected)

// CONFIG6L
#pragma config WRT0 = OFF       // Write Protection bit (Block 0 (000800-001FFFh) not write-protected)
#pragma config WRT1 = OFF       // Write Protection bit (Block 1 (002000-003FFFh) not write-protected)
#pragma config WRT2 = OFF       // Write Protection bit (Block 2 (004000-005FFFh) not write-protected)
#pragma config WRT3 = OFF       // Write Protection bit (Block 3 (006000-007FFFh) not write-protected)

// CONFIG6H
#pragma config WRTC = OFF       // Configuration Register Write Protection bit (Configuration registers (300000-3000FFh) not write-protected)
#pragma config WRTB = OFF       // Boot Block Write Protection bit (Boot block (000000-0007FFh) not write-protected)
#pragma config WRTD = OFF       // Data EEPROM Write Protection bit (Data EEPROM not write-protected)

// CONFIG7L
#pragma config EBTR0 = OFF      // Table Read Protection bit (Block 0 (000800-001FFFh) not protected from table reads executed in other blocks)
#pragma config EBTR1 = OFF      // Table Read Protection bit (Block 1 (002000-003FFFh) not protected from table reads executed in other blocks)
#pragma config EBTR2 = OFF      // Table Read Protection bit (Block 2 (004000-005FFFh) not protected from table reads executed in other blocks)
#pragma config EBTR3 = OFF      // Table Read Protection bit (Block 3 (006000-007FFFh) not protected from table reads executed in other blocks)

// CONFIG7H
#pragma config EBTRB = OFF      // Boot Block Table Read Protection bit (Boot block (000000-0007FFh) not protected from table reads executed in other blocks)

#include <xc.h>

void Init_LCD(void); // Initialize the LCD
void LCD_sendCW(char); // 8-bit Control word for LCD
void LCD_sendData(char); // 8-bit Text Data for LCD
void LCD_home(void);
void LCD_goto(char row, char column);

#define LCD_DATA LATC
#define LCD_RS LATCbits.LATC0	// RS signal for LCD
#define LCD_E LATCbits.LATC3		// E signal for LCD

#define SSD_DATA_PORT LATD
#define SSD_DIGIT1_PIN LATEbits.LATE0
#define SSD_DIGIT2_PIN LATEbits.LATE1
#define DIGIT1 0
#define DIGIT2 1

char txt1[] = "Project-Group 6";
char txt2[] = "Dam Gate Control";

char MESS[] = "WELCOME";

unsigned int counter = 0;
unsigned int count = 500;

int dummyCounter = 0;
const char ccMask[] = {0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90};
char selectDigit = 0;
char digits[2] = {0, 0};

//Timer1
//Prescaler 1:1; TMR1 Preload = 64536; Actual Interrupt Time : 1 ms
void InitTimer1() {
  T1CON = 0x01;
  PIR1bits.TMR1IF = 0;
  TMR1H = 0xFC;
  TMR1L = 0x18;
  TMR1IE = 1;
  INTCON	= 0xC0;
}

void __interrupt () my_isr_routine (void) {
   if ((PIE1bits.TMR1IE) && (PIR1bits.TMR1IF)) { 
    PIR1bits.TMR1IF = 0;
    TMR1H = 0xFC;
    TMR1L = 0x18;
    //Enter your code here
     //LATE = 0x03; 
     SSD_DIGIT1_PIN = 1;
     SSD_DIGIT2_PIN = 1;
      
      switch(selectDigit) {
	 case DIGIT1:
	       if(dummyCounter >= 10) {
		  SSD_DATA_PORT = ccMask[digits[0]];
		  SSD_DIGIT1_PIN = 0;
	       }
	       break;
	 case DIGIT2:
	       //if(dummyCounter >= 0) {
		  SSD_DATA_PORT = ccMask[digits[1]];
		  SSD_DIGIT2_PIN = 0;
	       //}
	       break;       	 
      };

      if(++selectDigit >= 2)selectDigit = 0;
  }
}

void main(void) {
    ADCON1 = 0x0F; // Set ports A,B & E as digital I/O
    TRISC = 0; // Port C all outputs.
    TRISD = 0;
    TRISE = 0;
   
    LATD = 0xFF; 
    LATE = 0x03;
   
    Init_LCD(); // Init LCD 8-bit interface,multiple line
    InitTimer1();

    while (1) {
        int i;
        LCD_home(); // Return cursor to home position
        for (i = 0; txt1[i] != 0; i++) {
            LCD_sendData(txt1[i]);
        }
        LCD_goto(1, 0);
        for (i = 0; txt2[i] != 0; i++) {
            LCD_sendData(txt2[i]);
        }
	
	digits[0] = dummyCounter / 10;
	digits[1] = dummyCounter % 10;
	_delay(1000000);
	
	if(++dummyCounter >= 100)dummyCounter = 0;	   	
    }
}

/* LCD display initialization */
void Init_LCD() {
    _delay(50000); // Wait for more than 40 ms
    LCD_sendCW(0b0011); // Function set  (Interface is 8 bits long.)
    _delay(5000); // Wait for more than 4.1 ms
    LCD_sendCW(0b0011); // Function set  (Interface is 8 bits long.)
    LCD_sendCW(0b0011); // Function set  (Interface is 8 bits long.)
    LCD_sendCW(0b0010); // Function set  (Interface is 8 bits long.)
    LCD_sendCW(0b0010); // Function set  0 0 1 DL N F * *
    LCD_sendCW(0b1000); // DL=0: 4-bits, N=1: 1-line, F=0: 5×8-dots
    LCD_sendCW(0b0000); // Display off   0 0 0 0 1 D C B
    LCD_sendCW(0b1100); // D=1:display on,C=0:cur off,B=0 blink off
    LCD_sendCW(0b0000); // Display clear
    LCD_sendCW(0b0001); // Clears display and sets DDRAM address 0
    LCD_sendCW(0b0000); // Entry mode set 0 0 0 0 0 1 I/D S
    LCD_sendCW(0b0110); // I/D=1: increment, S=0: no display shift
}

/* Write control word to LCD */
void LCD_sendCW(char c) {
    char temp;
    LCD_RS = 0;
    LCD_E = 1;
    temp = LCD_DATA & 0b1111;
    LCD_DATA = temp | c << 4;
    LCD_E = 0;
    _delay(2000); // 2 ms delay
}

/* Write text data to LCD */
void LCD_sendData(char c) {
    char temp;
    LCD_RS = 1;
    LCD_E = 1;
    temp = LCD_DATA & 0b00001111; // clear top nibble & save bottom nibble
    LCD_DATA = temp | (c & 0b11110000); // send top nibble
    LCD_E = 0;
    _delay(100); // 100 us delay
    LCD_E = 1;
    temp = LCD_DATA & 0b00001111; // clear top nibble & save bottom nibble 
    LCD_DATA = temp | (c << 4); // send bottom nibble
    LCD_E = 0;
    _delay(100); // 100 us delay
}

void LCD_home(void) {
    LCD_sendCW(0b0000);
    LCD_sendCW(0b0010);
}

void LCD_goto(char row, char column) {
    unsigned char temp;
    if (row == 1) {
        temp = 0xC0U + column;
    } else {
        temp = 0x80U + column;
    }
    LCD_sendCW(temp >> 4);
    LCD_sendCW(temp & 0b00001111);
}



Edit:


New/Old LCD code still not working on the board. Don't know the issue.

I am using ICD3 and it doesn't power PIC on board while doing ICSP and so I am using an external 9V DC adapter to power the board.

After dumping the code to PIC on board I am resetting the PIC.

Same issue with LCD as before.

LED Blink code works fine.

LVP = ON? or OFF?

LVP - low voltage programming.

I guess PIC uses 12V Vpp to do normal ICSP.

Is LVP = ON needed for a 9V VPP?
 
Last edited:

/* Write text data to LCD */
void LCD_sendData(char c) {
char temp;
LCD_RS = 1;
LCD_E = 1;
temp = LCD_DATA & 0b00001111; // clear top nibble & save bottom nibble
LCD_DATA = temp | (c & 0b11110000); // send top nibble
LCD_E = 0;
_delay(100); // 100 us delay
LCD_E = 1;
temp = LCD_DATA & 0b00001111; // clear top nibble & save bottom nibble
LCD_DATA = temp | (c << 4); // send bottom nibble
LCD_E = 0;
_delay(100); // 100 us delay
}
That is risky code!
Use a variable to hold the LCD data before writing it back, there is no guarantee the lower bits of LATC hold the data on the pins, in fact if the lower bits of PORTC are used for anything else the LATC register could hold something completely different.
I would use (using your symbols):
LCD_DATA &= 0b00001111; // clear the top 4 bits
LCD_DATA |= new data in top 4 bits.
then latch the data to the LCD.

You don't need a negative Vee, connect a potentiometer between ground and supply to set the contrast. If you ground Vee the contrast may be too high and the pixels you don't want will also be turned on, giving the apperance of 'boxes'.

LVP is only used to program the PIC. Use LVP if you do not have an external programmer but you do sacrifice the ability to use the LVP pin for other things. Also make sure it is NOT in programming mode when in normal use. If you are feeding VPP to the MCLR pin, keep the LVP turned off.

Brian.
 

I think you identified a problem with the fact that the display shows black squares and that - V0 - contrast - is wired to ground. Black squares are a contrast issue, and the contrast pin - V0 - needs to be adjusted to the appropriate voltage between Vcc and ground. This is usually done, as you noted, with a potentiometer. The pot is connected between Vcc and ground, with the wiper connected to V0.
 
Just seen this thread. The black squares is the classic 'contrast' issue with these LCD displays as @FenTrac has pointed out.
The thing I find fascinating is that it took 10 posts (5 from people other than the OP) to mention it.
Susan
 

In addition, most likely the working circuit running in simulation not being exactly the same on assembly; in Proteus the model is based on the HD44780 controller whose contrast voltage (Vo) is specified between 0v and 5v (Vcc) whereas for the one used on the above assembly (ST7066), Vo is recommended to be in the range of Vcc-10v to Vcc, typically -5v to +5v.
 
Hi,

The black squares is the classic 'contrast' issue with these LCD displays
I don't think so.
In post#6 we see the display. If there was the classic contrast problem, then all digits are identically dark.
But in the picture we see that one line is dark, while the other line is not.

--> I assume the display is not properly initialized.
Maybe wrong signal timing, wrong signal levels, wrong initialisation sequence..

Klaus
 
Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top