初出茅庐的小李第105篇博客之I2C时序函数指针形式

/*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;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值