I'm trying to read and write to an i2c serial eeprom (24lc01b) from a pic16f1936 to test functionality on an existing PCB design that has been implemented already. I'm using a library I got from the microchip website that was intended for the 16f877 using the hitech c compiler (Lite Mode). I just renamed constants (e.g. PSPIF to SSPIF; STAT_CKE to CKE) in the header file so it could compile. It compiles, I upload it to the board and no joy... Here's the header file:
and here's a snippet of my code:
Expecting an led to flash once... nothing... But the ledflash routine is working because I use it elsewhere in the program. It's as if it is stuck. Any code after trying to read eeprom does not run. I'm certain all the hardware is ok because when the micro is loaded with firmware. The EEPROM does it's job.
Notes:
- No pull up on SCL Line (must work without because other software makes it work);
- Internal oscillator used @8MHz (set in software using OSCCON register) - seems to work fine
Suspecting some interrupt related problem affecting the eeprom read routine. Like its getting stuck waiting for something from the eeprom. Maybe pic16f1936 interrupt settings are different (or does MSSP settings override?)
Please help.
Code:
/******************************************************************************************/
// Hardware I2C single master routines for PIC16F877
// for HI-TEC PIC C COMPILER.
//
// i2c_init - initialize I2C functions
// i2c_start - issue Start condition
// i2c_repStart- issue Repeated Start condition
// i2c_stop - issue Stop condition
// i2c_read(x) - receive unsigned char - x=0, don't acknowledge - x=1, acknowledge
// i2c_write - write unsigned char - returns ACK
//
// modified from CCS i2c_877 demo
//
// by
//
// Michael Alon - MICROCHIP FAE
// My E-mail michael@elina-micro.co.il
// www.elina-micro.co.il
// Tel: 972-3-6498543/4
// Fax: 972-3-6498745
// Elina Micro LTD .ISRAEL
//
/******************************************************************************************/
void i2c_init()
{
TRISC3=1; // set SCL and SDA pins as inputs
TRISC4=1;
SSPCON = 0x38; // set I2C master mode
SSPCON2 = 0x00;
//file://SSPADD = 0x6; // 400kHz bus with 10MHz xtal - use 0x0C with 20MHz xtal
SSPADD = 10; // 100k at 4Mhz clock
CKE=1; // use I2C levels worked also with '0'
SMP=1; // disable slew rate control worked also with '0'
SSPIF=0; // clear SSPIF interrupt flag
BCLIF=0; // clear bus collision flag
}
/******************************************************************************************/
void i2c_waitForIdle()
{
while (( SSPCON2 & 0x1F ) | R_nW ) {}; // wait for idle and not writing
}
/******************************************************************************************/
void i2c_start()
{
i2c_waitForIdle();
SEN=1;
}
/******************************************************************************************/
void i2c_repStart()
{
i2c_waitForIdle();
RSEN=1;
}
/******************************************************************************************/
void i2c_stop()
{
i2c_waitForIdle();
PEN=1;
}
/******************************************************************************************/
int i2c_read( unsigned char ack )
{
unsigned char i2cReadData;
i2c_waitForIdle();
RCEN=1;
i2c_waitForIdle();
i2cReadData = SSPBUF;
i2c_waitForIdle();
if ( ack )
{
ACKDT=0;
}
else
{
ACKDT=1;
}
ACKEN=1; // send acknowledge sequence
return( i2cReadData );
}
/******************************************************************************************/
unsigned char i2c_write( unsigned char i2cWriteData )
{
i2c_waitForIdle();
SSPBUF = i2cWriteData;
return ( ! ACKSTAT ); // function returns '1' if transmission is acknowledged
}
/******************************************************************************************/
Code:
#include <htc.h>
#include "877_i2c.h"
**************************** CONFIG FUSES *****************************/
//Set-up in MPLAB IDE...
void Delay10xUs(unsigned char );
void Delay10Us(void);
void setup_main(void);
void led(unsigned char);
void ledflash_slow(unsigned char);
void ledflash_fast(unsigned char);
unsigned char cByteToRead;
//use these defintions for the ee library
//#define SCL RC3
//#define SDA RC4
/////////////Delay Routines - based on 8MHZ internal clock///////////////
char _dcnt, _cnt;
void Delay10Us()
{_dcnt=1;
while(--_dcnt)continue;
}
void Delay10xUs(unsigned char x)
{
_cnt=x;
while(--_cnt)
Delay10Us();
}
void DelayMs(unsigned char p)
{
do
{
Delay10xUs(16);
Delay10xUs(16);
Delay10xUs(16);
Delay10xUs(16);
}while(--p != 0);
}
void Delay250Ms(unsigned char q)
{
do
{
DelayMs(250);
}while(--q != 0);
}
void DelayS(unsigned char r)
{
do
{
Delay250Ms(4);
}while(--r != 0);
}
/////////////End Delay Routines///////////////
/******************************************************************************************/
void write_ext_eeprom(unsigned char address, unsigned char data)
{
i2c_start();
i2c_write(0xa0);
i2c_write(address);
i2c_write(data);
i2c_stop();
DelayMs(11);
}
/******************************************************************************************/
unsigned char read_ext_eeprom(unsigned char address)
{
unsigned char data;
i2c_start();
i2c_write(0xa0);
i2c_write(address);
i2c_repStart();
i2c_write(0xa1);
data=i2c_read(0);
i2c_stop();
return(data);
}
/******************************************************************************************/
void main(void)
{
setup_main();
write_ext_eeprom(0x00, 0x01);
DelayS(1);
cByteToRead= read_ext_eeprom(0);
ledflash_fast(cByteToRead);
DelayS(1);
}
void setup_main(void)
{
OSCCON=0b11110010; //To select internal oscillator at 8MHz
ANSELA=0X02; //Set only Pin 28 in Port A (RA1 - Bump input) to analog input
ANSELB=0; //Set all analog pins in Port B to digital I/O
TRISA=0X3F; //Set RA6 and RA7 to outpur and the rest (RA5-0) to inputs
TRISB=0XFF; //Set all I/O pins on PortB to inputs
TRISC=0; //Set all I/O pins on PortC to outputs
PORTC=0;
}
Notes:
- No pull up on SCL Line (must work without because other software makes it work);
- Internal oscillator used @8MHz (set in software using OSCCON register) - seems to work fine
Suspecting some interrupt related problem affecting the eeprom read routine. Like its getting stuck waiting for something from the eeprom. Maybe pic16f1936 interrupt settings are different (or does MSSP settings override?)
Please help.