优龙S3C44B0X 的IIC驱动问题
具体代码如下:
有时候读写的时候,特别是写EEPROM的时候出现死机,即 while(_iicDataCount!=-1);在这一句处循环,无法退出。
但是又不确定,有时候又是好的,请问不知道哪里错了,望高手不吝赐教!!
谢谢!
========================
========================
void Iic_initial(void)
{
pISR_IIC = (UINT32) IicInt; /* EEPROM 中断入口 */
// enable IRQ IIC
rINTMSK &= (~BIT_IIC) ;
// initialize IIC module
rPCONF |= 0xa; //PF0:IICSCL, PF1:IICSDA
rPUPF |= 0x3; //pull-up disable
//Enable ACK generation, IICCLK=MCLK/16, Enable interrupt,IIC-Bus transmit clock prescaler (15+1)
//66000000hz/16/(15+1) = 257Khz (257812.5)
rIICCON = (1<<7) | (0<<6)| (1<<5) | (0xf);
rIICADD = 0x10; // S3C44B0X slave address
rIICSTAT = 0x10; // 1=Enable Rx/Tx
}
void Wr24C040(UINT32 slvAddr,UINT32 addr,UINT8 data)
{
_iicMode=WRITE_DATA;
_iicPt=0;
_iicData[0]=(UINT8)addr;
_iicData[1]=data;
_iicDataCount=2;
rIICDS=slvAddr;//0xa0
rIICSTAT=0xf0; //MasTx,Start
//Clearing the pending bit isn't needed because the pending bit has been cleared.
while(_iicDataCount!=-1);
_iicMode=POLLACK;
while(1)
{
rIICDS=slvAddr;
_iicStatus=0x100;
rIICSTAT=0xf0; //MasTx,Start
rIICCON=0xaf; //resumes IIC operation.
while(_iicStatus == 0x100)
{
;
}
if(!(_iicStatus & 0x1))
break; // when ACK is received
}
rIICSTAT=0xd0; //stop MasTx condition
rIICCON=0xaf; //resumes IIC operation.
Delay(1); //wait until stop condtion is in effect.
//write is completed.
}
SINT32 Rd24C040(UINT32 slvAddr,UINT32 addr,UINT8 *data)
{
UINT32 timeout;
_iicMode=SETRDADDR;
_iicPt=0;
_iicData[0]=(UINT8)addr;
_iicDataCount=1;
rIICDS=slvAddr;
rIICSTAT=0xf0; //MasTx,Start
//Clearing the pending bit isn't needed because the pending bit has been cleared.
timeout = 0xffff ;
while(_iicDataCount!=-1)
{
if (timeout-- == 0)
{
return -1 ;
}
}
_iicMode=READ_DATA;
_iicPt=0;
_iicDataCount=1;
rIICDS=slvAddr;
rIICSTAT=0xb0; //MasRx,Start
rIICCON=0xaf; //resumes IIC operation.
timeout = 0xffff ;
while(_iicDataCount!=-1)
{
if (timeout-- == 0)
{
return -1 ;
}
}
*data=_iicData[1];
return 0 ;
}
void __irq IicInt(void)
{
UINT32 iicSt,i;
rI_ISPC=BIT_IIC;
iicSt=rIICSTAT;
if(iicSt&0x8){} // when bus arbitration is failed.
if(iicSt&0x4){} // when a slave address is matched with IICADD
if(iicSt&0x2){} // when a slave address is 0000000b
if(iicSt&0x1){} // when ACK isn't received
switch(_iicMode)
{
case POLLACK:
_iicStatus=iicSt;
break;
case READ_DATA:
if((_iicDataCount--)==0)
{
_iicData[_iicPt++]=rIICDS;
rIICSTAT=0x90; //stop MasRx condition --> IIC-bus STOP signal generation
rIICCON=0xaf; //resumes IIC operation. --> Clear pending condition
Delay(1); //wait until stop condtion is in effect.
//too long time...
//The pending bit will not be set after issuing stop condition.
break;
}
_iicData[_iicPt++]=rIICDS;
//The last data has to be read with no ack.
if((_iicDataCount)==0)
{
rIICCON=0x2f; //resumes IIC operation with NOACK.
}
else
{
rIICCON=0xaf; //resumes IIC operation with ACK
}
break;
case WRITE_DATA:
if((_iicDataCount--)==0)
{
rIICSTAT=0xd0; //stop MasTx condition --> IIC-bus STOP signal generation
rIICCON=0xaf; //resumes IIC operation. --> Clear pending condition
Delay(1); //wait until stop condtion is in effect.
//The pending bit will not be set after issuing stop condition.
break;
}
rIICDS=_iicData[_iicPt++]; //_iicData[0] has dummy.
for(i=0;i<10;i++); //for setup time until rising edge of IICSCL
rIICCON=0xaf; //resumes IIC operation.
break;
case SETRDADDR:
//printf("[S%d]",_iicDataCount);
if((_iicDataCount--)==0)
{
break; //IIC operation is stopped because of IICCON[4]
}
rIICDS=_iicData[_iicPt++];
for(i=0;i<10;i++); //for setup time until rising edge of IICSCL
rIICCON=0xaf; //resumes IIC operation.
break;
default:
break;
}
}