⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 i2c.cpp

📁 SM501基于ARMV4/ARMV4I平台
💻 CPP
📖 第 1 页 / 共 2 页
字号:

#else

	nResult = VGXI2C_SUCCESS;

	// Turn the controller on and disable interrupts
	BYTE I2CControl = peekRegisterByte(I2C_CONTROL);
	I2CControl = (BYTE)FIELD_SET(I2CControl, I2C_CONTROL, INTERRUPT, DISABLE);
	I2CControl = (BYTE)FIELD_SET(I2CControl, I2C_CONTROL, I2C, ENABLE);
	pokeRegisterByte(I2C_CONTROL, I2CControl);

	// Reset the event
	ResetEvent(m_I2CIntEvent);

	// Wait a while
	Sleep(DELAY_TIME);

	// Check for busy
	if (FIELD_GET(peekRegisterByte(I2C_STATUS), I2C_STATUS, BUS)
		== I2C_STATUS_BUS_BUSY)
	{
		// Try to stop the current transaction
		pokeRegisterByte(I2C_CONTROL, (BYTE)FIELD_SET(peekRegisterByte(I2C_CONTROL),
			I2C_CONTROL, STATUS, STOP));

		// Wait a while
		Sleep(DELAY_TIME);

		// Check again
		if (FIELD_GET(peekRegisterByte(I2C_STATUS), I2C_STATUS, BUS)
			== I2C_STATUS_BUS_BUSY)
		{
			// Unable to stop
			MESSAGE(MESSAGE_ZONE, (TEXT("SMI::i2cReset - I2C controller is busy\r\n")));
			MESSAGE(MESSAGE_ZONE, (TEXT("-SMI::i2cReset\r\n")));
			return VGXI2C_BUS_BUSY;
		}
	}

	// Check for errors
	if (FIELD_GET(peekRegisterByte(I2C_STATUS), I2C_STATUS, ERROR)
		== I2C_STATUS_ERROR_BUS_ERROR)
	{
		// Try to clear the error
		pokeRegisterByte(I2C_CONTROL, (BYTE)FIELD_SET(peekRegisterByte(I2C_CONTROL),
			I2C_CONTROL, ERROR, ACKNOWLEDGE));

		pokeRegisterByte(I2C_STATUS, (BYTE)FIELD_SET(peekRegisterByte(I2C_STATUS),
			I2C_STATUS, ERROR, CLEAR));

		// Wait a while
		Sleep(DELAY_TIME);

		// Check again
		if (FIELD_GET(peekRegisterByte(I2C_STATUS), I2C_STATUS, ERROR)
			== I2C_STATUS_ERROR_BUS_ERROR)
		{
			// Unable to stop
			MESSAGE(MESSAGE_ZONE, (TEXT("SMI::i2cReset - bus error\r\n")));
			MESSAGE(MESSAGE_ZONE, (TEXT("-SMI::i2cReset\r\n")));
			return VGXI2C_BUS_ERROR;
		}
	}

	// Check the transfer bit
	if (FIELD_GET(peekRegisterByte(I2C_STATUS), I2C_STATUS, TRANSFER)
		== I2C_STATUS_TRANSFER_COMPLETE)
	{
		// Clear it
		pokeRegisterByte(I2C_STATUS, (BYTE)FIELD_SET(peekRegisterByte(I2C_STATUS),
			I2C_STATUS, TRANSFER, CLEAR));
	}

	// Check the acknowledge bit
	if (FIELD_GET(peekRegisterByte(I2C_STATUS), I2C_STATUS, ACK)
		== I2C_STATUS_ACK_NOT_RECEIVED)
	{
		// Clear it
		pokeRegisterByte(I2C_STATUS, (BYTE)FIELD_SET(peekRegisterByte(I2C_STATUS),
			I2C_STATUS, ACK, CLEAR));
	}

	// Configure the controller
	I2CControl = (BYTE)FIELD_SET(I2CControl, I2C_CONTROL, INTERRUPT, ENABLE);
	I2CControl = (BYTE)FIELD_SET(I2CControl, I2C_CONTROL, ERROR,     CLEAR);
	I2CControl = (BYTE)FIELD_SET(I2CControl, I2C_CONTROL, STATUS,    STOP);
	pokeRegisterByte(I2C_CONTROL, I2CControl);

	// Wait a while
	Sleep(DELAY_TIME);

#endif

	MESSAGE(MESSAGE_ZONE, (TEXT("-SMI::i2cReset\r\n")));
	return nResult;
}


///////////////////////////////////////////////////////////////////////////////
// This function does the actual reading.

ULONG SMI::i2cDoRead(PBYTE& pBuffer, DWORD dwCount)
{
	ULONG nResult;

#ifdef DISABLE_INTERRUPT_MANAGEMENT

	nResult = VGXI2C_INT_NOT_SUPPORTED;

#else

	// Set the byte count
	pokeRegisterByte(I2C_BYTE_COUNT,
		(BYTE)FIELD_VALUE(0, I2C_BYTE_COUNT, COUNT, dwCount - 1));

	// Start the transaction
	pokeRegisterByte(I2C_CONTROL, (BYTE)FIELD_SET(peekRegisterByte(I2C_CONTROL),
		I2C_CONTROL, STATUS, START));

	// Wait until the transfer is over
	nResult = WaitForSingleObject(m_I2CIntEvent, TRANSACTION_TIMEOUT);

	// Check results
	switch (nResult)
	{
	case WAIT_TIMEOUT:
		// No interrupt has been received, report the error
		nResult = VGXI2C_READ_TIMEOUT;

		// Reset I2C
		i2cReset();
		break;

	case WAIT_OBJECT_0:
		// Get the status
		nResult = m_I2CStatus;

		// If success, move the data
		if (nResult == VGXI2C_SUCCESS)
			for (DWORD i = 0; i < dwCount; i++)
				*pBuffer++ = peekRegisterByte(I2C_DATA + i);

		break;

	case WAIT_FAILED:
		nResult = VGXI2C_WAIT_FAILED;
	}

#endif

	return nResult;
}


///////////////////////////////////////////////////////////////////////////////
// Read data.

ULONG SMI::i2cRead(
	BYTE byAddress,		// Slave address
	DWORD dwCount,		// Number of bytes to be read
	PBYTE pBuffer)		// Buffer pointer
{
	MESSAGE(MESSAGE_ZONE, (TEXT("+SMI::i2cRead\r\n")));
	ULONG nResult;

#ifdef DISABLE_INTERRUPT_MANAGEMENT

	nResult = VGXI2C_INT_NOT_SUPPORTED;

#else

	if (m_bI2CEnabled)
	{
		// Reset the controller
		nResult = i2cReset();
		if (nResult == VGXI2C_SUCCESS)
		{
			// Set up the address
			BYTE Address = FIELD_VALUE(0, I2C_SLAVE, ADDRESS, byAddress);
			Address = (BYTE)FIELD_SET(Address, I2C_SLAVE, SELECT, READ);
			pokeRegisterByte(I2C_SLAVE, Address);

			// Set the direction
			pokeRegisterByte(I2C_CONTROL, (BYTE)FIELD_SET(peekRegisterByte(I2C_CONTROL),
				I2C_CONTROL, DIRECTION, READ));

			// Send full buffers
			DWORD fullBufferCount = dwCount / BUFFER_LENGTH;
			for (DWORD i = 0; i < fullBufferCount; i++)
			{
				nResult = i2cDoRead(pBuffer, BUFFER_LENGTH);
				if (nResult != VGXI2C_SUCCESS)
					break;
			}

			// Send the remainder
			if (nResult == VGXI2C_SUCCESS)
				nResult = i2cDoRead(pBuffer, dwCount % BUFFER_LENGTH);
		}
	}
	else
	{
		nResult = VGXI2C_NOT_INITIALIZED;
	}

#endif

	MESSAGE(MESSAGE_ZONE, (TEXT("-SMI::i2cRead\r\n")));
	return nResult;
}


///////////////////////////////////////////////////////////////////////////////
// This function does the actual writing.

ULONG SMI::i2cDoWrite(PBYTE& pBuffer, DWORD dwCount)
{
	ULONG nResult;

#ifdef DISABLE_INTERRUPT_MANAGEMENT

	nResult = VGXI2C_INT_NOT_SUPPORTED;

#else

	// Set the byte count
	pokeRegisterByte(I2C_BYTE_COUNT,
		(BYTE)FIELD_VALUE(0, I2C_BYTE_COUNT, COUNT, dwCount - 1));

	// Move the data
	for (DWORD i = 0; i < dwCount; i++)
		pokeRegisterByte(I2C_DATA + i, *pBuffer++);

	// Start the transaction
	pokeRegisterByte(I2C_CONTROL, (BYTE)FIELD_SET(peekRegisterByte(I2C_CONTROL),
		I2C_CONTROL, STATUS, START));

	// Wait until the transfer is over
	nResult = WaitForSingleObject(m_I2CIntEvent, TRANSACTION_TIMEOUT);

	// Check results
	if (nResult == WAIT_TIMEOUT)
	{
		// No interrupt has been received, report the error
		nResult = VGXI2C_WRITE_TIMEOUT;
		i2cReset();
	}
	else
	{
		// Get the status
		nResult = m_I2CStatus;
	}

#endif

	return nResult;
}


///////////////////////////////////////////////////////////////////////////////
// Write data.

ULONG SMI::i2cWrite(
	BYTE byAddress,		// Slave address
	DWORD dwCount,		// Number of bytes to be read
	PBYTE pBuffer)		// Buffer pointer
{
	MESSAGE(MESSAGE_ZONE, (TEXT("+SMI::i2cWrite\r\n")));
	ULONG nResult;

#ifdef DISABLE_INTERRUPT_MANAGEMENT

	nResult = VGXI2C_INT_NOT_SUPPORTED;

#else

	if (m_bI2CEnabled)
	{
		// Reset the controller
		nResult = i2cReset();
		if (nResult == VGXI2C_SUCCESS)
		{
			// Set up the address
			BYTE Address = FIELD_VALUE(0, I2C_SLAVE, ADDRESS, byAddress);
			Address = (BYTE)FIELD_SET(Address, I2C_SLAVE, SELECT, WRITE);
			pokeRegisterByte(I2C_SLAVE, Address);

			// Set the direction
			pokeRegisterByte(I2C_CONTROL, (BYTE)FIELD_SET(peekRegisterByte(I2C_CONTROL),
				I2C_CONTROL, DIRECTION, WRITE));

			// Send full buffers
			DWORD fullBufferCount = dwCount / BUFFER_LENGTH;
			for (DWORD i = 0; i < fullBufferCount; i++)
			{
				nResult = i2cDoWrite(pBuffer, BUFFER_LENGTH);
				if (nResult != VGXI2C_SUCCESS)
					break;
			}

			// Send the remainder
			if (nResult == VGXI2C_SUCCESS)
				nResult = i2cDoWrite(pBuffer, dwCount % BUFFER_LENGTH);
		}
	}
	else
	{
		nResult = VGXI2C_NOT_INITIALIZED;
	}

#endif

	MESSAGE(MESSAGE_ZONE, (TEXT("-SMI::i2cWrite\r\n")));
	return nResult;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -