# Testing I2C to run an SSD1306 OLED display with PIC16F1938

#### Vizier87

##### Active Member
Hi guys, been a while.

I'm attempting to run an SSD1306 display with this tutorial. The programs compiled pretty ok I guess. The PIC I'm using is PIC16F1938.

The display I'm using didn't have the RST/CS pins. Only SCL, SDA, Vcc and GND pins.

Here's the code:

C:
/**************************************************************************************

Interfacing PIC16F887 microcontroller with SSD1306 OLED display
C Code for mikroC PRO for PIC compiler
Internal oscillator used @ 8MHz
Configuration words: CONFIG1 = 0x2CD4
CONFIG2 = 0x0700
This is a free software with NO WARRANTY.
http://simple-circuit.com/

***************************************************************************************/

// define SSD1306 reset pin (if available)
//#define SSD1306_RST       RD4_bit
//#define SSD1306_RST_DIR   TRISD4_bit

#include <SSD1306.c>     // include SSD1306 OLED driver source file

char *text = "000\0";     // '\0' is the string terminator
unsigned short i = 0;

int i_= 0;
sbit Indicator at rb4_bit;

for (i_ = 0; i_ < z; i_++){
Indicator = 1;
Delay_ms(1000);
Indicator = 0;
Delay_ms(1000);
}
Indicator = 0;
}

void main() {

trisb4_bit = 0;
trisc = 0;
portc = 0;

delay_ms(500);   // wait half a second

I2C1_Init(400000);    // initialize I2C communication with clock frequency of 400KHz

// initialize the SSD1306 OLED with an I2C addr = 0x7A (default address)

// clear the screen
SSD1306_ClearDisplay();

SSD1306_GotoXY(1, 1);    // move cursor to column 1, row 1
SSD1306_Print("Interfacing PIC16F887 with SSD1306 OLED display");  // print text
delay_ms(5000);   // wait 5 seconds

// clear the screen
SSD1306_ClearDisplay();

SSD1306_GotoXY(6, 2);   // move cursor to column 6, row 2
SSD1306_Print("Hello world!");
delay_ms(2000);

SSD1306_StartScrollRight(1, 1);
delay_ms(3000);
SSD1306_StopScroll();

SSD1306_StartScrollLeft(1, 1);
delay_ms(3000);
SSD1306_StopScroll();

SSD1306_StartScrollDiagRight(1, 1);
delay_ms(3000);
SSD1306_StopScroll();

SSD1306_StartScrollDiagLeft(1, 1);
delay_ms(3000);
SSD1306_StopScroll();

delay_ms(3000);
SSD1306_ClearDisplay();

SSD1306_GotoXY(6, 2);
SSD1306_Print("Hello world!");
delay_ms(2000);

while(1) {

text[0] = (i / 100) % 10 + '0';   // extract hundreds digit
text[1] = (i / 10)  % 10 + '0';   // extract tens digit
text[2] =  i        % 10 + '0';   // extract ones digit

SSD1306_GotoXY(10, 5);
SSD1306_Print(text);

i += 1;   // increment i

delay_ms(500);

}

}
// End of code.
After compiling and burning the .HEX, didn't work. That's fine, troubleshooting then.

Then I checked RC3 and RC4 with a scope. No signals/clocked output observed, just a DC output.

So I tried checked the I2C hardware by a simple library code:

C:
void main(){
trisc = 0;
portc = 0;
PORTB = 0;
TRISB = 0;                 // Configure PORTB as output
I2C1_Init(100000);         // initialize I2C communication
I2C1_Start();              // issue I2C start signal
I2C1_Wr(0xA2);             // send byte via I2C  (device address + W)
I2C1_Wr(2);                // send byte (address of EEPROM location)

while (1){
I2C1_Wr(0xAA);             // send data (data to be written)
I2C1_Stop();               // issue I2C stop signal  Delay_100ms();
I2C1_Start();              // issue I2C start signal
I2C1_Wr(0xA2);             // send byte via I2C  (device address + W)
I2C1_Wr(2);                // send byte (data address)
I2C1_Repeated_Start();     // issue I2C signal repeated start
I2C1_Wr(0xA3);             // send byte (device address + R)
PORTB = I2C1_Rd(0u);       // Read the data (NO acknowledge)
I2C1_Stop();               // issue I2C stop signal

}

}
And no clocked signals either from RC3 or RC4.

Anyone can point me in the right direction here?

Thanks.
Vizier87

#### Vizier87

##### Active Member
Do you have the "pullups" in place.. I normally use 4k7 as the sda and sck lines are high impedance the lines are just pulled low...
Hi Ian! Nice to see you're still running ETO.
So the "pullups" are to the Vcc right? I didn't do it because the schematics didn't specify that part. Ok will do it soon and report the results.

Thanks!

#### Ian Rogers

##### User Extraordinaire
Forum Supporter
Hi Ian! Nice to see you're still running ETO.
Not quite!! Just helping out..

Pullups can be different values.. All depends on how many devices are on the bus... 2k7 ~ 10k are normal... I found 4k7 works for me..

#### Nigel Goodwin

##### Super Moderator
Not quite!! Just helping out..

Pullups can be different values.. All depends on how many devices are on the bus... 2k7 ~ 10k are normal... I found 4k7 works for me..
As you say, they aren't at all critical - I usually use 10k these days - but that could just be because I have a bandolier of 2000 of them!

My PIC tutorials used 12K - again, simply because they were to hand.

#### Mike - K8LH

##### Well-Known Member
All of the 0.91" (128x32) and 0.96" (128x64) displays I've purchased had built-in pull-ups.

Which display are you using?

Last edited:

#### Vizier87

##### Active Member
Not quite!! Just helping out..

Pullups can be different values.. All depends on how many devices are on the bus... 2k7 ~ 10k are normal... I found 4k7 works for me..
Ian, anyhow, with the hardware I2C code and pullup resistors (I used 1k ohm), it just still shows a DC signal. I think my configuration is messed up somewhere? Both RC3 and RC4 (SDA & SCL) pins are giving the DC output.

All of the 0.91" (128x32) and 0.96" (128x64) displays I've purchased had built-in pull-ups.

Which display are you using?
Hehe I'm not really sure. Got it from a friend. Here's how it looks like:

I think it's the 128x64? The glass part measures 2cm x 2.7 cm.

I believe it has to be my configuration settings but I'm not sure. Here's the settings:

Is there anything I might have missed? I'd like to just test if the hardware I2C is even giving out any clocked signals at the first place. I've tweaked a bit here and there and it didn't seem to change anything. The SCL is RC3 and SDA at RC4. The code is at the first post.

As per the PIC16F1938's pins, I can see a nice clock if I just do a simple 1010101 loop at 10us.

So I don't think the pin is damaged.

What else do I have to check?
Thanks,
Vizier87

#### Pommie

##### Well-Known Member
Both RC3 and RC4 (SDA & SCL) pins are giving the DC output.
What DC output? If it's zero then a device may be holding the bus low (clock stretching). This can happen when I²C communication is interrupted when you compile.

Mike.

#### Vizier87

##### Active Member
What DC output? If it's zero then a device may be holding the bus low (clock stretching). This can happen when I²C communication is interrupted when you compile.

Mike.
Hi Mike. The DC output is constantly HI at ~4.5V.

So how should I check if the hardware I2C is ok?

Thanks!

#### Ian Rogers

##### User Extraordinaire
Forum Supporter
Hi Mike. The DC output is constantly HI at ~4.5V.
It will be... It would appear that the I2C output isn't where you think it is That chip has analogue segment out for LCD's... Just check if it needs turning off..

#### Vizier87

##### Active Member
It will be... It would appear that the I2C output isn't where you think it is That chip has analogue segment out for LCD's... Just check if it needs turning off..
Hi Ian, I've attempted to tweak like the following:

C:
void main(){
LCDEN_bit = 0;
LCDIRE_bit = 0;
LCDREF = 0;
LCDSE1 = 0;
LCDSE0 = 0;
SSPEN_bit = 1;

ansela = 0;
anselb = 0;

trisc = 0;
portc = 0;

I2C1_Init(100000);         // initialize I2C communication
I2C1_Start();              // issue I2C start signal
while (1){
I2C1_Wr(0xff);             // send byte via I2C  (device address + W)
}

}
And still nothing else. I'm not sure if I'm doing this correctly though.. I just saw that the control bits/registers might have something to do with the I2C pins but I'm like shooting in the dark here.

What do you think? Here are the registers which might be associated as per the datasheet:

#### Nigel Goodwin

##### Super Moderator
Try setting it up using MCC, that should set whatever needs doing (hopefully), otherwise read the datasheet.

#### rjenkinsgb

##### Well-Known Member
Just a thought - the example project was for the 877, you are using the 1938.

Have you changed the MCU type in the overall compiler project settings? The addresses for peripheral control registers are very different between the two devices.

#### Vizier87

##### Active Member
Just a thought - the example project was for the 877, you are using the 1938.

Have you changed the MCU type in the overall compiler project settings? The addresses for peripheral control registers are very different between the two devices.
Yeah, I have. I'm using MikroC so the configuration settings are way easier. Just select the settings we want from Project Settings.

#### Vizier87

##### Active Member
Try setting it up using MCC, that should set whatever needs doing (hopefully), otherwise read the datasheet.
Hi Uncle Nigel. I've been reading the datasheet. Unfortunately the key to understanding the peripherals is also my weakness - the block diagrams are a bit enigmatic for me.

Otherwise I have been using PIC for quite a long time. Not intense enough for it to be a career though.

So MCC is this one right?

#### Ian Rogers

##### User Extraordinaire
Forum Supporter
Try setting it up using MCC, that should set whatever needs doing (hopefully), otherwise read the datasheet.
Sorry Nigel... MikroC isn't ANSI C its its own abomination.. Code configurator is a long way off..

Vizier87 The ports are in the datasheet, but If it has a LCDEN points to it not being that.. PORTC 3 and 2 should be configured as input!!! They HAVE to be high impedance..

#### Vizier87

##### Active Member
Sorry Nigel... MikroC isn't ANSI C its its own abomination.. Code configurator is a long way off..

Vizier87 The ports are in the datasheet, but If it has a LCDEN points to it not being that.. PORTC 3 and 2 should be configured as input!!! They HAVE to be high impedance..
So if I want to make sure the i2c output is enabled, I have to configure LCDEN as 0? Sorry not so clear..

#### Nigel Goodwin

##### Super Moderator
Sorry Nigel... MikroC isn't ANSI C its its own abomination.. Code configurator is a long way off..

Vizier87 The ports are in the datasheet, but If it has a LCDEN points to it not being that.. PORTC 3 and 2 should be configured as input!!! They HAVE to be high impedance..
Worth installing MPLABX and MCC just to use the MCC, he can always nick the setup routines if he really wants to continue with MicroC.

#### Pommie

##### Well-Known Member
Sorry but I really detest MCC. It produces incomprehensible nonsense. I'd rather spend the time going through the datasheet and write my own. However, never used anything more powerful than an 18 series.

Mike.

#### Ian Rogers

##### User Extraordinaire
Forum Supporter
Port C sda and scl 2 and 3 have to be inputs... right now you have them low and outputs..

portc = 0;
trisc = 0xff; <---- has to be inputs..
Sorry but I really detest MCC. It produces incomprehensible nonsense. I'd rather spend the time going through the datasheet and write my own. However, never used anything more powerful than an 18 series.

Mike.
Total agree here....