You need to log in to create posts and topics.

Does i2C work for any of the PIC16F MCUs?

Page 1 of 2Next

Hello, 

I'm new to embedded programming and I've been trying to write a small program that uses i2C on the PIC16F887 MCU. I've been struggling with it for awhile. I came across a tutorial for the firmware and even when I used the code in the tutorial I couldn't get the simulation to work.  

I came across another forum post that mentioned the USI module for one of the Attiny module's hadn't been completely implemented yet (It's been fixed now). I wanted to know if any of the PIC16F i2C modules work so I can make sure to use the right MCU in SimulIde for testing.

Hi.

I2C in PICs should work.
You can check this example: File explorer->Examples->Micro->PIC->16F876_I2C-Lcd

Oh thanks for pointing me to the examples, didn't know those were there. 

A little context:
I'm using the Xc8 compiler and it has a delay function that I've been using to debug. I hook up an unused pin to a SimulIde probe and when the program gets to the end I set the pin to high, delay, then low to see the probe flash.   

I set up a test using the 16F876 since it looks like the i2c module works on that MCU. I didn't set up the extra pin with the probe for testing. I only left in the i2c code. When I ran it I noticed the Oscope component I hooked up to the SDA and SCL pins was oscillating. That wasn't happening with the last setup, they would just be stuck high. 

I added the debug pin back with the delay and the SDA and SCL pins stopped oscillating. So I'm thinking maybe the delay causes some issues. I tried flashing the probe without the delay, but for some reason it won't flash at all without it...

Anyways, I think the oscillating SDA and SCL pins are a good sign. Do you have any tips for how to debug further?  

Here's the code for added context:

void i2c_Initialize(const unsigned long freq_K){
TRISCbits.TRISC3 = 1;
TRISCbits.TRISC4 = 1;

SSPCON = 0b00101000;
SSPCON2 = 0b000000000;

SSPADD = (_XTAL_FREQ/(4*freq_K*100)) - 1;
}

void i2c_Hold(){
while ((SSPCON2 & 0b00011111) || (SSPSTAT & 0b00000100) );// Wait until I2c is ready
}

void i2c_Begin(){
i2c_Hold();
SSPCON2bits.SEN = 1;
}

void i2c_End(){
i2c_Hold();
SSPCON2bits.PEN = 1;
}

void i2c_Write(unsigned char data){
i2c_Hold();
SSPBUF = data;
}

void main() {

while (1) {
i2c_Initialize(100);
i2c_Begin();
unsigned char lcd_address_write = 0b01111100;//Address = 62
i2c_Write(lcd_address_write);
// Send command bits
i2c_Write(0b00000000);
// Send A5 command to turn display on.
i2c_Write(0xA5); //turn on LCD
i2c_End();
}

}

 

Thanks for the code.

I tested it and found an error in Simulide related to the RW bit in SSPSTAT, so the hold() function will not work properly.
As a workaround you can try by using a 100 us delay instead of that while loop in hold().

This issue is solved at Rev 2207.
In a few days I will upload new executables with this issue solved here:
https://simulide.com/p/testers/

Thanks, I updated the hold function to use the 100 us delay instead. 

But, I still can't get the display to turn on. Do you have any suggestions for debugging?

It looks like the SSPBUF is getting cleared, but I can't verify that the display is actually receiving the commands.

 

Check that the I2C address of the display is the same you are using in the firmware.

 

Do you have any suggestions for debugging?

You can try something like this to see which data is actually sent.
Use an I2C to Parallel component (Logic->Converters) with the same I2C address than the display and the firmware:

oh nice, thanks for the suggestion. 

So i set the address of the i2c to parallel component and the OLED screen to be 62. 

Interestingly, when I write the address to the SSPBUF (with the write bit = 0b01111100 == 0x7C) it shows up correctly on the display. But, any following data I populate the SSPBUF doesn't show correctly. it usually ends up just showing FF. 

How'd you get it to display A5? I would assume you just set SSPBUF to the address then followed it up with A5?

 

 

 

Interestingly, when I write the address to the SSPBUF (with the write bit = 0b01111100 == 0x7C) it shows up correctly on the display.

Weird... the address should not show up in the display, only the data.
At least if you follow the sequence:

    i2c_Begin()
    i2c_Write( Address ); 
    i2c_Write( data0 );
    i2c_Write( data1 );
    ...
    i2c_Write( dataN );
    i2c_End();

Can you zip the folder with circuit, source code and hex and attach here?

sure

Uploaded files:

Thanks.

I didn't relize before but there is an error in the baudrate calculation.
SSPAD = 143 is not valid, it must be a 7 bit value.
I think it sould be:
SSPADD = (_XTAL_FREQ/(4*freq_K*1000)) - 1;

Not sure how much this can affect...

Page 1 of 2Next