What about writing to LCD before and after EEPROM write. To see if the code is hanging during write or read.
Maybe move the LCD print code around - to see where the code hangs (if it does)
The below code displays the text "tst EEPROM A" with EEPROM inserted into socket. It displays the text "tst EEPROM Z" with EEPROM removed from socket
Maybe move the LCD print code around - to see where the code hangs (if it does)
The below code displays the text "tst EEPROM A" with EEPROM inserted into socket. It displays the text "tst EEPROM Z" with EEPROM removed from socket
C:
//
#define _XTAL_FREQ 20000000 // crystal 20MHz
// PIC18F45K80 Configuration Bit Settings
// CONFIG1L
#pragma config RETEN = ON // VREG Sleep Enable bit (Ultra low-power regulator is Enabled (Controlled by SRETEN bit))
#pragma config INTOSCSEL = LOW // LF-INTOSC Low-power Enable bit (LF-INTOSC in Low-power mode during Sleep)
// SOSCSEL = No Setting
#pragma config XINST = OFF // Extended Instruction Set (Disabled)
// CONFIG1H
#pragma config FOSC = HS2 // HS oscillator (high power, 16 MHz-25 MHz
#pragma config PLLCFG = OFF // PLL x4 Enable bit (Disabled)
#pragma config FCMEN = OFF // Fail-Safe Clock Monitor (Disabled)
#pragma config IESO = OFF // Internal External Oscillator Switch Over Mode (Disabled)
// CONFIG2L
#pragma config PWRTEN = ON // Power Up Timer (Enabled)
#pragma config BOREN = OFF // Brown Out Detect (Disabled in hardware, SBOREN disabled)
#pragma config BORV = 0 // Brown-out Reset Voltage bits (3.0V)
#pragma config BORPWR = LOW // BORMV Power level (BORMV set to low power level)
// CONFIG2H
#pragma config WDTEN = OFF // Watchdog Timer (WDT disabled in hardware; SWDTEN bit disabled)
#pragma config WDTPS = 1 // Watchdog Postscaler (1:1)
// CONFIG3H
#pragma config CANMX = PORTC // ECAN Mux bit (ECAN TX and RX pins are located on RC6 and RC7, respectively)
#pragma config MSSPMSK = MSK5 // MSSP address masking (5 bit address masking mode)
#pragma config MCLRE = ON // Master Clear Enable (MCLR Enabled, RE3 Disabled)
// CONFIG4L
#pragma config STVREN = OFF // Stack Overflow Reset (Disabled)
#pragma config BBSIZ = BB1K // Boot Block Size (1K word Boot Block size)
// CONFIG5L
#pragma config CP0 = ON // Code Protect 00800-01FFF (Enabled)
#pragma config CP1 = ON // Code Protect 02000-03FFF (Enabled)
#pragma config CP2 = ON // Code Protect 04000-05FFF (Enabled)
#pragma config CP3 = ON // Code Protect 06000-07FFF (Enabled)
// CONFIG5H
#pragma config CPB = ON // Code Protect Boot (Enabled)
#pragma config CPD = ON // Data EE Read Protect (Enabled)
// CONFIG6L
#pragma config WRT0 = ON // Table Write Protect 00800-01FFF (Enabled)
#pragma config WRT1 = ON // Table Write Protect 02000-03FFF (Enabled)
#pragma config WRT2 = ON // Table Write Protect 04000-05FFF (Enabled)
#pragma config WRT3 = ON // Table Write Protect 06000-07FFF (Enabled)
// CONFIG6H
#pragma config WRTC = ON // Config. Write Protect (Enabled)
#pragma config WRTB = ON // Table Write Protect Boot (Enabled)
#pragma config WRTD = ON // Data EE Write Protect (Enabled)
// CONFIG7L
#pragma config EBTR0 = ON // Table Read Protect 00800-01FFF (Enabled)
#pragma config EBTR1 = ON // Table Read Protect 02000-03FFF (Enabled)
#pragma config EBTR2 = ON // Table Read Protect 04000-05FFF (Enabled)
#pragma config EBTR3 = ON // Table Read Protect 06000-07FFF (Enabled)
// CONFIG7H
#pragma config EBTRB = ON // Table Read Protect Boot (Enabled)
// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.
#pragma warning disable 520
#include <xc.h>
unsigned char Result1;
unsigned char Result2;
unsigned char Result3;
unsigned char Result4;
// The code should set the R/W bit according to its function
#define EEPROM_ADDRESS 0xA0 //I2C slave address of 24c02 (8 bit format)
#define Word_Address1 0x00
#define LCD_RS LATBbits.LATB4
#define LCD_TRIS_RS TRISBbits.TRISB4
#define LCD_RW LATBbits.LATB5
#define LCD_TRIS_RW TRISBbits.TRISB5
#define LCD_E LATBbits.LATB6
#define LCD_TRIS_E TRISBbits.TRISB6
#define LCDPORT LATD
#define LCDTRISD LATD
void Port_Initialized (void);
void WriteNibble(unsigned char command);
void WaitLCDBusy(void);
void WriteCommand(unsigned char command);
void Port_Initialized (void)
{
// LATx registers
LATA = 0x00;
LATB = 0x00;
LATC = 0x00;
LATD = 0x00;
LATE = 0x00;
// TRISx registers
TRISA = 0x00; // All are output, Unused
TRISB = 0x00; // all are output, Unused
TRISC = 0x18; //
TRISD = 0x00; // all are output, Unused
TRISE = 0x00; // All are output, Unused
ANCON0 = 0x00; // digital port
ANCON1 = 0x00; // Set to digital port
CM1CON = 0x00; // Comparator off
CM2CON = 0x00; // Comparator off
ADCON0 = 0x00; // A/D conversion Disabled
ADCON1 = 0x00; // A/D conversion Disabled
ADCON2 = 0x00; // A/D conversion Disabled
}
void WaitLCDBusy(void)
{
__delay_ms(5);
}
//Send a command to the LCD
void WriteCommand(unsigned char command)
{
WaitLCDBusy(); //wait until not busy
LCD_RS = 0; //setup to send command
WriteNibble(command); //write the high nibble
WriteNibble( (unsigned char)(command<<4) ); //then the low nibble
}
//Initialized LCD
void LCD_Initialized()
{
LCDTRISD &=0x0f; //ensure data bits are output
LCD_E=0; //clear enable
LCD_RS = 0; //going to write command
LCD_TRIS_E=0; //Set enable to output
LCD_TRIS_RS=0; //set RS to output
LCD_TRIS_RW=0;
LCD_RW=0;
__delay_ms(30); //delay for LCD to initialise.
WriteNibble(0x30); //Required for initialisation
__delay_ms(5); //required delay
WriteNibble(0x30); //Required for initialisation
__delay_ms(1); //required delay
WriteCommand(0x20); //set to 4 bit interface
WriteCommand(0x2c); //set to 4 bit interface, 2 line and 5*10 font
WriteCommand(0x01); //clear display
WriteCommand(0x06); //move cursor right after write
WriteCommand(0x0C); //turn on display
}
//Send a character to the LCD
void WriteChar(unsigned char chr)
{
WaitLCDBusy(); //wait until not busy
LCD_RS=1; //Setup to send character
WriteNibble(chr); //write the high nibble
WriteNibble( (unsigned char)(chr<<4)); //then the low nibble
}
//Send any 4 bits to the LCD
void WriteNibble(unsigned char command)
{
LCDPORT &= 0x0f; //clear the data bits
LCDPORT|=((command & 0xf0)); //or in the new data
LCD_E = 1; //enable the LCD interface
NOP(); //change to delay of 1uS
NOP();
NOP();
LCD_E = 0; //disable it
}
void LCD_Data( unsigned char *string)
{
while (*string != '\0')
{
WriteChar(*string);
string++;
}
}
//Initialize I2C in master mode
void I2C_Initialized(void)
{
TRISCbits.TRISC4 = 0; // commenting needed - will do another day
TRISCbits.TRISC3 = 0;
LATCbits.LATC4 = 0;
LATCbits.LATC3 = 0;
__delay_ms(1); // added in desperation - may not be needed
TRISCbits.TRISC4 = 1;
TRISCbits.TRISC3 = 1;
__delay_ms(1); // added in desperation - may not be needed
SSPSTATbits.SMP = 0;
SSPSTATbits.CKE = 0;
SSPCON1 = 0x38;
__delay_ms(1); // added in desperation - may not be needed
SSPSTAT = 0x80; // Slew rate control is disabled for Standard Speed mode (100 kHz and 1 MHz)
SSPCON1 = 0x28; // I2C Master mode, clock = FOSC/(4 * (SSPADD + 1))
SSPCON2 = 0x00;
SSPADD = 49; // 100kHz clock @ 20MHz Fosc SSPADD = ( (Fosc/4) / BiteRate )-1
// SSPADD = ( 20MHz / 100KHz ) - 1 = 49 //
}
// Send an I2C START
// Return 0 if all ok, 1 if bus collision
__bit I2C_Start(void)
{
BCLIF = 0; //Clear 'Bus collision" flag
SEN = 1; //initiate a START cycle
while (SEN); //wait until it has been sent
return BCLIF; //return value of BCLIF flag
}
// Send an I2C STOP
void I2C_Stop(void)
{
PEN = 1; //initiate a STOP cycle
while (PEN); //wait until it has been sent
}
// Send an I2C REPEATED START
void I2C_Restart(void)
{
RSEN = 1; //initiate a REPEATED START cycle
while (RSEN); //wait until it has been sent
}
//Receive one byte. ackflag=0 to send ACK, or 1 to send NAK in reply
//Send one byte. Return 0 if ACK received, or 1 if NAK received
__bit I2C_Sendbyte(unsigned char dat)
{
SSPBUF = dat;
asm("nop"); // <<<--- wait a little for R_W to be set
while (R_W); //wait until byte sent and ACK/NAK received
return ACKSTAT;
}
unsigned char I2C_Recvbyte(unsigned char ackflag)
{
RCEN = 1; // initiate a RECEIVE cycle
ACKDT =(__bit)ackflag; //specify if we should send ACK or NAK after receiving
while (RCEN); //wait until RECEIVE has completed
ACKEN = 1; //initiate an ACK cycle
while (ACKEN); //wait until it has completed
return SSPBUF;
}
//Send an array of data to an I2C device.
//Return 0 if all OK, 1 if bus error, 2 if slave address NAK, 3 if slave register NAK, 4 if slave data NAK
unsigned char EEPROM_Write(unsigned char slave_address, unsigned char start_reg, unsigned char buflen, const unsigned char * bufptr)
{
if (I2C_Start() ) //send a start, and check if it succeeded
return 1; //abort if bus collision
//send the I2C slave address (force R/W bit low)
if (I2C_Sendbyte(slave_address & 0xfe)) // <<---- Added AND to force R/W- low. Comment said it but code didn't do it
{
I2C_Stop(); //if address was NAKed, terminate the cycle
return 2; //and return error code
}
//send the device register index
if (I2C_Sendbyte(start_reg))
{
I2C_Stop(); //if register was NAKed, terminate the cycle
return 3; //and return error code
}
//send the data. buflen might be zero!
for (; buflen>0; --buflen)
{
if (I2C_Sendbyte(*bufptr++))
{
I2C_Stop(); //if register was NAKed, terminate the cycle
return 4; //and return error code
}
}
I2C_Stop();
return 0; //no error
}
//Receive an array of data from an I2C device.
//Return 0 if all OK, 1 if bus error, 2 if slave address NAK, 3 if slave register NAK
unsigned char EEPROM_Read(unsigned char slave_address, unsigned char start_reg, unsigned char buflen, unsigned char * bufptr)
{
//do a dummy zero length write cycle to set the register address
unsigned char retval = EEPROM_Write(slave_address, start_reg, 0, 0);
if (retval)
{
return retval; //abort if there was an error
}
//now start the READ cycle
if (I2C_Start() ) //send a start, and check if it succeeded
return 1; //abort if bus collision
//send the I2C slave address (force the R/W bit high)
if (I2C_Sendbyte(slave_address | 0x01))
{
I2C_Stop(); //if address was NAKed, terminate the cycle
return 2; //and return error code
}
//receive the data.
for (; buflen>0; --buflen)
{
unsigned char ackflag = (buflen == 1); //1 if this is the last byte to receive => send NAK
*bufptr++ = I2C_Recvbyte(ackflag);
}
I2C_Stop();
return 0; //no error
}
const unsigned char EEPROM_data[] =
{
0x07, // Count 7
0x06, // Count 6
0x05, // Count 5
0x04, // Count 4
0x03, // Count 3
0x02, // Count 2
0x01, // Count 1
};
unsigned char rd_buf[7];
// Test variable for one byte transfer
const unsigned char testchar = 'A';
unsigned char testchar_readback = 'Z'; // init to this to see difference after read
void main(void)
{
unsigned char i = 0;
unsigned char Data1 [10]="EEPROM ";
unsigned char Data2 [10]="tst ";
Port_Initialized ();
LCD_Initialized();
I2C_Initialized();
LCD_Data(Data2);
// Write test buffer
Result1 = EEPROM_Write(EEPROM_ADDRESS , Word_Address1 , sizeof(EEPROM_data), EEPROM_data);
__delay_ms(10);
// Read test buffer back
Result2 = EEPROM_Read(EEPROM_ADDRESS, Word_Address1 , sizeof(rd_buf), rd_buf) ;
__delay_ms(10);
// Write ONE character to location 0x15
Result3 = EEPROM_Write(EEPROM_ADDRESS, 0x15 , 1, &testchar);
__delay_ms(10);
// Read back ONE character from 0x15
Result4 = EEPROM_Read(EEPROM_ADDRESS, 0x15 , 1, &testchar_readback);
__delay_ms(10);
Data1[7] = testchar_readback; // testchar_readback should have changed 'Z' to 'A' if read/write worked
LCD_Data(Data1);
while(1); //endless loop to avoid exiting main() function)
}

