|
|
View previous topic :: View next topic |
Author |
Message |
rrb011270
Joined: 07 Sep 2003 Posts: 51
|
Anybody have done this code... |
Posted: Tue Oct 07, 2003 11:32 pm |
|
|
Mabuhay!
Anyone in the forum have done I2C using hardware for writing/reading to FM24C256 w/o using the ccs built-in functions....
It wud be better if somebody share to me a sample code which use interrupt and hardware I2C at the same time...
Any help will do?
Thnx |
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Wed Oct 08, 2003 6:29 am |
|
|
See below
Last edited by Mark on Wed Oct 08, 2003 6:37 am; edited 1 time in total |
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Wed Oct 08, 2003 6:30 am |
|
|
This code does not use interrupts but does use the hardware i2c. It does not use any CCS functions since I wrote it for the Microchip C18 compiler. I didn't post all the typedefs but they should be clear. Also note that this was done for a 24C08 so the addressing scheme would be a little different but it should give you a starting point.
Code: |
/* *************************************************************************
Useful defines for writing to the I2C bus
*************************************************************************** */
#define I2C_IDLE() while ((SSPCON2 & 0x1F) || (SSPSTATbits.R_W))
#define I2C_START() \
SSPCON2bits.SEN = 1; \
while (SSPCON2bits.SEN) \
{ \
_asm nop _endasm \
}
#define I2C_RESTART() \
SSPCON2bits.RSEN = 1; \
while (SSPCON2bits.RSEN) \
{ \
_asm nop _endasm \
}
#define I2C_STOP() \
SSPCON2bits.PEN = 1; \
while (SSPCON2bits.PEN) \
{ \
_asm nop _endasm \
}
#define I2C_WRITE(x) \
SSPBUF = (x); \
while (SSPSTATbits.BF) \
{ \
_asm nop _endasm \
} \
I2C_IDLE()
#define I2C_READ(x) \
SSPCON2bits.RCEN = 1; \
while (SSPCON2bits.RCEN) \
{ \
_asm nop _endasm \
} \
SSPCON2bits.ACKDT = (x); \
SSPCON2bits.ACKEN = 1; \
while (SSPCON2bits.ACKEN) \
{ \
_asm nop _endasm \
}
static BOOLEAN I2C_Device_Ready(UINT8 id);
void EEPROM_Write_Internal(UINT8 data, UINT16 address);
UINT8 EEPROM_Read_Internal(UINT16 address);
void EEPROM_Write_Byte(UINT8 data, UINT16 address);
UINT8 EEPROM_Read_Byte(UINT16 address);
void EEPROM_Write_Byte(UINT8 data, UINT16 address);
UINT8 EEPROM_Read_Byte(UINT16 address);
void EEPROM_Write_String(char *s, UINT16 address);
void EEPROM_Read_String(char *s, UINT16 address);
void EEPROM_Write_Block(char *data, UINT8 len, UINT16 address);
void EEPROM_Read_Block(char *data, UINT8 len, UINT16 address);
/* *************************************************************************
DESCRIPTION: This function checks to see if an i2c device will ACK
RETURN: TRUE if device ACKed otherwise FALSE
ALGORITHM: none
NOTES: none
*************************************************************************** */
static BOOLEAN I2C_Device_Ready(
UINT8 id) /* FIX ME: add comment */
{
do
{
/* Important to clear these bits before we attempt to write */
PIR2bits.BCLIF = 0;
SSPCON1bits.WCOL = 0;
I2C_IDLE(); /* ensure module is idle */
I2C_START();
} while (PIR2bits.BCLIF);
I2C_WRITE(id);
if (!SSPCON2bits.ACKSTAT) /* test for ACK condition, if received */
return (TRUE);
return (FALSE);
}
/* *************************************************************************
DESCRIPTION: This function writes the passed data to the specified
address of the serial eeprom.
RETURN: none
ALGORITHM: none
NOTES: none
*************************************************************************** */
void EEPROM_Write_Byte(
UINT8 data, /* byte written to seeprom */
UINT16 address) /* SEEPROM address to write data */
{
UINT8 control;
/* MSB if address > 0xFF. Should be in bit1 */
control = SEEPROM_WRITE_MODE | ((UINT8) (address >> 8) << 1);
while (!I2C_Device_Ready(control));
I2C_WRITE((UINT8) address);
I2C_WRITE(data);
I2C_STOP();
}
/* *************************************************************************
DESCRIPTION: This function reads a byte of data in from the serial
eeprom at the specified address.
RETURN: data byte read from SEEPROM
ALGORITHM: none
NOTES: none
*************************************************************************** */
UINT8 EEPROM_Read_Byte(
UINT16 address) /* seeprom address to write data */
{
UINT8 control;
/* MSB if address > 0xFF. Should be in bit1 */
control = SEEPROM_WRITE_MODE | (UINT8) (address >> 8) << 1;
while (!I2C_Device_Ready(control));
I2C_WRITE((UINT8) address);
I2C_RESTART();
I2C_WRITE(control + 1);
I2C_READ(1);
I2C_STOP();
return (SSPBUF); /* return with data */
}
/* *************************************************************************
DESCRIPTION: This function writes a byte of data to the specified
address of the internal eeprom.
RETURN: none
ALGORITHM: none
NOTES: none
*************************************************************************** */
void EEPROM_Write_Internal(
UINT8 data, /* byte written to eeprom */
UINT16 address) /* EEPROM address to write data */
{
EEADRH = address >> 8; /* Load our address */
EEADR = address; /* Load our address */
EEDATA = data; /* Load our data */
EECON1bits.EEPGD = 0; /* Point to data memory */
EECON1bits.WREN = 1; /* Enable writes */
/* Microchip recommends disabling ints here */
Global_Int(INT_DISABLED);
EECON2 = 0x55; /* Write 0x55 */
EECON2 = 0xAA; /* Write 0xAA */
EECON1bits.WR = 1; /* Set WR to begin write */
{
_asm nop _endasm
}
Global_Int(INT_RESTORE);
while (EECON1bits.WR) /* Wait for write to complete */
{
_asm nop _endasm
}
EECON1bits.WREN = 0; /* Disable writes */
return;
}
/* *************************************************************************
DESCRIPTION: This function reads a byte of data in from the internal
eeprom at the specified address.
RETURN: data - byte read from SEEPROM
ALGORITHM: none
NOTES: none
*************************************************************************** */
UINT8 EEPROM_Read_Internal(
UINT16 address) /* eeprom address to write data */
{
EEADRH = address >> 8; /* Load our address */
EEADR = address; /* Load our address */
EECON1bits.EEPGD = 0; /* Point to data memory */
EECON1bits.RD = 1; /* EEPROM Read */
return (EEDATA); /* Return with our value */
}
/* *************************************************************************
DESCRIPTION: This function writes a string to the SEEPROM
RETURN: none
ALGORITHM: none
NOTES: The routine should handle going across chip boundaries
*************************************************************************** */
void EEPROM_Write_String(
char *s, /* string to write to seeprom */
UINT16 address) /* SEEPROM address to write data */
{
EEPROM_Write_Block(s, strlen(s) + 1, address);
}
/* *************************************************************************
DESCRIPTION: This function reads a string from the serial eeprom at the
specified address.
RETURN: none
ALGORITHM: none
NOTES: This routine does not cross chip boundaries
*************************************************************************** */
void EEPROM_Read_String(
char *s, /* point to the string to load */
UINT16 address) /* seeprom address to write data */
{
UINT8 control;
/* check for a valid pointer */
if (s == 0)
return;
control = SEEPROM_WRITE_MODE | (UINT8) (address >> 8) << 1;
while (!I2C_Device_Ready(control));
I2C_WRITE((UINT8) address);
I2C_RESTART();
I2C_WRITE(control + 1);
while (TRUE)
{
I2C_READ(0);
*s = SSPBUF;
if (*s == 0)
break;
s++;
}
/* Terminate the read sequence */
I2C_READ(1);
I2C_STOP();
}
/* *************************************************************************
DESCRIPTION: This function writes a block of data to the SEEPROM
RETURN: none
ALGORITHM: none
NOTES: The routine should handle going across chip boundaries
*************************************************************************** */
void EEPROM_Write_Block(
char *data, /* pointer to the block of data to write */
UINT8 len, /* number of bytes to write */
UINT16 address) /* EEPROM address to write data */
{
UINT8 control;
UINT8 lastpage;
UINT8 page;
/* determine the control word for the device */
control = SEEPROM_WRITE_MODE | ((UINT8) (address >> 8) << 1);
/* Wait until our device is ready */
while (!I2C_Device_Ready(control));
/* Set the address pointer in the device */
I2C_WRITE((UINT8) address);
page = (UINT8) address >> 4;
lastpage = page;
while (len)
{
if (page != lastpage)
{
/* Issuing a STOP will start the write sequence */
I2C_STOP();
lastpage = page;
/* determine the control word for the device */
control = SEEPROM_WRITE_MODE | ((UINT8) (address >> 8) << 1);
/* Wait until our device is ready */
while (!I2C_Device_Ready(control));
/* Set the address pointer in the device */
I2C_WRITE((UINT8) address);
}
I2C_WRITE(*data);
data++;
address++;
/* The 24C08 has a 16 byte page for writing. */
page = (UINT8) address >> 4;
len--;
}
I2C_STOP();
}
/* *************************************************************************
DESCRIPTION: This function reads a block of data from the serial eeprom
at the specified address.
RETURN: none
ALGORITHM: none
NOTES: This routine does not cross chip boundaries
*************************************************************************** */
void EEPROM_Read_Block(
char *data, /* point to the data to load */
UINT8 len, /* number of bytes to read */
UINT16 address) /* seeprom address to write data */
{
UINT8 control;
control = SEEPROM_WRITE_MODE | (UINT8) (address >> 8) << 1;
while (!I2C_Device_Ready(control));
I2C_WRITE((UINT8) address);
I2C_RESTART();
I2C_WRITE(control + 1);
while (len > 1)
{
I2C_READ(0);
*data = SSPBUF;
data++;
len--;
}
I2C_READ(1);
*data = SSPBUF;
I2C_STOP();
}
|
|
|
|
rrb011270
Joined: 07 Sep 2003 Posts: 51
|
|
Posted: Wed Oct 08, 2003 5:29 pm |
|
|
Hello,
what is the purpose of "\" symbol?
Quote: | #define I2C_IDLE() while ((SSPCON2 & 0x1F) || (SSPSTATbits.R_W))
#define I2C_START() \
SSPCON2bits.SEN = 1; \
while (SSPCON2bits.SEN) \
{ \
_asm nop _endasm \
} |
|
|
|
rrb011270
Joined: 07 Sep 2003 Posts: 51
|
|
Posted: Wed Oct 08, 2003 7:39 pm |
|
|
Hi Mark,
With the code u mention... Do I have to have to use the #use i2c(master,...)?
thnx |
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Wed Oct 08, 2003 7:52 pm |
|
|
The "\" means continuation. It is a way to break up a long line of C code.
Quote: |
With the code u mention... Do I have to have to use the #use i2c(master,...)?
|
You will have to set up the ssp. I don't use the #use i2c. As I said before, this was done for the C18 compiler which does not have the CCS functions. |
|
|
Guest
|
|
Posted: Wed Oct 08, 2003 9:43 pm |
|
|
Hi Mark,
I compile the code u shared but it report an error with an unknown indentifier "_asm".
Can u check if this will work in PIC18452.
Thnx |
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Thu Oct 09, 2003 6:10 am |
|
|
This code was written for the MICROCHIP C18 compiler! Although it is C, you will have to make a few changes. CCS embeds their assembly a little differently. The Global_Int() function is one that I wrote that saves the current state of the interrupts (high and low priority) when they are disabled. I can then call the restore and they are set back to the state before I disabled them. This keeps me from enabling interrupts if they were already disabled for some reason. Also note that you will have to define all the registers. |
|
|
Guest
|
|
Posted: Thu Oct 09, 2003 5:19 pm |
|
|
Would it be possible to share a simple code snippet regarding Global_Int() and restore function? maybe I can utilize it with my application.
Thnx
Mark wrote: | This code was written for the MICROCHIP C18 compiler! Although it is C, you will have to make a few changes. CCS embeds their assembly a little differently. The Global_Int() function is one that I wrote that saves the current state of the interrupts (high and low priority) when they are disabled. I can then call the restore and they are set back to the state before I disabled them. This keeps me from enabling interrupts if they were already disabled for some reason. Also note that you will have to define all the registers. |
|
|
|
rrb011270
Joined: 07 Sep 2003 Posts: 51
|
|
Posted: Sat Oct 11, 2003 6:22 am |
|
|
Quote: | This code does not use interrupts but does use the hardware i2c. It does not use any CCS functions since I wrote it for the Microchip C18 compiler. I didn't post all the typedefs but they should be clear. Also note that this was done for a 24C08 so the addressing scheme would be a little different but it should give you a starting point. |
I have successfully converted the code u shared to PIC18452... I'll post this coming monday for others can have it use it in der project...
Tengkyu |
|
|
rrb011270
Joined: 07 Sep 2003 Posts: 51
|
|
Posted: Tue Oct 14, 2003 8:26 am |
|
|
Hello,
I have succesfully coded the source below for the PIC18F452...
I write to an external FRAM without affecting my timer interrupt (RTC) and other interrupt that I use (e.g. rda, tbe, timer1)... and it really did write without hanging-up my system..
My only convern is that would this affect my RTC and other interrupts if I am to read block of data from FRAM memory? say read 128bytes of data and send it to serial using interrupt(#int_rda)? such that my host PC will parse it.....
Anybody who can give me a tips, comments or any help will do....
--------------------------------
Mark wrote: | This code does not use interrupts but does use the hardware i2c. It does not use any CCS functions since I wrote it for the Microchip C18 compiler. I didn't post all the typedefs but they should be clear. Also note that this was done for a 24C08 so the addressing scheme would be a little different but it should give you a starting point.
Code: |
/* *************************************************************************
Useful defines for writing to the I2C bus
*************************************************************************** */
#define I2C_IDLE() while ((SSPCON2 & 0x1F) || (SSPSTATbits.R_W))
#define I2C_START() \
SSPCON2bits.SEN = 1; \
while (SSPCON2bits.SEN) \
{ \
_asm nop _endasm \
}
#define I2C_RESTART() \
SSPCON2bits.RSEN = 1; \
while (SSPCON2bits.RSEN) \
{ \
_asm nop _endasm \
}
#define I2C_STOP() \
SSPCON2bits.PEN = 1; \
while (SSPCON2bits.PEN) \
{ \
_asm nop _endasm \
}
#define I2C_WRITE(x) \
SSPBUF = (x); \
while (SSPSTATbits.BF) \
{ \
_asm nop _endasm \
} \
I2C_IDLE()
#define I2C_READ(x) \
SSPCON2bits.RCEN = 1; \
while (SSPCON2bits.RCEN) \
{ \
_asm nop _endasm \
} \
SSPCON2bits.ACKDT = (x); \
SSPCON2bits.ACKEN = 1; \
while (SSPCON2bits.ACKEN) \
{ \
_asm nop _endasm \
}
static BOOLEAN I2C_Device_Ready(UINT8 id);
void EEPROM_Write_Internal(UINT8 data, UINT16 address);
UINT8 EEPROM_Read_Internal(UINT16 address);
void EEPROM_Write_Byte(UINT8 data, UINT16 address);
UINT8 EEPROM_Read_Byte(UINT16 address);
void EEPROM_Write_Byte(UINT8 data, UINT16 address);
UINT8 EEPROM_Read_Byte(UINT16 address);
void EEPROM_Write_String(char *s, UINT16 address);
void EEPROM_Read_String(char *s, UINT16 address);
void EEPROM_Write_Block(char *data, UINT8 len, UINT16 address);
void EEPROM_Read_Block(char *data, UINT8 len, UINT16 address);
/* *************************************************************************
DESCRIPTION: This function checks to see if an i2c device will ACK
RETURN: TRUE if device ACKed otherwise FALSE
ALGORITHM: none
NOTES: none
*************************************************************************** */
static BOOLEAN I2C_Device_Ready(
UINT8 id) /* FIX ME: add comment */
{
do
{
/* Important to clear these bits before we attempt to write */
PIR2bits.BCLIF = 0;
SSPCON1bits.WCOL = 0;
I2C_IDLE(); /* ensure module is idle */
I2C_START();
} while (PIR2bits.BCLIF);
I2C_WRITE(id);
if (!SSPCON2bits.ACKSTAT) /* test for ACK condition, if received */
return (TRUE);
return (FALSE);
}
/* *************************************************************************
DESCRIPTION: This function writes the passed data to the specified
address of the serial eeprom.
RETURN: none
ALGORITHM: none
NOTES: none
*************************************************************************** */
void EEPROM_Write_Byte(
UINT8 data, /* byte written to seeprom */
UINT16 address) /* SEEPROM address to write data */
{
UINT8 control;
/* MSB if address > 0xFF. Should be in bit1 */
control = SEEPROM_WRITE_MODE | ((UINT8) (address >> 8) << 1);
while (!I2C_Device_Ready(control));
I2C_WRITE((UINT8) address);
I2C_WRITE(data);
I2C_STOP();
}
/* *************************************************************************
DESCRIPTION: This function reads a byte of data in from the serial
eeprom at the specified address.
RETURN: data byte read from SEEPROM
ALGORITHM: none
NOTES: none
*************************************************************************** */
UINT8 EEPROM_Read_Byte(
UINT16 address) /* seeprom address to write data */
{
UINT8 control;
/* MSB if address > 0xFF. Should be in bit1 */
control = SEEPROM_WRITE_MODE | (UINT8) (address >> 8) << 1;
while (!I2C_Device_Ready(control));
I2C_WRITE((UINT8) address);
I2C_RESTART();
I2C_WRITE(control + 1);
I2C_READ(1);
I2C_STOP();
return (SSPBUF); /* return with data */
}
/* *************************************************************************
DESCRIPTION: This function writes a byte of data to the specified
address of the internal eeprom.
RETURN: none
ALGORITHM: none
NOTES: none
*************************************************************************** */
void EEPROM_Write_Internal(
UINT8 data, /* byte written to eeprom */
UINT16 address) /* EEPROM address to write data */
{
EEADRH = address >> 8; /* Load our address */
EEADR = address; /* Load our address */
EEDATA = data; /* Load our data */
EECON1bits.EEPGD = 0; /* Point to data memory */
EECON1bits.WREN = 1; /* Enable writes */
/* Microchip recommends disabling ints here */
Global_Int(INT_DISABLED);
EECON2 = 0x55; /* Write 0x55 */
EECON2 = 0xAA; /* Write 0xAA */
EECON1bits.WR = 1; /* Set WR to begin write */
{
_asm nop _endasm
}
Global_Int(INT_RESTORE);
while (EECON1bits.WR) /* Wait for write to complete */
{
_asm nop _endasm
}
EECON1bits.WREN = 0; /* Disable writes */
return;
}
/* *************************************************************************
DESCRIPTION: This function reads a byte of data in from the internal
eeprom at the specified address.
RETURN: data - byte read from SEEPROM
ALGORITHM: none
NOTES: none
*************************************************************************** */
UINT8 EEPROM_Read_Internal(
UINT16 address) /* eeprom address to write data */
{
EEADRH = address >> 8; /* Load our address */
EEADR = address; /* Load our address */
EECON1bits.EEPGD = 0; /* Point to data memory */
EECON1bits.RD = 1; /* EEPROM Read */
return (EEDATA); /* Return with our value */
}
/* *************************************************************************
DESCRIPTION: This function writes a string to the SEEPROM
RETURN: none
ALGORITHM: none
NOTES: The routine should handle going across chip boundaries
*************************************************************************** */
void EEPROM_Write_String(
char *s, /* string to write to seeprom */
UINT16 address) /* SEEPROM address to write data */
{
EEPROM_Write_Block(s, strlen(s) + 1, address);
}
/* *************************************************************************
DESCRIPTION: This function reads a string from the serial eeprom at the
specified address.
RETURN: none
ALGORITHM: none
NOTES: This routine does not cross chip boundaries
*************************************************************************** */
void EEPROM_Read_String(
char *s, /* point to the string to load */
UINT16 address) /* seeprom address to write data */
{
UINT8 control;
/* check for a valid pointer */
if (s == 0)
return;
control = SEEPROM_WRITE_MODE | (UINT8) (address >> 8) << 1;
while (!I2C_Device_Ready(control));
I2C_WRITE((UINT8) address);
I2C_RESTART();
I2C_WRITE(control + 1);
while (TRUE)
{
I2C_READ(0);
*s = SSPBUF;
if (*s == 0)
break;
s++;
}
/* Terminate the read sequence */
I2C_READ(1);
I2C_STOP();
}
/* *************************************************************************
DESCRIPTION: This function writes a block of data to the SEEPROM
RETURN: none
ALGORITHM: none
NOTES: The routine should handle going across chip boundaries
*************************************************************************** */
void EEPROM_Write_Block(
char *data, /* pointer to the block of data to write */
UINT8 len, /* number of bytes to write */
UINT16 address) /* EEPROM address to write data */
{
UINT8 control;
UINT8 lastpage;
UINT8 page;
/* determine the control word for the device */
control = SEEPROM_WRITE_MODE | ((UINT8) (address >> 8) << 1);
/* Wait until our device is ready */
while (!I2C_Device_Ready(control));
/* Set the address pointer in the device */
I2C_WRITE((UINT8) address);
page = (UINT8) address >> 4;
lastpage = page;
while (len)
{
if (page != lastpage)
{
/* Issuing a STOP will start the write sequence */
I2C_STOP();
lastpage = page;
/* determine the control word for the device */
control = SEEPROM_WRITE_MODE | ((UINT8) (address >> 8) << 1);
/* Wait until our device is ready */
while (!I2C_Device_Ready(control));
/* Set the address pointer in the device */
I2C_WRITE((UINT8) address);
}
I2C_WRITE(*data);
data++;
address++;
/* The 24C08 has a 16 byte page for writing. */
page = (UINT8) address >> 4;
len--;
}
I2C_STOP();
}
/* *************************************************************************
DESCRIPTION: This function reads a block of data from the serial eeprom
at the specified address.
RETURN: none
ALGORITHM: none
NOTES: This routine does not cross chip boundaries
*************************************************************************** */
void EEPROM_Read_Block(
char *data, /* point to the data to load */
UINT8 len, /* number of bytes to read */
UINT16 address) /* seeprom address to write data */
{
UINT8 control;
control = SEEPROM_WRITE_MODE | (UINT8) (address >> 8) << 1;
while (!I2C_Device_Ready(control));
I2C_WRITE((UINT8) address);
I2C_RESTART();
I2C_WRITE(control + 1);
while (len > 1)
{
I2C_READ(0);
*data = SSPBUF;
data++;
len--;
}
I2C_READ(1);
*data = SSPBUF;
I2C_STOP();
}
|
|
|
|
|
|
|
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
|