PIC Development Board with PK3

JohnInTX

Joined Jun 26, 2012
4,787
32768.0 would be the way to specify that value.
I would keep ADC_Result an integer while combining bytes (line 28) then cast it to a float for the arithmetic:
Result_V = ( ((float) ADC_Result) / 32768.0) * 2.048); // or something like that
 

Thread Starter

Djsarakar

Joined Jul 26, 2020
489
32768.0 would be the way to specify that value.
I would keep ADC_Result an integer while combining bytes (line 28) then cast it to a float for the arithmetic:
Result_V = ( ((float) ADC_Result) / 32768.0) * 2.048); // or something like that
What's wrong with this
main.c:332:55: warning: implicit conversion loses floating-point precision: 'double' to 'float' [-Wconversion]
Result_V = ((float)(ADC_Result /32768.0) * 2.048);
~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~

C:
int ADC_Result;
float Result_V;

void main(void)
{
     unsigned char i = 0;

     unsigned char Data1 [10]="Test";

     Port_Initialized ();
     LCD_Initialized();
     I2C_Initialized();

    // Write to Config register
     Result1 = Write_I2C_Device(SLAVE_ADDRESS , Word_Address , sizeof(ADS1115_data), ADS1115_data);
     __delay_ms(10);

    while(1)
    {      
       Result3 = Read_I2C_Device(SLAVE_ADDRESS, 0x00 , 2, rd_buf) ;
       __delay_ms(10);
        asm("nop");
       
        if(Result3 == 0)  // if successful read..
        {
            ADC_Result = (rd_buf[0] << 8) + rd_buf[1];
            Result_V =  ((float)(ADC_Result /32768.0) * 2.048);
           sprintf( (char *) A_buffer,"ADC value: %f", Result_V );
     
           WriteCommand(0x80); //// Move the cursor to beginning of first line.

           LCD_Data(A_buffer);
         
        }
     
    }
  
}
 

JohnInTX

Joined Jun 26, 2012
4,787
Line 27: Result_V = ( (float) (ADC_Result /32768.0) * 2.048);
Your parenthesis are in the wrong place. The parentheses you have are first dividing an integer by a float then casting the result to float then multiplying. You want to cast ADC_Result to a float first before other calculations. It may be easier to see if you split it up:

Result_V = (float)ADC_Result;
Result_V /= 32768.0;
Result_V *= 2.048;
 

Thread Starter

Djsarakar

Joined Jul 26, 2020
489
Line 27: Result_V = ( (float) (ADC_Result /32768.0) * 2.048);
Your parenthesis are in the wrong place. The parentheses you have are first dividing an integer by a float then casting the result to float then multiplying. You want to cast ADC_Result to a float first before other calculations. It may be easier to see if you split it up:

Result_V = (float)ADC_Result;
Result_V /= 32768.0;
Result_V *= 2.048;
no warnings but I don't know why program doesn't reach at last line 334

1626183914394.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>
#include <stdio.h>
#include <conio.h>

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

// The code should set the R/W bit according to its function
#define SLAVE_ADDRESS        0x90         //I2C slave address of ADS1115 (8 bit format)
#define Word_Address         0x01         // Points to Config register


#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

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;      // Slave SDA and CLOCK
    TRISD = 0x00;      // LCD
    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
}

// Wait for 5 ms
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 initialize.
    WriteNibble(0x30);              //Required for initialization
    __delay_ms(5);                  //required delay
    WriteNibble(0x30);              //Required for initialization
    __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(0x06);             //move cursor right after write
    WriteCommand(0x0C);             //turn on display
    WriteCommand(0x01);             //clear 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();                                  // delay of 1uS
    NOP();
    NOP();
    LCD_E = 0;                              //disable it
}

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_Write(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_Read(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 Write_I2C_Device(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_Write(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_Write(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_Write(*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 Read_I2C_Device(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 = Write_I2C_Device(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_Write(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_Read(ackflag);
    }
    I2C_Stop();
    return 0;   //no error
}
const unsigned char ADS1115_data[] =
{
    0x84,  // MSB of the Config register to be written
    0x83,  // LSB of the Config register to be written
};

unsigned char rd_buf[2];
unsigned char A_buffer[20];

int ADC_Result;
float Result_V;

void main(void)
{
     unsigned char i = 0;

     unsigned char Data1 [10]="Test";

     Port_Initialized ();
     LCD_Initialized();
     I2C_Initialized();
 
    // Write to Config register
     Result1 = Write_I2C_Device(SLAVE_ADDRESS , Word_Address , sizeof(ADS1115_data), ADS1115_data);
     __delay_ms(10);

    
    while(1)
    {       
       Result3 = Read_I2C_Device(SLAVE_ADDRESS, 0x00 , 2, rd_buf) ;
       __delay_ms(10);
        asm("nop");
        
        if(Result3 == 0)  // if successful read..
        {
            ADC_Result = (rd_buf[0] << 8) + rd_buf[1];
            Result_V = (float)ADC_Result;
            Result_V /= 32768.0;
            Result_V *= 2.048;
        
           sprintf( (char *) A_buffer,"ADC value: %5f", Result_V );
      
           WriteCommand(0x80); //// Move the cursor to beginning of first line.

           LCD_Data(A_buffer);
          
        }
        
        
      
    }
    
    
}
 

JohnInTX

Joined Jun 26, 2012
4,787
I do not see anything wrong, either. A common mistake is making the sprintf buffer too small but it looks OK at 20. Try making it bigger if you want but I don’t think it is a problem.
 

Thread Starter

Djsarakar

Joined Jul 26, 2020
489
I do not see anything wrong, either. A common mistake is making the sprintf buffer too small but it looks OK at 20. Try making it bigger if you want but I don’t think it is a problem.
I changed the size to 30 but still the data is not displayed.
 

JohnInTX

Joined Jun 26, 2012
4,787
I changed the size to 30 but still the data is not displayed.
Does the formatted string appear in A_buffer after sprintf?
Try relocating WriteCommand(0x80) to just before lie 331 to give it a little time to execute.
Did you say that it does not do the loop like it did before?

In cases like this you just have to step it through and see where it is failing.
 

Thread Starter

Djsarakar

Joined Jul 26, 2020
489
Does the formatted string appear in A_buffer after sprintf?
yes look the picture
Try relocating WriteCommand(0x80) to just before lie 331 to give it a little time to execute.
Tried but doesn't work

In cases like this you just have to step it through and see where it is failing.
Part of code
C:
    // Write to Config register
     Result1 = Write_I2C_Device(SLAVE_ADDRESS , Word_Address , sizeof(ADS1115_data), ADS1115_data);
     __delay_ms(10);

   
    while(1)
    {      
       Result3 = Read_I2C_Device(SLAVE_ADDRESS, 0x00 , 2, rd_buf) ;
       __delay_ms(10);
        asm("nop");
       
        if(Result3 == 0)  // if successful read..
        {
           // WriteCommand(0x80);
            ADC_Result = (rd_buf[0] << 8) + rd_buf[1];
            Result_V = (float)ADC_Result;
            Result_V /= 32768.0;
            Result_V *= 2.048;
       
           sprintf( (char *) A_buffer,"ADC value: %5f", Result_V );
           asm("nop");
           WriteCommand(0x80); //// Move the cursor to beginning of first line.

           LCD_Data(A_buffer);
           asm("nop");
        }
       
           
     
    }
   
   
}
Result in debug windows

1626194293326.png
 

JohnInTX

Joined Jun 26, 2012
4,787
So with WriteCommand (0x80) relocated to line 331 (and not present on line 341) it doesn't display?

Does it loop and change the string in Result_V as you adjust the pot? If so, it looks like a hardware or timing error on the LCD.
 

Thread Starter

Djsarakar

Joined Jul 26, 2020
489
So with WriteCommand (0x80) relocated to line 331 (and not present on line 341) it doesn't display?

Does it loop and change the string in Result_V as you adjust the pot? If so, it looks like a hardware or timing error on the LCD.
yes it loop and change the string in Result_V when I adjust the pot

I've attached three test results

1626196431829.png

1626196548436.png

1626196588226.png
 

JohnInTX

Joined Jun 26, 2012
4,787
Can you break on line 342, the nop? The display should have the message there. Change the pot and click RUN and break on the nop again. The display should have a new value.

EDIT: Have you cycled the power to cold-start the LCD? Sometimes a 4 bit interface can get out of sync.

Consider turning on the cursor when you initialize the LCD. That way you can see if your initialization is OK and where the LCD thinks it should be on the line.
Change:
WriteCommand(0x0C); //turn on display
To:
WriteCommand(0x0F); //turn on display with flashing cursor

Consider writing 'RESET' on the display when you power up or reset the PIC. That way you know the LCD is ready to go.

You need a 2ms delay after the Clear Display command in the initialization.
 
Last edited:

Thread Starter

Djsarakar

Joined Jul 26, 2020
489
Can you break on line 342, the nop? The display should have the message there. Change the pot and click RUN and break on the nop again. The display should have a new value.

EDIT: Have you cycled the power to cold-start the LCD? Sometimes a 4 bit interface can get out of sync.

Consider turning on the cursor when you initialize the LCD. That way you can see if your initialization is OK and where the LCD thinks it should be on the line.
Change:
WriteCommand(0x0C); //turn on display
To:
WriteCommand(0x0F); //turn on display with flashing cursor

Consider writing 'RESET' on the display when you power up or reset the PIC. That way you know the LCD is ready to go.

You need a 2ms delay after the Clear Display command in the initialization.
@JohnInTX Thank you for being with me in tough time

When I ran the below code cursor is blinking with balck box on first line
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>
#include <stdio.h>
#include <conio.h>

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

// The code should set the R/W bit according to its function
#define SLAVE_ADDRESS        0x90         //I2C slave address of ADS1115 (8 bit format)
#define Word_Address         0x01         // Points to Config register


#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

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;      // Slave SDA and CLOCK
    TRISD = 0x00;      // LCD
    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
}

// Wait for 5 ms
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 initialize.
    WriteNibble(0x30);              //Required for initialization
    __delay_ms(5);                  //required delay
    WriteNibble(0x30);              //Required for initialization
    __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(0x06);             //move cursor right after write
    WriteCommand(0x0F);             //turn on display with flashing cursor
    WriteCommand(0x01);             //clear display
    __delay_ms(2);
}

//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();                                  // delay of 1uS
    NOP();
    NOP();
    LCD_E = 0;                              //disable it
}

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_Write(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_Read(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 Write_I2C_Device(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_Write(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_Write(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_Write(*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 Read_I2C_Device(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 = Write_I2C_Device(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_Write(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_Read(ackflag);
    }
    I2C_Stop();
    return 0;   //no error
}
const unsigned char ADS1115_data[] =
{
    0x84,  // MSB of the Config register to be written
    0x83,  // LSB of the Config register to be written
};

unsigned char rd_buf[2];
unsigned char A_buffer[18];

int ADC_Result;
float Result_V;

void main(void)
{
     unsigned char i = 0;

     unsigned char Data1 [10]="Test";

     Port_Initialized ();
     LCD_Initialized();
     I2C_Initialized();

    // Write to Config register
     Result1 = Write_I2C_Device(SLAVE_ADDRESS , Word_Address , sizeof(ADS1115_data), ADS1115_data);
     __delay_ms(10);

  
    while(1)
    {     
       Result3 = Read_I2C_Device(SLAVE_ADDRESS, 0x00 , 2, rd_buf) ;
       __delay_ms(10);
        asm("nop");
      
        if(Result3 == 0)  // if successful read..
        {
            WriteCommand(0x80);
            ADC_Result = (rd_buf[0] << 8) + rd_buf[1];
            Result_V = (float)ADC_Result;
            Result_V /= 32768.0;
            Result_V *= 2.048;
      
           sprintf( (char *) A_buffer,"ADC value: %5f", Result_V );
           asm("nop");
    
           LCD_Data(A_buffer);
           asm("nop");
        }
      
    }
  
  
}
Can you break on line 342, the nop? The display should have the message there. Change the pot and click RUN and break on the nop again. The display should have a new value.
When I click on debug button cursor doesn't blink so when I break on line "nop", Display doesn't show any message
I see green cursor never stop at line 342. It stop at line 341
1626203632259.png


When I Change the pot and click RUN and break on the nop again. The display doesn't show any value. Watch variable window should new value. for example 0.00300

1626203844461.png
 
Last edited:

JohnInTX

Joined Jun 26, 2012
4,787
If you have not made any other changes to the LCD code since the previous version that worked, I don’t know what is going on. A string is a string. If the LCD code is the same it should work with any string.
 

Thread Starter

Djsarakar

Joined Jul 26, 2020
489
If you have not made any other changes to the LCD code since the previous version that worked, I don’t know what is going on. A string is a string. If the LCD code is the same it should work with any string.
previous version is working fine. I've tested below code

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>
#include <stdio.h>
#include <conio.h>

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

// The code should set the R/W bit according to its function
#define SLAVE_ADDRESS        0x90         //I2C slave address of ADS1115 (8 bit format)
#define Word_Address         0x01         // Points to Config register


#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

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;      // Slave SDA and CLOCK
    TRISD = 0x00;      // LCD
    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
}

// Wait for 5 ms
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 initialize.
    WriteNibble(0x30);              //Required for initialization
    __delay_ms(5);                  //required delay
    WriteNibble(0x30);              //Required for initialization
    __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(0x06);             //move cursor right after write
    WriteCommand(0x0F);             //turn on display with flashing cursor
    WriteCommand(0x01);             //clear display
    __delay_ms(2);
}

//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();                                  // delay of 1uS
    NOP();
    NOP();
    LCD_E = 0;                              //disable it
}

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_Write(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_Read(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 Write_I2C_Device(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_Write(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_Write(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_Write(*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 Read_I2C_Device(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 = Write_I2C_Device(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_Write(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_Read(ackflag);
    }
    I2C_Stop();
    return 0;   //no error
}
const unsigned char ADS1115_data[] =
{
    0x84,  // MSB of the Config register to be written
    0x83,  // LSB of the Config register to be written
};

unsigned char rd_buf[2];
unsigned char A_buffer[18];

int ADC_Result;
float Result_V;

void main(void)
{
     unsigned char i = 0;

     unsigned char Data1 [10]="Test";

     Port_Initialized ();
     LCD_Initialized();
     I2C_Initialized();
 
    // Write to Config register
     Result1 = Write_I2C_Device(SLAVE_ADDRESS , Word_Address , sizeof(ADS1115_data), ADS1115_data);
     __delay_ms(10);

    
     while(1)
    {     
       Result3 = Read_I2C_Device(SLAVE_ADDRESS, 0x00 , 2, rd_buf) ;
       __delay_ms(10);
        asm("nop");
      
        if(Result3 == 0)  // if successful read..
        {
           WriteCommand(0x80); //// Move the cursor to beginning of first line.
            
           ADC_Result = (rd_buf[0] << 8) + rd_buf[1];
          
          
           sprintf( (char *) A_buffer,"ADC value: %d", ADC_Result );
           LCD_Data(A_buffer);
        
        }
      
    }
    
}
When I just add below part in code I wonder why I don't get adc value on display


Code:
       if(Result3 == 0)  // if successful read..
        {
           WriteCommand(0x80); //// Move the cursor to beginning of first line.
            
           ADC_Result = (rd_buf[0] << 8) + rd_buf[1];
            Result_V = (float)ADC_Result;
            Result_V /= 32768.0;
            Result_V *= 2.048;
          
           sprintf( (char *) A_buffer,"ADC value: %d", ADC_Result );
           LCD_Data(A_buffer);
        
        }
 

JohnInTX

Joined Jun 26, 2012
4,787
When I just add below part in code I wonder why I don't get adc value on display
I sure don’t know…
EDIT: maybe I do know: At 18 bytes, A_buffer is not big enough for the message with the floating point and will overwrite whatever is next in RAM. Make A_buffer[40] for now.
That doesn't explain why just the 3 floating point operations in lines 6-8 would have an effect but get A_buffer bigger.
You might also mess around with where you declare Result_V, try it inside of main - compiler allocation problem?
Visit the Project Properties and see if there is any setting that affects floating point numbers - make sure they are set to 32 bits.

Grasping at straws here as I don't have a setup I can use to compile your code and test it right now.
Good luck!
 
Last edited:

Thread Starter

Djsarakar

Joined Jul 26, 2020
489
I sure don’t know…
EDIT: maybe I do know: At 18 bytes, A_buffer is not big enough for the message with the floating point and will overwrite whatever is next in RAM. Make A_buffer[40] for now.
That doesn't explain why just the 3 floating point operations in lines 6-8 would have an effect but get A_buffer bigger.
You might also mess around with where you declare Result_V, try it inside of main - compiler allocation problem?
Visit the Project Properties and see if there is any setting that affects floating point numbers - make sure they are set to 32 bits.

Grasping at straws here as I don't have a setup I can use to compile your code and test it right now.
Good luck!
done all as suggested but still facing same problem

I have done experiment to find out why data is not displaying
This is not what we really want but it confirm there is problem with float variable
when I declare int variable data display on screen but when I declare float, double, data doesn't display.
C:
if(Result3 == 0)  // if successful read..
        {
           WriteCommand(0x80); //// Move the cursor to beginning of first line.
            
           ADC_Result = (rd_buf[0] << 8) + rd_buf[1];
          
           Result_V = ADC_Result;
           Result_V /= 32768;
           Result_V *= 2;
            sprintf( (char *) A_buffer,"ADC value: %d",  Result_V );
           LCD_Data(A_buffer);
        
        }
 

djsfantasi

Joined Apr 11, 2010
9,237
done all as suggested but still facing same problem

I have done experiment to find out why data is not displaying
This is not what we really want but it confirm there is problem with float variable
when I declare int variable data display on screen but when I declare float, double, data doesn't display.
C:
if(Result3 == 0)  // if successful read..
        {
           WriteCommand(0x80); //// Move the cursor to beginning of first line.
           
           ADC_Result = (rd_buf[0] << 8) + rd_buf[1];
         
           Result_V = ADC_Result;
           Result_V /= 32768;
           Result_V *= 2;
            sprintf( (char *) A_buffer,"ADC value: %d",  Result_V );
           LCD_Data(A_buffer);
       
        }
Where is the declaration of the result variable? I initially thought you were creating a different instance of it with a different scope…

Then I thought I saw a statement like this.

float double Result_V;

AFAIK, there is no such declaration. It’s either float or double. “double” is a double precision float variable. I think the line should just be this.

double Result_V;
 

Thread Starter

Djsarakar

Joined Jul 26, 2020
489
I think you’ve been doing that but be sure you use %f in the format string when you are using Result_V or any other float.
@JohnInTX sorry I'm coming back after almost a month. Me and my mother had some health issues so I couldn't continue thread. everything is fine now.

Back to thread. I had issue with floating point conversion. Code was works when using integer and fails when using float. I found solution to this problem on microchip forum. The problem only solved by changing the CONFIG settings . also I connected LCD RS, R/W. and E pin to PortC instead of PortB

I just disabled below setting.

Code:
#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)
I ran below code on my board
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 = 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 (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>
#include <stdio.h>
#include <conio.h>

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


#define SLAVE_ADDRESS        0x90         //I2C slave address of ADS1115 (8 bit format)
#define Word_Address         0x01         // Points to Config register

#define LCD_RS              LATAbits.LATA2
#define LCD_TRIS_RS         TRISAbits.TRISA2
#define LCD_RW              LATAbits.LATA1
#define LCD_TRIS_RW         TRISAbits.TRISA1
#define LCD_E               LATAbits.LATA0
#define LCD_TRIS_E          TRISAbits.TRISA0

#define  LCDPORT            LATD
#define  LCDTRISD           LATD

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;      // Slave SDA and CLOCK
    TRISD = 0x00;      // LCD
    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
}

// Wait for 5 ms
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 initialize.
    WriteNibble(0x30);              //Required for initialization
    __delay_ms(5);                  //required delay
    WriteNibble(0x30);              //Required for initialization
    __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(0x06);             //move cursor right after write
    WriteCommand(0x0F);             //turn on display with flashing cursor
    WriteCommand(0x01);             //clear display
    __delay_ms(2);
}

//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();                                  // delay of 1uS
    NOP();
    NOP();
    LCD_E = 0;                              //disable it
}

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_Write(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_Read(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 Write_I2C_Device(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_Write(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_Write(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_Write(*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 Read_I2C_Device(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 = Write_I2C_Device(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_Write(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_Read(ackflag);
    }
    I2C_Stop();
    return 0;   //no error
}
const unsigned char ADS1115_data[] =
{
    0x84,  // MSB of the Config register to be written
    0x83,  // LSB of the Config register to be written
};

unsigned char rd_buf[2];
unsigned char A_buffer[40];

int ADC_Result;
float Result_V;
void main(void)
{
 
     Port_Initialized ();
     LCD_Initialized();
     I2C_Initialized();

    // Write to Config register
     Result1 = Write_I2C_Device(SLAVE_ADDRESS , Word_Address , sizeof(ADS1115_data), ADS1115_data);
     __delay_ms(10);


    while(1)
    {  
       Result3 = Read_I2C_Device(SLAVE_ADDRESS, 0x00 , 2, rd_buf) ;
       __delay_ms(10);
     
   
     if(Result3 == 0) // if successful read..
{
       WriteCommand(0x80); // this line update lcd line position
        ADC_Result = (rd_buf[0] << 8) + rd_buf[1]; // this line update ADC value
        Result_V = (float)ADC_Result;
        Result_V *= 2.048 / 32768.0;
        sprintf( (char *) A_buffer,"value: %5.3f", Result_V );
        LCD_Data(A_buffer);
        asm("nop");

}
    }


}
This is test result

1629045636552.png

As can see in image floating value is being displaced on the LCD
 

JohnInTX

Joined Jun 26, 2012
4,787
Welcome back! I followed your progress on Microchip and am glad you got it working.

Based on your posts with the debugging info, it looked like sprintf with floats was working as you had a valid string in the buffer but turning OFF the table reads from program ROM was a good catch in any case.
So was catching that you were using the debug pins for the display controls. Indeed, we discussed that one here awhile ago:
https://forum.allaboutcircuits.com/threads/pic-development-board-with-pk3.172494/post-1553868
Things like that will eat your sack lunch. I would recommend you mark those pins, clip them off or slide piece of wire insulation over them to remind you never to use them for anything for debugging.

I am delighted that you have success. Kudos to ric, 1and0, and the others at the Microchip forum for their diligence. I was reminded that floats could use ROM tables and never thought to look at your config.. so good on them. I also picked up a couple of good tips on using XC8 while over there.

Finally, we're sorry to hear you had health issues. I was worried about you but am very happy to know that you and your mother are doing better.
Warm regards,
JohnInTX
 
Top