I'm relatively new using PIC microcontrollers and MPLAB XC8 compiler.

I want to communicate two PIC16F887 using I2C. I did use this tutorial (https:// electrosome .com /i2c- pic-microcontroller-mplab-xc8/) as my introduction to this protocol, but although my code compiles, my proteus simulation doesn't do anything. The objective is only send the count from 0 to 3 through I2C from the master to one Slave, and the slave should show that number on 2 led on PORTB.

Proteus simulation of my circuit

I debugg the program on the master side and the program seems to get stuck inside my I2C_Master_Wait() function, I really try to understand whats happening inside this function, but i dont get any result since too many days ago.

void I2C_Master_Wait(){
    while ((SSPSTAT & 0x04) || (SSPCON2 & 0x1F)); 

Hope someone could help me with a better tutorial or some explanation about whats going on in that function and maybe other way to do it. I attach here the folder with the code of master and slave and the proteus simulation.



1 Answer 1


Before starting, if you want to work with digital communication such as I2C, SPI, I2S, CAN, etc. I strongly recommend you invest money in a logic analyzer. These protocols doesn't require a fast sampling rate, so you can most likely find an affordable device. In any case, it will save you valuable time. I personnaly uses Saleae devices.

Understanding registers

To understand the little piece of code you shared, we will have to calrifies a little how microprocesseors works and how they interracts with hardware. I assume that you are aware of how pointers works in C/C++ ; they points to a memory address. What you probably don't know is that they don't only points to a memory location, but can also point to a hardware register. When you read or write into a variable, you processor will put that address on it address bus and either read or write the content on the data bus.

Like I said, not all addresses refers to a memory location. If you look at the PIC16F887 datasheet, you will find many registers located between addresse 000h-1FFh. You can either read or write their content. Sometime they will be accessible only in for one or the other, that will be specified in the datasheet.

These registers are used for 1) Configuring your peripheral (like an I2C trasceiver) 2) Passing data to the a device (like the data you want to send/receive with I2c)

The pieces of code you gave is reading these resgisters. SSPSTAT (0x94) and SSPCON2 (0x91) are two constants defined in a header file that comes along with your compiler. They basically are pointers, and the code is making bitwise operation to get the value of a specific bit within these register. In other words, your program is waiting as long as SSPSTAT bit 2 or SSPCON2 bits 8 to 0 are set to high. This seems like it won't work because SSPCON2 contains configurations bits, like bit 7 : GCEN. If you set this bit to high, interrupts are enabled for I2C and this bit will not changes.

your problem

As for where the problem is, the wiring seems right. Problems could be :

  1. Bad configuration of register
  2. Slave never trasmit (that's where the logic analyzer becomes handy)
  3. Reception logic is not good. The one you have seems odd to me.

I think for reception, you should be looking at SSPSTAT bit0 (BF). This bit becomes high when your reception buffer is full.

Good luck


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.