PIC16F1459 & LCD PC1602LRS config

nerdegutta

Joined Dec 15, 2009
2,684
Maybe none, but it is needed in ICSP? Without seeing you programming breadboard, I'll assume that we can consider that as ICSP. I allways use a 10K.
 

Thread Starter

Jswale

Joined Jun 30, 2015
121
The ICSP does work because it is the same set up as I have used in previous projects, So it must be the initialization of the ports or perhaps the LCD is blocking inputs somehow. It is very confusing.
 

JohnInTX

Joined Jun 26, 2012
4,787
If you have built the project for running without a debugger and are pulling the chip out of the proto board and programming it in separate programmer, you don't have to worry about the ISCP pins.
You SHOULD pull MCLR/ up with some resistor OR turn MCLRE off in the config bit #pragmas. Either one will work fine. The fact that you are getting something out of the PIC says its running.

If you want to debug on the proto board, and you should, then you need to install a header that picks up the two ISCP pins as well as GND, Vdd and Vpp (on the MCLR/ pin) for the PICkit. Turn low voltage programming OFF in the config #pragmas. On your PIC, the ICSP pins are RC0 and RC1 which are shared by the LCD bus. You want to avoid that. Move the databus to RC4-7 and fix up writeLCD() that outputs to the bus. Relocate E and RS either to RC2,3 or another port. That's done in a #define so you can do it without messing with the source.

There is a bug in writeLCD() anyway.. It always sets RS=0.
 

JohnInTX

Joined Jun 26, 2012
4,787
FWIW
Here's the code with LCD data moved to RC7-4, E on RC3 and RS on RC2. ICSP pins RC1,0 can now be used for programming/debug with a PICkit. Fixed up writeLCD() and lcd_reset for new data bus. MCLR/ is still enabled so you need to pull it up. It wouldn't hurt to have a button to reset the PIC by hand. I turned on the power up timer.

C:
#include <xc.h>
#define _XTAL_FREQ 31250

// PIC16F1459 Configuration Bit Settings
// 'C' source line config statements

// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.

// CONFIG1
#pragma config FOSC = INTOSC    // Oscillator Selection Bits (INTOSC oscillator: I/O function on CLKIN pin)
#pragma config WDTE = OFF       // Watchdog Timer Enable (WDT disabled)
#pragma config PWRTE = ON      // Power-up Timer Enable (PWRT enabled
#pragma config MCLRE = ON       // MCLR Pin Function Select (MCLR/VPP pin function is MCLR) - PULL UP PIN 4 OR TURN THIS OFF
#pragma config CP = OFF         // Flash Program Memory Code Protection (Program memory code protection is disabled)
#pragma config BOREN = OFF      // Brown-out Reset Enable (Brown-out Reset disabled)
#pragma config CLKOUTEN = OFF   // Clock Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin)
#pragma config IESO = ON        // Internal/External Switchover Mode (Internal/External Switchover Mode is enabled)
#pragma config FCMEN = ON       // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor is enabled)

// CONFIG2
#pragma config WRT = OFF        // Flash Memory Self-Write Protection (Write protection off)
#pragma config CPUDIV = CLKDIV6 // CPU System Clock Selection Bit (CPU system clock divided by 6)
#pragma config USBLSCLK = 48MHz // USB Low SPeed Clock Selection bit (System clock expects 48 MHz, FS/LS USB CLKENs divide-by is set to 8.)
#pragma config PLLMULT = 3x     // PLL Multipler Selection Bit (3x Output Frequency Selected)
#pragma config PLLEN = ENABLED  // PLL Enable Bit (3x or 4x PLL Enabled)
#pragma config STVREN = ON      // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will cause a Reset)
#pragma config BORV = LO        // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.)
#pragma config LPBOR = OFF      // Low-Power Brown Out Reset (Low-Power BOR is disabled)
#pragma config LVP = OFF        // Low-Voltage Programming Enable (High-voltage on MCLR/VPP must be used for programming)

//The pins used are same as explained earlier
#define lcd_port  LATC        // write to LAT, read from PORT
// RC7-4 is the LCD 4 bit databus
#define LCD_RSout LATC2     // moved from ICSP
#define LCD_ENout LATC3

// RC0,RC1 reserved for ICSP DEBUG

//--------------------- STROBE LCD ---------------------------
// Pulses E line on LCD to write
int strobeLCD(void)
{
LCD_ENout = 1;
__delay_us(1);
LCD_ENout = 0;
}

//--------------------- WRITE 8 BIT DATA TO LCD  -----------------
// Assumes LCD is ready and RS is set to correct value
// LCD data bus is RC4-RC7
void writeLCD(unsigned char dat)
{
    lcd_port &= 0x0f;               // get current port, clear upper bits
    lcd_port |= (dat & 0xf0);       // combine w/upper nibble, leave lower same
    strobeLCD();

    lcd_port &= 0x0f;               // get current port, clear upper bits
    lcd_port |= ((dat <<4) & (0xf0)); // combine w/lower nibble, leave lower port same
    strobeLCD();

    __delay_us(200);                // wait for display to process
}

//-------------------- WRITE LCD COMMAND  --------------------
// Assumes E is low and display is NOT busy
void lcd_cmd (unsigned char cmd)
{
    LCD_RSout = 0;       // select command register
    writeLCD(cmd);
}

//---------------------- WRITE LCD DATA  --------------------------

void lcd_data (unsigned char dat)
{
    LCD_RSout = 1;       // select data register
    writeLCD(dat);
}

//-------------------- RESET/CONFIGURE LCD  -------------------------
// Delays are generous, trim when able
void lcd_reset()
{
    lcd_port &= 0x0f;       // clear upper bits of LCD port
    lcd_port |= 0x30;       // direct data to LCD DB7-4
    LCD_RSout = 0;

    strobeLCD();        // write 3h, wait 10ms
    __delay_ms(10);

    strobeLCD();        // write 3h, wait..
    __delay_ms(10);

     strobeLCD();       // write 3h
    __delay_ms(10);
}

//------------------------ INIT AND CONFIGURE LCD  ---------------------
void lcd_init ()
{
    lcd_reset();         // LCD reset
    lcd_cmd(0x28);       // Funciton Set: 4-bit mode - 2 line - 5x7 font.
    lcd_cmd(0x0C);       // Display no cursor - no blink.
    lcd_cmd(0x06);       // Automatic Increment - No Display shift.
    lcd_cmd(0x80);       // Address DDRAM with 0 offset 80h.
}

//======================= MAIN =====================================
void main ()
{
    TRISC=0b00000000;
    PORTC=0b00000000;
    ANSELC=0b00000000;
    TRISB=0b00000000;
    PORTB=0b00000000;
    ANSELB=0b00000000;
    TRISA=0b00000000;
    PORTA=0b00000000;
    ANSELA=0b00000000;

    __delay_ms(300);         // power up delay for LCD

    lcd_init();
    lcd_data('H');
    lcd_data('E');
    lcd_data('L');
    lcd_data('L');
    lcd_data('O');

    while(1);       // wait forever
}
 

JohnInTX

Joined Jun 26, 2012
4,787
I mentioned that it would be a success if we got to a cursor .. so update lcd_init: change lcd_cmd(0x0C) to lcd_cmd(oxoE) to turn it on.
 

Thread Starter

Jswale

Joined Jun 30, 2015
121
/The debug wont work, saying that there is a configuration bit conflict because4 LVP is enabled (which it is not) and that once it disables it tells me to enable it to program,

I ran the code without debug and the voltages are logic voltages when the LCD is not plugged in, however do not change so are just a steady DC level, e.g 5V and once the LCD is plugged in it seems to short it out somehow. My only thoughts are a faulty LCD because it all looks fine in the simulator. Not sure why the levels are not square waves and are just steady lines though.------------> All 5V EXCEPT Enable.

@nerdegutta did you manage to get it to work on any of your ICs?

I am losing the will to live!
 
Last edited:

Thread Starter

Jswale

Joined Jun 30, 2015
121
I have got rid of all connections as a test and just have VDD and VSS connected to the PIC, I have been scoping the data bus, EN and RS and none of them deliver a square wave, only steady DC values.... I have not changed the code and have even tried the code in post #24 with no luck, even though I got square waves out last time!
 

nerdegutta

Joined Dec 15, 2009
2,684
I'm currently on a PIC16F688 project, with 16x02 LCD. This is already breadboarded, with ICSP, so I thought that I could use that. I got a PICKit3 to program it. The code from post #46 was altered to suit the PIC 16F688.

This is my program running:
C:
// INCLUDES
#include <xc.h>
#include <stdio.h>
#include <stdlib.h>

// CONFIG
#pragma config FOSC = INTOSCIO  // Oscillator Selection bits (INTOSCIO oscillator: I/O function on RA4/OSC2/CLKOUT pin, I/O function on RA5/OSC1/CLKIN)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = ON       // Power-up Timer Enable bit (PWRT enabled)
#pragma config MCLRE = ON       // MCLR Pin Function Select bit (MCLR pin function is MCLR)
#pragma config CP = OFF         // Code Protection bit (Program memory code protection is disabled)
#pragma config CPD = OFF        // Data Code Protection bit (Data memory code protection is disabled)
#pragma config BOREN = OFF      // Brown Out Detect (BOR disabled)
#pragma config IESO = ON        // Internal External Switchover bit (Internal External Switchover mode is enabled)
#pragma config FCMEN = ON       // Fail-Safe Clock Monitor Enabled bit (Fail-Safe Clock Monitor is enabled)

// DEFINES
#define _XTAL_FREQ 31250
#define lcd_port TRISC    
#define LCD_RSout PORTAbits.RA0
#define LCD_ENout PORTAbits.RA2

//--------------------- STROBE LCD ---------------------------
// Pulses E line on LCD to write
int strobeLCD(void)
{
LCD_ENout = 1;
__delay_us(1);
LCD_ENout = 0;
}
//--------------------- WRITE 8 BIT DATA TO LCD  -----------------
// Assumes LCD is ready and RS is set to correct value
// LCD data bus is RC4-RC7
void writeLCD(unsigned char dat)
{
    lcd_port &= 0x0f;               // get current port, clear upper bits
    lcd_port |= (dat & 0xf0);       // combine w/upper nibble, leave lower same
    strobeLCD();
    lcd_port &= 0x0f;               // get current port, clear upper bits
    lcd_port |= ((dat <<4) & (0xf0)); // combine w/lower nibble, leave lower port same
    strobeLCD();
    __delay_us(200);                // wait for display to process
}
//-------------------- WRITE LCD COMMAND  --------------------
// Assumes E is low and display is NOT busy
void lcd_cmd (unsigned char cmd)
{
    LCD_RSout = 0;       // select command register
    writeLCD(cmd);
}
//---------------------- WRITE LCD DATA  --------------------------
void lcd_data (unsigned char dat)
{
    LCD_RSout = 1;       // select data register
    writeLCD(dat);
}
//-------------------- RESET/CONFIGURE LCD  -------------------------
// Delays are generous, trim when able
void lcd_reset()
{
    lcd_port &= 0x0f;       // clear upper bits of LCD port
    lcd_port |= 0x30;       // direct data to LCD DB7-4
    LCD_RSout = 0;
    strobeLCD();        // write 3h, wait 10ms
    __delay_ms(10);
    strobeLCD();        // write 3h, wait..
    __delay_ms(10);
     strobeLCD();       // write 3h
    __delay_ms(10);
}
//------------------------ INIT AND CONFIGURE LCD  ---------------------
void lcd_init ()
{
    lcd_reset();         // LCD reset
    lcd_cmd(0x28);       // Funciton Set: 4-bit mode - 2 line - 5x7 font.
    lcd_cmd(0x0E);       // Display cursor -  blink.
    lcd_cmd(0x06);       // Automatic Increment - No Display shift.
    lcd_cmd(0x80);       // Address DDRAM with 0 offset 80h.
}
//======================= MAIN =====================================
void main ()
{
    TRISC=0b00000000;
    PORTC=0b00000000;
    ANSEL=0b00000000;
    //ANSELB=0b00000000;
    TRISA=0b00000000;
    PORTA=0b00000000;
    //ANSELA=0b00000000;
    CMCON0 = 0x07;
    __delay_ms(300);         // power up delay for LCD
    lcd_init();
    //lcd_data('H');
    //lcd_data('E');
    //lcd_data('L');
    //lcd_data('L');
    //lcd_data('O');
    while(1);       // wait forever
}
Connection:
PIC 16F688 PIN
1 - VDD
2 - NC
3 - NC
4 - MLCR, connected to VDD with a 10K resistor
5 - NC
6 - NC
7 - RC3 - D7
8 - RC2 - D6
9 - RC1 - D5
10- RC0 - D4
11 - RA2 - Enable
12 - NC
13 - RA0 - RS
14 - VSS


I get only the blinking cursor. When I tried to uncomment the lcd_data lines, I got some signs that makes no sense.

I have not used an oscilloscope on the pins.
 

nerdegutta

Joined Dec 15, 2009
2,684
According to the datasheet for the 16F688: PORT is bi-directional, and the corresponding datadirection register is TRIS.

My IC do not have LAT, but TRIS.
 

Thread Starter

Jswale

Joined Jun 30, 2015
121
Tried the above and all my Pins read 0V......The simulator looks fine though on MPLAB.

I have no connections after programming apart from:

VDD, VSS and a 10k between VDD and MCLRE
 

Thread Starter

Jswale

Joined Jun 30, 2015
121
Took it back to a single square wave interval 10ms using the enable pin and all worked fine... so this if anything confuses the situation more.
 
Top