/*I2C总线的时序描述*/
static uint8_t IIC_clear_bus(const IIC_PIN* pin)
{
uint8_t bus_clear = 0;
if (pin->error)
return bus_clear;
pin->SDAOutPut(1);
pin->SCLOutPut(1);
pin->Delay();
pin->SCLInputConfig();
pin->SDAInputConfig();
if (pin->ReadSCLInput() == 1 && pin->ReadSDAInput() == 1)
{
pin->SCLOutputConfig();
pin->SDAOutputConfig();
bus_clear = 1;
}
else if (pin->ReadSCLInput() == 1)
{
uint_fast8_t i;
bus_clear = 0;
pin->SCLOutputConfig();
for (i = 18; i--;)
{
pin->SCLOutPut(0);
pin->Delay();
pin->SCLOutPut(1);
pin->Delay();
if (pin->ReadSDAInput() == 1)
{
pin->SDAOutputConfig();
bus_clear = 1;
break;
}
}
}
return bus_clear;
}
static uint8_t IIC_issue_startcondition(const IIC_PIN* pin)
{
uint8_t transfer_succeeded = 1;
if (pin->error)
return 0;
pin->SCLOutPut(1);
pin->SDAOutPut(1);
pin->Delay();
transfer_succeeded &= pin->ReadSDAInput();
transfer_succeeded &= pin->ReadSCLInput();
pin->SDAOutPut(0);
pin->Delay();
pin->SCLOutPut(0);
pin->Delay();
return transfer_succeeded;
}
static uint8_t IIC_issue_stopcondition(const IIC_PIN* pin)
{
if (pin->error)
return 0;
pin->SCLOutPut(1);
pin->SDAOutPut(0);
pin->Delay();
pin->SDAOutPut(1);
pin->Delay();
return 1;
}
void IIC_SendAck(const IIC_PIN* pin)
{
pin->SCLOutPut(0);
pin->SDAOutPut(0);
pin->Delay();
pin->SCLOutPut(1);
pin->Delay();
pin->SCLOutPut(0);
}
static uint8_t IIC_WaitAck(const IIC_PIN* pin)
{
uint8_t cAck = 0;
uint16_t tmp = 0;
pin->SDAInputConfig();
pin->SDAOutPut(1);
pin->SCLOutPut(0);
pin->Delay();
pin->SCLOutPut(1);
while (1)
{
cAck = pin->ReadSDAInput();
tmp++;
if (!cAck)
break;
if (tmp > 100)
break;
}
pin->SDAOutputConfig();
pin->SCLOutPut(0);
pin->SDAOutPut(0);
return 1 - cAck;
}
void IIC_clock_byte(const IIC_PIN* pin, uint_fast8_t databyte)
{
uint_fast8_t i;
if (pin->error)
return;
pin->SDAOutputConfig();
pin->Delay();
for (i = 0x80; i != 0; i >>= 1)
{
pin->SCLOutPut(0);
pin->Delay();
if (databyte & i)
pin->SDAOutPut(1);
else
pin->SDAOutPut(0);
pin->Delay();
pin->SCLOutPut(1);
pin->Delay();
pin->SCLOutPut(0);
}
}
void IIC_clock_byte_in(const IIC_PIN* pin, uint8_t* databyte)
{
uint_fast8_t byte_read = 0;
uint_fast8_t i;
pin->SDAOutPut(1);
pin->SDAInputConfig();
for (i = 0x80; i != 0; i >>= 1)
{
pin->SCLOutPut(0);
pin->Delay();
pin->SCLOutPut(1);
if (pin->ReadSDAInput() == 1)
byte_read |= i;
pin->Delay();
pin->SCLOutPut(0);
}
// Make sure SDA is an output before we exit the function
pin->SDAOutputConfig();
pin->SDAOutPut(0);
*databyte = (uint8_t)byte_read;
}
uint8_t IIC_Init(IIC_PIN* pin)
{
if ((pin->Init == NULL) && (pin->Delay == NULL) && (pin->Disable == NULL) &&
(pin->ReadSDAInput == NULL) && (pin->ReadSCLInput == NULL) &&
(pin->SCLOutPut == NULL) && (pin->SCLOutputConfig == NULL) && (pin->SDAInputConfig == NULL)
&& (pin->SDAOutPut == NULL) && (pin->SDAOutputConfig == NULL) && (pin->SCLInputConfig == NULL))
{
pin->error = 1;
return 0;
}
pin->Init();
pin->SDAOutputConfig();
pin->SDAOutPut(1);
pin->SCLOutputConfig();
pin->SCLOutPut(1);
return IIC_clear_bus(pin);
}
void IIC_InitDisable(IIC_PIN* pin)
{
if (pin->Disable != NULL)
pin->Disable();
}
uint8_t IIC_transfer(uint8_t address, IIC_PIN* pin, uint8_t* data, uint16_t data_length, uint8_t issue_stop_condition)
{
uint8_t transfer_succeeded = 1;
if (pin->error)
return 0;
transfer_succeeded &= IIC_issue_startcondition(pin);
IIC_clock_byte(pin, address);
transfer_succeeded &= IIC_WaitAck(pin);
if (address & IIC_READ_BIT)
{
/* Transfer direction is from Slave to Master */
while (data_length-- && transfer_succeeded)
{
// To indicate to slave that we've finished transferring last data byte
// we need to NACK the last transfer.
if (data_length == 0)
{
IIC_clock_byte_in(pin, data);
break;
}
else
{
IIC_clock_byte_in(pin, data);
IIC_SendAck(pin);
}
data++;
}
}
else
{
/* Transfer direction is from Master to Slave */
while (data_length-- && transfer_succeeded)
{
IIC_clock_byte(pin, *data);
transfer_succeeded &= IIC_WaitAck(pin);
data++;
}
}
if (issue_stop_condition || !transfer_succeeded)
{
transfer_succeeded &= IIC_issue_stopcondition(pin);
}
return transfer_succeeded;
}
初出茅庐的小李第105篇博客之I2C时序函数指针形式
最新推荐文章于 2024-05-16 18:45:52 发布