本帖最后由 AutochipsMCU 于 2019-10-23 13:35 编辑
贴一个模拟I2C的配置,供您参考://EEPROM
#define EEPROM_WP GPIO_PC11
#define EEPROM_SCL GPIO_PC12
#define EEPROM_SDA GPIO_PC13
// E2PROM操作
#define SET_SDA GPIO_SetPinBits(EEPROM_SDA) //SDA = 1
#define CLR_SDA GPIO_ResetPinBits(EEPROM_SDA) //SDA = 0
#define SDA_IN GPIO_GetPinValue(EEPROM_SDA) //Read SDA
#define SET_SCL GPIO_SetPinBits(EEPROM_SCL) //SCL = 1
#define CLR_SCL GPIO_ResetPinBits(EEPROM_SCL) //SCL = 0
#define E2P_DIS GPIO_SetPinBits(EEPROM_WP) //DIS = 1 (WP)
#define E2P_EN GPIO_ResetPinBits(EEPROM_WP) //EN = 0
void I2C_Delay(uint16_t number)
{
uint16_t j;
for(j=0;j<number;j++);
}
void DIR_In(void)
{
GPIO_SetDir(EEPROM_SDA, 0);//设置SDA引脚为输入
GPIO_SetPullupEnable(EEPROM_SDA, ENABLE); //上拉使能
}
void DIR_Out(void)
{
GPIO_SetDir(EEPROM_SDA, 1);//设置SDA引脚为输出
}
void Start_I2c(void)
{
DIR_Out();
SET_SDA;
I2C_Delay(400);
SET_SCL;
I2C_Delay(400);
CLR_SDA;
I2C_Delay(400);
CLR_SCL;
I2C_Delay(400);
}
void Stop_I2c(void)
{
DIR_Out();
CLR_SDA;
I2C_Delay(400);
SET_SCL;
I2C_Delay(400);
SET_SDA;
I2C_Delay(400);
CLR_SCL;
I2C_Delay(400);
}
void WriteAByte(uint16_t data)
{
uint16_t i;
DIR_Out();
for(i=0;i<8;i++)
{
CLR_SCL;
I2C_Delay(400);
if ((data>>7)&0x0001)
{
SET_SDA;
}
else
{
CLR_SDA;
}
I2C_Delay(400);
SET_SCL;
data <<= 1;
I2C_Delay(400);
}
CLR_SCL;
I2C_Delay(400);
}
uint16_t ReadAByte(void)
{
uint16_t i,bit=0,data=0;
DIR_In();
CLR_SCL;
I2C_Delay(400);
for (i=0; i<8; i++)
{
SET_SCL;
I2C_Delay(400);
if(SDA_IN)
{
bit=1;
}
else
{
bit=0;
}
data = (data << 1) | bit;
CLR_SCL;
I2C_Delay(400);
}
return (data);
}
uint16_t ReceiveI2CAck(void)
{
uint16_t i=5000;
SET_SDA;
DIR_In();
SET_SCL;
I2C_Delay(400);
while (SDA_IN)
{
if(!(--i))
{
CLR_SCL;
return(FALSE);
}
}
CLR_SCL;
I2C_Delay(400);
return(TRUE);
}
void SendI2CAck(void)
{
CLR_SCL;
I2C_Delay(400);
DIR_Out();
CLR_SDA;
SET_SCL;
I2C_Delay(400);
CLR_SCL;
I2C_Delay(400);
}
void SendI2CNAck(void)
{
CLR_SCL;
I2C_Delay(400);
DIR_Out();
SET_SDA;
SET_SCL;
I2C_Delay(400);
CLR_SCL;
I2C_Delay(400);
}
/**
* EEPROM_Config
*
* @param[in] void
*
* @return void
*
* @brief config eeprom pinmux and gpio
*
*/
void EEPROM_Config(void)
{
GPIO_SetDir(EEPROM_WP, 1);//设置WP引脚为输出
GPIO_SetDir(EEPROM_SCL, 1);//设置SCL引脚为输出
GPIO_SetDir(EEPROM_SDA, 1);//设置SDA引脚为输出
}
/**
* EEPROM_Read
*
* @param[in] address range 0-511(24c08)
*
* @return the value from address.
*
* @brief read eeprom
*
*/
uint16_t EEPROM_Read(uint16_t address)
{
uint16_t AX;
if( address >=384 ) // the forth page
{
AX = (address - 384) << 1;
Start_I2c();
WriteAByte(WriteDeviceDddress);
if (!ReceiveI2CAck())
{
return (FALSE);
}
WriteAByte(AX);
if (!ReceiveI2CAck())
{
return( FALSE );
}
Start_I2c();
WriteAByte(ReadDviceDddress);
if (!ReceiveI2CAck())
{
return( FALSE );
}
AX = ReadAByte();
SendI2CAck();
AX += (ReadAByte()) << 8;
SendI2CNAck();
Stop_I2c();
return (AX); // 读成功,返回实际数据,否则返回零
}
else if( address >=256 ) // the third page
{
AX = (address - 256)<<1;
Start_I2c();
WriteAByte(WriteDeviceCddress);
if (!ReceiveI2CAck())
{
return( FALSE );
}
WriteAByte(AX);
if (!ReceiveI2CAck())
{
return( FALSE );
}
Start_I2c();
WriteAByte(ReadDviceCddress);
if(!ReceiveI2CAck())
{
return( FALSE );
}
AX = ReadAByte();
SendI2CAck();
AX += (ReadAByte()) << 8;
SendI2CNAck();
Stop_I2c();
return( AX ); // 读成功,返回实际数据,否则返回零
}
else if( address >=128 ) // the second page
{
AX = (address - 128) << 1;
Start_I2c();
WriteAByte(WriteDeviceBddress);
if (!ReceiveI2CAck())
{
return( FALSE );
}
WriteAByte(AX);
if (!ReceiveI2CAck())
{
return( FALSE );
}
Start_I2c();
WriteAByte(ReadDviceBddress);
if (!ReceiveI2CAck())
{
return( FALSE );
}
AX = ReadAByte();
SendI2CAck();
AX += (ReadAByte()) << 8;
SendI2CNAck();
Stop_I2c();
return( AX ); // 读成功,返回实际数据,否则返回零
}
else // the first page
{
AX = address << 1;
Start_I2c();
WriteAByte(WriteDeviceAddress);
if (!ReceiveI2CAck())
{
return( FALSE );
}
WriteAByte( AX );
if (!ReceiveI2CAck())
{
return( FALSE );
}
Start_I2c();
WriteAByte(ReadDviceAddress);
if (!ReceiveI2CAck())
{
return( FALSE );
}
AX = ReadAByte();
SendI2CAck();
AX += (ReadAByte()) << 8;
SendI2CNAck();
Stop_I2c();
return( AX ); // 读成功,返回实际数据,否则返回零
}
}
/**
* EEPROM_Write
*
* @param[in] address: 0-511(24c08), data: a 16bit value
*
* @return void
*
* @brief write eeprom
*
*/
void EEPROM_Write(uint16_t address, uint16_t data)
{
uint16_t AX;
E2P_EN;
if ( address >=384 ) // the forth page
{
AX = (address - 384)<<1;
Start_I2c();
WriteAByte(WriteDeviceDddress);
ReceiveI2CAck();
WriteAByte( AX );
ReceiveI2CAck();
WriteAByte(data);
ReceiveI2CAck();
WriteAByte((data)>>8);
ReceiveI2CAck();
Stop_I2c();
}
else if( address >=256 ) // the third page
{
AX = (address - 256)<<1;
Start_I2c();
WriteAByte(WriteDeviceCddress);
ReceiveI2CAck();
WriteAByte( AX );
ReceiveI2CAck();
WriteAByte(data);
ReceiveI2CAck();
WriteAByte((data)>>8);
ReceiveI2CAck();
Stop_I2c();
}
else if( address >=128 ) // the second page
{
AX = (address - 128)<<1;
Start_I2c();
WriteAByte(WriteDeviceBddress);
ReceiveI2CAck();
WriteAByte( AX );
ReceiveI2CAck();
WriteAByte(data);
ReceiveI2CAck();
WriteAByte((data)>>8);
ReceiveI2CAck();
Stop_I2c();
}
else
{
AX = address <<1;
Start_I2c();
WriteAByte(WriteDeviceAddress);
ReceiveI2CAck();
WriteAByte( AX );
ReceiveI2CAck();
WriteAByte(data);
ReceiveI2CAck();
WriteAByte((data)>>8);
ReceiveI2CAck();
Stop_I2c();
}
I2C_Delay(5000);
I2C_Delay(5000);
I2C_Delay(5000);
I2C_Delay(5000);
I2C_Delay(5000);
I2C_Delay(5000);
I2C_Delay(5000);
I2C_Delay(5000);
E2P_DIS;
}
uint16_t test[512] = {0};
/**
* EEPROM_Test
*
* @param[in] void
*
* @return 0 : ok, 1:ng
*
* @brief test eeprom
*
*/
uint8_t EEPROM_Test(void)
{
uint16_t i = 0;
uint16_t read = 0;
memset(test, 0x00, sizeof(test));
for (i = 0; i < 512; i++)
{
EEPROM_Write(i, i);
read = EEPROM_Read(i);
test = read;
}
return 0;
}
|