阅读:1868回复:8
pxa270 I2C驱动奇怪问题
硬件:
PXA270,ATmega8 软件: WINCE5.0 系统构成: PXA270上的I2C做主,ATmega8的做从。 在PB5.0中做了个I2C的驱动,驱动能够正常加载。 在DWORD IIC_Init( PVOID Context )中映射I2C控制器的地址后,调用probe函数探测I2C从设备,能够正确探测到ATmega8(probe的工作就是向指定的从设备发送一帧命令,然后读取从设备的回应)。 之后用EVC写个测试程序对I2C进行读写测试,均都失败,于是将probe函数放到 DWORD IIC_Write( DWORD dwContext, LPVOID pBuf, DWORD count ) 中,在EVC写的测试程序中对I2C进行写操作,probe在这里就不正确了,发送第一个字节时调试信息显示:BUS ERROR,即I2C的sda线上没有检测到ACK,拿示波器看了下波形,的确不对。 现在的问题是,为什么probe在 IIC_Init 可以,在IIC_Write却出错? I2C控制器地址映射代码如下: #define PAGE_SIZE 0x1000 ptr = VirtualAlloc(0,PAGE_SIZE,MEM_RESERVE,PAGE_NOACCESS); if (ptr == NULL) { printf("VirtualAlloc failed! size=0x%x, (0x%x)\n",size,GetLastError()); return(FALSE); } //i2c printf("I2C VirtualAddress = 0x%x\n",I2C_BASE_U_VIRTUAL); if ( !VirtualCopy( (PVOID)ptr, (PVOID)(I2C_BASE_U_VIRTUAL+0x1000), PAGE_SIZE, PAGE_READWRITE | PAGE_NOCACHE ) ) { printf("VirtualCopy failed!: \n"); return(FALSE); } pI2C_v = ptr + 0x680 ; |
|
沙发#
发布于:2007-12-26 12:57
望高人指点下~~~~~
|
|
板凳#
发布于:2007-12-26 15:47
I2C_BASE_U_VIRTUAL,改用物理地址看看
最好的做法是做成驱动,用readfile或writefile,iocontrol来弄,简单 |
|
地板#
发布于:2007-12-26 16:27
IIC_init操作之后,总线是否已被释放?我没有用过probe,能否将其原理贴出来看看?
|
|
地下室#
发布于:2007-12-26 17:23
最终的目的就是做成驱动,在应用程序中调用writefile出错:ISR寄存器的值在发送从机地址后始终为0X442。这才在驱动里写个probe看看问题在那里。
probe的流程: 向从机发送:0X03,0X00,0X03 读取从机回复,若从机回应为:0x03,0x01,0x04表示探测到从机,总线也正常 代码如下: int write_iic_bus(P_XLLP_I2C_T I2C_regs,unsigned char data,unsigned char ByteType) { int timeout; U32 isr; // 1 Load target slave address and R/nW bit in the IDBR. R/nW must be 0 for a write. I2C_regs->IDBR=data; printf("data = 0x%x\n",data); // 2.Initiate the write. Set ICR[START], clear ICR[STOP], clear ICR[ALDIE], set ICR[TB] if(FRISTBYTE == ByteType){ I2C_regs->ICR |= ICR_START; I2C_regs->ICR &= (~ICR_STOP); }else if (MIDBYTE == ByteType){ I2C_regs->ICR &= (~ICR_START); I2C_regs->ICR &= (~ICR_STOP); }else if(LASTBYTE == ByteType){ I2C_regs->ICR &= (~ICR_START); I2C_regs->ICR |= (ICR_STOP); } //printf("ICR= 0x%x\n",I2C_regs->ICR); I2C_regs->ICR |= ICR_TB; /* 3.When an IDBR Transmit Empty interrupt occurs. //printf("TB is set:ICR= 0x%x\n",I2C_regs->ICR); timeout=0; do{ isr = I2C_regs->ISR; printf("ISR = 0x%x \t timeout = %d\n",isr,timeout); if(isr&ISR_BED) { printf("bus error-no ack\n"); I2C_regs->ICR &= (~ICR_TB); return -1; } if(isr&ISR_ITE) { I2C_regs->ISR |= ISR_ITE; I2C_regs->ICR &= (~ICR_TB); return 1; } timeout++; if(I2C_TIMEOUT < timeout) { printf("time out\n"); I2C_regs->ICR &= (~ICR_TB); return -1; } //usWait(25); }while( 1 ); return 1; } probe代码片段: if( write_iic_bus(I2C_regs,(I2C_SLAVE_DEVICE_ADDR<<1)&0xfe,FRISTBYTE) < 0) { i2c_reset(I2C_regs); i2c_pxa_data.reset_mcu(); } //printf("probe_buf[0]\n"); for(i=0;i < 3-1 ; i++) { if( write_iic_bus(I2C_regs,probe_buf,MIDBYTE) < 0) { i2c_reset(I2C_regs); i2c_pxa_data.reset_mcu(); } //printf("probe_buf\n"); } //printf("probe_buf[2]\n"); if( write_iic_bus(I2C_regs,probe_buf[2],LASTBYTE) < 0) { i2c_reset(I2C_regs); i2c_pxa_data.reset_mcu(); } //read response memset(read_buff,0,256); if( !i2c_read_nByte(pHWhead,read_buff,3) ) { for(i=0;i<3;i++) printf("0x%x ",read_buff); } |
|
5楼#
发布于:2007-12-27 10:15
write_iic_bus函数没有完全按照SPEC上的流程来写,我没有验证过你这样写是否可以,不过我想应该完全按照SPEC来写吧,有两点:一是在送FIRSTBYTE,以及MIDBYTE和LASTBYTE的时候,你没有SET或者CLEAR寄存器ICR-> ALDIE,还有就是在发送从机地址以后没有执行 ”Write 0b1to the ISR[ALD] bit if set.“。还有就是i2c_read_nByte这个函数始终都工作正常吗,读和写道理应该是一样的啊。。。
|
|
6楼#
发布于:2007-12-27 11:43
我再查下流程
奇怪的就是在两个位置分别调用probe,结果却不同 |
|
7楼#
发布于:2007-12-29 15:10
流程没问题的。
不知道驱动里面XXX_Init与XXX_Write的环境有什么区别,是否有其他的因素影响, |
|
8楼#
发布于:2008-01-04 17:29
总算查出问题了,单片机被其它驱动复位了,一直处于复位状态
|
|