Author Topic: PIC 16F1503 16x2 LCD I2C Communication issues  (Read 814 times)

0 Members and 1 Guest are viewing this topic.

Offline sumithcmohan

  • Contributor
  • Posts: 8
  • Country: in
PIC 16F1503 16x2 LCD I2C Communication issues
« on: January 09, 2019, 09:46:58 am »
Code: [Select]
PIC 16F1503
Clock: Internal 10MHz
Compiler: MPLAB XC8
Simulation: Proteus 8 Professional


I am trying to show a text "Hello world" in my LCD via PIC I2C communication. Tried sevaral codes but fails everytime.

Here is the LCD details in proteus.

Code: [Select]
Part value: JHD-2X16-I2C

{MODDLL=LCDALPHA}
{PRIMITIVE=DIGITAL,I2C}
{NUMCOLS=16}
{NUMROWS=2}
CLOCK=100kHz
{ROW1=80-8F}
{ROW2=C0-CF}
{DVCADDR=$7C}
{TRACE=1}



Below shows the code in PIC 16F1503
Code: [Select]
// PIC16F1503 Configuration Bit Settings

// 'C' source line config statements

// CONFIG1
#pragma config FOSC = INTOSC    // Oscillator Selection Bits (INTOSC oscillator: I/O function on CLKIN pin)
#pragma config WDTE = OFF       // Watchdog Timer Enable (WDT disabled)
#pragma config PWRTE = OFF      // Power-up Timer Enable (PWRT disabled)
#pragma config MCLRE = OFF      // MCLR Pin Function Select (MCLR/VPP pin function is digital input)
#pragma config CP = OFF         // Flash Program Memory Code Protection (Program memory code protection is disabled)
#pragma config BOREN = ON       // Brown-out Reset Enable (Brown-out Reset enabled)
#pragma config CLKOUTEN = OFF   // Clock Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin)

// CONFIG2
#pragma config WRT = OFF        // Flash Memory Self-Write Protection (Write protection off)
#pragma config STVREN = ON      // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will cause a Reset)
#pragma config BORV = LO        // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.)
#pragma config LPBOR = OFF      // Low-Power Brown Out Reset (Low-Power BOR is disabled)
#pragma config LVP = OFF        // Low-Voltage Programming Enable (High-voltage on MCLR/VPP must be used for programming)

 
#include <xc.h>
#include <stdint.h>
#include <stdio.h>
 
#define _XTAL_FREQ 10000000
 
void I2C_init (uint32_t clock)
{
    SSPADD = (_XTAL_FREQ/(4*clock))-1;  // here clock is the BR/clock speed   
    SSP1CON1 = 0b00101000;     //first 4 bits I2c master mode , 6th bit is SSPEN enables the scl and sda line
      //Set/Reset: S, P, SSPxSTAT, WCOL, SSPOV
    SSP1CON2 |= 0x00; //Reset SEN, PEN (SSPxCON2)
    SSP1IF = 1; BCL1IF = 1;//Set SSPxIF, BCLxIF
    SSP1STAT = 0;
    TRISC0 = 1;
    TRISC1 = 1;
}
 
I2C_wait (void)
{
    while ((SSPSTAT & 0x04) || (SSPCON2 & 0x1F));    // wait for start bit to clear in SSPSTAT and bits 0 to 4 in SSPCON2
}
 
void I2C_start (void)
{
    I2C_wait ();
    SSPCON2 |= 0x01; // SEN=1 -> initiate the START condition on SDA and SCL pins
}
 
 
void I2C_repeated_start (void)
{
    I2C_wait();
    SSPCON2 |= 0x02; // RSEN=1  -> initiate REPEATED START condition on SDA and SCL pins
}
 
 
void I2C_stop (void)
{
    I2C_wait ();
    SSPCON2 |= 0x04; // PEN=1 -> initiate the STOP condition on SDA and SCL pins
}
 
 
void I2C_write (uint8_t data)
{
    I2C_wait ();
    SSPBUF = data;  // load data into SSPBUF register
}
 
 
uint8_t I2C_read (uint8_t ack)
{
    uint8_t temp;
    I2C_wait();
    RCEN = 1;    // enable receive mode for I2c
    I2C_wait();
    temp = SSPBUF;   // load data from Buffer to the temp
    I2C_wait();
    ACKDT = (ack);  // 0-- not ACK , 1-- ACK
    ACKEN = 1;   // Send Acknowledgement
    return temp;
}
 
#define SLAVE_ADDRESS_LCD 0x40 // change this according to ur setup
 
void lcd_send_data (unsigned char data)
{
unsigned char data_l, data_u;
data_l = (data<<4)&0xf0;  //select lower nibble by moving it to the upper nibble position
data_u = data&0xf0;  //select upper nibble
 
I2C_start();
I2C_write (SLAVE_ADDRESS_LCD);
I2C_write (data_u|0x0D);  //enable=1 and rs =1
I2C_write (data_u|0x09);  //enable=0 and rs =1
 
I2C_write (data_l|0x0D);  //enable =1 and rs =1
I2C_write (data_l|0x09);  //enable=0 and rs =1
 
I2C_stop();
}
 
void lcd_send_cmd (unsigned char data)
{
unsigned char data_l, data_u;
data_l = (data<<4)&0xf0;  //select lower nibble by moving it to the upper nibble position
data_u = data&0xf0;  //select upper nibble
 
I2C_start();
I2C_write (SLAVE_ADDRESS_LCD);
I2C_write (data_u|0x0C);  //enable=1 and rs =0
I2C_write (data_u|0x08);  //enable=0 and rs =0
 
I2C_write (data_l|0x0C);  //enable =1 and rs =0
I2C_write (data_l|0x08);  //enable=0 and rs =0
 
I2C_stop();
}
 
void lcd_init (void)
{
lcd_send_cmd (0x02);
lcd_send_cmd (0x28);
lcd_send_cmd (0x0c);
lcd_send_cmd (0x80);
}
 
void lcd_send_string (char *str)
{
while (*str) lcd_send_data (*str++);
}
 
//void lcd_send_float (float data, int numberofdigits) 
//{
// char xg_char[12];
// snprintf (xg_char, 8, "%f", data);
// for (int i=0; i<numberofdigits; i++)
// {
// lcd_send_data (xg_char[i]);
// }
//}
 
 
 
int main ()
{
   
    I2C_init (100000);
    lcd_init ();
   
    lcd_send_string ("h");
   
    while (1)
    {
 
    }
}


Please help on this issue. I am trying for last 2 weeks. :(


« Last Edit: January 10, 2019, 06:11:11 am by sumithcmohan »
 

Offline JoeP

  • Contributor
  • Posts: 37
  • Country: gb
Re: PIC 16F1503 16x2 LCD I2C Communication issues
« Reply #1 on: January 12, 2019, 01:13:48 pm »
I'm not familiar with proteus, but it could help you diagnose the problem better if you look at the waveforms on the SDA and SCL lines; I'm also having trouble with I2C, and using a dual-channel oscilloscope it revealed that the slave device wasn't sending an acknowledge bit when I transmitted its address.
 

Offline sumithcmohan

  • Contributor
  • Posts: 8
  • Country: in
Re: PIC 16F1503 16x2 LCD I2C Communication issues
« Reply #2 on: January 12, 2019, 02:08:46 pm »
Do you have any workable code for 16F1503 for I2C ?

In my code I am getting good wave form from SDA and SCL. I will share the screen shot on Monday. Need some guidance about how to know “Aknowledge receipt “ from slave.

Also I am doubt about the device address asper the example code for 16F877A it’s 0x28 but it’s not work with 16F1503 and LCD I2C display.
 

Offline JoeP

  • Contributor
  • Posts: 37
  • Country: gb
Re: PIC 16F1503 16x2 LCD I2C Communication issues
« Reply #3 on: January 12, 2019, 06:33:15 pm »
Before I go any further, I should probably mention that I've never actually got I2C working - though I do know the basic principles. I'm not the most qualified person to answer this question.
Are you familiar with what is going on on the SDA and CLK lines in a working I2C communication? If not, there are plenty of guides online, so it would be a good idea to get accustomed with it.
To begin to analyse the waveforms, first look for the start bit. Then look at the logic level of SDA at each preceding falling edge. The first 7 of these bits form the device address. The bit after that determines whether the master intends to read (1) or write to (0) the slave device. The bit after that is the acknowledge bit. If this is low, then the slave has received the address and is ready to continue the communication. If not, something's going wrong.
The line in your code
Code: [Select]
#define SLAVE_ADDRESS_LCD 0x40 would be an obvious mistake if, as you say, the LCD address is actually 0x28.
 

Offline @rt

  • Frequent Contributor
  • **
  • Posts: 996
Re: PIC 16F1503 16x2 LCD I2C Communication issues
« Reply #4 on: January 13, 2019, 03:22:43 am »
You should delay for about a second before sending to any HD44780 compatible display (which I assume this is after the I2C decoder).
For some it doesn’t matter, but for others it will never initialise, and never come good for the rest of the power cycle.
 

Offline newbrain

  • Frequent Contributor
  • **
  • Posts: 934
  • Country: se
Re: PIC 16F1503 16x2 LCD I2C Communication issues
« Reply #5 on: January 13, 2019, 08:50:53 pm »
Not being a PICky person, I won't comment on the I2C and other PIC specific stuff.

BUT:
Code: [Select]
void lcd_init (void)
{
lcd_send_cmd (0x02);
lcd_send_cmd (0x28);
lcd_send_cmd (0x0c);
lcd_send_cmd (0x80);
}
This does not look like a correct initialization sequence for a HD44870 based display.
The sequence can be found at page 68 here.

I see at least two problems:
  • Not following the described sequence with the specified delays.
  • This is the major one: the code send the commands in two nibbles, that's OK only if the controller is already in 4 bit mode.
    At initialization, it will default to 8 bit mode: only the most significant nibble must be sent (the commands to set interface width do not have meaningful bits in the lower nibble).
Nandemo wa shiranai wa yo, shitteru koto dake.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf