Hot!LCD String write issue

Author
Trackhappy
Starting Member
  • Total Posts : 51
  • Reward points : 0
  • Joined: 2016/11/03 16:07:08
  • Location: 0
  • Status: offline
2018/11/02 02:41:10 (permalink)
0

LCD String write issue

Hi all,
I am a newbie to code, hobby only 2 years "playing". I have tried to read all I can but no real training. I have manage to design and bring to life a Dalek Voice Modulator using a dsPIC33 though.
New project is 18F26K40 using 

Product Version: MPLAB X IDE v5.05
XC8 V2.00.
Pic Kit 3.
The project is to control a pump, but the LCD display is eluding me. I can write to a specific location and display a character, but trying to write a string doesn't work. I get no compile errors, but just a flashing cursor after the initialisation (which works as expected). I get Init on both lines from the initialisation, then the screen clears and I get a flashing cursor (configured that way) on the top line. I have tried several variations of the write string function, with no success. It just refuses to show a character when using the write string function. 
 
I am stumped. The display is a SD1602GULB, which is QP5512 from Jaycar in Australia (local electronics store). It may be odd in that the first line start address is 0x80 and line 2 is 0xC0, which seems to be at odds with standard displays, but everything else seems the same.
 
Any ideas to guide me forward???

// 18F26K40 Configuration Bit Settings

// CONFIG1L
#pragma config FEXTOSC = OFF // ->External Oscillator not enabled
#pragma config RSTOSC = HFINTOSC_64MHZ // ->HFINTOSC with HFFRQ = 64 MHz and CDIV = 1:1
// CONFIG1H
#pragma config CLKOUTEN = OFF // ->CLKOUT function is disabled
#pragma config CSWEN = ON // ->Writing to NOSC and NDIV is allowed
#pragma config FCMEN = OFF // Fail-Safe Clock Monitor Enable bit->Fail-Safe Clock Monitor disabled

// CONFIG2L
#pragma config MCLRE = EXTMCLR // ->If LVP = 0, MCLR pin is MCLR; If LVP = 1, RE3 pin function is MCLR
#pragma config PWRTE = OFF // Power-up Timer Enable bit->Power up timer disabled
#pragma config LPBOREN = OFF // ->ULPBOR disabled
#pragma config BOREN = OFF // Brown-out Reset Enable bits->Brown-out Reset disabled

// CONFIG2H
#pragma config BORV = VBOR_2P45 // Brown Out Reset Voltage selection bits->Brown-out Reset Voltage (VBOR) set to 2.45V
#pragma config ZCD = OFF // ZCD Disable bit->ZCD disabled. ZCD can be enabled by setting the ZCDSEN bit of ZCDCON
#pragma config PPS1WAY = ON // PPSLOCK bit One-Way Set Enable bit->PPSLOCK bit can be cleared and set only once; PPS registers remain locked after one clear/set cycle
#pragma config STVREN = ON // Stack Full/Underflow Reset Enable bit->Stack full/underflow will cause Reset
#pragma config DEBUG = OFF // Debugger Enable bit->Background debugger disabled
#pragma config XINST = OFF // Extended Instruction Set Enable bit->Extended Instruction Set and Indexed Addressing Mode disabled

// CONFIG3L
#pragma config WDTCPS = WDTCPS_31 // ->Divider ratio 1:65536; software control of WDTPS
#pragma config WDTE = OFF // WDT operating mode->WDT Disabled

// CONFIG3H
#pragma config WDTCWS = WDTCWS_7 // WDT Window Select bits->window always open (100%); software control; keyed access not required
#pragma config WDTCCS = SC // WDT input clock selector->Software Control

// CONFIG4L
#pragma config WRT0 = OFF // Write Protection Block 0->Block 0 (000800-003FFFh) not write-protected
#pragma config WRT1 = OFF // Write Protection Block 1->Block 1 (004000-007FFFh) not write-protected
#pragma config WRT2 = OFF // Write Protection Block 2->Block 2 (008000-00BFFFh) not write-protected
#pragma config WRT3 = OFF // Write Protection Block 3->Block 3 (00C000-00FFFFh) not write-protected

// CONFIG4H
#pragma config WRTC = OFF // Configuration Register Write Protection bit->Configuration registers (300000-30000Bh) 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
#pragma config SCANE = ON // ->Scanner module is available for use, SCANMD bit can control the module
#pragma config LVP = ON // Low Voltage Programming Enable bit->HV on MCLR/VPP must be used for programming

// CONFIG5L
#pragma config CP = OFF // UserNVM Program Memory Code Protection bit->UserNVM code protection disabled
#pragma config CPD = OFF // DataNVM Memory Code Protection bit->DataNVM code protection disabled

// CONFIG6L
#pragma config EBTR0 = OFF // Table Read Protection Block 0->Block 0 (000800-003FFFh) not protected from table reads executed in other blocks
#pragma config EBTR1 = OFF // Table Read Protection Block 1->Block 1 (004000-007FFFh) not protected from table reads executed in other blocks
#pragma config EBTR2 = OFF // Table Read Protection Block 2->Block 2 (008000-00BFFFh) not protected from table reads executed in other blocks
#pragma config EBTR3 = OFF // Table Read Protection Block 3->Block 3 (00C000-00FFFFh) not protected from table reads executed in other blocks

// CONFIG6H
#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> /* XC8 General Include File */
#include <stdint.h> /* For uint8_t definition */
#include <stdbool.h> /* For true/false definition */
#include <stdio.h>

#define _XTAL_FREQ 64000000 //Define 64Mb used for __delay_()
#define PressureSensor RA0 //Analog sensor 0.5-4.5 volts linear 0-100PSI
#define FlowSensorPin RA1 //Digital sensor - Flow pulse characteristics: (8.1Q-3) Q = L / Min ± 10% 15L/Min = 118.5 PPS
#define LED LATCbits.LATC4 //Test LED pin


/****************** PIN Mapping *******************/
#define RS LATCbits.LATC5
#define RW LATCbits.LATC6
#define EN LATCbits.LATC7
#define BF PORTBbits.RB7
#define DATAPORT LATB

/************** Line Addr Mapping ******************/
#define LCD_LINE1 0x80
#define LCD_LINE2 0xC0
#define LCD_LINE3 0x94
#define LCD_LINE4 0xD4

#define CLRSCR 0x01
#define DISPLAY_ON 0x0C
#define DISPLAY_OFF 0x08
#define DISPLAY_HOME 0x02
#define CURSOR_ON 0x0A
#define CURSOR_OFF 0x08
#define CURSOR_INC 0x06
#define MODE_8BIT 0x38
#define MODE_4BIT 0x28


/******************************************************************************/
/* User Global Variable Declaration */
/******************************************************************************/

void PLL_Init();
void TIMER_Init();
void PIN_Init();

void LCD_Init(void);
void LCD_data(unsigned char data);
void LCD_cmd(unsigned char cmd);
//void LCD_string(const rom char *ptr);
void LCD_string(unsigned char *buffer);
void LCD_isbusy(void);



void LCD_blink(void);



void main(void)
{
   NVMCON1|=0x80; //errata fix for table array issue

 
 
    PLL_Init(); //Configure the oscillator for the device
    TIMER_Init(); //Configure timers
    PIN_Init(); //Initialize I/O and Peripherals
    LCD_Init(); //Setup display
        
    while(1)
        {
            unsigned char message[] = "Hello";
            LCD_string(message);
        }

}

void PLL_Init()//Set up PLL for 64 MHz operation, enable secondary oscillator
{
    OSCCON1 = 0x60; // NOSC HFINTOSC; NDIV 1;
    OSCCON3 = 0x00; // CSWHOLD may proceed; SOSCPWR Low power;
    OSCEN = 0x08; // MFOEN disabled; LFOEN disabled; ADOEN disabled; SOSCEN enabled; EXTOEN disabled; HFOEN disabled;
    OSCFRQ = 0x08; // HFFRQ 64_MHz;
    OSCTUNE = 0x00; // TUN 0;
}

void TIMER_Init(void)
{
    //TMR0 1:64 prescaler preload 6 = 1mS
   T0CON0bits.T0EN = 0; //Stop timer0 while we setup parameters
   PIE0bits.TMR0IE = 1; //Enable Timer0 Interrupts
   T0CON1bits.T0CS = 2; //FOSC/4 as source (16Mhz))
   T0CON0bits.T016BIT = 0; //Set timer0 as 16 bit
   T0CON1bits.T0CKPS = 0x3; //Prescaler 1:64
   T0CON1bits.T0ASYNC = 1; //Async mode
   TMR0H = 250; //Preload 250 into TMR0H counter to make 1mS
  // TMR0L = 255;
   PIR0bits.TMR0IF = 0;
   T0CON0bits.T0EN = 1; //Enable timer 0
}

void PIN_Init(void)
{
    //LATx registers
    LATA = 0x00;
    LATB = 0x00;
    LATC = 0x00;

    //TRISx registers
    TRISA = 0xFF; //PORTA as inputs
    TRISB = 0x00;
    TRISC = 0x00;

    //ANSELx registers
    ANSELA = 0b00000001; //RA0 analog input
    ANSELB = 0x00;
    ANSELC = 0x00;
    
    //WPUx registers
    WPUA = 0x00;
    WPUB = 0x00;
    WPUC = 0x00;
    WPUE = 0x00;

    //ODx registers
    ODCONA = 0x00;
    ODCONB = 0x00;
    ODCONC = 0x00;

    CM1CON0bits.C1EN = 0; //Disable Comparator 1
    CM2CON0bits.C2EN = 0; //Disable Comparator 2
    INTCONbits.GIE =1; //Enable global interrupts
    INTCONbits.GIEH =1;
    INTCONbits.GIEL =1;
    INTCONbits.PEIE = 1; //Enable peripheral interrupts
    INTCONbits.IPEN = 0; //Disable interrupt priority
    PIE0bits.IOCIE = 1; //Enable Interrupt On Change interrupts
    
    PPSLOCK = 0x55;
    PPSLOCK = 0xAA;
    PPSLOCKbits.PPSLOCKED = 0x00; // unlock PPS

    //IOCx registers

    // interrupt on change for group IOCxF - flag
    IOCAF = 0;
    IOCBFbits.IOCBF0 = 0;
    IOCBFbits.IOCBF1 = 0;
    IOCBFbits.IOCBF2 = 0;
    IOCBFbits.IOCBF3 = 0;
    IOCCFbits.IOCCF0 = 0;
    IOCCFbits.IOCCF1 = 0;

    // interrupt on change for group IOCxN - negative
    IOCAN = 0;
    //IOCANbits.IOCAN1 = 1; //Enable IOC negative detection on RA1 for flow sensor
    IOCBNbits.IOCBN0 = 0;
    IOCBNbits.IOCBN1 = 0;
    IOCBNbits.IOCBN2 = 0;
    IOCBNbits.IOCBN3 = 0;
    IOCCNbits.IOCCN0 = 0;
    IOCCNbits.IOCCN1 = 0;

    // interrupt on change for group IOCCP - positive
    IOCAP = 0;
    IOCAPbits.IOCAP1 = 1; //Enable IOC positive detection on RA1 for flow sensor
    IOCBPbits.IOCBP0 = 0;
    IOCBPbits.IOCBP1 = 0;
    IOCBPbits.IOCBP2 = 0;
    IOCBPbits.IOCBP3 = 0;
    IOCCPbits.IOCCP0 = 0;
    IOCCPbits.IOCCP1 = 0;

    PPSLOCK = 0x55;
    PPSLOCK = 0xAA;
    PPSLOCKbits.PPSLOCKED = 0x01; // lock PPS
}


void LCD_Init(void)
{
   
    __delay_ms(45);
    LCD_cmd(0x30);//Initialise
    LCD_cmd(0x30);//Initialise
    LCD_cmd(0x30);//Initialise
    
    //LCD_cmd(0b00110000);//Initialise
    //LCD_cmd(0b00110000);//Initialise
    //LCD_cmd(0b00110000);//Initialise
    
    LCD_cmd(MODE_8BIT); // 2 Line, 5x7 display, 8 bit
    //LCD_cmd(0x38);
    //LCD_cmd(0b00111000);//001 DL(data lines) N(lines) F(font) * * Sets to 8-bit operation and selects 2-line display and 5x7 dots character font.
    
    //LCD_cmd(0x06);//Set mode to increment the address by one and to shift the cursor to the right, at the time of write, to the DD/CG RAM Display is not shifted.
    LCD_cmd(0x06);//Set mode to increment the address by one and to shift the cursor to the right, at the time of write.
    
    //LCD_cmd(0b00000101);//Set mode to increment the address by one and to shift the cursor to the right, at the time of write, to the DD/CG RAM Display is not shifted.
  
    LCD_cmd(0x0F);//Turn on display and flashing cursor 00001D(display on/off)C(cursor on/off)B(Blink on/off)
    //LCD_cmd(0b00001111);//Turn on display and flashing cursor
    
    LCD_cmd(0x80);//set cursor to position top left
    LCD_data(0x49);//Display Init
    LCD_data(0x6E);
    LCD_data(0x69);
    LCD_data(0x74);
    
    LCD_cmd(0xC0);
    LCD_data(0x49);//Display Init
    LCD_data(0x6E);
    LCD_data(0x69);
    LCD_data(0x74);
    
    __delay_ms(3000);
    
    LCD_cmd(CLRSCR); // clear the screen
    //LCD_cmd(0x01);// Clear display
    
    //LCD_cmd(CURSOR_INC); // Cursor Increments on each write
    //LCD_cmd(DISPLAY_ON | CURSOR_ON); // Display on and Cursor Off
  
}


void LCD_data(unsigned char data)
{
    LCD_isbusy();
    RS = 1;
    RW = 0;
    EN = 1;
    DATAPORT = data;
    __delay_ms(2);
    EN = 0;
}
void LCD_cmd(unsigned char cmd)
{
    LCD_isbusy();
    RS = 0;
    RW = 0;
    EN = 1;
    DATAPORT = cmd;
    __delay_ms(1);
    EN = 0;
}

void LCD_isbusy(void)
{
    TRISBbits.TRISB7=1; // Make D7 as input
    RS = 0;
    RW = 1;
    EN = 1;
    __delay_ms(1);
    while(BF);
    EN = 0;
    TRISBbits.TRISB7=0; // Back to Output
}
/*
void LCD_string(unsigned char *buffer)
{
    while(*buffer) // Write data to LCD up to null
    {
      
        LCD_data(*buffer); // Write character to LCD
        buffer++; // Increment buffer
    }
}
*/

void LCD_string(unsigned char *buffer)
{
  int i=0;
  while(buffer[i]!='\0'){
  // loop will go on till the NULL character in the string
    LCD_cmd(buffer[i]); // sending data on LCD byte by byte
    i++;
  }
}

 
Thanks in advance,
Glenn.

 
#1

3 Replies Related Threads

    qhb
    Superb Member
    • Total Posts : 9625
    • Reward points : 0
    • Joined: 2016/06/05 14:55:32
    • Location: One step ahead...
    • Status: offline
    Re: LCD String write issue 2018/11/02 04:20:20 (permalink)
    +1 (1)
    This is due to an errata in early K40 chips.
    The compiler knows how to work around it, but you have to tell it to.
    See: https://www.microchip.com/forums/m969418.aspx
    #2
    Trackhappy
    Starting Member
    • Total Posts : 51
    • Reward points : 0
    • Joined: 2016/11/03 16:07:08
    • Location: 0
    • Status: offline
    Re: LCD String write issue 2018/11/02 13:22:20 (permalink)
    0
    Thanks qhb. I thought I had ruled that out but will take another look.
    #3
    Trackhappy
    Starting Member
    • Total Posts : 51
    • Reward points : 0
    • Joined: 2016/11/03 16:07:08
    • Location: 0
    • Status: offline
    Re: LCD String write issue 2018/11/06 19:04:49 (permalink)
    0
    Just wanted to say thanks. After trying the various solutions to the errata issue, I found the post that detailed adding the errata entry to the compiler string worked for me where the assembler file did not.
    Appreciate the help.
    post edited by Trackhappy - 2018/11/06 19:06:29
    #4
    Jump to:
    © 2019 APG vNext Commercial Version 4.5