6410 iic 读写问题

ele01 2010-10-13 05:36:09
网上说6410的iic驱动有些问题,根据网上的资料修改了一下驱动后,用网上下载的一个exe测试程序随便读写都没有任何问题,网址如下:http://download.csdn.net/source/1488970
后来我自己研究下驱动后,根据自己的理解写了一个测试的代码,可以读写,但是读写的数据很不正常。代码如下:请做过的高手指点错误:


DWORD
HW_WriteRegisters(
PUCHAR pBuff, // Optional buffer
UCHAR StartRegs,
DWORD nRegs // number of registers
)
{
UCHAR tmpbuf[512];
DWORD dwErr=1;
DWORD bytes;
IIC_IO_DESC IIC_Data;

tmpbuf[0]=StartRegs;
memcpy(&tmpbuf[1],pBuff,nRegs);

IIC_Data.SlaveAddress = CAMERA_WRITE;
IIC_Data.Count = nRegs;
IIC_Data.Data = tmpbuf;

// use iocontrol to write
if ( !DeviceIoControl(hI2C,
IOCTL_IIC_WRITE,
&IIC_Data, sizeof(IIC_IO_DESC),
NULL, 0,
&bytes, NULL) )
{
dwErr = 0;
}


return dwErr;
}

DWORD
HW_ReadRegisters(
PUCHAR pBuff, // Optional buffer
UCHAR StartReg, // Start Register
DWORD nRegs // Number of Registers
)
{
DWORD dwErr=1;
DWORD bytes;
IIC_IO_DESC IIC_AddressData, IIC_Data;

IIC_AddressData.SlaveAddress = CAMERA_WRITE;
IIC_AddressData.Data = &StartReg;
IIC_AddressData.Count = 1;

IIC_Data.SlaveAddress = CAMERA_WRITE;
IIC_Data.Data = pBuff;
IIC_Data.Count = 1;

// use iocontrol to read
if ( !DeviceIoControl(hI2C,
IOCTL_IIC_READ,
&IIC_AddressData, sizeof(IIC_IO_DESC),
&IIC_Data, sizeof(IIC_IO_DESC),
&bytes, NULL) )
{
dwErr = 0;
}


return dwErr;
}

int _tmain(int argc, _TCHAR* argv[])
{
DWORD i;
UCHAR bufin[100];
UCHAR bufout[100];
DWORD nbyte=100;
DWORD bytes;
UCHAR StartAddr=0x2;
UINT32 IICClock = 412500;
UINT32 uiIICDelay;
for(i=0;i<100;i++)
bufin[i]=0;

bufin[0]=0x5;

hI2C = CreateFile( L"IIC0:",
GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, 0);
if ( INVALID_HANDLE_VALUE == hI2C )
{
MessageBox (0,TEXT("Open Error!"),NULL,MB_OK);
return FALSE;
}
else
{
MessageBox (0,TEXT("Open !"),NULL,MB_OK);
}

if ( !DeviceIoControl(hI2C,
IOCTL_IIC_SET_CLOCK,
&IICClock, sizeof(UINT32),
NULL, 0,
&bytes, NULL) )
{
RETAILMSG(1,(TEXT("IOCTL_IIC_SET_CLOCK ERROR: %u \r\n")));
return FALSE;
}
uiIICDelay = Clk_5;

if ( !DeviceIoControl(hI2C,
IOCTL_IIC_SET_DELAY,
&uiIICDelay, sizeof(UINT32),
NULL, 0,
&bytes, NULL) )
{
RETAILMSG(1,(TEXT("IOCTL_IIC_SET_DELAY ERROR: %u \r\n")));
return FALSE;
}


//HW_WriteRegisters(&bufin[0],0,1);
HW_ReadRegisters(bufout,StartAddr,1);
CloseHandle(hI2C);

return 0;
}


程序大部分是参考camera驱动里的。
...全文
1020 29 打赏 收藏 转发到动态 举报
写回复
用AI写文章
29 条回复
切换为时间正序
请发表友善的回复…
发表回复
tescaxl 2012-08-24
  • 打赏
  • 举报
回复
裸奔很简单的事,被Microsoft Windows一折腾,就把问题搞得巨复杂,唉。。。
电子青蛙 2011-08-25
  • 打赏
  • 举报
回复
[Quote=引用 23 楼 ele01 的回复:]
首先,引用7楼flandy1982兄的建议:


引用 7 楼 flandy1982 的回复:
IIC_IO_DESC IIC_Data;
IIC_Data.SlaveAddress = CAMERA_WRITE;
IIC_Data.Count = nRegs;
IIC_Data.Data = tmpbuf;

这个结构体里面的Data就是内嵌指针,有一种处理方法是在驱动里面分配……
[/Quote]
楼主您好 我的iic器件现在可以读出来 但是写入不进去 不知道你在驱动中写的那部分加了什么呢?可否交流一下,多谢
ele01 2010-10-14
  • 打赏
  • 举报
回复
你也可以试试我那个网上下的程序 看你能否写入成功
ele01 2010-10-14
  • 打赏
  • 举报
回复
楼上 把你写的代码贴下 我来测试下 我这边的情况是数据可以读出,但读出的不是写入的地址,所以也可以归类于写的问题
eason1119 2010-10-14
  • 打赏
  • 举报
回复
关注,我也在搞IIC的读写,也遇到了同样的问题,写IIC没问题,就是读的数据一直是错的。
ele01 2010-10-14
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 flandy1982 的回复:]
IIC_IO_DESC IIC_Data;
IIC_Data.SlaveAddress = CAMERA_WRITE;
IIC_Data.Count = nRegs;
IIC_Data.Data = tmpbuf;

这个结构体里面的Data就是内嵌指针,有一种处理方法是在驱动里面分配一段缓存,暂定名字为buf
对于写入数据,先把.Data的数据复制到buf里,然后把缓……
[/Quote]

分配了一个buf用来缓存pbufin的数据,结果还是一样。 下面贴2段打印信息:
读取一个字节,从地址2开始读取,这个是偶尔正确的时候打印的数据:

IIC InData:addr is 160 data is 2 //160是slaveaddr 0xa0 EEPROM的器件地址 2是读取的起始地址
IICSTAT:0xf0 IICCON:0xb9 IICDS:0xa0 IICADD:0xa0 IICLC : 0x5
[IIC TX THREAD]g_pIICReg->IICDS is 0x02 //2被写入IICDS中
IICSTAT:0xf0 IICCON:0xb9 IICDS:0x2 IICADD:0xa0 IICLC : 0x5
IIC Write Buf:addr is 160 data is 2 len is 1 g_sbIIC_Buffer is 02
IICSTAT:0xb0 IICCON:0xb9 IICDS:0xa1 IICADD:0xa0 IICLC : 0x5 //IICDS为0xa1读
IICSTAT:0xb1 IICCON:0x39 IICDS:0xe3 IICADD:0xa0 IICLC : 0x5 //IICDS为读到的数据
I2C_IST[0xd6dda2e0, 1]: ACK NOT received
IIC OutData:addr is 160 data is 227

这个是错误数据:

IIC InData:addr is 160 data is 2
IICSTAT:0xf0 IICCON:0xb9 IICDS:0xa0 IICADD:0xa0 IICLC : 0x5
[IIC TX THREAD]g_pIICReg->IICDS is 0x04 //在这里 传入IICDS的数据不是0x2而变成了0x4
IICSTAT:0xf0 IICCON:0xb9 IICDS:0x4 IICADD:0xa0 IICLC : 0x5
IIC Write Buf:addr is 160 data is 2 len is 1 g_pcIIC_Buffer is 02
IICSTAT:0xb0 IICCON:0xb9 IICDS:0xa1 IICADD:0xa0 IICLC : 0x5
IICSTAT:0xb1 IICCON:0x39 IICDS:0x30 IICADD:0xa0 IICLC : 0x5
I2C_IST[0xd6dd9ce0, 1]: ACK NOT received
IIC OutData:addr is 160 data is 48

而用那个网上下的测试程序 每次都能读对,所以我怀疑不是驱动的问题 而是应用的问题。

FLandY1982 能把你的测试代码贴一下吗?
FLandY1982 2010-10-14
  • 打赏
  • 举报
回复
中文版本的在这里:
http://www.armce.com/bbs/viewthread.php?tid=1210
FLandY1982 2010-10-14
  • 打赏
  • 举报
回复
IIC_IO_DESC IIC_Data;
IIC_Data.SlaveAddress = CAMERA_WRITE;
IIC_Data.Count = nRegs;
IIC_Data.Data = tmpbuf;

这个结构体里面的Data就是内嵌指针,有一种处理方法是在驱动里面分配一段缓存,暂定名字为buf
对于写入数据,先把.Data的数据复制到buf里,然后把缓存的指针传给HW_Write;对于读取数据将数据使用HW_Read读取到buf里,然后memcpy到.Data里传给应用。这种处理方法的缺点就是必须预先知道IIC传输数据的总长度。
另外一种处理方式我研究过,但是没有具体使用,只能给篇文章给你参考了:
http://blogs.msdn.com/b/ce_base/archive/2006/11/09/memory-marshalling-in-windows-ce.aspx
ele01 2010-10-14
  • 打赏
  • 举报
回复
出现这个问题是 读完最后一个字节后,因为NO ACK而进入了IST,所以应该算是正常的情况。但是Write写完就不会有这个出现。以后有时间再仔细研究下驱动和IIC,现在能够用就ok了。
ele01 2010-10-14
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 flandy1982 的回复:]
楼主贴下IOCtrl的驱动代码,我之前也碰到过这种问题。主要是因为wince6.0对内嵌指针的操作有了限制。
[/Quote]

代码如下:
BOOL
IIC_IOControl(PHW_OPEN_INFO pOpenContext,
DWORD dwCode, PBYTE pBufIn,
DWORD dwLenIn, PBYTE pBufOut, DWORD dwLenOut,
PDWORD pdwActualOut)
{
BOOL RetVal = TRUE; // Initialize to success
PHW_INIT_INFO pInitContext;

if (pOpenContext==NULL) {
SetLastError (ERROR_INVALID_HANDLE);
return(FALSE);
}
pInitContext = pOpenContext->pInitContext;
if ( pInitContext == NULL )
{
SetLastError (ERROR_INVALID_HANDLE);
return(FALSE);
}

DEBUGMSG (ZONE_FUNCTION,
(TEXT("+IIC_IOControl(0x%X, %d, 0x%X, %d, 0x%X, %d, 0x%X)\r\n"),
pOpenContext, dwCode, pBufIn, dwLenIn, pBufOut,
dwLenOut, pdwActualOut));

if ( !pInitContext->OpenCnt ) {
DEBUGMSG (ZONE_ERROR,
(TEXT(" IIC_IOControl - device was closed\r\n")));
SetLastError (ERROR_INVALID_HANDLE);
return(FALSE);
}

switch ( dwCode ) {
case IOCTL_POWER_CAPABILITIES:
{
if ( !pdwActualOut || !pBufOut || (dwLenOut < sizeof(POWER_CAPABILITIES)) )
{
RetVal = FALSE;
SetLastError (ERROR_INVALID_PARAMETER);
break;
}

memcpy(pBufOut, &g_PowerCaps, sizeof(POWER_CAPABILITIES));

*pdwActualOut = sizeof(POWER_CAPABILITIES);
}
break;
case IOCTL_POWER_QUERY:
break;
case IOCTL_POWER_SET:
break;
case IOCTL_IIC_WRITE:
if ( (dwLenIn < sizeof(IIC_IO_DESC)) || (NULL == pBufIn) ) {
SetLastError (ERROR_INVALID_PARAMETER);
RetVal = FALSE;
DEBUGMSG (ZONE_ERROR, (TEXT(" Invalid parameter\r\n")));
break;
}

EnterCriticalSection(&(pInitContext->CritSec));
if((HW_Write(pOpenContext,(PIIC_IO_DESC)pBufIn))==NULL)
{
SetLastError(ERROR_TIMEOUT);
RetVal = FALSE;
}
LeaveCriticalSection(&(pInitContext->CritSec));
break;

case IOCTL_IIC_READ:
if ( (dwLenIn < sizeof(IIC_IO_DESC)) || (NULL == pBufIn) || (dwLenOut < sizeof(IIC_IO_DESC)) || (NULL == pBufOut) ) {
SetLastError (ERROR_INVALID_PARAMETER);
RetVal = FALSE;
DEBUGMSG (ZONE_ERROR, (TEXT(" Invalid parameter\r\n")));
break;
}
EnterCriticalSection(&(pInitContext->CritSec));
if(HW_Read(pOpenContext, (PIIC_IO_DESC)pBufIn, (PIIC_IO_DESC)pBufOut))
{
// success
*pdwActualOut = sizeof(IIC_IO_DESC);
}
else
{
SetLastError(ERROR_TIMEOUT);
*pdwActualOut = 0;
RetVal = FALSE;
}
LeaveCriticalSection(&(pInitContext->CritSec));

break;

case IOCTL_IIC_SET_CLOCK:
if ( (dwLenIn < sizeof(UINT32)) || (NULL == pBufIn) ) {
SetLastError (ERROR_INVALID_PARAMETER);
RetVal = FALSE;
DEBUGMSG (ZONE_ERROR, (TEXT(" Invalid parameter\r\n")));
break;
}
EnterCriticalSection(&(pInitContext->CritSec));
pOpenContext->PDDContextVal.Clock = *(UINT32*)pBufIn;
HW_SetClock(pOpenContext);
pOpenContext->DirtyBit = TRUE;
LeaveCriticalSection(&(pInitContext->CritSec));
break;

case IOCTL_IIC_GET_CLOCK:
if ( (dwLenOut < sizeof(UINT32)) || (NULL == pBufOut) ||
(NULL == pdwActualOut) ) {
SetLastError (ERROR_INVALID_PARAMETER);
RetVal = FALSE;
DEBUGMSG (ZONE_ERROR, (TEXT(" Invalid parameter\r\n")));
break;
}

*(UINT32*)pBufIn = pOpenContext->PDDContextVal.Clock;
// Return the size
*pdwActualOut = sizeof(UINT32);
break;

case IOCTL_IIC_SET_MODE:
if ( (dwLenIn < sizeof(UINT32)) || (NULL == pBufIn) ) {
SetLastError (ERROR_INVALID_PARAMETER);
RetVal = FALSE;
DEBUGMSG (ZONE_ERROR, (TEXT(" Invalid parameter\r\n")));
break;
}
pOpenContext->PDDContextVal.ModeSel = (IIC_MODE)*(UINT32*)pBufIn;
pOpenContext->DirtyBit = TRUE;
break;

case IOCTL_IIC_GET_MODE:
if ( (dwLenOut < sizeof(UINT32)) || (NULL == pBufOut) ||
(NULL == pdwActualOut) ) {
SetLastError (ERROR_INVALID_PARAMETER);
RetVal = FALSE;
DEBUGMSG (ZONE_ERROR, (TEXT(" Invalid parameter\r\n")));
break;
}

*(UINT32*)pBufIn = pOpenContext->PDDContextVal.ModeSel;
// Return the size
*pdwActualOut = sizeof(UINT32);
break;

case IOCTL_IIC_SET_FILTER:
...
case IOCTL_IIC_GET_FILTER:
...
case IOCTL_IIC_SET_DELAY:
if ( (dwLenIn < sizeof(UINT32)) || (NULL == pBufIn) ) {
SetLastError (ERROR_INVALID_PARAMETER);
RetVal = FALSE;
DEBUGMSG (ZONE_ERROR, (TEXT(" Invalid parameter\r\n")));
break;
}
pOpenContext->PDDContextVal.Delay = (IIC_DELAY)*(UINT32*)pBufIn;
pOpenContext->DirtyBit = TRUE;
break;

case IOCTL_IIC_GET_DELAY:
if ( (dwLenOut < sizeof(UINT32)) || (NULL == pBufOut) ||
(NULL == pdwActualOut) ) {
SetLastError (ERROR_INVALID_PARAMETER);
RetVal = FALSE;
DEBUGMSG (ZONE_ERROR, (TEXT(" Invalid parameter\r\n")));
break;
}

*(UINT32*)pBufIn = pOpenContext->PDDContextVal.Delay;
// Return the size
*pdwActualOut = sizeof(UINT32);
break;
}

return(RetVal);
}


好像听说过内嵌指针的问题,不知道FLandY1982兄是怎么处理的?
ele01 2010-10-14
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 loongembedded 的回复:]
我看了_tmain函数中用DeviceIoControl函数两次,分别传递的控制码是IOCTL_IIC_SET_CLOCK和IOCTL_IIC_SET_DELAY,你这样做的目的是修改IIC接口的时钟和delay time吗?这两个时间不是IIC驱动中自己设置好了吗?你这样修改不知是否有副作用。
[/Quote]

这里是驱动中默认的
#define DEFAULT_DELAY Clk_15
#define DEFAULT_CLOCK 3000
先就是用默认的,结果正确率更低。后来我在驱动中打印IIC各个寄存器的值,对比那个网上下的测试程序的IIC控制器的值,改成了现在这个样,发现偶尔会正确。这个问题不知道是否是时钟的问题。

FLandY1982 2010-10-14
  • 打赏
  • 举报
回复
楼主贴下IOCtrl的驱动代码,我之前也碰到过这种问题。主要是因为wince6.0对内嵌指针的操作有了限制。
loongembedded 2010-10-14
  • 打赏
  • 举报
回复
我看了_tmain函数中用DeviceIoControl函数两次,分别传递的控制码是IOCTL_IIC_SET_CLOCK和IOCTL_IIC_SET_DELAY,你这样做的目的是修改IIC接口的时钟和delay time吗?这两个时间不是IIC驱动中自己设置好了吗?你这样修改不知是否有副作用。
myearth 2010-10-14
  • 打赏
  • 举报
回复
非常感谢,我测试后发现
ACK NOT received

不知道楼主有没有
ele01 2010-10-14
  • 打赏
  • 举报
回复
我刚来这里混,以前注册这个只是为了下载东西,所以分不多 请见谅!
ele01 2010-10-14
  • 打赏
  • 举报
回复
首先,引用7楼flandy1982兄的建议:

[Quote=引用 7 楼 flandy1982 的回复:]
IIC_IO_DESC IIC_Data;
IIC_Data.SlaveAddress = CAMERA_WRITE;
IIC_Data.Count = nRegs;
IIC_Data.Data = tmpbuf;

这个结构体里面的Data就是内嵌指针,有一种处理方法是在驱动里面分配一段缓存,暂定名字为buf
对于写入数据,先把.Data的数据复制到buf里,然后把缓……
[/Quote]

起先我说我试过拷贝到了一个buf里,结果还是一样,是因为我先认为读出来的地址错误的原因是写入的问题,所以我把buf加在了 case IOCTL_IIC_WRITE: 下面 然后再测试,结果一样。

后来又折腾了半天,因为一直是拿HW_ReadRegisters这个函数测试的,应该改的地方是
case IOCTL_IIC_READ: 里面 具体修改的结果如下:

UCHAR tmpbuf[10];
IIC_IO_DESC tmpin;

case IOCTL_IIC_READ:
if ( (dwLenIn < sizeof(IIC_IO_DESC)) || (NULL == pBufIn) || (dwLenOut < sizeof(IIC_IO_DESC)) || (NULL == pBufOut) ) {
SetLastError (ERROR_INVALID_PARAMETER);
RetVal = FALSE;
DEBUGMSG (ZONE_ERROR, (TEXT(" Invalid parameter\r\n")));
break;
}
memset(tmpbuf,0,((PIIC_IO_DESC)pBufIn)->Count);
memcpy(tmpbuf,((PIIC_IO_DESC)pBufIn)->Data,((PIIC_IO_DESC)pBufIn)->Count);
tmpin.Count = ((PIIC_IO_DESC)pBufIn)->Count;
tmpin.SlaveAddress = ((PIIC_IO_DESC)pBufIn)->SlaveAddress;
tmpin.Data = tmpbuf;
EnterCriticalSection(&(pInitContext->CritSec));
if(HW_Read(pOpenContext, &tmpin, (PIIC_IO_DESC)pBufOut))
{
// success
*pdwActualOut = sizeof(IIC_IO_DESC);
}
else
{
SetLastError(ERROR_TIMEOUT);
*pdwActualOut = 0;
RetVal = FALSE;
}
LeaveCriticalSection(&(pInitContext->CritSec));

break;


这样 传入HW_READ里的就是缓存的buf了,测试结果正常。应用程序中我把时钟设为了2500,delay设置成15个clock,然后连续调用几次HW_ReadRegisters 都没问题。

6410IIC驱动按照http://blog.csdn.net/knock/archive/2009/11/04/4766991.aspx 这个人的blog里修改就可以改好。

问题是解决了,但是还有几个疑问和几点不足:
疑问:
1.在没有修改驱动之前,使用在网上下载的那个6410 iic测试程序来读写24C02完全正常,不管怎么读都行,但我自己的程序就不行,由于找不到他的源码,所以这个问题也无法得知原因。我也对windows系统编程不太熟悉。
不足:
1.由于无法确定传进来的数据大小,所以要定义一个足够大的buf,我这里用的是100,如果有超过100的数据传进来就要出BUG了,定义大了又占资源,所以这里要根据个人来设置。由于我是用来取电池电量,所以100远远足够了。
2.后来我测试写100个数据,果然dataabort了。然后又试了写50个,这次写成功了,但是读出来相应地址的数据不对,可能是没有写进去。写50个是调用一次HW_WriteRegisters传入参数50.如果这样写:
for(i=0;i<50;i++)
HW_WriteRegisters(&bufin[i],i,1); 即调用50次HW_WriteRegisters
则写入正确。可能问题是出在时序的上面吧(应该是应答的问题)。而读调用一次HW_ReadRegisters 读n个都没有问题。
eason1119 2010-10-14
  • 打赏
  • 举报
回复
[Quote=引用 20 楼 ele01 的回复:]
我已解决了 等下来结贴。读已正常
FLandY1982兄说的没有错 内嵌指针的问题。

IIC InData:addr is 160 data is 3
IICSTAT:0xf0 IICCON:0xf2 IICDS:0xa0 IICADD:0xa0 IICLC : 0x7
[IIC TX THREAD]g_pIICReg->IICDS is 0x03
IICSTAT:0xf0 IICC……
[/Quote]

怎么解决的啊,能贴出来看看吗 谢谢了
myearth 2010-10-14
  • 打赏
  • 举报
回复
能否把结果贴出来,省得每个人都研究一遍,谢谢
ele01 2010-10-14
  • 打赏
  • 举报
回复
我已解决了 等下来结贴。读已正常
FLandY1982兄说的没有错 内嵌指针的问题。

IIC InData:addr is 160 data is 3
IICSTAT:0xf0 IICCON:0xf2 IICDS:0xa0 IICADD:0xa0 IICLC : 0x7
[IIC TX THREAD]g_pIICReg->IICDS is 0x03
IICSTAT:0xf0 IICCON:0xf2 IICDS:0x3 IICADD:0xa0 IICLC : 0x7
IIC Write Buf:addr is 160 data is 3 len is 1 g_sbIIC_Buffer is 03
IICSTAT:0xb0 IICCON:0xf2 IICDS:0xa1 IICADD:0xa0 IICLC : 0x7
IICSTAT:0xb1 IICCON:0x72 IICDS:0xef IICADD:0xa0 IICLC : 0x7
I2C_IST[0xd6dde220, 1]: ACK NOT received
IIC OutData:addr is 161 data is 239
eason1119 2010-10-14
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 myearth 的回复:]
引用 1 楼 haiou_arm 的回复:
楼主:读写的数据怎么不正常,能说明白点吗?
用6410的IIC写过CH7004(VGA)的控制命令,挺正常,没发现问题啊。但当时确实是不知道什么原因,把一块板子的IIC的接口给烧掉了。

haiou_arm,你好;能否把你的IIC驱动发给我,myearth@21cn.com
我测试一下啊
谢谢!
[/Quote]

我也想看看,能发个吗 907486257@qq.com
加载更多回复(8)

19,502

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 嵌入开发(WinCE)
社区管理员
  • 嵌入开发(WinCE)社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧