|
|
View previous topic :: View next topic |
Author |
Message |
chingB
Joined: 29 Dec 2003 Posts: 81
|
I2C Help-- error data return |
Posted: Fri Apr 23, 2004 7:54 am |
|
|
Hi,
I got an I2C application and my code is listed below:
Code: |
#define REC_MARKER (0xb0)
#define FRAM_SDA PIN_C4 // i2c data line
#define FRAM_SCL PIN_C3 // i2c clock line
// total external memory size
#define FRAM_TOTAL_MEM_SIZE 131072
// block length for one transaction (data size)
#define BLOCK_LENGTH 16
// define I2C read/write address
#define FRAM_WR_ADDR 0xA0 // initial FRAM write address at 1st chip
#define FRAM_RD_ADDR 0xA1 // initial FRAM read address at 1st chip
#define ENABLE_FRAM_WP() \
output_high(PIN_C5) // enable FRAM write protect
#define DISABLE_FRAM_WP() \
output_low(PIN_C5) // disable FRAM write protect
// for I2C read/write routines
#define I2C_IDLE() \
while ((SSPCON2 & 0x1F) || (SSP_RW))
#define I2C_START() \
SSP_SEN = 1; \
while (SSP_SEN) { \
#asm nop #endasm \
}
#define I2C_RESTART() \
SSP_RSEN = 1; \
while (SSP_RSEN) { \
#asm nop #endasm \
}
#define I2C_STOP() \
SSP_PEN = 1; \
while (SSP_PEN) { \
#asm nop #endasm \
}
#define I2C_WRITE(x) \
SSPBUF = (x); \
while (SSP_BF) { \
#asm nop #endasm \
} \
I2C_IDLE()
#define I2C_READ(x) \
SSP_RCEN = 1; \
while (SSP_RCEN) { \
#asm nop #endasm \
} \
SSP_ACKDT = (x); \
SSP_ACKEN = 1; \
while (SSP_ACKEN) { \
#asm nop #endasm \
}
static BOOLEAN I2C_Device_Ready(unsigned int8 uID);
static BOOLEAN I2C_Device_Ready(unsigned int8 uID)
{
do
{
// Important to clear these bits before we attempt to write
BCLIF = 0;
SSP_WCOL = 0;
I2C_IDLE(); // ensure module is idle
I2C_START();
} while (BCLIF);
I2C_WRITE(uID); // send memID
if (!SSP_ACKSTAT) // test for ACK condition, if received
return (TRUE);
return (FALSE); // no ACK
}
// Write one block of data to the FM24C256 chip
void write_fram_block(
unsigned int32 uAddress, // FM24C256 address to write data
unsigned int8 Block, // block length or page length to write
unsigned int8 *data) // pointer to data buffer for write
{
unsigned int8 uControl; // FM24C256 chipselect
unsigned int8 uI;
// chipselect for specific FM24C256 to write
uControl = (FRAM_WR_ADDR | make8(uAddress<<2,2)) & 0xFE;
DISABLE_FRAM_WP(); // write protect is disabled
while (!I2C_Device_Ready(uControl));
I2C_WRITE((make8(uAddress,1)) & 0x7F); // send MSB of mem address
I2C_WRITE(make8(uAddress,0)); // send LSB of mem address
for (uI=0; uI<Block; uI++) {
I2C_WRITE(*data++); // send data to FM24C256
}
I2C_STOP();
ENABLE_FRAM_WP(); // write protect is enabled/engage
}
// Write one byte data to FM24C256 chip
void write_fram_Byte(
unsigned int32 uAddress, // FRAM address to write data
unsigned int8 uData) // byte written to FRAM
{
unsigned int8 uControl;
// chipselect for specific FM24C256 to write
uControl = (FRAM_WR_ADDR | make8(uAddress<<2,2)) & 0xFE;
DISABLE_FRAM_WP(); // write protect is disabled
while (!I2C_Device_Ready(uControl));
I2C_WRITE((make8(uAddress,1)) & 0x7F); // send MSB of mem address
I2C_WRITE(make8(uAddress,0)); // send LSB of mem address
I2C_WRITE(uData); // send data
I2C_STOP();
ENABLE_FRAM_WP(); // write protect is enabled/engage
}
// Read one block of data from FM24C256 chip
void read_fram_block(
unsigned int32 uAddress, // FM24C256 address to read data
unsigned int8 Block, // block length or one page write
unsigned int8 *data) // pointer to gaReadMemRFbuf to store data
{
unsigned int8 uControl;
// chipselect for specific FM24C256 to read
uControl = (FRAM_WR_ADDR | make8(uAddress<<2,2)) & 0xFE;
while (!I2C_Device_Ready(uControl));
I2C_WRITE((make8(uAddress,1)) & 0x7F); // send MSB of mem address
I2C_WRITE(make8(uAddress,0)); // send LSB of mem address
I2C_RESTART();
I2C_WRITE(uControl | 0x01); // set address for read
while (Block > 1) {
I2C_READ(0);
*data = SSPBUF;
data++;
Block--;
}
I2C_READ(1);
*data = SSPBUF;
I2C_STOP();
}
// Read one byte data from FM24C256 chip
unsigned int8 read_fram_byte(
unsigned int32 uAddress) // FM24C256 address to read data
{
unsigned int8 uControl;
// chipselect for specific FM24C256
uControl = (FRAM_WR_ADDR | make8(uAddress<<2,2)) & 0xFE;
while (!I2C_Device_Ready(uControl));
I2C_WRITE((make8(uAddress,1)) & 0x7F); // send MSB of mem address
I2C_WRITE(make8(uAddress,0)); // send LSB of mem address
I2C_RESTART();
I2C_WRITE(uControl | 0x01); // set address for read
I2C_READ(1);
I2C_STOP();
return (SSPBUF); // return with data
}
void ConfigureI2C()
{
// initialize FRAM clock and data I/O
output_float(FRAM_SCL); // set clock lines to input
output_float(FRAM_SDA); // set data lines to input
// Configure the MSSP as an I2C Port for PIC18F452
// Relevant port pins configured as inputs
SSP_SSPEN = 1; // Enable I2C mode
SSP_SSPM3 = 1; // setup I2C mode
SSP_SSPM2 = 0;
SSP_SSPM1 = 0;
SSP_SSPM0 = 0;
SSPCON2 = 0;
SSP_SMP = 0;
SSP_CKE = 0; // Set I2C Levels
// Set I2C Speed. The formula is:
//
// SSPADD value = (Fosc/(i2c clock speed * 4)) -1
//
// Examples:
//
// SSPADD values for an Fosc of 8 MHz:
// *** NOTE: If you run your PIC at a different Fosc, then you
// *** you need to calculate new values.
//
// For an i2c clock of 100 KHz, SSPADD = 19
// For an i2c clock of 400 KHz, SSPADD = 4
// For an i2c clock of 1 MHz, SSPADD = 1
SSPADD = 4; // 1 MHz i2c clock at 20MHz oscillator
SSP_SMP = 1; // disable slew rate control for 1 MHz operation ONLY
// *** NOTE: Based on my oscilloscope readings, the i2c clock
// *** speed seems to run a little slower than what the formula says.
// *** For example, "400 KHz" is really 370 KHz or so.
// *** "1 MHz" is really running slightly less than that speed.
}
void init_mcu() // MCU Initialization Routine
{
delay_ms(2000); // delay for 2 seconds (stabilized MCU?)
ConfigureI2C(); // initialize I2C I/O and configure for I2C mode
setup_adc_ports(NO_ANALOGS); // setup PortA to digital I/O
}
|
The code below is my test program:
Code: |
main()
{
unsigned int8 i;
char tempbuffer[16];
char temp2=0;
unsigned int8 minutes;
unsigned int8 hours;
unsigned int8 mthdays;
unsigned int8 months;
unsigned int8 years;
unsigned int8 y2kyrs;
unsigned int32 addr=0;
unsigned int16 cnt=0;
unsigned int16 logcount=0;
init_mcu();
delay_ms(500);
output_low(PIN_A0);
for (i=0; i<16; i++)
tempbuffer[i]=0;
minutes = 30; // 00 ~ 59 minutes
hours = 14; // 00 ~ 23 hours, military format
mthdays = 15; // 01 ~ 31 day(s) of the month
months = 11; // 01 ~ 12 months, 1-Jan ... 12-Dec
years = 04; // 00 ~ 99 2-digit year within a century
y2kyrs = 20; // 20 ~ 99 Y2K year or century
for (cnt=0; cnt<8192; cnt++){
addr = cnt*16;
write_fram_block(addr,16,tempbuffer);
}
tempbuffer[0] = (months & 0x0f) | REC_MARKER;
tempbuffer[1] = mthdays;
tempbuffer[2] = y2kyrs;
tempbuffer[3] = years;
tempbuffer[4] = '0';
tempbuffer[5] = '1';
tempbuffer[6] = '2';
tempbuffer[7] = '3';
tempbuffer[8] = '4';
tempbuffer[9] = '5';
tempbuffer[10] = '6';
tempbuffer[11] = '7';
tempbuffer[12] = '8';
tempbuffer[13] = '9';
tempbuffer[14] = hours;
tempbuffer[15] = minutes;
printf("\r\n\r\n");
delay_ms(500);
for (cnt=1000; cnt<3600; cnt++){
addr = cnt*16;
write_fram_block(addr,16,tempbuffer);
}
printf("\r\n\r\n");
delay_ms(1000);
temp2=0;
for (cnt=0;cnt<8192;cnt++){
addr = cnt*16;
temp2 = read_fram_byte(addr);
temp2 = temp2 & 0xf0;
if (temp2 == REC_MARKER)
logcount++;
}
printf("\r\nLogCount=%lu",logcount);
printf("\r\n\r\n");
while (TRUE);
}
|
My application is like this... I write a 16byte data to the FRAM with the 1st byte of the array is and'ed with 0x0f then or'ed with 0xb0.
Then I scan the entire 4 FRAM chip reading the 1st byte of 16 byte data for 0xb0 and increment the FRAM reading by 16bytes...
If 0xb0 found it increment the log counter....
My problem really is that I got an incorrect value of log count.
I need ur help guys... I can't figure out the problem...
BTW, I have four(4) FM24C256 from ramtron with a total records of 8192 where each record consist of 16bytes data. I run this on PIC18F452 at 20MHz using PCWH v3.188.
In addition, I'm using linear addressing in reading the entire 4 FRAM chips.
Thank u. |
|
|
chingB
Joined: 29 Dec 2003 Posts: 81
|
|
Posted: Fri Apr 23, 2004 5:18 pm |
|
|
Anyone can help me with my problem?
Thnx |
|
|
Guest
|
FRAM linear addressing |
Posted: Fri Apr 23, 2004 10:16 pm |
|
|
Quote:
In addition, I'm using linear addressing in reading the entire 4 FRAM chips.
End quote:
You cannot linear address across chips. each chip starts at 0 and ends at 32767
You have to take care of the linear addressing.
Anyway, there are plenty of code samples on this forum, search for FRAM or EEPROM both will works just don't bother with the delay for the FRAM. |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|