Ну вот собственно сам код. Не смотрите на несколько странное именование переменных и функций - переименуете на свой вкус.
Вам необходимо определить несколько макросов для работы с пинами SCL и SDA (установка/сброс/чтение).
Пины должны быть настроены как "Выход с открытым коллектором". Как это сделать смотрите даташит на свой процессор.
CODE
//Пины SCL и SDA должны быть настроены как GPIO_Mode_Out_OD
//
#define I2CSWM_DELAY 32
#define I2CSWM_SETSCL()
#define I2CSWM_CLEARSCL()
#define I2CSWM_GETSCL()
#define I2CSWM_SETSDA()
#define I2CSWM_CLEARSDA()
#define I2CSWM_GETSDA()
/*
*/
inline static void __i2cswm___delay( int n )
{
do
{
__no_operation();
}while( --n > 0 );
}
/*
*/
inline static void __i2cswm___start()
{
I2CSWM_SETSDA();
I2CSWM_SETSCL();
I2CSWM_CLEARSDA();
__i2cswm___delay(I2CSWM_DELAY);
I2CSWM_CLEARSCL();
}
/*
*/
inline static void __i2cswm___stop()
{
I2CSWM_CLEARSDA();
I2CSWM_SETSCL();
__i2cswm___delay(I2CSWM_DELAY);
I2CSWM_SETSDA();
}
/*
*/
inline static uint_fast8_t __i2cswm___clock()
{
uint_fast8_t l;
I2CSWM_SETSCL();
__i2cswm___delay(I2CSWM_DELAY);
l = I2CSWM_GETSDA() == Bit_SET ? 1 : 0;
I2CSWM_CLEARSCL();
__i2cswm___delay(I2CSWM_DELAY);
return l;
}
/*
*/
inline static uint_fast8_t __i2cswm___sendb(uint8_t b)
{
uint_fast8_t db = 0x80;
for(uint_fast8_t i = 0; i < 8; i++)
{
if( b & db )
{
I2CSWM_SETSDA();
}else
{
I2CSWM_CLEARSDA();
}
__i2cswm___clock();
db >>= 1;
}
/* Получим ACK */
I2CSWM_SETSDA(); /* отпускаем линию SDA */
return __i2cswm___clock();
}
/*
*/
inline static uint_fast8_t __i2cswm___recvb( uint_fast8_t ack )
{
uint_fast8_t rb = 0;
uint_fast8_t db = 0x80;
for(uint_fast8_t i = 0; i < 8; i++)
{
if( __i2cswm___clock() )
rb |= db;
db >>= 1;
}
if( ack == I2CSWM_ACK )
{
/* шлем ацк */
I2CSWM_CLEARSDA();
__i2cswm___clock();
I2CSWM_SETSDA();
}else
{
/* шлем нацк */
I2CSWM_SETSDA();
__i2cswm___clock();
}
return rb;
}
/*
*/
void __i2cswm___reset()
{
I2CSWM_SETSDA();
for(int i = 0; i < 15; i++)
{
I2CSWM_SETSCL();
__i2cswm___delay(I2CSWM_DELAY);
I2CSWM_CLEARSCL();
__i2cswm___delay(I2CSWM_DELAY);
}
I2CSWM_SETSDA();
I2CSWM_SETSCL();
}
/*
*/
int __i2cswm___recvex(const uint16_t saddr, uint8_t* lpdata1, uint32_t size1, uint8_t* lpdata2, uint32_t size2)
{
__i2cswm___start();
if( lpdata1 != NULL )
{
if( __i2cswm___sendb( saddr | I2CSWM_DIRECTION_TX) == I2CSWM_NACK )
{
__i2cswm___stop();
return FALSE;
}
for(int i = 0; i < size1; i++)
{
if( __i2cswm___sendb(*lpdata1++) == I2CSWM_NACK )
{
__i2cswm___stop();
return FALSE;
}
}
__i2cswm___start();
}
if( lpdata2 != NULL )
{
if( __i2cswm___sendb( saddr | I2CSWM_DIRECTION_RX) == I2CSWM_NACK )
{
__i2cswm___stop();
return FALSE;
}
I2CSWM_SETSCL();
for(int i = 1; i < size2; i++)
{
*lpdata2 = __i2cswm___recvb( I2CSWM_ACK );
lpdata2++;
}
*lpdata2 = __i2cswm___recvb( I2CSWM_NACK );
lpdata2++;
}
__i2cswm___stop();
return TRUE;
}
/*
*/
int __i2cswm___sendex(const uint16_t saddr, uint8_t* lpdata1, uint32_t size1, uint8_t* lpdata2, uint32_t size2)
{
__i2cswm___start();
if( lpdata1 != NULL )
{
if( __i2cswm___sendb( saddr | I2CSWM_DIRECTION_TX) == I2CSWM_NACK )
{
__i2cswm___stop();
return FALSE;
}
for(int i = 0; i < size1; i++)
{
if( __i2cswm___sendb(*lpdata1++) == I2CSWM_NACK )
{
__i2cswm___stop();
return FALSE;
}
}
}
if( lpdata2 != NULL )
{
for(int i = 0; i < size2; i++)
{
if( __i2cswm___sendb(*lpdata2++) == I2CSWM_NACK )
{
__i2cswm___stop();
return FALSE;
}
}
}
__i2cswm___stop();
return TRUE;
}
//использвоание на примере FRAM
static const uint8_t EEPROM_SADDR = 0xA0;
/*******************************************************************************
*
*******************************************************************************/
uint_fast8_t eeprom_read(uint16_t addr, uint8_t* buf, size_t size)
{
addr = SWP(addr);
uint_fast8_t rep_cnt = 3;
uint_fast8_t rc = FALSE;
while( --rep_cnt > 0 && rc == FALSE )
{
rc = i2c_recvex(EEPROM_SADDR, (uint8_t*)&addr, sizeof(addr), buf, size);
}
return rc;
}
/******************************************************************************/
/*******************************************************************************
*
*******************************************************************************/
uint_fast8_t eeprom_write(uint16_t addr, uint8_t* buf, size_t size)
{
addr = SWP(addr);
uint_fast8_t rep_cnt = 3;
uint_fast8_t rc = FALSE;
while( --rep_cnt > 0 && rc == FALSE )
{
rc = i2c_sendex(EEPROM_SADDR, (uint8_t*)&addr, sizeof(addr), buf, size);
}
return rc;
}
/******************************************************************************/
//и где то в программе
.....
TAPPPARAMS_C d_params_c;
if( eeprom_read(0, (uint8_t*)&d_params_c, sizeof(TAPPPARAMS_C)) )
{
}else
{
//error
}
.....