📄 at24c.c
字号:
/*-----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support - ROUSSET -
*------------------------------------------------------------------------------
* The software is delivered "AS IS" without warranty or condition of any
* kind, either express, implied or statutory. This includes without
* limitation any warranty or condition with respect to merchantability or
* fitness for any particular purpose, or against the infringements of
* intellectual property rights of others.
*------------------------------------------------------------------------------
* File Name : at24c.c
* Object : ATMEL AT24C Two-wire Serial EEPROM low level functions
*
* Version | mm | dd | yy | author :
* 1.0 12 14 06 PFi : Creation
* 1.1 12 04 07 PFi : Update of Multiple read/write function
* according to the new TWI doc.
* 1.11 14 08 07 PFi : Cleanup.
* : AT91F_AT24C_MemoryReset Corrected to match
* : reset sequence from ATMEL AT24C datasheet
*------------------------------------------------------------------------------
* 1)Description:
*
* This Demo code uses an ATMEL Two-wire Serial EEPROM connnected
* to the TWI port.
* A set of standalone read or write functions are provided.
* Address used in this example with a AT24C1024 wit A1 = 1 (+VDD)
*
* AT91F_AT24C_WriteByte
* AT91F_AT24C_WritePage
* AT91F_AT24C_ReadByte
* AT91F_AT24C_ReadPage
* AT91F_AT24C_SequentialRead
*
* ------| AT91 / IO | AT24 / IO
* CLOCK | TWCK / PA3 | TWCK / 6
* DATA | TWD / PA4 | TWD / 5
*
*
* * WARNINGS ** :
* - No pull ups are mounted on the board on TWD and TWCK. 2.2K Pull up used
* - By default IAR compiler use the Tiny printf and scanf library format.
* To be able to make print of float variables, you must set the library
* format to large.
*
* 3) Remarks:
*
* No time out loops or good read or write sequence checking is done.
* This example runs in polling mode and makes no use of IRQs. To have further
* details and implementation example about using IRQs, refer to any Interrupt
* project examples, * like AT91SAM7Sxx-Interrupt-IAR4_XX-X_X
* available on www.at91.com --> KIT --> AT91SAM7S-EK --> Software
*
*----------------------------------------------------------------------------*/
/*---------------------------- Include files --------------------------------*/
#include "at24c.h"
#include "project.h"
#include "..\common\init.h"
#include "..\common\lib_twi.h"
/*--------------------------- Constants definition -------------------------*/
/* value of the PIT value to have 333ns @ 48 MHz
668 -1 since real time out = PIV + 1 */
#define PIT_PIV_MILI_SECOND_VALUE 0x667
/* value of the PIT value to have 333ns @ 48 MHz
3 -1 since real time out = PIV + 1 */
#define PIT_PIV_MICRO_SECOND_VALUE 0x2
/*----------------------------- Global Variables ----------------------------*/
/*----------------------------- External Functions --------------------------*/
/*-----------------------------------------------------------------------------
* Wait function with the Periodic Interval Timer (PIT)
* The wait time is from 1ms to 999ms.
-----------------------------------------------------------------------------*/
void AT91F_AT24C_WaitMiliSecond (unsigned int MiliSeconds)
{
unsigned int PitStatus = 0; /* Status register of the PIT */
unsigned int PitLoop = 0; /* Store the number of PIT Loop */
AT91C_BASE_PITC->PITC_PIMR = AT91C_PITC_PITEN|PIT_PIV_MILI_SECOND_VALUE;
for( PitLoop=0; PitLoop <(MiliSeconds*3);) /* One PIT loop equals 333ms */
{
/* Wait for the PIT counter overflow occurs */
while ((AT91C_BASE_PITC->PITC_PISR & AT91C_PITC_PITS)==0);
/* Read the PIT Interval Value Reg. to clear it for the next overflow */
PitStatus = AT91C_BASE_PITC->PITC_PIVR ;
/* dummy access to avoid IAR warning */
PitStatus = PitStatus ;
PitLoop++;
}
}
/*-----------------------------------------------------------------------------
* Wait function with the Periodic Interval Timer (PIT)
* The wait time is from 1us to 999us.
-----------------------------------------------------------------------------*/
void AT91F_AT24C_WaitMicroSecond (unsigned int MicroSecond)
{
unsigned int PitStatus = 0; /* Status register of the PIT */
unsigned int PitLoop = 0; /* Store the number of PIT Loop */
AT91C_BASE_PITC->PITC_PIMR = AT91C_PITC_PITEN|PIT_PIV_MICRO_SECOND_VALUE;
for( PitLoop=0; PitLoop <(MicroSecond);) /* One PIT loop equals 333ns */
{
/* Wait for the PIT counter overflow occurs */
while ((AT91C_BASE_PITC->PITC_PISR & AT91C_PITC_PITS)==0);
/* Read the PIT Interval Value Reg. to clear it for the next overflow */
PitStatus = AT91C_BASE_PITC->PITC_PIVR ;
/* dummy access to avoid IAR warning */
PitStatus = PitStatus ;
PitLoop++;
}
}
/*-----------------------------------------------------------------------------
Function: AT91F_AT24C_WriteByte(..;..;..)
Arguments:
- <struct at24c *ptAt24c> : Structure of an AT24C Two-wire Eeprom
- <char Data2Write>: The data to write into the eeprom
- <unsigned int Address>: Address where to write
Comments:
This function uses a two bytes internal address (IADR) in relation of the
Eeprom's Internal "Word Address".
Return Value: None. No write error checking is done.
-----------------------------------------------------------------------------*/
void AT91F_AT24C_WriteByte (struct at24c *ptAt24c,
char Data2Write,
unsigned int Address)
{
unsigned int WordAddress;
unsigned int SlaveAddress;
/* 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 ;
}
}
AT91F_TWI_WriteSingleIadr(SlaveAddress,
WordAddress,
AT91C_TWI_IADRSZ_2_BYTE,
&Data2Write);
/* Wait 10ms before sending another start.
See Twr time spec. in the datasheet */
AT91F_AT24C_WaitMiliSecond (10);
}
/*-----------------------------------------------------------------------------
Function: AT91F_AT24C_WritePage(..;..;..)
Arguments:
- <struct at24c *ptAt24c> : Structure of an AT24C Two-wire Eeprom
- <char *Buffer>: The data (*buffer) to write into the eeprom
- <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 write error checking is done.
-----------------------------------------------------------------------------*/
void AT91F_AT24C_WritePage (struct at24c *ptAt24c,
char *Buffer,
unsigned int NumOfBytes,
unsigned int PageNumber,
unsigned int AddressOffSet)
{
unsigned int WordAddress;
unsigned int SlaveAddress;
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 ;
/* Wait until TXRDY is high to transmit the next data */
status = AT91C_BASE_TWI->TWI_SR;
while (!(status & AT91C_TWI_TXRDY_MASTER))
status = AT91C_BASE_TWI->TWI_SR;
/* Send the buffer to the page */
for ( Count=0; Count < NumOfBytes ;Count++ )
{
AT91C_BASE_TWI->TWI_THR = *Buffer++;
/* Wait until TXRDY is high to transmit the next data */
status = AT91C_BASE_TWI->TWI_SR;
while (!(status & AT91C_TWI_TXRDY_MASTER))
status = AT91C_BASE_TWI->TWI_SR;
}
/* 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;
/* Wait 10ms before sending another start.
See Twr time spec. in the datasheet */
AT91F_AT24C_WaitMiliSecond (10);
}
/*-----------------------------------------------------------------------------
Function: AT91F_AT24C_ReadByte(..;..;..)
Arguments:
- <struct at24c *ptAt24c> : Structure of an AT24C Two-wire Eeprom
- <unsigned int Address>: Address to read
Comments:
This function uses a two bytes internal address (IADR) in relation of the
Eeprom's Internal "Word Address".
Return Value: Data to read. No read error checking is done.
-----------------------------------------------------------------------------*/
char AT91F_AT24C_ReadByte (struct at24c *ptAt24c,
unsigned int Address)
{
unsigned int WordAddress;
unsigned int SlaveAddress;
char Data2Read ;
/* 17th bit of the word address. Applicable to the AT24C1024 only */
unsigned char p0=0;
if (ptAt24c->EepromName == AT24C1024)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -