📄 i2c.cpp
字号:
#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 + -