PIC Development Board with PK3

Thread Starter

Djsarakar

Joined Jul 26, 2020
489
LOL! If it were not for the 3 way tag team we've created, things might be different :cool: I appreciate the respites, much appreciated.
Case in point @Djsarakar , It would be really nice to know if you got the terminal echo working before going off in some new task with new IO code and a host of new errors. That is ..uhh.. frustrating, for me at least, because I never quite know where things are and I don't like solving the same problem more than once.
I'll leave it here for now, carry on and good luck!
I've solved my problem by changing new cable

I wrote the LED test program because I was not sure that whatever I typed on terminal I am getting it back. Sometimes I was getting what I was typing and sometime I wasn't getting back what I was typing.

I wrote and posted the LED program in a hurry, then went to the shop to buy new serial cable. Changing the cable solved my problem

I've trouble with development board. Even before this the LCD was not working due to jumper wires. now I have directly mounted the LCD on the board I have solder and de soldered the pull up resistor many times on the board to run RTC.

Here is working program for LED I've written and It works as I wanted. you can test @hexreader on your board
C:
#define _XTAL_FREQ 8000000

// Configuration bits: selected in the GUI
// CONFIG1L
#pragma config RETEN = OFF    // VREG Sleep Enable bit->Ultra low-power regulator is Disabled (Controlled by REGSLP bit)
#pragma config INTOSCSEL = HIGH    // LF-INTOSC Low-power Enable bit->LF-INTOSC in High-power mode during Sleep
#pragma config SOSCSEL = DIG    // SOSC Power Selection and mode Configuration bits->Digital (SCLKI) mode
#pragma config XINST = OFF    // Extended Instruction Set->Disabled
// CONFIG1H
#pragma config FOSC = INTIO2    // Oscillator->Internal RC oscillator
#pragma config PLLCFG = OFF    // PLL x4 Enable bit->Disabled
#pragma config FCMEN = OFF    // Fail-Safe Clock Monitor->Disabled
#pragma config IESO = OFF    // Internal External Oscillator Switch Over Mode->Disabled
// CONFIG2L
#pragma config PWRTEN = OFF    // Power Up Timer->Disabled
#pragma config BOREN = SBORDIS    // Brown Out Detect->Enabled in hardware, SBOREN disabled
#pragma config BORV = 3    // Brown-out Reset Voltage bits->1.8V
#pragma config BORPWR = ZPBORMV    // BORMV Power level->ZPBORMV instead of BORMV is selected
// CONFIG2H
#pragma config WDTEN = OFF    // Watchdog Timer->WDT disabled in hardware; SWDTEN bit disabled
#pragma config WDTPS = 1048576    // Watchdog Postscaler->1:1048576
// CONFIG3H
#pragma config CANMX = PORTB    // ECAN Mux bit->ECAN TX and RX pins are located on RB2 and RB3, respectively
#pragma config MSSPMSK = MSK7    // MSSP address masking->7 Bit address masking mode
#pragma config MCLRE = ON    // Master Clear Enable->MCLR Enabled, RE3 Disabled
// CONFIG4L
#pragma config STVREN = ON    // Stack Overflow Reset->Enabled
#pragma config BBSIZ = BB2K    // Boot Block Size->2K word Boot Block size
// CONFIG5L
#pragma config CP0 = OFF    // Code Protect 00800-01FFF->Disabled
#pragma config CP1 = OFF    // Code Protect 02000-03FFF->Disabled
#pragma config CP2 = OFF    // Code Protect 04000-05FFF->Disabled
#pragma config CP3 = OFF    // Code Protect 06000-07FFF->Disabled
// CONFIG5H
#pragma config CPB = OFF    // Code Protect Boot->Disabled
#pragma config CPD = OFF    // Data EE Read Protect->Disabled
// CONFIG6L
#pragma config WRT0 = OFF    // Table Write Protect 00800-01FFF->Disabled
#pragma config WRT1 = OFF    // Table Write Protect 02000-03FFF->Disabled
#pragma config WRT2 = OFF    // Table Write Protect 04000-05FFF->Disabled
#pragma config WRT3 = OFF    // Table Write Protect 06000-07FFF->Disabled
// CONFIG6H
#pragma config WRTC = OFF    // Config. Write Protect->Disabled
#pragma config WRTB = OFF    // Table Write Protect Boot->Disabled
#pragma config WRTD = OFF    // Data EE Write Protect->Disabled
// CONFIG7L
#pragma config EBTR0 = OFF    // Table Read Protect 00800-01FFF->Disabled
#pragma config EBTR1 = OFF    // Table Read Protect 02000-03FFF->Disabled
#pragma config EBTR2 = OFF    // Table Read Protect 04000-05FFF->Disabled
#pragma config EBTR3 = OFF    // Table Read Protect 06000-07FFF->Disabled
// CONFIG7H
#pragma config EBTRB = OFF    // Table Read Protect Boot->Disabled

#include <xc.h>
#include <stdio.h>
#include <conio.h>

#define LED              LATDbits.LATD2

void PIN_MANAGER_Initialize(void)
{
    /**
    LATx registers
    */
    LATE = 0x00;
    LATD = 0x00;
    LATA = 0x00;
    LATB = 0x00;
    LATC = 0x00;
    /**
    TRISx registers
    */
    TRISE = 0x07;
    TRISA = 0xEF;
    TRISB = 0x01;
    TRISC = 0xBF;
    TRISD = 0x00;
    /**
    ANSELx registers
    */
    ANCON0 = 0x00;
    ANCON1 = 0x00;

    CM1CON = 0; // Comparator off
    CM2CON = 0; // Comparator off
    ADCON0 = 0; // A/D conversion Disabled
}

void OSCILLATOR_Initialize(void)
{
    // SCS FOSC; HFIOFS not stable; IDLEN disabled; IRCF 8MHz_HF;
    OSCCON = 0x60;
    // SOSCGO disabled; MFIOSEL disabled; SOSCDRV Low Power;
    OSCCON2 = 0x00;
    // INTSRC INTRC; PLLEN disabled; TUN 0;
    OSCTUNE = 0x00;
    // ROSEL System Clock(FOSC); ROON disabled; ROSSLP Disabled in Sleep mode; RODIV Fosc;
    REFOCON = 0x00;
}
void EUSART1_Initialize(void)
{
    // Set the EUSART1 module to the options selected in the user interface.
    // ABDOVF no_overflow; TXCKP async_noninverted_sync_fallingedge; BRG16 16bit_generator; WUE disabled; ABDEN disabled; RXDTP not_inverted;
    BAUDCON1 = 0x08;
    // SPEN enabled; RX9 8-bit; RX9D 0; CREN enabled; ADDEN disabled; SREN disabled;
    RCSTA1 = 0x90;
    // TX9 8-bit; TX9D 0; SENDB sync_break_complete; TXEN enabled; SYNC asynchronous; BRGH hi_speed; CSRC slave_mode;
    TXSTA1 = 0x24;
    //
    SPBRG1 = 0xCF;
    //
    SPBRGH1 = 0x00;

}

void SYSTEM_Initialize(void)
{
    PIN_MANAGER_Initialize();
    OSCILLATOR_Initialize();
    EUSART1_Initialize();
}

//Receive Byte
//char Receive_Byte(void)
char getch()
{
    if(RCSTAbits.OERR == 1)
    {
       RCSTAbits.CREN = 0;
       NOP();
       RCSTAbits.CREN = 1;
    }
    while(RCIF == 0 );               // Wait till the rx register becomes empty

    return (RCREG);
}

//Send a byte
void putch(char message)
{
    while(TXIF == 0 );               // Wait till the transmitter register becomes empty
    TXREG1 = message;
}

void String(char *p)
{
   while(*p != '\0') {
       __delay_ms(1);
     putch(*p);
     p++;
   }
}

void main(void)
{
    char Receive ;
    char message[]= {"Hello"};

    SYSTEM_Initialize();

    __delay_ms(10);  // Wait for 10 ms

    String(message); // Send one byte to hyper terminal

    while (1)
    {
      Receive = getch(); //  Receive a byte from hyper terminal
  
       if (Receive == '1')
      {
          LED = 1;
          __delay_ms(1000);
          LED = 0;
          __delay_ms(1000);
      }
      else
      {
           LED = 0;
      }

    }

    return;
}
 
Last edited:

Thread Starter

Djsarakar

Joined Jul 26, 2020
489
Here is my untested program to R/W data of EEPROM with UART. Program is only ready for debug. Right now I am yet to make some logic correction which I will do when I get time

C:
#define _XTAL_FREQ 8000000

// Configuration bits: selected in the GUI
// CONFIG1L
#pragma config RETEN = OFF    // VREG Sleep Enable bit->Ultra low-power regulator is Disabled (Controlled by REGSLP bit)
#pragma config INTOSCSEL = HIGH    // LF-INTOSC Low-power Enable bit->LF-INTOSC in High-power mode during Sleep
#pragma config SOSCSEL = DIG    // SOSC Power Selection and mode Configuration bits->Digital (SCLKI) mode
#pragma config XINST = OFF    // Extended Instruction Set->Disabled
// CONFIG1H
#pragma config FOSC = INTIO2    // Oscillator->Internal RC oscillator
#pragma config PLLCFG = OFF    // PLL x4 Enable bit->Disabled
#pragma config FCMEN = OFF    // Fail-Safe Clock Monitor->Disabled
#pragma config IESO = OFF    // Internal External Oscillator Switch Over Mode->Disabled
// CONFIG2L
#pragma config PWRTEN = OFF    // Power Up Timer->Disabled
#pragma config BOREN = SBORDIS    // Brown Out Detect->Enabled in hardware, SBOREN disabled
#pragma config BORV = 3    // Brown-out Reset Voltage bits->1.8V
#pragma config BORPWR = ZPBORMV    // BORMV Power level->ZPBORMV instead of BORMV is selected
// CONFIG2H
#pragma config WDTEN = OFF    // Watchdog Timer->WDT disabled in hardware; SWDTEN bit disabled
#pragma config WDTPS = 1048576    // Watchdog Postscaler->1:1048576
// CONFIG3H
#pragma config CANMX = PORTB    // ECAN Mux bit->ECAN TX and RX pins are located on RB2 and RB3, respectively
#pragma config MSSPMSK = MSK7    // MSSP address masking->7 Bit address masking mode
#pragma config MCLRE = ON    // Master Clear Enable->MCLR Enabled, RE3 Disabled
// CONFIG4L
#pragma config STVREN = ON    // Stack Overflow Reset->Enabled
#pragma config BBSIZ = BB2K    // Boot Block Size->2K word Boot Block size
// CONFIG5L
#pragma config CP0 = OFF    // Code Protect 00800-01FFF->Disabled
#pragma config CP1 = OFF    // Code Protect 02000-03FFF->Disabled
#pragma config CP2 = OFF    // Code Protect 04000-05FFF->Disabled
#pragma config CP3 = OFF    // Code Protect 06000-07FFF->Disabled
// CONFIG5H
#pragma config CPB = OFF    // Code Protect Boot->Disabled
#pragma config CPD = OFF    // Data EE Read Protect->Disabled
// CONFIG6L
#pragma config WRT0 = OFF    // Table Write Protect 00800-01FFF->Disabled
#pragma config WRT1 = OFF    // Table Write Protect 02000-03FFF->Disabled
#pragma config WRT2 = OFF    // Table Write Protect 04000-05FFF->Disabled
#pragma config WRT3 = OFF    // Table Write Protect 06000-07FFF->Disabled
// CONFIG6H
#pragma config WRTC = OFF    // Config. Write Protect->Disabled
#pragma config WRTB = OFF    // Table Write Protect Boot->Disabled
#pragma config WRTD = OFF    // Data EE Write Protect->Disabled
// CONFIG7L
#pragma config EBTR0 = OFF    // Table Read Protect 00800-01FFF->Disabled
#pragma config EBTR1 = OFF    // Table Read Protect 02000-03FFF->Disabled
#pragma config EBTR2 = OFF    // Table Read Protect 04000-05FFF->Disabled
#pragma config EBTR3 = OFF    // Table Read Protect 06000-07FFF->Disabled
// CONFIG7H
#pragma config EBTRB = OFF    // Table Read Protect Boot->Disabled

#include <xc.h>
#include <stdio.h>
#include <conio.h>

unsigned char Result1;
unsigned char Result2;
unsigned char Result3;
unsigned char Result4;

//I2C slave address of 24c02 (8 bit format R/W bit)
#define EEPROM_ADDRESS      0xA0        
#define Word_Address1       0x00

void PIN_Initialize(void)
{
    /**
    LATx registers
    */
    LATE = 0x00;
    LATD = 0x00;
    LATA = 0x00;
    LATB = 0x00;
    LATC = 0x00;
    /**
    TRISx registers
    */
    TRISE = 0x00;
    TRISA = 0x00;
    TRISB = 0x00;
    TRISC = 0x58;
    TRISD = 0x00;
    /**
    ANSELx registers
    */
    ANCON0 = 0x00;
    ANCON1 = 0x00;

    CM1CON = 0; // Comparator off
    CM2CON = 0; // Comparator off
    ADCON0 = 0; // A/D conversion Disabled
}
// 8Mhz speed
void OSCILLATOR_Initialize(void)
{
    OSCCON = 0x60;  // SCS FOSC; HFIOFS not stable; IDLEN disabled; IRCF 8MHz_HF;  
    OSCCON2 = 0x00; // SOSCGO disabled; MFIOSEL disabled; SOSCDRV Low Power;  
    OSCTUNE = 0x00; // INTSRC INTRC; PLLEN disabled; TUN 0;  
    REFOCON = 0x00;  // ROSEL System Clock(FOSC); ROON disabled; ROSSLP Disabled in Sleep mode; RODIV Fosc;  
}

//Initialize I2C in master mode
void I2C_Initialize()
{
    SSPSTAT = 0x00;
    SSPCON1 = 0x08;
    SSPCON2 = 0x00;
    SSPADD  = 0x13;
    SSPCON1bits.SSPEN = 0;
}

void EUSART_Initialize(void)
{  
    BAUDCON1 = 0x08;  // ABDOVF no_overflow; TXCKP async_noninverted_sync_fallingedge; BRG16 16bit_generator; WUE disabled; ABDEN disabled; RXDTP not_inverted;
    RCSTA1 = 0x90;    // SPEN enabled; RX9 8-bit; RX9D 0; CREN enabled; ADDEN disabled; SREN disabled;
    TXSTA1 = 0x24;   // TX9 8-bit; TX9D 0; SENDB sync_break_complete; TXEN enabled; SYNC asynchronous; BRGH hi_speed; CSRC slave_mode;
    SPBRG1 = 0xCF;
    SPBRGH1 = 0x00;
}

void SYSTEM_Initialize(void)
{
    PIN_Initialize();
    OSCILLATOR_Initialize();
    I2C_Initialize();
    EUSART_Initialize();
}

//Receive Byte
char getch()
{
    if(RCSTAbits.OERR == 1)
    {
       RCSTAbits.CREN = 0;
       NOP();
       RCSTAbits.CREN = 1;
    }
    while(RCIF == 0 );               // Wait till the rx register becomes empty
 
    return (RCREG);
}

//Send a byte
void putch(char message)
{
    while(TXIF == 0 );               // Wait till the transmitter register becomes empty
    TXREG1 = message;
}

void String(char *p)
{
   while(*p != '\0') {
       __delay_ms(1);
     putch(*p);
     p++;
   }
}

// Send an I2C START
// Return 0 if all ok, 1 if bus collision
__bit I2C_Start(void)
{
    BCLIF = 0;  //Clear 'Bus collision" flag
    SEN = 1;    //initiate a START cycle
    while (SEN);    //wait until it has been sent
    return BCLIF;   //return value of BCLIF flag
}
// Send an I2C STOP
void I2C_Stop(void)
{
    PEN = 1;    //initiate a STOP cycle
    while (PEN);    //wait until it has been sent
}


//Receive one byte. ackflag=0 to send ACK, or 1 to send NAK in reply
//Send one byte. Return 0 if ACK received, or 1 if NAK received
__bit I2C_Sendbyte(unsigned char dat)
{
    SSPBUF = dat;

    asm("nop");     // wait a little for R_W to be set

    while (R_W);    //wait until byte sent and ACK/NAK received
    return ACKSTAT;
}

unsigned char I2C_Recvbyte(unsigned char ackflag)
{
    RCEN = 1;   // initiate a RECEIVE cycle
    ACKDT =(__bit)ackflag;    //specify if we should send ACK or NAK after receiving
    while (RCEN);   //wait until RECEIVE has completed
    ACKEN = 1;  //initiate an ACK cycle
    while (ACKEN);  //wait until it has completed
    return SSPBUF;
}

//Send an array of data to an I2C device.
//Return 0 if all OK, 1 if bus error, 2 if slave address NAK, 3 if slave register NAK, 4 if slave data NAK
unsigned char EEPROM_Write(unsigned char slave_address, unsigned char start_reg, unsigned char buflen, const unsigned char * bufptr)
{
    if (I2C_Start() )   //send a start, and check if it succeeded
        return 1;   //abort if bus collision
    //send the I2C slave address (force R/W bit low)
    if (I2C_Sendbyte(slave_address & 0xfe))  // <<---- Added AND to force R/W- low.
    {
        I2C_Stop(); //if address was NAKed, terminate the cycle
        return 2;   //and return error code
    }
    //send the device register index
    if (I2C_Sendbyte(start_reg))
    {
        I2C_Stop(); //if register was NAKed, terminate the cycle
        return 3;   //and return error code
    }
    //send the data. buflen might be zero!
    for (; buflen>0; --buflen)
    {
        if (I2C_Sendbyte(*bufptr++))
        {
            I2C_Stop(); //if register was NAKed, terminate the cycle
            return 4;   //and return error code
        }
    }
    I2C_Stop();
    return 0;   //no error
}

//Receive an array of data from an I2C device.
//Return 0 if all OK, 1 if bus error, 2 if slave address NAK, 3 if slave register NAK
unsigned char EEPROM_Read(unsigned char slave_address, unsigned char start_reg, unsigned char buflen, unsigned char * bufptr)
{
    //do a dummy zero length write cycle to set the register address
    unsigned char retval = EEPROM_Write(slave_address, start_reg, 0, 0);
    if (retval)
    {
        return retval;  //abort if there was an error
    }
    //now start the READ cycle
    if (I2C_Start() )   //send a start, and check if it succeeded
        return 1;   //abort if bus collision
    //send the I2C slave address (force the R/W bit high)
    if (I2C_Sendbyte(slave_address | 0x01))
    {
        I2C_Stop(); //if address was NAKed, terminate the cycle
        return 2;   //and return error code
    }
    //receive the data.
    for (; buflen>0; --buflen)
    {
        unsigned char ackflag = (buflen == 1);   //1 if this is the last byte to receive => send NAK

        *bufptr++ = I2C_Recvbyte(ackflag);
    }
    I2C_Stop();
    return 0;   //no error
}
const unsigned char EEPROM_data[] =
{
    0x07,   // Count 7
    0x06,   // Count 6
    0x05,   // Count 5
    0x04,   // Count 4
    0x03,   // Count 3
    0x02,   // Count 2
    0x01,   // Count 1
};

unsigned char rd_buf[7];

// Test variable for one byte transfer
const unsigned char testchar = 'A';
unsigned char testchar_readback[17];


void main(void)
{
    unsigned char i;
    unsigned char Data1 [10]="xx";
   
    SYSTEM_Initialize();
 
    __delay_ms(10);  // Wait for 10 ms
   
    // Write test buffer
     Result1 = EEPROM_Write(EEPROM_ADDRESS , Word_Address1 , sizeof(EEPROM_data), EEPROM_data);
     __delay_ms(10);

    // Read test buffer back
     Result2 = EEPROM_Read(EEPROM_ADDRESS, Word_Address1 , sizeof(rd_buf), rd_buf) ;
     __delay_ms(10);

     // Read back ONE number from 0x01
     Result4 = EEPROM_Read(EEPROM_ADDRESS, 0x00 , 8, rd_buf);           // read first 8 bytes of EEPROM data
    __delay_ms(10);


    for (i = 0; i < 8; i++)                                              // output buffer contents address 0 to 7
    {                                  
        Data1[0] = (rd_buf[i] >> 4) & 0x0f;                             // hex conversion - high nibble
        Data1[1] = (rd_buf[i] & 0x0f);                                  // hex conversion - low nibble
        putch(Data1);
    }
     
    while (1);
 

    return;
}
 

JohnInTX

Joined Jun 26, 2012
4,787
@hexreader I really appreciate their patience But you're opposite You have admitted yourself in your another post. It seems that you are shouting loudly, You get angry when I fail to do work I have seen your anger in your posts but later you edit the post.

as far as I see, working on embedded projects is not that easy if you're newbie or experienced. Every one take their time

When I requested you to modify RTC project for LCD. you tried and when you couldn't, then You gave up. When you're done, you edited the post again. you must stick to your words.

I don't mean to disrespect you. It may be that I'm stupid and I don't understand simple things easily.

You know why I like ACC most because here are so many nice people. Everyone respects each other. There is no discrimination on the forum

@Djsarakar
I think you are being unfair or at least unrealistic. You can't continue this way and expect members not to get upset with you. We are here to help and teach and I think we do a pretty good job considering you are 12.5 time zones away and don't always follow directions. Consider our interaction on post #279 and #280.

In 279, after days of work, tracing your board's circuitry, photos and everything else we were right on the very threshold of success with your serial link. I asked a simple, direct question "Does it work now?"
Instead of a simple, direct answer you instead posted a lump of sloppy code that, besides not indicating success or failure of the serial echo, had inexplicable, incorrect changes to the IO setup, compiler warnings issued and an apparent inability or unwillingness to debug any of it. I was speechless. In one post you demonstrated that you either didn't understand all of those things we've been telling you over hundreds of posts or you didn't care to apply them. Inexcusable in either case and not something to be upset about when some of us object.

Later, you explain that you just posted the code before looking at it, the echo did work and you were moving on to the next thing. Don't you think it would have been better to first answer my 'does it work' question instead of making it appear that you had abandoned the effort and now were off in another direction? From all indications, you quit work validating the serial link and moved on to something that required a working serial link. Can you understand the frustration some of us feel when you do that?

Look. When we are helping you with your hardware problems you are our eyes and hands, half a world away. If I tell those hands to measure a voltage and come back to find them tying my shoes, I am not going to be happy. As for someone 'sticking to their words' I agree that should be the goal but sometimes that's impossible. We don't have your hardware and our distant 'hands' don't always do what we ask them to do.

I agree with your assessment of AAC. We try very hard to keep it a friendly, respectful place. Most importantly, we strive to make it a useful place with competent advice. We have solved problems in this very thread that other forums couldn't. But you have to recognize the inherent limitations of forum-based instruction and help and you have to accept that this is volunteer work and you may not always get things served up exactly as you would wish. In the final analysis your ultimate success or failure is completely up to you.

That's how I see it.
Good luck!
 
Last edited:

Thread Starter

Djsarakar

Joined Jul 26, 2020
489
@JohnInTX , @hexreader

I think the track between SDA and Jumper pin is damaged because of soldering and desoldering pull up resistor on board.

The buzzer doesn't make a sound when I do the continuity test with multimeter between these two pins

Can I short these two pins with a wire to make complete signal ?


Problem sda.jpg
 

Thread Starter

Djsarakar

Joined Jul 26, 2020
489
Yes - just solder a piece of plain wire where the broken track used to be.
hex Thank you! I've solved my problem. There were tow reasons not being displayed RTC clock on LCD

  1. The track between jumper pin and SDA pin was damaged
  2. When enable pin goes to low after that I've added small delay in code (I mean nop(); )

LCD Clock.jpg


C:
//
#define _XTAL_FREQ 20000000     // crystal 20MHz

// PIC18F45K80 Configuration Bit Settings
// CONFIG1L
#pragma config RETEN = ON       // VREG Sleep Enable bit (Ultra low-power regulator is Enabled (Controlled by SRETEN bit))
#pragma config INTOSCSEL = LOW  // LF-INTOSC Low-power Enable bit (LF-INTOSC in Low-power mode during Sleep)
// SOSCSEL = No Setting
#pragma config XINST = OFF      // Extended Instruction Set (Disabled)
// CONFIG1H
#pragma config FOSC = HS2       // HS oscillator (high power, 16 MHz-25 MHz
#pragma config PLLCFG = OFF     // PLL x4 Enable bit (Disabled)
#pragma config FCMEN = OFF      // Fail-Safe Clock Monitor (Disabled)
#pragma config IESO = OFF       // Internal External Oscillator Switch Over Mode (Disabled)
// CONFIG2L
#pragma config PWRTEN = ON      // Power Up Timer (Enabled)
#pragma config BOREN = OFF      // Brown Out Detect (Disabled in hardware, SBOREN disabled)
#pragma config BORV = 0         // Brown-out Reset Voltage bits (3.0V)
#pragma config BORPWR = LOW     // BORMV Power level (BORMV set to low power level)
// CONFIG2H
#pragma config WDTEN = OFF      // Watchdog Timer (WDT disabled in hardware; SWDTEN bit disabled)
#pragma config WDTPS = 1        // Watchdog Postscaler (1:1)
// CONFIG3H
#pragma config CANMX = PORTC    // ECAN Mux bit (ECAN TX and RX pins are located on RC6 and RC7, respectively)
#pragma config MSSPMSK = MSK5   // MSSP address masking (5 bit address masking mode)
#pragma config MCLRE = ON      // Master Clear Enable (MCLR Enabled, RE3 Disabled)
// CONFIG4L
#pragma config STVREN = OFF     // Stack Overflow Reset (Disabled)
#pragma config BBSIZ = BB1K     // Boot Block Size (1K word Boot Block size)
// CONFIG5L
#pragma config CP0 = ON         // Code Protect 00800-01FFF (Enabled)
#pragma config CP1 = ON         // Code Protect 02000-03FFF (Enabled)
#pragma config CP2 = ON         // Code Protect 04000-05FFF (Enabled)
#pragma config CP3 = ON         // Code Protect 06000-07FFF (Enabled)
// CONFIG5H
#pragma config CPB = ON         // Code Protect Boot (Enabled)
#pragma config CPD = ON         // Data EE Read Protect (Enabled)
// CONFIG6L
#pragma config WRT0 = ON        // Table Write Protect 00800-01FFF (Enabled)
#pragma config WRT1 = ON        // Table Write Protect 02000-03FFF (Enabled)
#pragma config WRT2 = ON        // Table Write Protect 04000-05FFF (Enabled)
#pragma config WRT3 = ON        // Table Write Protect 06000-07FFF (Enabled)
// CONFIG6H
#pragma config WRTC = ON        // Config. Write Protect (Enabled)
#pragma config WRTB = ON        // Table Write Protect Boot (Enabled)
#pragma config WRTD = ON        // Data EE Write Protect (Enabled)
// CONFIG7L
#pragma config EBTR0 = ON       // Table Read Protect 00800-01FFF (Enabled)
#pragma config EBTR1 = ON       // Table Read Protect 02000-03FFF (Enabled)
#pragma config EBTR2 = ON       // Table Read Protect 04000-05FFF (Enabled)
#pragma config EBTR3 = ON       // Table Read Protect 06000-07FFF (Enabled)
// CONFIG7H
#pragma config EBTRB = ON       // Table Read Protect Boot (Enabled)
// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.

#pragma warning disable 520

#include <xc.h>

unsigned char Result1;
unsigned char Result2;
unsigned char Result3;
unsigned char Result4;

// The code should set the R/W bit according to its function
#define DS1307_ADDRESS      0xD0         //I2C slave address of DS1307 (8 bit format)
#define Word_Address        0x00


#define LCD_RS              LATBbits.LATB4
#define LCD_TRIS_RS         TRISBbits.TRISB4
#define LCD_RW              LATBbits.LATB5
#define LCD_TRIS_RW         TRISBbits.TRISB5
#define LCD_E               LATBbits.LATB6
#define LCD_TRIS_E          TRISBbits.TRISB6

#define  LCDPORT            LATD
#define  LCDTRISD           LATD

//Prototype function
void Port_Initialized (void);
void WriteNibble(unsigned char command);
void WaitLCDBusy(void);
void WriteCommand(unsigned char command);

void Port_Initialized (void)
{
// LATx registers
    LATA =  0x00;
    LATB =  0x00;
    LATC =  0x00;
    LATD =  0x00;
    LATE =  0x00;

//  TRISx registers
    TRISA = 0x00;    // All are output, Unused
    TRISB = 0x00;   // all are output, Unused
    TRISC = 0x18;    //
    TRISD = 0x00;   // all are output, Unused
    TRISE = 0x00;   // All are output, Unused

    ANCON0 = 0x00;    // digital port
    ANCON1 = 0x00;    // Set to digital port
    CM1CON = 0x00;      // Comparator off
    CM2CON = 0x00;      // Comparator off
    ADCON0 = 0x00;      // A/D conversion Disabled
    ADCON1 = 0x00;      // A/D conversion Disabled
    ADCON2 = 0x00;     // A/D conversion Disabled
}

void WaitLCDBusy(void)
{
    __delay_ms(5);
}

//Send a command to the LCD
void WriteCommand(unsigned char command)
{
    WaitLCDBusy();                        //wait until not busy
    LCD_RS = 0;                           //setup to send command
    WriteNibble(command);                 //write the high nibble
    WriteNibble( (unsigned char)(command<<4) ); //then the low nibble
}

//Initialized  LCD
void LCD_Initialized()
{
    LCDTRISD &=0x0f;                //ensure data bits are output
    LCD_E=0;                        //clear enable
    LCD_RS = 0;                     //going to write command
    LCD_TRIS_E=0;                   //Set enable to output
    LCD_TRIS_RS=0;                  //set RS to output
    LCD_TRIS_RW=0;
    LCD_RW=0;
    __delay_ms(30);                 //delay for LCD to initialise.
    WriteNibble(0x30);              //Required for initialisation
    __delay_ms(5);                  //required delay
    WriteNibble(0x30);              //Required for initialisation
    __delay_ms(1);                  //required delay
    WriteCommand(0x20);             //set to 4 bit interface
    WriteCommand(0x2c);             //set to 4 bit interface, 2 line and 5*10 font
    WriteCommand(0x01);             //clear display
    WriteCommand(0x06);             //move cursor right after write
    WriteCommand(0x0C);             //turn on display
}

//Send a character to the LCD
void WriteChar(unsigned char chr)
{
    WaitLCDBusy();                         //wait until not busy
    LCD_RS=1;                              //Setup to send character
    WriteNibble(chr);                      //write the high nibble        
    WriteNibble( (unsigned char)(chr<<4)); //then the low nibble
}

//Send any 4 bits to the LCD
void WriteNibble(unsigned char command)
{
    LCDPORT &= 0x0f;                        //clear the data bits
    LCDPORT|=((command & 0xf0));            //or in the new data
    LCD_E = 1;                              //enable the LCD interface
    NOP();                                  //change to delay of 1uS
    NOP();
    NOP();
    LCD_E = 0;                              //disable it
    NOP();                                  //----> I did changes in this line
}

void LCD_Data( unsigned char *string)
{
    while (*string != '\0')
    {
      WriteChar(*string);
        string++;
    }
}

//Initialize I2C in master mode
void I2C_Initialized(void)
{
    SSPSTAT=0x80; //Slew rate control is disabled for Standard Speed mode (100 kHz and 1 MHz)
    SSPCON1=0x28; // I2C Master mode, clock = FOSC/(4 * (SSPADD + 1))
    SSPCON2=0x00;
    SSPADD = 49;  //100kHz clock @ 20MHz Fosc SSPADD = ( (Fosc/4) / BiteRate )-1
   // SSPADD = ( 20MHz / 100KHz ) - 1 = 49 //
}

// Send an I2C START
// Return 0 if all ok, 1 if bus collision
__bit I2C_Start(void)
{
    BCLIF = 0;  //Clear 'Bus collision" flag
    SEN = 1;    //initiate a START cycle
    while (SEN);    //wait until it has been sent
    return BCLIF;   //return value of BCLIF flag
}
// Send an I2C STOP
void I2C_Stop(void)
{
    PEN = 1;    //initiate a STOP cycle
    while (PEN);    //wait until it has been sent
}
// Send an I2C REPEATED START
void I2C_Restart(void)
{
    RSEN = 1;    //initiate a REPEATED START cycle
    while (RSEN);    //wait until it has been sent
}
//Receive one byte. ackflag=0 to send ACK, or 1 to send NAK in reply
//Send one byte. Return 0 if ACK received, or 1 if NAK received
__bit I2C_Sendbyte(unsigned char dat)
{
    SSPBUF = dat;

    asm("nop");     // <<<--- wait a little for R_W to be set

    while (R_W);    //wait until byte sent and ACK/NAK received
    return ACKSTAT;
}

unsigned char I2C_Recvbyte(unsigned char ackflag)
{
    RCEN = 1;   // initiate a RECEIVE cycle
    ACKDT =(__bit)ackflag;    //specify if we should send ACK or NAK after receiving
    while (RCEN);   //wait until RECEIVE has completed
    ACKEN = 1;  //initiate an ACK cycle
    while (ACKEN);  //wait until it has completed
    return SSPBUF;
}
//Send an array of data to an I2C device.
//Return 0 if all OK, 1 if bus error, 2 if slave address NAK, 3 if slave register NAK, 4 if slave data NAK
unsigned char DS1307_Write(unsigned char slave_address, unsigned char start_reg, unsigned char buflen, const unsigned char * bufptr)
{
    if (I2C_Start() )   //send a start, and check if it succeeded
        return 1;   //abort if bus collision
    //send the I2C slave address (force R/W bit low)
    if (I2C_Sendbyte(slave_address & 0xfe))  //
    {
        I2C_Stop(); //if address was NAKed, terminate the cycle
        return 2;   //and return error code
    }
    //send the device register index
    if (I2C_Sendbyte(start_reg))
    {
        I2C_Stop(); //if register was NAKed, terminate the cycle
        return 3;   //and return error code
    }
    //send the data. buflen might be zero!
    for (; buflen>0; --buflen)
    {
        if (I2C_Sendbyte(*bufptr++))
        {
            I2C_Stop(); //if register was NAKed, terminate the cycle
            return 4;   //and return error code
        }
    }
    I2C_Stop();
    return 0;   //no error
}
//Receive an array of data from an I2C device.
//Return 0 if all OK, 1 if bus error, 2 if slave address NAK, 3 if slave register NAK
unsigned char DS1307_Read(unsigned char slave_address, unsigned char start_reg, unsigned char buflen, unsigned char * bufptr)
{
    //do a dummy zero length write cycle to set the register address
    unsigned char retval = DS1307_Write(slave_address, start_reg, 0, 0);
    if (retval)
    {
        return retval;  //abort if there was an error
    }
    //now start the READ cycle
    if (I2C_Start() )   //send a start, and check if it succeeded
        return 1;   //abort if bus collision
    //send the I2C slave address (force the R/W bit high)
    if (I2C_Sendbyte(slave_address | 0x01))
    {
        I2C_Stop(); //if address was NAKed, terminate the cycle
        return 2;   //and return error code
    }
    //receive the data.
    for (; buflen>0; --buflen)
    {
        unsigned char ackflag = (buflen == 1);   //1 if this is the last byte to receive => send NAK

        *bufptr++ = I2C_Recvbyte(ackflag);
    }
    I2C_Stop();
    return 0;   //no error
}
const unsigned char DS1307_data[] =
{
    0x00,   // seconds
    0x00,   // minutes
    0x12,   // hours
    0x07,   // day
    0x23,   // date
    0x05,   // month
    0x01,   // year
};
unsigned char rd_buf[7];


// Test variable for one byte transfer
const unsigned char testchar = 'A';
unsigned char testchar_readback[17];  // init to this to see difference after read

void main(void)
{
    unsigned char i = 0;
    unsigned char Data2 [17] = "tst ";
    unsigned char old_second = 99;
 
    Port_Initialized ();
    LCD_Initialized();
    I2C_Initialized();
    LCD_Data(Data2);

    // Write test buffer
    Result1 = DS1307_Write(DS1307_ADDRESS , Word_Address , sizeof(DS1307_data), DS1307_data);
     __delay_ms(10);

    // Read test buffer back
     Result2 = DS1307_Read(DS1307_ADDRESS, Word_Address , sizeof(rd_buf), rd_buf) ;
     __delay_ms(10);

    // Write Minutes 1 minute to location 0x1, size 1
    //Result3 = DS1307_Write(DS1307_ADDRESS, 0x01 , 1, 31);
     __delay_ms(10);

    while(1){
        __delay_ms(100);                                                        // limit read rate of RTC
        Result4 = DS1307_Read(DS1307_ADDRESS, 0 , 7, testchar_readback);        // read RTC registers
        if(old_second != (testchar_readback[0] & 0x0f)){                        // only allow LCD update if seconds units have changed
            LCD_Initialized();
            Data2[0] = ((testchar_readback[4] >> 4) & 0x0f) + '0';
            Data2[1] = (testchar_readback[4] & 0x0f) + '0';
            Data2[2] = ((testchar_readback[5] >> 4) & 0x0f) + '0';
            Data2[3] = (testchar_readback[5] & 0x0f) + '0';
            Data2[4] = '2';
            Data2[5] = (testchar_readback[6] & 0x0f) + '0';
            Data2[6] = ' ';
            Data2[7] = ((testchar_readback[2] >> 4) & 0x0f) + '0';
            Data2[8] = (testchar_readback[2] & 0x0f) + '0';
            Data2[9] = ':';
            Data2[10] = ((testchar_readback[1] >> 4) & 0x0f) + '0';
            Data2[11] = (testchar_readback[1] & 0x0f) + '0';
            Data2[12] = ':';
            Data2[13] = ((testchar_readback[0] >> 4) & 0x0f) + '0';
            Data2[14] = (testchar_readback[0] & 0x0f) + '0';
            Data2[15] = ' ';
            Data2[16] = 0;
            LCD_Data(Data2);
            old_second = testchar_readback[0] & 0x0f;                           // prevent next LCD update until seconds have chanaged
        }
    }
}
 

JohnInTX

Joined Jun 26, 2012
4,787
First of all, good job! Nice to see such progress.

A few things for you consider:
Line 163: comment says 1uS delay. At 20MHz, 3 NOPs are 600ns. That is a long enough time for E but it's not 1uS. Since you sometimes use other oscillator speeds using one of the delay macros would be better.
Line 143: The CLEAR DISPLAY command takes longer to process than other commands. Most generic LCDs use some clone of a Hitachi 44780 controller and CLEAR DISPLAY takes nominally 1.52 milliseconds to execute. It is likely that the 2 following lines are not executed by the display and you are also probably missing some of the initial messages as well (like Line 316). Consider clearing the display last in the initiallization sequence and give it enough time to process. NOTE: some clones are faster or slower. In the absence of a complete datasheet for your exact display it would be prudent to be conservative.
Line 167: What is the purpose of the last NOP?

But all in all, good stuff. Well done!

EDIT: Line: 137
WriteNibble(0x30); //Required for initialisation
You need to do that 3 TIMES before sending the 20h to set it for 4 bit bus. You can get away without it if you never call LCD init again after power up but it's a good idea to have it anyway.
 
Last edited:

Thread Starter

Djsarakar

Joined Jul 26, 2020
489
First of all, good job! Nice to see such progress.

A few things for you consider:
Line 163: comment says 1uS delay. At 20MHz, 3 NOPs are 600ns.
Line 167:
But all in all, good stuff. Well done!
EDIT: Line: 137
@JohnInTX The code for LCD is not mine. I wrote my own code for LCD by reading datasheet but my code wasn't working. A few month's ago Mike gave me display code on ETO forum. Code were working on my hardware so that's why I used code.

I wrote following code for LCD. I only shows the black square on LCD. I worked hard for many day's but I couldn't understand why my code were not working

C:
//
#define _XTAL_FREQ 20000000     // crystal 20MHz

// PIC18F45K80 Configuration Bit Settings
// CONFIG1L
#pragma config RETEN = ON       // VREG Sleep Enable bit (Ultra low-power regulator is Enabled (Controlled by SRETEN bit))
#pragma config INTOSCSEL = LOW  // LF-INTOSC Low-power Enable bit (LF-INTOSC in Low-power mode during Sleep)
// SOSCSEL = No Setting
#pragma config XINST = OFF      // Extended Instruction Set (Disabled)
// CONFIG1H
#pragma config FOSC = HS2       // HS oscillator (high power, 16 MHz-25 MHz
#pragma config PLLCFG = OFF     // PLL x4 Enable bit (Disabled)
#pragma config FCMEN = OFF      // Fail-Safe Clock Monitor (Disabled)
#pragma config IESO = OFF       // Internal External Oscillator Switch Over Mode (Disabled)
// CONFIG2L
#pragma config PWRTEN = ON      // Power Up Timer (Enabled)
#pragma config BOREN = OFF      // Brown Out Detect (Disabled in hardware, SBOREN disabled)
#pragma config BORV = 0         // Brown-out Reset Voltage bits (3.0V)
#pragma config BORPWR = LOW     // BORMV Power level (BORMV set to low power level)
// CONFIG2H
#pragma config WDTEN = OFF      // Watchdog Timer (WDT disabled in hardware; SWDTEN bit disabled)
#pragma config WDTPS = 1        // Watchdog Postscaler (1:1)
// CONFIG3H
#pragma config CANMX = PORTC    // ECAN Mux bit (ECAN TX and RX pins are located on RC6 and RC7, respectively)
#pragma config MSSPMSK = MSK5   // MSSP address masking (5 bit address masking mode)
#pragma config MCLRE = ON      // Master Clear Enable (MCLR Enabled, RE3 Disabled)
// CONFIG4L
#pragma config STVREN = OFF     // Stack Overflow Reset (Disabled)
#pragma config BBSIZ = BB1K     // Boot Block Size (1K word Boot Block size)
// CONFIG5L
#pragma config CP0 = ON         // Code Protect 00800-01FFF (Enabled)
#pragma config CP1 = ON         // Code Protect 02000-03FFF (Enabled)
#pragma config CP2 = ON         // Code Protect 04000-05FFF (Enabled)
#pragma config CP3 = ON         // Code Protect 06000-07FFF (Enabled)
// CONFIG5H
#pragma config CPB = ON         // Code Protect Boot (Enabled)
#pragma config CPD = ON         // Data EE Read Protect (Enabled)
// CONFIG6L
#pragma config WRT0 = ON        // Table Write Protect 00800-01FFF (Enabled)
#pragma config WRT1 = ON        // Table Write Protect 02000-03FFF (Enabled)
#pragma config WRT2 = ON        // Table Write Protect 04000-05FFF (Enabled)
#pragma config WRT3 = ON        // Table Write Protect 06000-07FFF (Enabled)
// CONFIG6H
#pragma config WRTC = ON        // Config. Write Protect (Enabled)
#pragma config WRTB = ON        // Table Write Protect Boot (Enabled)
#pragma config WRTD = ON        // Data EE Write Protect (Enabled)
// CONFIG7L
#pragma config EBTR0 = ON       // Table Read Protect 00800-01FFF (Enabled)
#pragma config EBTR1 = ON       // Table Read Protect 02000-03FFF (Enabled)
#pragma config EBTR2 = ON       // Table Read Protect 04000-05FFF (Enabled)
#pragma config EBTR3 = ON       // Table Read Protect 06000-07FFF (Enabled)
// CONFIG7H
#pragma config EBTRB = ON       // Table Read Protect Boot (Enabled)
// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.

#pragma warning disable 520

#include <xc.h>

#define RS            LATBbits.LATB4
#define RW            LATBbits.LATB5
#define EN            LATBbits.LATB6

#define LCD_Port      LATD

//Port Initialized
void Port_Initialized (void)
{
// LATx registers
    LATA =  0x00;
    LATB =  0x00;
    LATC =  0x00;
    LATD =  0x00;
    LATE =  0x00;

//  TRISx registers
    TRISA = 0x00;     // All are output, Unused
    TRISB = 0x00;     // RS, R/W EN
    TRISC = 0x00;     //all are output, Unused
    TRISD = 0x00;     // LCD Port
    TRISE = 0x00;     // All are output, Unused

    ANCON0 = 0x00;    // digital port
    ANCON1 = 0x00;    // Set to digital port
    CM1CON = 0x00;    // Comparator off
    CM2CON = 0x00;    // Comparator off
    ADCON0 = 0x00;    // A/D conversion Disabled
    ADCON1 = 0x00;    // A/D conversion Disabled
    ADCON2 = 0x00;    // A/D conversion Disabled
}

//Send only high nibble to the LCD
void WriteNibble(unsigned char command)
{
     RS = 0; RW = 0;
    // wait more then 40ns Figure 25 Write Operation
    NOP();   //300ns

    LCD_Port = command & 0xF0 ;  // Send only four upper nibble

    EN = 1;
    __delay_us(1);
    EN = 0;
    __delay_us(1);
}

//Send a high nibble and low nibble to the LCD
void LCD_WriteCommand(unsigned char command)
{
    RS = 0; RW = 0;
    // wait more then 40ns Figure 25 Write Operation
    NOP();// 300ns 
    LCD_Port = command & 0xF0 ;  // Send only high nibble
    EN = 1;
    __delay_us(1);
    EN = 0;
    __delay_us(1);

    LCD_Port =  ((command << 4) & 0xF0); // Send low nibble

    EN = 1;
    __delay_us(1);
    EN = 0;
    __delay_us(1);

    __delay_us(40); //// wait more then 37us
}

// This function is written by looking at figure 24 given in Datasheet
//Initialized  LCD
void  LCD_Initialized()
{
    __delay_ms(15);          // Wait more than 15 ms
    WriteNibble(0x30);       // Function set
    __delay_ms(5);           // Wait more than 4.1 ms
    WriteNibble(0x30);       // Function set
    __delay_us(100);         // Wait for more than 100 μs
    WriteNibble(0x30);       // Function set
    __delay_us(40);          // wait more then 37us
    WriteNibble(0x20);       // set to 4 bit interface
    LCD_WriteCommand(0x2A);  // set to 4 bit interface, 2 line and 5*10 font
    LCD_WriteCommand(0x0C);  // Display On
    LCD_WriteCommand(0x06);  // cursor ON
    LCD_WriteCommand(0x08);  // clear display
}

// Send Data to LCD
void LCD_WriteData(unsigned char Byte)
{
    RS = 1;                     
    RW = 0 ; 
    //
    NOP();
    LCD_Port = Byte & 0xF0 ;                // send high nibble
    EN = 1;
    __delay_us(1);
    EN = 0;
    __delay_us(1);

    LCD_Port = (unsigned char)(Byte << 4 );  // send low nibble
    EN = 1;
    __delay_us(1);
    EN = 0;
    __delay_us(1);

   __delay_us(40); //// wait more then 37us
}

//Send a character to the LCD
void LCD_Data( unsigned char *S)
{

    while (*S != '\0')
    {
      LCD_WriteData(*S);
        S++;
    }
}

void main ()
{
    unsigned char String []={"Thank You"};

    Port_Initialized ();
    LCD_Initialized();
    LCD_Data(String);

    while (1)
    {
 }
}
1623688382059.png

1623688544215.png
 

Attachments

Last edited:

JohnInTX

Joined Jun 26, 2012
4,787
Compare your register values in LCD_Initialized() with those used in #293. Some of yours are incorrect.
As I noted in #294, these commands take a little or a lot of time to execute. See page 24 in the Hitachi spec. Consider adding 40us delay after each 'fast' command and 2ms after Clear Display or Return Home commands.
Set it up to turn the cursor on to flash to start and set a breakpoint after initializing the display. If your initialize sequence is correct, you'll have a blinking cursor at location 0.

If not, work through the actual writing of each command to the display. You can set a breakpoint while E is high and verify D7-D4, RS, RW/ to ensure you are sending the correct values. Compare with your earlier code to look for any differences.

Note that you have to delay 40us after each character written, too.

The Hitachi LCD controller requires care in initialization and use. The datasheet is not particularly well written either so work slowly and pay attention to the timings.

Good luck!
 
Last edited:

Thread Starter

Djsarakar

Joined Jul 26, 2020
489
The Hitachi LCD controller requires care in initialization and use. The datasheet is not particularly well written either so work slowly and pay attention to the timings.

Good luck!
Datasheet is very difficult to understand. specially I don't understand how to get timing in program that's shown in picture. as you said At 20MHz, 3 NOPs are 600ns so one NOP is 200ns how to get required time 10ns 40ns time

1623716767141.png


Edit

Note that you have to delay 40us after each character written,
I think In the below function I should wait 40us after sending each character. Am I doing ?

C:
//Send a character to the LCD
void LCD_Data( unsigned char *S)
{

    while (*S != '\0')
    {
      LCD_WriteData(*S);
      __delay_us(40); //// wait more then 37us
        S++;
    }
}
 
Last edited:

JohnInTX

Joined Jun 26, 2012
4,787
Those times in the datasheet are MINIMUM times. They can be longer and always are when you control the display using IO lines. The timings you show apply when the display is operated as a memory or IO device on a processor with an external memory / IO bus to read and write the 44780’s registers as a memory or IO device.

The timings you are missing are the times required to EXECUTE the command or data write after it is written to the LCD.. The 44780 is its own dedicated microcontroller that is executing it’s internal program to perform the tasks you tell it to do when you write commands or data to it. Executing thise commands takes time. Any command or data you send it while it is executing the previous command or data will be lost. That’s why you have to pay attention to the execution times in the datasheet.

Adding the 40us delay after writing data as shown is a good start. What about writing commands, especially the ones with long execution times?
 

Thread Starter

Djsarakar

Joined Jul 26, 2020
489
Those times in the datasheet are MINIMUM times. They can be longer and always are when you control the display using IO lines. The timings you show apply when the display is operated as a memory or IO device on a processor with an external memory / IO bus to read and write the 44780’s registers as a memory or IO device.

The timings you are missing are the times required to EXECUTE the command or data write after it is written to the LCD.. The 44780 is its own dedicated microcontroller that is executing it’s internal program to perform the tasks you tell it to do when you write commands or data to it. Executing thise commands takes time. Any command or data you send it while it is executing the previous command or data will be lost. That’s why you have to pay attention to the execution times in the datasheet.

Adding the 40us delay after writing data as shown is a good start. What about writing commands, especially the ones with long execution times?
@JohnInTX Thank you!

I've adjusted required time for LCD Initialization and now my code is working

1623750649306.png


C:
//
#define _XTAL_FREQ 20000000     // crystal 20MHz

// PIC18F45K80 Configuration Bit Settings
// CONFIG1L
#pragma config RETEN = ON       // VREG Sleep Enable bit (Ultra low-power regulator is Enabled (Controlled by SRETEN bit))
#pragma config INTOSCSEL = LOW  // LF-INTOSC Low-power Enable bit (LF-INTOSC in Low-power mode during Sleep)
// SOSCSEL = No Setting
#pragma config XINST = OFF      // Extended Instruction Set (Disabled)
// CONFIG1H
#pragma config FOSC = HS2       // HS oscillator (high power, 16 MHz-25 MHz
#pragma config PLLCFG = OFF     // PLL x4 Enable bit (Disabled)
#pragma config FCMEN = OFF      // Fail-Safe Clock Monitor (Disabled)
#pragma config IESO = OFF       // Internal External Oscillator Switch Over Mode (Disabled)
// CONFIG2L
#pragma config PWRTEN = ON      // Power Up Timer (Enabled)
#pragma config BOREN = OFF      // Brown Out Detect (Disabled in hardware, SBOREN disabled)
#pragma config BORV = 0         // Brown-out Reset Voltage bits (3.0V)
#pragma config BORPWR = LOW     // BORMV Power level (BORMV set to low power level)
// CONFIG2H
#pragma config WDTEN = OFF      // Watchdog Timer (WDT disabled in hardware; SWDTEN bit disabled)
#pragma config WDTPS = 1        // Watchdog Postscaler (1:1)
// CONFIG3H
#pragma config CANMX = PORTC    // ECAN Mux bit (ECAN TX and RX pins are located on RC6 and RC7, respectively)
#pragma config MSSPMSK = MSK5   // MSSP address masking (5 bit address masking mode)
#pragma config MCLRE = ON      // Master Clear Enable (MCLR Enabled, RE3 Disabled)
// CONFIG4L
#pragma config STVREN = OFF     // Stack Overflow Reset (Disabled)
#pragma config BBSIZ = BB1K     // Boot Block Size (1K word Boot Block size)
// CONFIG5L
#pragma config CP0 = ON         // Code Protect 00800-01FFF (Enabled)
#pragma config CP1 = ON         // Code Protect 02000-03FFF (Enabled)
#pragma config CP2 = ON         // Code Protect 04000-05FFF (Enabled)
#pragma config CP3 = ON         // Code Protect 06000-07FFF (Enabled)
// CONFIG5H
#pragma config CPB = ON         // Code Protect Boot (Enabled)
#pragma config CPD = ON         // Data EE Read Protect (Enabled)
// CONFIG6L
#pragma config WRT0 = ON        // Table Write Protect 00800-01FFF (Enabled)
#pragma config WRT1 = ON        // Table Write Protect 02000-03FFF (Enabled)
#pragma config WRT2 = ON        // Table Write Protect 04000-05FFF (Enabled)
#pragma config WRT3 = ON        // Table Write Protect 06000-07FFF (Enabled)
// CONFIG6H
#pragma config WRTC = ON        // Config. Write Protect (Enabled)
#pragma config WRTB = ON        // Table Write Protect Boot (Enabled)
#pragma config WRTD = ON        // Data EE Write Protect (Enabled)
// CONFIG7L
#pragma config EBTR0 = ON       // Table Read Protect 00800-01FFF (Enabled)
#pragma config EBTR1 = ON       // Table Read Protect 02000-03FFF (Enabled)
#pragma config EBTR2 = ON       // Table Read Protect 04000-05FFF (Enabled)
#pragma config EBTR3 = ON       // Table Read Protect 06000-07FFF (Enabled)
// CONFIG7H
#pragma config EBTRB = ON       // Table Read Protect Boot (Enabled)
// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.

#pragma warning disable 520

#include <xc.h>

#define RS            LATBbits.LATB4
#define RW            LATBbits.LATB5
#define EN            LATBbits.LATB6

#define LCD_Port      LATD

//Port Initialized
void Port_Initialized (void)
{
// LATx registers
    LATA =  0x00;
    LATB =  0x00;
    LATC =  0x00;
    LATD =  0x00;
    LATE =  0x00;

//  TRISx registers
    TRISA = 0x00;     // All are output, Unused
    TRISB = 0x00;     // RS, R/W EN
    TRISC = 0x00;     //all are output, Unused
    TRISD = 0x00;     // LCD Port
    TRISE = 0x00;     // All are output, Unused
 
    ANCON0 = 0x00;    // digital port
    ANCON1 = 0x00;    // Set to digital port
    CM1CON = 0x00;    // Comparator off
    CM2CON = 0x00;    // Comparator off
    ADCON0 = 0x00;    // A/D conversion Disabled
    ADCON1 = 0x00;    // A/D conversion Disabled
    ADCON2 = 0x00;    // A/D conversion Disabled
}
void Enable_Pulse()
{
    EN = 1;
    NOP();   //200ns ;
    EN = 0;
    NOP();   //200ns ;
}
//Send only high nibble to the LCD
void WriteNibble(unsigned char command)
{
    RS = 0; RW = 0; // Make RS, RW low to write command   
    NOP();   //200ns 
    LCD_Port = command & 0xF0 ;  // Send only four upper nibble
    Enable_Pulse(); 
}

//Send a high nibble and low nibble to the LCD
void LCD_WriteCommand(unsigned char command)
{ 
   //
    RS = 0; RW = 0;
    NOP();// 200ns 
    
    LCD_Port = command & 0xF0 ;             // Send only high nibble
    Enable_Pulse();
    
    LCD_Port =  ((command << 4) & 0xF0);   // Send low nibble 
    Enable_Pulse();
    
    __delay_us(50);                        // wait more then 37us
}

//Initialized  LCD
void  LCD_Initialized()
{
    __delay_ms(15);          // Wait more than 15 ms
    WriteNibble(0x30);       // Function set
    __delay_ms(5);           // Wait more than 4.1 ms
    WriteNibble(0x30);       // Function set
    __delay_us(100);         // Wait for more than 100 ?s
    WriteNibble(0x30);       // Function set
    __delay_ms(1);     
    LCD_WriteCommand(0x20);  // set to 4 bit interface
    LCD_WriteCommand(0x2C);  // set to 4 bit interface, 2 line and 5*10 font
    LCD_WriteCommand(0x06);  // move cursor right after write
    LCD_WriteCommand(0x0C);  // Display On   
    LCD_WriteCommand(0x01);  // clear display
    __delay_ms(3); 
}

// Send Data to LCD
void LCD_WriteData(unsigned char Byte)
{
    RS = 1; RW = 0 ;                        // Make RS high and RW low to write data     
    NOP();   
    LCD_Port = Byte & 0xF0 ;                // send high nibble
    Enable_Pulse();
    LCD_Port = (unsigned char)(Byte << 4 );  // send low nibble
    Enable_Pulse();   
   __delay_us(40);                           // wait more then 37us
}

//Send a character to the LCD
void LCD_Data( unsigned char *S)
{
    while (*S != '\0')
    {
      LCD_WriteData(*S);
      __delay_ms(1); //// wait more 1ms
        S++;
    }
}


void main ()
{
    unsigned char String []={"Thank you John"};
    
    Port_Initialized (); //Port Initialized
    LCD_Initialized();   //Initialized  LCD
    LCD_Data(String);    // Send a string to LCD
    
    while (1);
}
 

Thread Starter

Djsarakar

Joined Jul 26, 2020
489
@JohnInTX Taking next step I've written code to received ACK/NAK from ADS1115. When I send slave address device is Not ACKnowledged

ADC VDD ---> 5V
ADC GND ---> GND
ADC SDA ----> PIC SDA
ADC SCL -----> PIC SCL
ADC ADDR----> GND

C:
//
#define _XTAL_FREQ 20000000     // crystal 20MHz

// PIC18F45K80 Configuration Bit Settings
// CONFIG1L
#pragma config RETEN = ON       // VREG Sleep Enable bit (Ultra low-power regulator is Enabled (Controlled by SRETEN bit))
#pragma config INTOSCSEL = LOW  // LF-INTOSC Low-power Enable bit (LF-INTOSC in Low-power mode during Sleep)
// SOSCSEL = No Setting
#pragma config XINST = OFF      // Extended Instruction Set (Disabled)
// CONFIG1H
#pragma config FOSC = HS2       // HS oscillator (high power, 16 MHz-25 MHz
#pragma config PLLCFG = OFF     // PLL x4 Enable bit (Disabled)
#pragma config FCMEN = OFF      // Fail-Safe Clock Monitor (Disabled)
#pragma config IESO = OFF       // Internal External Oscillator Switch Over Mode (Disabled)
// CONFIG2L
#pragma config PWRTEN = ON      // Power Up Timer (Enabled)
#pragma config BOREN = OFF      // Brown Out Detect (Disabled in hardware, SBOREN disabled)
#pragma config BORV = 0         // Brown-out Reset Voltage bits (3.0V)
#pragma config BORPWR = LOW     // BORMV Power level (BORMV set to low power level)
// CONFIG2H
#pragma config WDTEN = OFF      // Watchdog Timer (WDT disabled in hardware; SWDTEN bit disabled)
#pragma config WDTPS = 1        // Watchdog Postscaler (1:1)
// CONFIG3H
#pragma config CANMX = PORTC    // ECAN Mux bit (ECAN TX and RX pins are located on RC6 and RC7, respectively)
#pragma config MSSPMSK = MSK5   // MSSP address masking (5 bit address masking mode)
#pragma config MCLRE = ON      // Master Clear Enable (MCLR Enabled, RE3 Disabled)
// CONFIG4L
#pragma config STVREN = OFF     // Stack Overflow Reset (Disabled)
#pragma config BBSIZ = BB1K     // Boot Block Size (1K word Boot Block size)
// CONFIG5L
#pragma config CP0 = ON         // Code Protect 00800-01FFF (Enabled)
#pragma config CP1 = ON         // Code Protect 02000-03FFF (Enabled)
#pragma config CP2 = ON         // Code Protect 04000-05FFF (Enabled)
#pragma config CP3 = ON         // Code Protect 06000-07FFF (Enabled)
// CONFIG5H
#pragma config CPB = ON         // Code Protect Boot (Enabled)
#pragma config CPD = ON         // Data EE Read Protect (Enabled)
// CONFIG6L
#pragma config WRT0 = ON        // Table Write Protect 00800-01FFF (Enabled)
#pragma config WRT1 = ON        // Table Write Protect 02000-03FFF (Enabled)
#pragma config WRT2 = ON        // Table Write Protect 04000-05FFF (Enabled)
#pragma config WRT3 = ON        // Table Write Protect 06000-07FFF (Enabled)
// CONFIG6H
#pragma config WRTC = ON        // Config. Write Protect (Enabled)
#pragma config WRTB = ON        // Table Write Protect Boot (Enabled)
#pragma config WRTD = ON        // Data EE Write Protect (Enabled)
// CONFIG7L
#pragma config EBTR0 = ON       // Table Read Protect 00800-01FFF (Enabled)
#pragma config EBTR1 = ON       // Table Read Protect 02000-03FFF (Enabled)
#pragma config EBTR2 = ON       // Table Read Protect 04000-05FFF (Enabled)
#pragma config EBTR3 = ON       // Table Read Protect 06000-07FFF (Enabled)
// CONFIG7H
#pragma config EBTRB = ON       // Table Read Protect Boot (Enabled)
// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.

#pragma warning disable 520

#include <xc.h>

#define ADC_ADDRESS_WRITE        0x90 //first 7-bit I2C address with a low R/W bit
#define CONFIG_REGISTER          0x01 // points to Config register
#define MSB_CONFIG_REGISTER      0x84 // MSB of the Config register to be written
#define LSB_CONFIG_REGISTER      0x83 //LSB of the Config register to be written


void Port_Initialized (void)
{
// LATx registers
    LATA =  0x00;
    LATB =  0x00;
    LATC =  0x00;
    LATD =  0x00;
    LATE =  0x00;

//  TRISx registers
    TRISA = 0x00;    // All are output, Unused
    TRISB = 0x00;    // all are output, Unused
    TRISC = 0x18;    // SDA SCL
    TRISD = 0x00;    // all are output, Unused
    TRISE = 0x00;    // All are output, Unused

    ANCON0 = 0x00;    // Set to digital port
    ANCON1 = 0x00;    // Set to digital port
    CM1CON = 0x00;    // Comparator off
    CM2CON = 0x00;    // Comparator off
    ADCON0 = 0x00;    // A/D conversion Disabled
    ADCON1 = 0x00;    // A/D conversion Disabled
    ADCON2 = 0x00;    // A/D conversion Disabled
}

//Initialize I2C in master mode
void I2C_Initialized(void)
{
    SSPSTAT=0x80; //Slew rate control is disabled for Standard Speed mode (100 kHz and 1 MHz)
    SSPCON1=0x28; // I2C Master mode, clock = FOSC/(4 * (SSPADD + 1))
    SSPCON2=0x00;
    SSPADD = 49;
}

// Send an I2C START
// Return 0 if all ok, 1 if bus collision
__bit I2C_Start(void)
{
    BCLIF = 0;        //Clear 'Bus collision" flag
    SEN = 1;          //initiate a START cycle
    while (SEN);      //wait until it has been sent
    return BCLIF;     //return value of BCLIF flag
}

// Send an I2C STOP
void I2C_Stop(void)
{
    PEN = 1;          //initiate a STOP cycle
    while (PEN);      //wait until it has been sent
}

//Receive one byte. ackflag=0 to send ACK, or 1 to send NAK in reply
//Send one byte. Return 0 if ACK received, or 1 if NAK received
__bit I2C_Sendbyte(unsigned char dat)
{
    SSPBUF = dat;
    NOP();          //wait a little for R_W to be set
    while (R_W);    //wait until byte sent and ACK/NAK received
    return ACKSTAT;
}

//Return 0 if all OK,
unsigned char ADC_Write(unsigned char adc_address, unsigned char config_register, unsigned char MSB_config, unsigned char LSB_config )
{
    if (I2C_Start() )   //send a start, and check if it succeeded
        return 1;   //abort if bus collision

    //send the I2C slave address
    if (I2C_Sendbyte(adc_address))  //
    {
        I2C_Stop(); //if address was NAKed, terminate the cycle
        return 2;   //and return error code
    }
    //send the Config register
    if (I2C_Sendbyte(config_register))
    {
        I2C_Stop(); //if register was NAKed, terminate the cycle
        return 3;   //and return error code
    }

    //send MSB of Config register
    if (I2C_Sendbyte(MSB_config))
    {
        I2C_Stop(); //terminate the cycle
        return 4;   //and return error code
    }

    //send the LSB ofConfig register
    if (I2C_Sendbyte(LSB_config))
    {
        I2C_Stop(); // terminate the cycle
        return 5;   //and return error code
    }

    I2C_Stop();
    return 0;   //no error
}

void main(void)
{
    unsigned char ADC_Send;
    Port_Initialized ();
    I2C_Initialized();

    ADC_Send = ADC_Write(ADC_ADDRESS_WRITE , CONFIG_REGISTER, MSB_CONFIG_REGISTER, LSB_CONFIG_REGISTER );

    while(1);
}
Debugging show When I send device address ADC is not ACK signal. What's wrong in my code

1623761772318.png
 

Attachments

Last edited:

JohnInTX

Joined Jun 26, 2012
4,787
9.5.1.1 I2C Address Selection
The ADS111x have one address pin, ADDR, that configures the I2C address of the device. This pin can be
connected to GND, VDD, SDA, or SCL, allowing for four different addresses to be selected with one pin, as
shown in Table 4. The state of address pin ADDR is sampled continuously. Use the GND, VDD and SCL
addresses first. If SDA is used as the device address, hold the SDA line low for at least 100 ns after the SCL line
goes low to make sure the device decodes the address correctly during I2C communication.
Table 4. ADDR Pin Connection and Corresponding Slave Address
ADDR PIN CONNECTION SLAVE ADDRESS
GND 1001000
VDD 1001001
SDA 1001010
SCL 1001011
Do you have the ADDR pin strapped to ground?
 
Top