Цитата(addi @ Sep 28 2008, 19:28)

т.к свой вариант работает в некоторых случаях неправильно, пока не нашел причину.
Ну так показали бы - вместе и нашли бы.
CODE
#ifndef I2C_SOFT_H__
#define I2C_SOFT_H__
#include <stdint.h>
#include "../common/Hardware.h"
template <uint8_t address>
class i2c_t
{
public:
static void on() {}
static void off() {}
static uint8_t read(bool ack);
static bool write(uint8_t byte);
private:
static void start();
static void stop();
static INLINE inline void SDA_low() { DRIVER(SDA, OUTPUT); }
static INLINE inline void SDA_high() { DRIVER(SDA, INPUT); }
static INLINE inline bool SDA_get() { return ACTIVE(SDA); }
static INLINE inline void SCL_low() { DRIVER(SCL, OUTPUT); }
static INLINE inline void SCL_high() { DRIVER(SCL, INPUT); }
};
template <uint8_t address>
void i2c_t<address>::start()
{
SDA_high();
SCL_high();
nop(); //nop(); nop(); nop(); // ~0.6us TSU:SUA
SDA_low();
nop(); //nop(); nop(); nop(); // ~0.6us THD:STA
SCL_low();
}
template <uint8_t address>
void i2c_t<address>::stop()
{
SDA_low();
nop(); //nop(); nop(); nop(); // ~0.6us TSU:SUA
SCL_high();
nop(); //nop(); nop(); nop(); // ~0.6us TSU:STO
SDA_high();
nop(); //nop(); nop(); nop(); // ~1.3us TBUF - TSU:SUA delay by wrapping commands
}
template <uint8_t address>
bool i2c_t<address>::write(uint8_t value)
{
uint8_t Counter = 8;
do
{
if(value & (1 << 7))
{
SDA_high();
}
else
{
SDA_low();
}
SCL_high();
value <<= 1;
SCL_low();
}
while(--Counter);
SDA_high();
SCL_high();
nop(); nop();
if(SDA_get())
{
stop();
return false;
}
SCL_low();
return true;
}
template <uint8_t address>
uint8_t i2c_t<address>::read(bool ack)
{
uint8_t Counter = 8;
uint8_t Result = 0;
do
{
SDA_high();
SCL_high();
Result <<= 1;
if(SDA_get())
Result |= 1;
SCL_low();
}
while (--Counter);
if(ack)
SDA_low();
else
SDA_high();
SCL_high();
nop(); nop();
SCL_low();
return Result;
}
#endif // I2C_SOFT_H__