📄 i2c.c
字号:
{
IICError = I2C_ERROR_NO_ERR;
SetEvent(gI2CEvent);
}
else
{
v_pIICPregs->rIICSTAT = (3 << 6) | (0 << 5) | (1 << 4);
IICCON_DACK(v_pIICPregs->rIICCON);
Sleep(1); // 等待结束信号产生完毕
IICError = I2C_ERROR_SEND;
SetEvent(gI2CEvent);
}
break;
// Receive Bytes
case I2C_STATUS_RECEIVE:
if((v_pIICPregs->rIICSTAT & 0x08) == 0)
{
IICError = I2C_ERROR_NO_ERR;
SetEvent(gI2CEvent);
}
else
{
// 发送结束信号
v_pIICPregs->rIICSTAT = (2 << 6) | (0 << 5) | (1 << 4);
IICCON_DACK(v_pIICPregs->rIICCON);
Sleep(1); // 等待结束信号产生完毕
IICError = I2C_ERROR_RECEIVE;
SetEvent(gI2CEvent);
}
break;
default:
break;
}
InterruptDone(g_I2CSysIntr);
}
}
/*******************************************************************************************
函数名称: IIC_Init
描 述: 驱动程序初始化函数
输入参数: DWORD dwContext: 设备管理器传递给本驱动的参数, 通常为流接口驱动在注册表内的位置
输出参数: 无
返 回: 驱动程序句柄
*******************************************************************************************/
DWORD
IIC_Init(DWORD dwContext)
{
DWORD IDThread;
RETAILMSG(1, (TEXT("IIC_Init\r\n")));
// 取得 GPIO 及 IIC 相关寄存器的虚拟地址空间
I2C_InitializeAddresses();
// 使能 IIC 引脚为中断引脚, 并初始化相关寄存器
I2C_InitHareware();
// 从 OAL 请求一个 SYSINTR 值
/*if (!KernelIoControl(IOCTL_HAL_TRANSLATE_IRQ, &g_I2CIrq, sizeof(UINT32), &g_I2CSysIntr, sizeof(UINT32), NULL))
{
RETAILMSG(1, (TEXT("ERROR: I2C Bus: Failed to request sysintr value for I2C Bus interrupt.\r\n")));
return(0);
}
*/
g_I2CSysIntr=0x10+20;
RETAILMSG(1,(TEXT("INFO: I2C Bus: Mapped Irq 0x%x to SysIntr 0x%x.\r\n"), g_I2CIrq, g_I2CSysIntr));
gI2CIntrThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE) I2C_IntrThread, 0, 0, &IDThread);
if (gI2CIntrThread == 0)
{
RETAILMSG(1, (TEXT("::: CreateThread() Fail\r\n")));
return 0;
}
SetThreadPriority(gI2CIntrThread, THREAD_PRIORITY_ABOVE_NORMAL);
gI2CEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
return (DWORD)gI2CIntrThread;
}
/*******************************************************************************************
函数名称: DllEntry
描 述: 驱动程序动态库入口
输入参数:
输出参数:
返 回:
*******************************************************************************************/
PUBLIC BOOL WINAPI
DllEntry(HANDLE hInstDll, DWORD dwReason, LPVOID lpvReserved)
{
switch ( dwReason )
{
case DLL_PROCESS_ATTACH:
RETAILMSG(1, (TEXT("IIC: DLL_PROCESS_ATTACH\r\n")));
DisableThreadLibraryCalls((HMODULE) hInstDll);
break;
case DLL_PROCESS_DETACH:
RETAILMSG(1, (TEXT("IIC: DLL_PROCESS_DETACH\r\n")));
break;
}
return (TRUE);
}
/*******************************************************************************************
函数名称: IIC_Close
描 述: 驱动程序关闭函数
输入参数: DWORD Handle:驱动程序句柄
输出参数: 无
返 回: FALSE: 失败 TRUE: 成功
*******************************************************************************************/
BOOL IIC_Close(DWORD Handle)
{
g_OpenCount = 0;
return TRUE;
} // IIC_Close
/*******************************************************************************************
函数名称: IIC_Deinit
描 述: 驱动程序卸载函数
输入参数: DWORD dwContext: 驱动程序句柄
输出参数: 无
返 回: FALSE: 失败 TRUE: 成功
*******************************************************************************************/
BOOL IIC_Deinit(DWORD dwContext)
{
RETAILMSG(1, (TEXT(":::IIC: IIC Driver deinit.\r\n")));
// 通知中断服务线程退出
g_bKillIST = TRUE;
PulseEvent(gI2CIntrEvent);
Sleep(200); /* 等待.... */
// 释放中断资源
InterruptDone(g_I2CSysIntr);
InterruptDisable(g_I2CSysIntr);
KernelIoControl(IOCTL_HAL_RELEASE_SYSINTR, &g_I2CSysIntr, sizeof(UINT32), NULL, 0, NULL);
// 恢复 I2C 引脚为输入引脚
I2C_ConfigPinDefault();
/* 释放申请的虚拟内存 */
if (v_pIOPregs)
VirtualFree((PVOID)v_pIOPregs, 0, MEM_RELEASE);
if (v_pIICPregs)
VirtualFree((PVOID)v_pIICPregs, 0, MEM_RELEASE);
// 关闭 I2C 事件句柄
CloseHandle(gI2CEvent);
g_OpenCount = 0;
return TRUE;
} // IIC_Deinit
/*******************************************************************************************
函数名称: IIC_Open
描 述: 打开驱动程序
输入参数: DWORD dwData : 设备驱动程序句柄
DWORD dwAccess : 访问请求代码,是读和写的组合
DWORD dwShareMode: 共享模式
输出参数:
返 回: 驱动程序引用事例句柄
*******************************************************************************************/
DWORD
IIC_Open(
DWORD dwData,
DWORD dwAccess,
DWORD dwShareMode
)
{
if(g_OpenCount > 0)
return 0;
g_OpenCount++;
return g_OpenCount;
} // IIC_Open
/*******************************************************************************************
函数名称: IIC_IOControl
描 述: 驱动程序 I/O 请求
输入参数:
输出参数:
返 回: TRUE: 成功 FALSE: 失败
*******************************************************************************************/
BOOL
IIC_IOControl(
DWORD Handle,
DWORD dwIoControlCode,
PBYTE pInBuf,
DWORD nInBufSize,
PBYTE pOutBuf,
DWORD nOutBufSize,
PDWORD pBytesReturned
)
{
BOOL bErr = FALSE;
switch (dwIoControlCode)
{
case IOCTL_SET_I2C_SLAVE: /* 设置从机地址 */
if (nInBufSize > 0)
{
I2cSla = pInBuf[0];
bErr = TRUE;
}
break;
case IOCTL_SET_SPEED_DIV:
if ((nInBufSize > 0) &&
(pInBuf[0] <= 15) && /* I2C的分频值为: 0 ~ 15 */
(nOutBufSize >= 0)) /* pOutBuf 为 DWORD */
{
/* 写入分频值 */
v_pIICPregs->rIICCON = IICCON_DEFAULT | pInBuf[0];
*(DWORD *)pOutBuf = I2C_GetSpeed(); /* 取得I2C传输速度(HZ) */
*pBytesReturned = 1;
bErr = TRUE;
}
break;
case IOCTL_GET_SPEED: /* pOutBuf 为 DWORD */
if (nOutBufSize > 0)
{
*(DWORD *)pOutBuf = I2C_GetSpeed(); /* 取得I2C传输速度(HZ) */
*pBytesReturned = 1;
bErr = TRUE;
}
break;
default:
break;
}
return bErr;
} // IIC_IOControl
/*******************************************************************************************
函数名称: IIC_Read
描 述: 从 IIC 从机读取数据
输入参数: DWORD Handle : 驱动程序引用事例句柄
LPVOID pBuffer : 接收缓冲区
DWORD dwNumBytes: 要读的字节数
输出参数: 无
返 回: 实际读到字节数
*******************************************************************************************/
DWORD IIC_Read(DWORD Handle, LPVOID pBuffer, DWORD dwNumBytes)
{
UINT32 count, ret;
uchar *pReadBuffer;
if ((pBuffer == NULL) || (dwNumBytes <= 0))
return 0;
pReadBuffer = MapPtrToProcess(pBuffer, GetCallerProcess());
// 设置从机地址及当前状态
I2cCurSla = I2cSla | 0x01;
I2cStatus = I2C_STATUS_SETADDR;
StartI2C(I2cCurSla);
ret = WaitForSingleObject(gI2CEvent, I2C_RW_TIMEOUT); /* 挂起当前线程,直到IIC中断的产生 */
ResetEvent(gI2CEvent);
if ((IICError != I2C_ERROR_NO_ERR) || (ret != WAIT_OBJECT_0))
{
RETAILMSG(1, (TEXT("ERROR: IIC_Read: Send Slave Address fail! \r\n")));
return 0;
}
I2cStatus = I2C_STATUS_RECEIVE; // 进入接收状态
for (count = 0; count < dwNumBytes; count++)
{
if (count == (dwNumBytes - 1))
IIC_StartRecByteNA();
else
IIC_StartRecByteA();
/* 挂起当前线程,直到IIC中断的产生 */
ret = WaitForSingleObject(gI2CEvent, I2C_RW_TIMEOUT);
ResetEvent(gI2CEvent);
if (ret != WAIT_OBJECT_0)
{
if (ret == WAIT_TIMEOUT)
RETAILMSG(1, (TEXT("ERROR: IIC read data time out! \r\n")));
else
RETAILMSG(1, (TEXT("ERROR: IIC read data fail! \r\n")));
return count;
}
*pReadBuffer = IIC_RecByte();
pReadBuffer++;
if (IICError != I2C_ERROR_NO_ERR)
{
RETAILMSG(1, (TEXT("ERROR: IIC_Read: Receive data fail! \r\n")));
break;
}
}
StopI2C(0);
return count;
}
/*******************************************************************************************
函数名称: IIC_Write
描 述: 向 IIC 从机发送数据
输入参数:
输出参数:
返 回: 成功发送的字节数
*******************************************************************************************/
DWORD IIC_Write(DWORD Handle, LPCVOID pBuffer, DWORD dwNumBytes)
{
UINT32 count, ret;
uchar *pWriteBuffer;
if ((pBuffer == NULL) || (dwNumBytes <= 0))
return 0;
pWriteBuffer = MapPtrToProcess((LPVOID)pBuffer, GetCallerProcess());
// 设置从机地址及当前状态
I2cCurSla = I2cSla;
I2cStatus = I2C_STATUS_SETADDR;
StartI2C(I2cCurSla);
ret = WaitForSingleObject(gI2CEvent, I2C_RW_TIMEOUT); /* 挂起当前线程,直到IIC中断的产生 */
ResetEvent(gI2CEvent);
if ((IICError != I2C_ERROR_NO_ERR) || (ret != WAIT_OBJECT_0))
{
RETAILMSG(1, (TEXT("ERROR: IIC_Write: send slave address fail! \r\n")));
return 0;
}
I2cStatus = I2C_STATUS_SEND; // 进入发送状态
for (count = 0; count < dwNumBytes; count ++)
{
IIC_SendByte(*pWriteBuffer); /* 启动I2C总线,发送在中断中进行 */
pWriteBuffer++;
/* 挂起当前线程,直到IIC中断的产生 */
ret = WaitForSingleObject(gI2CEvent, I2C_RW_TIMEOUT);
ResetEvent(gI2CEvent);
if (ret != WAIT_OBJECT_0)
{
RETAILMSG(1, (TEXT("ERROR: IIC write data fail! \r\n")));
return count;
}
if (IICError != I2C_ERROR_NO_ERR)
{
RETAILMSG(1, (TEXT("ERROR: IIC_Write: send data fail! \r\n")));
break;
}
}
StopI2C(1);
return count;
}
/*******************************************************************************************
函数名称: IIC_Seek
描 述: 对设备的数据指针进行操作,本驱动不支持该函数
输入参数:
输出参数:
返 回:
*******************************************************************************************/
DWORD IIC_Seek(DWORD Handle, long lDistance, DWORD dwMoveMethod)
{
return 0;
}
/*******************************************************************************************
函数名称: IIC_PowerUp
描 述: 电源上电驱动处理函数
输入参数:
输出参数:
返 回: 无
*******************************************************************************************/
void IIC_PowerUp(void)
{
return 1;
}
/*******************************************************************************************
函数名称: IIC_PowerDown
描 述: 电源下电驱动处理函数
输入参数:
输出参数:
返 回: 无
*******************************************************************************************/
void IIC_PowerDown(void)
{
return 1;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -