camer IIC设置寄存器问题

kathyzju 2011-01-17 04:00:56
使用MT9V022CMOS成像,发现在IIC初始register的时候,BSP中初始程序为
#elif (CIS_TYPE == CIS_OV9650)
for(i=0; i<(sizeof(OV9650Reg)/2); i++)
{
if (OV9650Reg[i][0] == CHIP_DELAY) Delay(OV9650Reg[i][1]);
else HW_WriteRegisters(pCIS, &OV9650Reg[i][1], OV9650Reg[i][0], 1);
}
i = 0;
HW_ReadRegisters(pCIS, (PUCHAR)&i, 0xB, 1);
HW_ReadRegisters(pCIS, (PUCHAR)&i+1, 0xA, 1);
RETAILMSG(1,(TEXT("Camera::Product id is 0x%x\r\n"),i));
#endif
现在我想用MT9V022代替OV9650,MT9V022的寄存器的地址是8位,控制字是16位(OV9650的寄存器地址和控制字都是8位的),请问怎样修改驱动以适应这一变化。是不是修改HW_WriteReg的最后nReg(写寄存器字节数?),1变为2.还是要改IIC的驱动?
哪位做过相关的,帮帮忙吧!
...全文
310 24 打赏 收藏 转发到动态 举报
写回复
用AI写文章
24 条回复
切换为时间正序
请发表友善的回复…
发表回复
kathyzju 2011-01-20
  • 打赏
  • 举报
回复
pI2C->Mode == INTERRUPT? pI2C->Mode这个东西是在什么地方赋值的?
kathyzju 2011-01-20
  • 打赏
  • 举报
回复
只能等我们板子好了我还试一下了
kathyzju 2011-01-20
  • 打赏
  • 举报
回复
[Quote=引用 21 楼 disciplinantwk 的回复:]
看代码里面
======================================================================
case WRITE_DATA:
ASSERT(pI2C->Data);
if ( (pI2C->DataCount--) == 0 )
{
DEBUGMSG(ZONE_WRITE|ZONE_TRACE,(TEXT("W3[%d……
[/Quote]

你说的很有道理呢,我也仔细看了一下,应该是这么回事,那应该就等在WaitForSingleObject(pI2C->ISTEvent, INFINITE)这里了,不会再进行下一个8位数据的传送了呀?好奇怪
kathyzju 2011-01-19
  • 打赏
  • 举报
回复
case WRITE_DATA:
ASSERT(pI2C->Data);
if ( (pI2C->DataCount--) == 0 )//如果datacount=0,则data transmit结束
{
DEBUGMSG(ZONE_WRITE|ZONE_TRACE,(TEXT("W3[%d] \r\n"), pI2C->DataCount));
//RETAILMSG(1,(TEXT("W3[%d] \r\n"), pI2C->DataCount));

bDone = TRUE;

rIICSTAT = MTX_STOP; / 停止位
rIICCON = RESUME_ACK; // resume operation.

//The pending bit will not be set after issuing stop condition.
break;
}

if (pI2C->Flags.WordAddr) { //发送的data是否为register地址
rIICDS = pI2C->WordAddr; //写入地址
DEBUGMSG(ZONE_WRITE|ZONE_TRACE,(TEXT("W1[%d]: 0x%X \r\n"),
pI2C->DataCount, pI2C->WordAddr));
pI2C->Flags.WordAddr = FALSE;
} else {
DEBUGMSG(ZONE_WRITE|ZONE_TRACE,(TEXT("W2[%d]: 0x%X \r\n"),
pI2C->DataCount, *pI2C->Data));
rIICDS = (UCHAR)*pI2C->Data; //写入数据

pI2C->Data++; //数据地址增加
}

rIICCON = RESUME_ACK; // resume operation.
break;

现在我比较疑惑的是如果是16位的数据,应该是传送两次data才对,现在在程序中没看出来,不知道我的方法是否可行呢?但是如果这样不行,我觉得就没有必要设置pI2C->DataCount这个变量了。
大家探讨一下吧
kathyzju 2011-01-19
  • 打赏
  • 举报
回复
追踪了一下运行的过程:最终应该是在下面的函数里面写入的wordAddr&*Pdata
static DWORD
I2C_IST(
LPVOID Context
)
{
PI2C_CONTEXT pI2C = (PI2C_CONTEXT)Context;
DWORD i2cSt;
BOOL bDone = FALSE;
SetProcPermissions((DWORD)-1);
if ( !pI2C ) {
TEST_TRAP;
return ERROR_INVALID_PARAMETER;
}
do {

if (pI2C->Mode == INTERRUPT) {

DWORD we;

bDone = FALSE;

we = WaitForSingleObject(pI2C->ISTEvent, INFINITE);
// clear the interrupt here because we re-arm another below
InterruptDone(gIntrIIC);
// Ensure correct state initiated by Read/Write
//
switch(pI2C->State)
{
case OFF:
DEBUGMSG(ZONE_IST|ZONE_TRACE,(TEXT("I2C_IST: ExitThread \r\n")));
ExitThread(ERROR_SUCCESS);
break;

case IDLE:
DEBUGMSG(ZONE_IST|ZONE_TRACE,(TEXT("I2C_IST: IDLE \r\n")));
continue;
break;

default:
if (pI2C->State != WRITE_ACK &&
pI2C->State != RESUME &&
pI2C->DataCount == INVALID_DATA_COUNT) {
DEBUGMSG(ZONE_IST|ZONE_TRACE,(TEXT("I2C_IST: INVALID_DATA_COUNT\r\n")));
continue;
}
break;
}
}

i2cSt = rIICSTAT;

if (i2cSt & 0x8) {
DEBUGMSG(ZONE_ERR,(TEXT("I2C_IST[%u, %d]: bus arbitration failed \r\n"),
pI2C->State, pI2C->DataCount));
}

if (i2cSt & 0x4) {
DEBUGMSG(ZONE_ERR,(TEXT("I2C_IST[%u, %d]: slave address matches IICADD \r\n"),
pI2C->State, pI2C->DataCount));
}

if (i2cSt & 0x2) {
DEBUGMSG(ZONE_ERR,(TEXT("I2C_IST[%u, %d]: received slave address 0x0 \r\n"),
pI2C->State, pI2C->DataCount));
}

if (i2cSt & 0x1) {
DEBUGMSG(ZONE_READ|ZONE_WRITE,(TEXT("I2C_IST[%u, %d]: ACK NOT received \r\n"),
pI2C->State, pI2C->DataCount));
}

__try {

switch(pI2C->State)
{
case IDLE:
case SUSPEND:
continue;
break;

case RESUME:
DEBUGMSG(ZONE_WRN, (TEXT("I2C_IST: RESUME \r\n")));
// RETAILMSG(1, (TEXT("I2C_IST: RESUME \r\n")));
InitRegs(pI2C);
pI2C->LastError = ERROR_OPERATION_ABORTED;
SetEvent(pI2C->DoneEvent);
break;

case SET_READ_ADDR:
if ( (pI2C->DataCount--) == 0 )
{
DEBUGMSG(ZONE_READ|ZONE_TRACE, (TEXT("A2[%d] \r\n"),
pI2C->DataCount ));
// RETAILMSG(1, (TEXT("A2[%d] \r\n"),
// pI2C->DataCount ));
bDone = TRUE;
break;
}

DEBUGMSG(ZONE_READ|ZONE_TRACE, (TEXT("A1[%d]: 0x%X \r\n"),
pI2C->DataCount, pI2C->WordAddr));
// RETAILMSG(1, (TEXT("A1[%d]: 0x%X \r\n"),
// pI2C->DataCount, pI2C->WordAddr));
// write word address
// For setup time of SDA before SCL rising edge, rIICDS must be written
// before clearing the interrupt pending bit.
if (pI2C->Flags.WordAddr) {
rIICDS = pI2C->WordAddr;
// clear interrupt pending bit (resume)
rIICCON = RESUME_ACK;
pI2C->Flags.WordAddr = FALSE;
}
break;


case READ_DATA:
ASSERT(pI2C->Data);
if ( (pI2C->DataCount--) == 0 )
{
bDone = TRUE;

*pI2C->Data = (UCHAR)rIICDS;
#ifdef DEBUG
r = *pI2C->Data;

//RETAILMSG(1,(TEXT("R3_1:0x%X, pI2C->Data(0x%X) \r\n"), r, pI2C->Data));
//RETAILMSG(1,(_T("pI2C->Data(0x%X)\r\n"), pI2C->Data));
#endif
pI2C->Data++;

rIICSTAT = MRX_STOP;
rIICCON = RESUME_ACK; // resume operation.

//RETAILMSG(1,(_T("pI2C->Data(0x%X)\r\n"), pI2C->Data));
//RETAILMSG(1,(TEXT("R3_2:0x%X, pI2C->Data(0x%X) \r\n"), r, pI2C->Data));
//DEBUGMSG(ZONE_READ|ZONE_TRACE,(TEXT("R3:0x%X \r\n"), r));

//The pending bit will not be set after issuing stop condition.
break;
}

// Drop the returned Slave WordAddr?
if ( pI2C->Flags.DropRxAddr )
{
pI2C->RxRetAddr = (UCHAR)rIICDS;
pI2C->Flags.DropRxAddr = FALSE;
DEBUGMSG(ZONE_READ|ZONE_TRACE,(TEXT("Drop: 0x%X \r\n"),
pI2C->RxRetAddr));

} else {
*pI2C->Data = (UCHAR)rIICDS;
#ifdef DEBUG
r = *pI2C->Data;
#endif
pI2C->Data++;
}

//RETAILMSG(1,(TEXT("R3_3:0x%X, pI2C->Data(0x%X) \r\n"), r, pI2C->Data));

// The last data is read with no ack.
if ( pI2C->DataCount == 0 ) {
rIICCON = RESUME_NO_ACK; // resume operation with NOACK.
DEBUGMSG(ZONE_READ|ZONE_TRACE,(TEXT("R1:0x%X \r\n"), r));
} else {
rIICCON = RESUME_ACK; // resume operation with ACK
DEBUGMSG(ZONE_READ|ZONE_TRACE,(TEXT("R2:0x%X \r\n"), r));
}
break;


case WRITE_DATA:
ASSERT(pI2C->Data);
if ( (pI2C->DataCount--) == 0 )
{
DEBUGMSG(ZONE_WRITE|ZONE_TRACE,(TEXT("W3[%d] \r\n"), pI2C->DataCount));
//RETAILMSG(1,(TEXT("W3[%d] \r\n"), pI2C->DataCount));

bDone = TRUE;

rIICSTAT = MTX_STOP;
rIICCON = RESUME_ACK; // resume operation.

//The pending bit will not be set after issuing stop condition.
break;
}

if (pI2C->Flags.WordAddr) {
rIICDS = pI2C->WordAddr;
DEBUGMSG(ZONE_WRITE|ZONE_TRACE,(TEXT("W1[%d]: 0x%X \r\n"),
pI2C->DataCount, pI2C->WordAddr));
RETAILMSG(1, (TEXT("W1[%d]: 0x%X \r\n"), pI2C->DataCount, pI2C->WordAddr));//kathy 110118 debug
pI2C->Flags.WordAddr = FALSE;
} else {
DEBUGMSG(ZONE_WRITE|ZONE_TRACE,(TEXT("W2[%d]: 0x%X \r\n"),
pI2C->DataCount, *pI2C->Data));
RETAILMSG(1, (TEXT("W2[%d]: 0x%X \r\n"), pI2C->DataCount, *pI2C->Data));//kathy 110118 debug

rIICDS = (UCHAR)*pI2C->Data;

pI2C->Data++;
}

rIICCON = RESUME_ACK; // resume operation.
break;

case WRITE_ACK:
DEBUGMSG(ZONE_WRITE|ZONE_TRACE,(TEXT("WRITE_ACK \r\n") ));
//RETAILMSG(1,(TEXT("WRITE_ACK \r\n") ));
pI2C->Status = i2cSt;
bDone = TRUE;
break;


case IO_COMPLETE:
DEBUGMSG(ZONE_IST, (TEXT("IO_COMPLETE \r\n")));
bDone = TRUE;
break;


case IO_ABANDONED:
DEBUGMSG(ZONE_ERR|ZONE_WRN,(TEXT("IO_ABANDONED \r\n") ));
bDone = TRUE;
break;


default:
DEBUGMSG(ZONE_ERR,(TEXT("!!! I2C_IST ERROR: Invalid State: %u !!!\r\n"),
pI2C->State));
bDone = TRUE;
break;
}

} _except(EXCEPTION_EXECUTE_HANDLER) {

rIICSTAT = (pI2C->State == READ_DATA) ? MRX_STOP : MTX_STOP;
rIICCON = RESUME_ACK;

pI2C->DataCount = INVALID_DATA_COUNT;

pI2C->LastError = GetExceptionCode();
// RETAILMSG(1,(TEXT("!!! I2C_IST EXCEPTION: 0x%X !!!\r\n"), pI2C->LastError ));
}


if (bDone) {
DEBUGMSG(ZONE_IST, (TEXT("SetEvent DONE\r\n")));
SetEvent(pI2C->DoneEvent);
}

// LeaveCriticalSection(&pI2C->RegCS);

} while (pI2C->Mode == INTERRUPT);


//DEBUGMSG(ZONE_IST|ZONE_TRACE,(TEXT("-I2C_IST[%u] \r\n"), pI2C->Mode));

return ERROR_SUCCESS;
}
write的操作应该是在上述红色标注的地方
kathyzju 2011-01-19
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 disciplinantwk 的回复:]
HW_Write(
PI2C_CONTEXT pI2C,
DWORD SlaveAddr, // slave address
UCHAR WordAddr, // starting slave word address
PUCHAR pData, // pdata
DWORD Count // bytes to write
)

SlaveAddr……
[/Quote]
wordADDR是对应的寄存器地址
pData是写入数据的地址
count是wordaddr(1byte)+len(*pData)
如果我要写入的data是16位的,则count=3
那么如果我的数组初始化为:
struct MT9V022 MT9V022Array[3]=
{
{0x00,0x00,0x00},
{0x0f,0x00, 0x02},
{0x80,0x15, 0x00},
};
因为Pdata是个指针,所以pdata++应该就指向数组的第三个元素了。
我觉得只要对应的write函数里面写了相关的内容应该就可以操作了
disciplinantwk 2011-01-19
  • 打赏
  • 举报
回复
看代码里面
======================================================================
case WRITE_DATA:
ASSERT(pI2C->Data);
if ( (pI2C->DataCount--) == 0 )
{
DEBUGMSG(ZONE_WRITE|ZONE_TRACE,(TEXT("W3[%d] \r\n"), pI2C->DataCount));
//RETAILMSG(1,(TEXT("W3[%d] \r\n"), pI2C->DataCount));

bDone = TRUE;

rIICSTAT = MTX_STOP;
rIICCON = RESUME_ACK; // resume operation.

//The pending bit will not be set after issuing stop condition.
break;
}
======================================================================
pI2C->DataCount应该是起作用的吧。
DataCount值为0的时候bDone = TRUE,然后在do-while内部的后面SetEvent(pI2C->DoneEvent),应该是使得前面的we = WaitForSingleObject(pI2C->ISTEvent, INFINITE);得以继续运行吧,如果没错的话,这应该是完整写完一个寄存器的流程,我不明白的是当我们写完一个寄存器的偏移地址的时候应该bDone还是FALSE吧,那样就不能SetEvent(pI2C->DoneEvent),然后就卡在WaitForSingleObject(pI2C->ISTEvent, INFINITE);这里了吗?
loongembedded 2011-01-18
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 kathyzju 的回复:]
PUCHAR pBuff这个是个地址,因此我如果寄存器地址为0x80,data为0x1500,我就可以把数组定义为{0x80,0x15,0x00}来用IIC传输数据,不知道这种方法是否可行,有人知道吗????
[/Quote]
这样应该不可行。
loongembedded 2011-01-18
  • 打赏
  • 举报
回复
楼主可以采用这样的方式,举例如下
struct MT9V022
{
unsigned char addr;
USHORT data;
};

struct MT9V022 MT9V022Array[3]=
{
{0x00,0x0000},
{0x0f,0x0002},
{0x80,0x1500},
};
但可能涉及到修改到好一些函数的参数的定义等
kathyzju 2011-01-18
  • 打赏
  • 举报
回复
我们现在时间比较急,想直接在原来的程序上改了,不想用IO口模拟了,你们的控制字也是16的吗?我现在想不好怎么读写
disciplinantwk 2011-01-18
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 zhuevan 的回复:]
引用 13 楼 disciplinantwk 的回复:
HW_Write(
PI2C_CONTEXT pI2C,
DWORD SlaveAddr, // slave address
UCHAR WordAddr, // starting slave word address
PUCHAR pData, // pdata
DWORD Count // bytes to write
)
……
[/Quote]
WordAddr VS pData 搞不清楚。。。
zhuEvan 2011-01-18
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 disciplinantwk 的回复:]
HW_Write(
PI2C_CONTEXT pI2C,
DWORD SlaveAddr, // slave address
UCHAR WordAddr, // starting slave word address
PUCHAR pData, // pdata
DWORD Count // bytes to write
)

SlaveAddr……
[/Quote]
SlaveAddr:是指器件ID
WordAddr:指字节地址
disciplinantwk 2011-01-18
  • 打赏
  • 举报
回复
HW_Write(
PI2C_CONTEXT pI2C,
DWORD SlaveAddr, // slave address
UCHAR WordAddr, // starting slave word address
PUCHAR pData, // pdata
DWORD Count // bytes to write
)

SlaveAddr:设备地址
pData:指向要写入数据的指针
Count:写入的字节数
我不太明白WordAddr是作什么的,还请指点
disciplinantwk 2011-01-18
  • 打赏
  • 举报
回复
既然把数据信息给了“pI2C”
pI2C->State = WRITE_DATA;
pI2C->DataCount = 1 + Count; // slave word address + data
pI2C->WordAddr = WordAddr;
pI2C->Flags.WordAddr = TRUE;
pI2C->Data = pData;
pI2C里面应该有对应的写操作函数吧?
kathyzju 2011-01-18
  • 打赏
  • 举报
回复
HW_WriteRegisters函数很简单的,他会调用
DWORD
HW_Write(
PI2C_CONTEXT pI2C,
DWORD SlaveAddr, // slave address
UCHAR WordAddr, // starting slave word address
PUCHAR pData, // pdata
DWORD Count // bytes to write
)
{
DWORD dwErr;

if ( !VALID_CONTEXT(pI2C) )
return ERROR_INVALID_PARAMETER;

// DEBUGMSG(ZONE_WRITE|ZONE_TRACE,(TEXT("+I2C_Write[%u]: 0x%X, 0x%X, 0x%X, %u \r\n"),
// RETAILMSG(1,(TEXT("+I2C_Write[%u]: 0x%X, 0x%X, 0x%X, %u \r\n"),
// pI2C->State, SlaveAddr, WordAddr, *pData, Count));

if ( !pData || !Count || IsBadReadPtr(pData, Count) ) {
DEBUGMSG(ZONE_ERR,(TEXT("I2C_Write ERROR: invalid parameter \r\n")));
return ERROR_INVALID_PARAMETER;
}

EnterCriticalSection(&pI2C->RegCS);

if ( pI2C->State != IDLE) {
DEBUGMSG(ZONE_ERR,(TEXT("I2C_Write ERROR: i2cState: %u \r\n"), pI2C->State));
LeaveCriticalSection(&pI2C->RegCS);
return ERROR_BUSY;
}

pI2C->LastError = ERROR_SUCCESS;

ResetEvent(pI2C->DoneEvent);

rIICSTAT = M_ACTIVE;

// pre-setup write data
pI2C->State = WRITE_DATA;
pI2C->DataCount = 1 + Count; // slave word address + data
pI2C->WordAddr = WordAddr;
pI2C->Flags.WordAddr = TRUE;
pI2C->Data = pData;

// write slave address
rIICDS = (UCHAR)SlaveAddr;
rIICSTAT = MTX_START;

// IST writes the slave word address & data
if (WAIT_OBJECT_0 != SyncIst(pI2C, TX_TIMEOUT)) {

DEBUGMSG(ZONE_WRITE|ZONE_ERR,(TEXT("TX_TIMEOUT.1\r\n")));

goto _done;
}

// LJY, 20040724, commented out
#if 0
// get ACK
while(1)
{
pI2C->State = WRITE_ACK;
pI2C->Status = INVALID_IICSTAT;

rIICDS = (UCHAR)SlaveAddr;
rIICSTAT = MTX_START;
rIICCON = RESUME_ACK;

while ( pI2C->Status == INVALID_IICSTAT ) {
if (WAIT_OBJECT_0 != SyncIst(pI2C, TX_TIMEOUT)) {
DEBUGMSG(ZONE_WRITE|ZONE_ERR,(TEXT("TX_TIMEOUT.2\r\n")));
break;
}
}

// done when ACK received
if ( !(pI2C->Status & 0x1))
break;
}
#endif

_done:
rIICSTAT = MTX_STOP;
rIICCON = RESUME_ACK;

rIICSTAT = M_IDLE; // disable Rx/Tx
pI2C->State = IDLE;
pI2C->Data = NULL;
pI2C->DataCount = INVALID_DATA_COUNT;

dwErr = pI2C->LastError;

LeaveCriticalSection(&pI2C->RegCS);

DEBUGMSG(ZONE_WRITE|ZONE_TRACE,(TEXT("-I2C_Write: %u \r\n"), dwErr));

return dwErr;
}
kathyzju 2011-01-18
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 disciplinantwk 的回复:]
我做过IIC,不同设备的IIC是有些区别的:
1.有的可以一次性写任意个位置的寄存器;
2.有的是必须从某个固定的寄存器开始写,一直写到目的寄存器为止
感觉你的是第二种情况把?
[/Quote]
我这边是对CAMERA的寄存器配置时用IIC,应该是第一种情况
disciplinantwk 2011-01-18
  • 打赏
  • 举报
回复
把你的“HW_WriteRegisters”函数贴出来看看啊
disciplinantwk 2011-01-18
  • 打赏
  • 举报
回复
我做过IIC,不同设备的IIC是有些区别的:
1.有的可以一次性写任意个位置的寄存器;
2.有的是必须从某个固定的寄存器开始写,一直写到目的寄存器为止
感觉你的是第二种情况把?
kathyzju 2011-01-18
  • 打赏
  • 举报
回复
PUCHAR pBuff这个是个地址,因此我如果寄存器地址为0x80,data为0x1500,我就可以把数组定义为{0x80,0x15,0x00}来用IIC传输数据,不知道这种方法是否可行,有人知道吗????
kathyzju 2011-01-18
  • 打赏
  • 举报
回复
研究了一天,有了点收获
HW_WriteRegisters(
PCIS_CONTEXT pCIS,
PUCHAR pBuff, // Optional buffer
UCHAR StartReg, // start register
DWORD nRegs // number of registers
)
这个函数的最后一个值 nRegs ,如果是16位的是否应该为2???有人做过没,说说看呀!!!
加载更多回复(2)

19,502

社区成员

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

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