int chdrv_read_byte(ch_dev_t *dev_ptr, uint16_t mem_addr, uint8_t *data) {
return (chbsp_i2c_mem_read(dev_ptr, mem_addr, data, 1));
}
int chbsp_i2c_mem_read(ch_dev_t *dev_ptr, uint16_t u16_mem_addr, uint8_t *pu8_data, uint16_t u16_num_bytes)
{
int i32_error = 1; // default is error return
uint8_t u8_i2c_addr = ch_get_i2c_address(dev_ptr);
i32_error = i2c_master_read_register(u8_i2c_addr, u16_mem_addr, u16_num_bytes, pu8_data);
return i32_error;
}
uint64_t i2c_master_read_register(uint8_t u8_Address, uint8_t u8_RegisterAddr, uint16_t u16_RegisterLen, uint8_t *pu8_RegisterValue)
{
return !(u16_RegisterLen == I2C_ReadMultiBytesOneReg(I2C0, u8_Address, u8_RegisterAddr, pu8_RegisterValue, u16_RegisterLen));
}
uint32_t I2C_ReadMultiBytesOneReg(I2C_T *i2c, uint8_t u8SlaveAddr, uint8_t u8DataAddr, uint8_t au8Rdata[], uint32_t u32rLen)
{
uint8_t u8Xfering = 1u, u8Err = 0u, u8Ctrl = 0u;
uint32_t u32rxLen = 0u;
I2C_START(i2c); /* Send START */
while (u8Xfering && (u8Err == 0u))
{
I2C_WAIT_READY(i2c) {}
switch (I2C_GET_STATUS(i2c))
{
case 0x08u:
I2C_SET_DATA(i2c, (uint8_t)(u8SlaveAddr << 1u | 0x00u)); /* Write SLA+W to Register I2CDAT */
u8Ctrl = I2C_CTL_SI; /* Clear SI */
break;
case 0x18u: /* Slave Address ACK */
I2C_SET_DATA(i2c, u8DataAddr); /* Write Lo byte address of register */
break;
case 0x20u: /* Slave Address NACK */
case 0x30u: /* Master transmit data NACK */
u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
u8Err = 1u;
break;
case 0x28u:
u8Ctrl = I2C_CTL_STA_SI; /* Send repeat START */
break;
case 0x10u:
I2C_SET_DATA(i2c, (uint8_t)((u8SlaveAddr << 1u) | 0x01u)); /* Write SLA+R to Register I2CDAT */
u8Ctrl = I2C_CTL_SI; /* Clear SI */
break;
case 0x40u: /* Slave Address ACK */
u8Ctrl = I2C_CTL_SI_AA; /* Clear SI and set ACK */
break;
case 0x48u: /* Slave Address NACK */
u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
u8Err = 1u;
break;
case 0x50u:
au8Rdata[u32rxLen++] = (uint8_t) I2C_GET_DATA(i2c); /* Receive Data */
if (u32rxLen < (u32rLen - 1u))
{
u8Ctrl = I2C_CTL_SI_AA; /* Clear SI and set ACK */
}
else
{
u8Ctrl = I2C_CTL_SI; /* Clear SI */
}
break;
case 0x58u:
au8Rdata[u32rxLen++] = (uint8_t) I2C_GET_DATA(i2c); /* Receive Data */
u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
u8Xfering = 0u;
break;
case 0x38u: /* Arbitration Lost */
default: /* Unknow status */
u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
u8Err = 1u;
break;
}
I2C_SET_CONTROL_REG(i2c, u8Ctrl); /* Write controlbit to I2C_CTL register */
}
return u32rxLen; /* Return bytes length that have been received */
}
以上代码来自于新唐m263的例子,功能是从I2C设备读取内部寄存器一个字节。
ret_val = chdrv_write_byte(dev_ptr, 0x07, 2);
int chdrv_write_byte(ch_dev_t *dev_ptr, uint16_t mem_addr, uint8_t data_value) {
uint8_t message[] = { sizeof(data_value), data_value }; // insert byte count (1) at start of data
int ch_err = chbsp_i2c_mem_write(dev_ptr, mem_addr, message, sizeof(message));
return ch_err;
}
int chbsp_i2c_mem_write(ch_dev_t *dev_ptr, uint16_t mem_addr, uint8_t *pu8_data, uint16_t u16_num_bytes)
{
int i32_error = 0;
i32_error = i2c_master_write_register(dev_ptr->i2c_address, mem_addr, u16_num_bytes, pu8_data);
return i32_error;
}
uint64_t i2c_master_write_register(uint8_t u8_Address, uint8_t u8_RegisterAddr, uint16_t u16_RegisterLen, uint8_t *pu8_RegisterValue)
{
return !(u16_RegisterLen == I2C_WriteMultiBytesOneReg(I2C0, u8_Address, u8_RegisterAddr, pu8_RegisterValue, u16_RegisterLen));
}
uint32_t I2C_WriteMultiBytesOneReg(I2C_T *i2c, uint8_t u8SlaveAddr, uint8_t u8DataAddr, uint8_t au8Data[], uint32_t u32wLen)
{
uint8_t u8Xfering = 1u, u8Err = 0u, u8Ctrl = 0u;
uint32_t u32txLen = 0u;
I2C_START(i2c); /* Send START */
while (u8Xfering && (u8Err == 0u))
{
I2C_WAIT_READY(i2c) {}
switch (I2C_GET_STATUS(i2c))
{
case 0x08u:
I2C_SET_DATA(i2c, (uint8_t)(u8SlaveAddr << 1u | 0x00u)); /* Write SLA+W to Register I2CDAT */
u8Ctrl = I2C_CTL_SI;
break;
case 0x18u: /* Slave Address ACK */
I2C_SET_DATA(i2c, u8DataAddr); /* Write Lo byte address of register */
break;
case 0x20u: /* Slave Address NACK */
case 0x30u: /* Master transmit data NACK */
u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
u8Err = 1u;
break;
case 0x28u:
if (u32txLen < u32wLen)
{
I2C_SET_DATA(i2c, au8Data[u32txLen++]);
}
else
{
u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
u8Xfering = 0u;
}
break;
case 0x38u: /* Arbitration Lost */
default: /* Unknow status */
u8Ctrl = I2C_CTL_STO_SI; /* Clear SI and send STOP */
u8Err = 1u;
break;
}
I2C_SET_CONTROL_REG(i2c, u8Ctrl); /* Write controlbit to I2C_CTL register */
}
return u32txLen; /* Return bytes length that have been transmitted */
}
以上代码来自于新唐m263的例子,功能是从I2C设备写入内部寄存器2个字节。感觉好绕,最后底层的I2C代码我已看不出时序,现在用arduino来取代,代码如下:
int chbsp_i2c_mem_write(ch_dev_t *dev_ptr, uint16_t mem_addr, uint8_t *data, uint16_t num_bytes){
TwoWire* pWire;
pWire=chbsp_i2c_get_device(dev_ptr);
if (pWire != NULL) {
pWire->beginTransmission(dev_ptr->i2c_address);
pWire->write(lowByte(mem_addr)); // LSB
pWire->write(data,num_bytes);
info = pWire->endTransmission();
}
}
int chbsp_i2c_mem_read(ch_dev_t *dev_ptr, uint16_t mem_addr, uint8_t *data, uint16_t num_bytes){
TwoWire* pWire = NULL;
int retval = 0;
pWire=chbsp_i2c_get_device(dev_ptr);
if (pWire != NULL) {
pWire->beginTransmission(dev_ptr->i2c_address);
pWire->write(lowByte(mem_addr));
pWire->endTransmission();
int receivedBytes = pWire->requestFrom((int)dev_ptr->i2c_address,(int)num_bytes,1);
if(receivedBytes != num_bytes)
{
Serial.printf("did not receive enough bytes %dmem %dnum %drec %d\n.",mem_addr,num_bytes,receivedBytes,dev_ptr->i2c_address);
retval = 1;
}else{
for(int i = 0; i < num_bytes; i++)
{
data[i] = pWire->read(); // receive a byte as character
}
}
}else{
retval = 1;
}
return retval;
}
但是我的arduino代码执行不正确,写入收到NACK,读出返回0字节,新唐的底层I2C实在看不懂,有大侠帮看看问题出在哪里,谢谢! |
|