📄 at24c.c
字号:
{
if ( Address > 0xFFFF) {
p0 = 1;
/* Mask the 17th bit to get the 16th LSB */
WordAddress = Address & 0xFFFF ;
SlaveAddress = ptAt24c->SlaveAddress + (p0<<16) ;
}
else {
SlaveAddress = ptAt24c->SlaveAddress ;
WordAddress = Address ;
}
}
AT91F_TWI_ReadSingleIadr(SlaveAddress,
WordAddress,
AT91C_TWI_IADRSZ_2_BYTE,
&Data2Read);
return (Data2Read);
}
/*-----------------------------------------------------------------------------
Function: AT91F_AT24C_ReadPage(..;..;..)
Arguments:
- <struct at24c *ptAt24c> : Structure of an AT24C Two-wire Eeprom
- <char *Buffer>: The data (*buffer) to store the values read
- <NumOfBytes>: Size of the buffer
- <unsigned int AddressOffSet>: Address offset form the page address
Comments:
This function uses a two bytes internal address (IADR) in relation of the
Eeprom's Internal "Word Address". NACK error not handled
Return Value: None. No read error checking is done.
-----------------------------------------------------------------------------*/
void AT91F_AT24C_ReadPage (struct at24c *ptAt24c,
char *Buffer,
unsigned int NumOfBytes,
unsigned int PageNumber,
unsigned int AddressOffSet)
{
unsigned int WordAddress; /* Word Address to access within the EEPROM */
unsigned int SlaveAddress; /* Address of the Slave device on the bus */
unsigned int Count ;
unsigned int status;
/* 17th bit of the word address. Applicable to the AT24C1024 only */
unsigned char p0=0;
if (ptAt24c->EepromName == AT24C1024)
{
if ( ( (PageNumber*ptAt24c->PageSize) + AddressOffSet ) > 0xFFFF) {
p0 = 1;
/* Mask the 17th bit to get the 16th LSB */
WordAddress = ( (PageNumber*ptAt24c->PageSize) + AddressOffSet ) & 0xFFFF ;
SlaveAddress = ptAt24c->SlaveAddress + (p0<<16) ;
}
else {
SlaveAddress = ptAt24c->SlaveAddress ;
WordAddress = (PageNumber*ptAt24c->PageSize) + AddressOffSet ;
}
}
/****************************************************************************/
/* Speed improvement w/ large buffer, TWI is accessed witout calling TWI */
/* functions */
/****************************************************************************/
/* Enable Master Mode of the TWI */
AT91C_BASE_TWI->TWI_CR = AT91C_TWI_MSEN|AT91C_TWI_SVDIS ;
/* Set the TWI Master Mode Register */
AT91C_BASE_TWI->TWI_MMR = SlaveAddress | AT91C_TWI_MREAD | AT91C_TWI_IADRSZ_2_BYTE;
/* Set the internal address to access the wanted page */
AT91C_BASE_TWI->TWI_IADR = WordAddress ;
/* Send the Start + slave address + Internal Address */
/* Read operation starts automatically */
AT91C_BASE_TWI->TWI_CR = AT91C_TWI_START;
/* Read the page and store it into the buffer */
for ( Count=0; Count <NumOfBytes; Count++ )
{
/* Send the STOP cmd after the next-to-last data */
if (Count == (NumOfBytes -1) )
/* We are finished, send the stop command */
AT91C_BASE_TWI->TWI_CR = AT91C_TWI_STOP;
/* Wait until RXRDY is high to read the next data */
status = AT91C_BASE_TWI->TWI_SR;
while (!(status & AT91C_TWI_RXRDY))
status = AT91C_BASE_TWI->TWI_SR;
/* Read the char received */
*Buffer++ = AT91C_BASE_TWI->TWI_RHR;
}
/* Wait for the Transmit complete flag is set */
status = AT91C_BASE_TWI->TWI_SR;
while (!(status & AT91C_TWI_TXCOMP_MASTER))
status = AT91C_BASE_TWI->TWI_SR;
}
/*-----------------------------------------------------------------------------
Function: AT91F_AT24C_SequentialRead(..;..;..)
Arguments:
- <struct at24c *ptAt24c> : Structure of an AT24C Two-wire Eeprom
- <char *Buffer>: The data (*buffer) to store the values read
- <NumOfBytes>: Size of the buffer
- <unsigned int Address>: Address to strat reading from
Comments:
This function uses a two bytes internal address (IADR) in relation of the
Eeprom's Internal "Word Address"
Return Value: None. No read error checking is done.
-----------------------------------------------------------------------------*/
void AT91F_AT24C_SequentialRead (struct at24c *ptAt24c,
char *Buffer,
unsigned int NumOfBytes,
unsigned int Address)
{
unsigned int WordAddress; /* Word Address to access within the EEPROM */
unsigned int SlaveAddress; /* Address of the Slave device on the bus */
unsigned int Count ;
unsigned int status;
/* 17th bit of the word address. Applicable to the AT24C1024 only */
unsigned char p0=0;
if (ptAt24c->EepromName == AT24C1024)
{
if ( Address > 0xFFFF) {
p0 = 1;
/* Mask the 17th bit to get the 16th LSB */
WordAddress = Address & 0xFFFF ;
SlaveAddress = ptAt24c->SlaveAddress + (p0<<16) ;
}
else {
SlaveAddress = ptAt24c->SlaveAddress ;
WordAddress = Address ;
}
}
/****************************************************************************/
/* Speed improvement w/ large buffer, TWI is accessed witout calling TWI */
/* functions */
/****************************************************************************/
/* Enable Master Mode of the TWI */
AT91C_BASE_TWI->TWI_CR = AT91C_TWI_MSEN|AT91C_TWI_SVDIS ;
/* Set the TWI Master Mode Register */
AT91C_BASE_TWI->TWI_MMR = SlaveAddress | AT91C_TWI_MREAD | AT91C_TWI_IADRSZ_2_BYTE;
/* Set the internal address to access the wanted page */
AT91C_BASE_TWI->TWI_IADR = WordAddress ;
/* Send the Start + slave address + Internal Address */
AT91C_BASE_TWI->TWI_CR = AT91C_TWI_START;
/* Read the page and store it into the buffer */
for ( Count=0; Count <NumOfBytes; Count++ )
{
if (Count == (NumOfBytes -1) )
/* We are finished, send the stop command */
AT91C_BASE_TWI->TWI_CR = AT91C_TWI_STOP;
/* Wait until RXRDY is high to read the next data */
status = AT91C_BASE_TWI->TWI_SR;
while (!(status & AT91C_TWI_RXRDY))
status = AT91C_BASE_TWI->TWI_SR;
/* Read the char received */
*Buffer++ = AT91C_BASE_TWI->TWI_RHR;
}
/* Wait for the Transmit complete flag is set */
status = AT91C_BASE_TWI->TWI_SR;
while (!(status & AT91C_TWI_TXCOMP_MASTER))
status = AT91C_BASE_TWI->TWI_SR;
}
/*-----------------------------------------------------------------------------
Function: AT91F_AT24C_MemoryReset(void)
Arguments:
- <const AT91PS_PIO pPio> : Pointer to a PIO structure,
- <int PioID> : PIO peripheral ID
- <int Twck> : PIO/TWI clock pin
- <int Twd> : PIO/TWI data pin
Comments:
This function sends a "bus recovery" sequence" compatible with I2C(tm)
MEMORY RESET: After an interruption in protocol, power loss or system reset,
any two-wire part can be reset by following these steps:
1. Clock up to 9 cycles.
2. Look for SDA high in each cycle while SCL is high.
3. Create a start condition.
Since the TWI Port does not have the embedded "bus recovery" sequence, it
is managed in PIO mode. The clock peiod is set to 400KHz.
Return Value: None
-----------------------------------------------------------------------------*/
void AT91F_AT24C_MemoryReset (const AT91PS_PIO pPio, int PioID, int Twck, int Twd)
{
unsigned int ClockPulse;
/* First, enable the clock of the PIO */
AT91F_PMC_EnablePeriphClock ( AT91C_BASE_PMC, 1 << PioID ) ;
/* Set the TWI pins controlled by the PIO */
AT91F_PIO_Enable(pPio,Twck|Twd ) ;
/* then, we configure the PIO Lines corresponding to TWD & TWCK
to be outputs. */
AT91F_PIO_CfgOutput (pPio, Twck|Twd ) ;
/* Enable open drain on TWCK / TWD PIO lines */
pPio->PIO_MDER = (Twck|Twd) ;
/* Disable the pull up on the TWI line */
pPio->PIO_PPUDR = (Twck|Twd) ;
/* Set TWCK and TWD to high level */
AT91F_PIO_SetOutput(pPio, Twck|Twd ) ;
AT91F_AT24C_WaitMicroSecond(2);
/* Perform the bus recovery sequence */
/* 1. Clock up to 9 cycles */
for (ClockPulse=0 ; ClockPulse < 9 ; ClockPulse++)
{
/* Toggle the clock */
AT91F_PIO_SetOutput(pPio, Twck );
AT91F_AT24C_WaitMicroSecond(2);
AT91F_PIO_ClearOutput(pPio, Twck );
AT91F_AT24C_WaitMicroSecond(2);
AT91F_PIO_SetOutput(pPio, Twck );
AT91F_AT24C_WaitMicroSecond(2);
/* 2. Look for SDA high in each cycle while SCL is high */
AT91F_PIO_CfgInput(pPio,Twd );
if ( (AT91F_PIO_GetInput(pPio)&Twd) == Twd)
ClockPulse = 10;
}
AT91F_PIO_SetOutput(pPio, Twck|Twd ) ;
AT91F_PIO_CfgOutput (pPio, Twd ) ;
/* Set the TWCK and TWD to send the next start */
AT91F_PIO_SetOutput(pPio, Twck|Twd );
AT91F_AT24C_WaitMicroSecond(2);
/* 3. Create a start condition */
AT91F_PIO_ClearOutput(pPio, Twd );
AT91F_AT24C_WaitMicroSecond(2);
AT91F_PIO_ClearOutput(pPio, Twck );
AT91F_AT24C_WaitMicroSecond(2);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -