再來,AD71471 在做讀寫時,Register address 與 data 都是 2 bytes,而 i2ctools 裡,處理 Register address 都只傳 1 byte(I2C_SMBUS),因此不適用在 AD71471 上。我把 Linux kernel i2c-core.c 裡的 code 翻出來改寫,改用 I2C_RDWR 來處理:
bool Write( uint16_t address, uint16_t value ) {
int res=0;
struct i2c_rdwr_ioctl_data msg_rdwr;
char msgbuf0[I2C_SMBUS_BLOCK_MAX+4];
char msgbuf1[I2C_SMBUS_BLOCK_MAX+2];
struct i2c_msg msg[1] = { { _address, 0, 4, msgbuf0 } };
uint8_t* pAddr = (uint8_t*)&address;
uint8_t* pValue = (uint8_t*)&value;
msg_rdwr.msgs = &msg[0];
msg_rdwr.nmsgs = 1; // write // read = 2
// 因為 little endian,所以要作調整
msgbuf0[0] = *(pAddr+1);
msgbuf0[1] = *(pAddr+0);
msgbuf0[2] = *(pValue+1); // (1)
msgbuf0[3] = *(pValue+0);
res = ioctl( _file, I2C_RDWR, &msg_rdwr );
usleep(10000);
return true;
}
bool Read( uint16_t address, uint16_t& data ) {
int res=0;
struct i2c_rdwr_ioctl_data msg_rdwr;
char msgbuf0[I2C_SMBUS_BLOCK_MAX+2];
char msgbuf1[I2C_SMBUS_BLOCK_MAX+2]={0};
struct i2c_msg msg[2] = { { _address, 0, 2, msgbuf0 },
{ _address, I2C_M_RD, 2, msgbuf1 }
};
uint8_t* pAddr = (uint8_t*)&address;
msg_rdwr.msgs = &msg[0];
msg_rdwr.nmsgs = 1; // read = 2
// 因為 little endian,所以要作調整
msgbuf0[0] = *(pAddr+1);
msgbuf0[1] = *(pAddr+0);
res = ioctl( _file, I2C_RDWR, &msg_rdwr );
usleep(10000);
msg_rdwr.msgs = &msg[1];
msg_rdwr.nmsgs = 1; // read = 2
res = ioctl( _file, I2C_RDWR, &msg_rdwr ); #ifdef DEBUG
data = msgbuf1[0] | (msgbuf1[1] << 8);
return true;
}
int main( int argc, char* argv[] )
{
int data=0;
Read( 0x17, data );
printf("data=%d\n", data );
// 這邊其實不好,實際上寫 0x0052會比較清楚,這邊必須寫 0x5200,因為我在 Write() 裡有作對調,參看(1)
Write( 0x00, 0x5200 );
}
沒有留言:
張貼留言