I have an existing PCB that is no longer supported by the manufacturer and has been plagued with software issues for years. So i don't have much control over how the board is laid out and what components are used.
The board has a PIC16F747 running on the internal oscillator at 8Mhz, and a 24AA01 EEPROM chip with 1k ohm pullups (to 5v).
I have had no problem with any other aspects of the PIC, ive got ADC and PWM working fine but i just cannot get I2C communication to work as expected.
All I2C commands are being accepted but I'm not getting the data i have written back as I expected.
I know the EEPROM is working as i can interface with the chip using a AVR MCU using a PCB header that has connections to the I2C bus.
The next port of call is for me to invest in a oscilloscope or I2C buss sniffer so i can actually see what is being sent.
Here is some stripped down code of what I'm trying to achieve.
#pragma config FOSC = INTOSCIO // Oscillator Selection bits (INTRC oscillator; port I/O function on OSC1/CLKI/RA7 and OSC2/CLKO/RA6)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT enabled)
#pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled)
#pragma config MCLRE = OFF // MCLR/VPP/RE3 Pin Function Select bit (MCLR/VPP/RE3 pin function is digital input only, MCLR gated to '1')
#pragma config BOREN = ON // Brown-out Reset Enable bit (Enabled)
#pragma config BORV = 20 // Brown-out Reset Voltage bits (VBOR set to 2.0V)
#pragma config CCP2MX = RC1 // CCP2 Multiplex bit (CCP2 is on RC1)
#pragma config CP = OFF // Flash Program Memory Code Protection bits (Code protection off)
// CONFIG2
#pragma config FCMEN = ON // Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor enabled)
#pragma config IESO = ON // Internal External Switchover bit (Internal External Switchover mode enabled)
#pragma config BORSEN = ON // Brown-out Reset Software Enable bit (Enabled)
// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.
#define _XTAL_FREQ 8000000
#include <xc.h>
void i2c_wait(){
while (!SSPIF);
SSPIF = 0;
while ((SSPCON2 & 0b00011111) || (SSPSTAT & 0b00000100));
}
int address = 0x01; // Address to write to
int value = 0x11; // Value to write
int result = 0x00; // Result returned from SSPBUF
void main(void) {
// Set Internal Oscillator to 8Mhz
OSCCONbits.IRCF = 0x7;
// Setup EEPROM Write Enable
TRISA4 = 0;
RA4 = 0;
// Setup output for testing
TRISD6 = 0;
RD6 = 0;
// Set SDA & SCL to inputs
TRISC3 = 1;
TRISC4 = 1;
SSPCONbits.SSPM = 0x8; // i2c Master mode
SSPADD = 4; // Set Clock for 400k
SSPEN = 1; // Enable SSP Module
while(1)
{
// Init Interrupt
SSPIF = 0;
// Write Data
// Start
SEN = 1;
i2c_wait();
// Send Addres + W
SSPBUF = 0xA0;
i2c_wait();
// Send EEPROM Address
SSPBUF = address;
i2c_wait();
// Send Data to set in address
SSPBUF = value;
i2c_wait();
// Send Stop
PEN = 1;
i2c_wait();
// Let EEPROM Settle
__delay_ms(10);
// Read Data
// Start
SEN = 1;
i2c_wait();
// Send Address + W
SSPBUF = 0xA0;
i2c_wait();
// Send EEPROM Address
SSPBUF = address;
i2c_wait();
// Repeat Start
RSEN = 1;
i2c_wait();
// Send Address + R
SSPBUF = 0xA1;
i2c_wait();
// Read Data
RCEN = 1;
i2c_wait();
result = (SSPBUF);
// Set NACK
ACKDT = 1;
ACKEN = 1;
i2c_wait();
// Stop
PEN = 1;
i2c_wait();
// Let see what we got then!
if (result < 0x22){
RD6 = 1;
}
else
{
RD6 = 0;
}
// Settle
__delay_ms(10);
}
return;
}
```