I2C device with 2 byte response

⚠️
嗨,...感谢您来论坛。令人兴奋的消息!我们现在正在迁至我们的新论坛平台,将提供更好的功能,并包含在主对话框网站中。所有帖子和帐户都已迁移。我们现在只接受新论坛上的流量 - 请发布任何新线程https://www.dialog-seminile.com/support.。我们将在未来几天修复错误/优化搜索和标记。
9 posts / 0 new
最后一篇
Boydy1989
离线
最后一次露面:1 year 9 months ago
加入:2017-10-18 16:11
I2C device with 2 byte response

Hello

I am trying to interface to an I2C sensor device (https://docs-emea.rs-online.com/webdocs/142c/0900766b8142cdd9.pdf

I have already successfully used the I2C device on the 14586 with another different sensor.

This new sensor when sent a PROM or ADC read request replies with 2 or 3 bytes of data.

I have based the code on the I2C EEPROM example, and cannot get the system to read more than 1 byte from the reply.

The test code is below. I am setting a break point and looking at 'byte1' and 'byte2' in the debugger watch window. Only byte1 is populated with any data.
I have tried a few different approaches, but am stuck. I can see on my ocilloscope that the device is replying with 2 bytes of data, so I am happy that the basic communications are working OK.

Any input greatly appreciated!

代码:

// Critical section
global_int_disable();

i2c_send_address(address);

SEND_I2C_COMMAND(0x0100); // Set R/W bit to 1 (read access)
// End of critical section
GLOBAL_INT_RESTORE();
uint16_t byte1 = 0;
uint16_t byte2 = 0;

WAIT_FOR_RECEIVED_BYTE(); // Wait for received data

byte1 = (GetWord16(I2C_DATA_CMD_REG) & 0xFF); // Get first received byte
byte2 = (GetWord16(I2C_DATA_CMD_REG) & 0xFF); // The problem seems to be around here...

WAIT_UNTIL_NO_MASTER_ACTIVITY ();// wait until no master activity

return I2C_NO_ERROR;

Device:
mt_dialog.
离线
最后一次露面:3 months 2 days ago
职员
加入:2015-06-08 11:34
你好Boydy1989,

你好Boydy1989,

You invoke the SEND_I2C_COMMAND(0x100) only one time, that means that the I2C module of the 58x will access to bus only for one read, so you actually read only once, you dont provide clock for the second data that you expect to get, and the slave needs the clock from the master in order to send the data out. For instance lets take as an example the read_data_single() function in the peripheral examples in the SDK that reads 32bytes of data at a time, so the function will send the address of the device that would like to communicate and the read indication, and then it will start filling the Tx FIFO with read commands 0x100 (the 0x100 is a dummy command that will just generate the clocks on the bus), as many read commands as the bytes the device would like to read (32 bytes which is also the FIFO), then all of the 32 bytes can be read from the receive FIFO.

Thanks MT_dialog

Boydy1989
离线
最后一次露面:1 year 9 months ago
加入:2017-10-18 16:11
Hello

Hello

Thank you for the reply.

I am struggling a little more now though, any call to SEND_I2C_COMMAND only causes the device to send the I2C Device address (with an ACK received).

I cannot send any data out.

Code snippet:
send_i2c_command(0x1e);

Logic output attached on PDF.

我相信我错过了一些简单的东西,所有人都有助于极大地赞赏。

附件:
mt_dialog.
离线
最后一次露面:3 months 2 days ago
职员
加入:2015-06-08 11:34
你好Boydy1989,

你好Boydy1989,

那么,你已经使用的目标的地址是0xee?如果您在设备发出之前发送字节,则停止条件,I2C模块将继续发送其要与其通信的设备的地址。在代码段上,您只提供send_i2c_command(0x1e),如果您已正确初始化I2C模块,并且您只需使用send_i2c_command(0x1e)才能通过公共汽车发出字节字节(0x1e),我无法求出任何结论。然后,只要外部设备ACK的数据发送到58倍,就应该能够在总线上看到字节。如果您不想在I2C中使用SDK中的驱动程序,则可以将它们用作创建自己的驱动程序的引用。

Thanks MT_dialog

Boydy1989
离线
最后一次露面:1 year 9 months ago
加入:2017-10-18 16:11
你好

你好

I have based my code on the driver in the SDK.

Init code: (copied from the SDK)

void i2c_init(uint16_t dev_address, uint8_t speed, uint8_t address_mode, uint8_t address_size)
{
setbits16(clk_per_reg,i2c_enable,1);//为i2c启用时钟
setword16(i2c_enable_reg,0x0);//禁用I2C控制器
SetWord16(I2C_CON_REG, I2C_MASTER_MODE | I2C_SLAVE_DISABLE | I2C_RESTART_EN); // Slave is disabled
setBits16(i2c_con_reg,i2c_speed,speed);//设置速度
#ifdef I2C_SS_FREQ_TRIM
setword16(i2c_ss_scl_hcnt_reg,i2c_ss_scl_hcnt_val);//设置标准速度的SCL时钟高周期计数
SetWord16(I2C_SS_SCL_LCNT_REG, I2C_SS_SCL_LCNT_VAL); // Set the SCL clock low-period count for standard speed
#endif // I2C_SS_FREQ_TRIM
#ifdef i2c_fs_freq_trim.
SetWord16(I2C_FS_SCL_HCNT_REG, I2C_FS_SCL_HCNT_VAL); // Set the SCL clock high-period count for fast speed
SetWord16(I2C_FS_SCL_LCNT_REG, I2C_FS_SCL_LCNT_VAL); // Set the SCL clock low-period count for fast speed
#endif // I2C_HS_FREQ_TRIM
setbits16(i2c_con_reg,i2c_10bitaddr_master,address_mode);//设置寻址模式
setword16(i2c_tar_reg,dev_address&0x3ff);//设置从设备地址
SetWord16(I2C_ENABLE_REG, 0x1); // Enable the I2C controller
WAIT_UNTIL_NO_MASTER_ACTIVITY ();//等待i2c主fsm变得空闲
i2c_dev_address = dev_address;
WAIT_UNTIL_NO_MASTER_ACTIVITY ();/ /等待master activity
}

I have used the correct address for the device, as if I change the address I no longer see the Ack on my logic analyser.

我在做错了吗?我希望只需调用send_i2c_command(),并查看Start,地址,字节,停止在总线上。我得到的只是开始,地址,停止。

我已经顺序放置了几个send_i2c_command(),但仍未看任何数据。

Is there a way of confirming receipt of the Ack by the 586? Or, is there something that would be preventing it receiving the Ack?

Thanks again!

mt_dialog.
离线
最后一次露面:3 months 2 days ago
职员
加入:2015-06-08 11:34
你好Boydy1989,

你好Boydy1989,

如果主(585)不会从th ACKe slave device in every attempt that you do to write something on the bus the master module will keep on sending the address and wait for an ACK, every SEND_I2C_COMMAND() will result the defined target address in an attempt of the master to communicate with the slave. If the master doesn't get an ACK from the slave then you wont see the bytes that you have instructed the device to send. If you dont get an ACK then something is wrong with the slave device attached. Regarding the checking if the ACK from the external device has been received, there is a function in the i2c_eeprom.c called i2c_wait_until_eeprom_ready(), the function will send out a dummy byte 0x08 and check if the ABRT_7B_ADDR_NOACK bit of the I2C_TX_ABRT_SOURCE_REG if there is no ACK from the slave that bit will be set to 1, that means that the device hasn't acked the address.

Thanks MT_dialog

Boydy1989
离线
最后一次露面:1 year 9 months ago
加入:2017-10-18 16:11
Hello

Hello

I have made some more progress now, and am receiving the data correctly. Thank you for your help.

For completeness, and in the hope that it will help someone else in the future I will post my code extract here with an explanation - I found that the documentation for the I2C controller for this microprocessor was not very clear, however I think I am now understanding it.

The below code will transmit the following sequence on the I2C bus:
addr_wr |reg_addr |addr_re |CLK |CLK.

我不得不替换wait_for_received_byte()宏(getword16(i2c_rxflr_reg)!= 2);

I found that trying to read the data from the FIFO immediately resulted in one of the bytes being lost. Maybe this is pipeline related, I'm not sure.

我发现添加一个wait_for_received_byte();在send_i2c_command(0x0100)之间;调用为I2C控制器产生足够的等待时间,以在总线上生成停止条件。

另一个观察结果是,当端口配置为I2C时,在14586内部存在相当强的拉起/高状态驱动器 - 我使用的设备为其“低”状态具有相当薄弱的驱动力为了将外部拉动电阻值增加到大约47K,只是为了让设备将总线拉低,以便它的ACK。我注意到,即使没有拉出电阻,也没有被配置为没有上拉的端口,在未驱动时仍然在总线上存在高状态。这与我以前使用的其他MICRO,这与I2C的开放收集器驱动器不同。Some clarification would be appreciated from Dialog as to the structure of the I2C hardware.

Thank you again for the help, and I hope this information helps someone else using the DA14585 or DA14586 devices with an I2C device!

I2C_ERROR_CODE I2C_READ_INT16(UINT32_T地址,UINT16_T * DATA)
{
uint8_t byte1 = 0;
uint8_t byte2 = 0;
// Critical section
global_int_disable();

i2c_send_address(address);

SEND_I2C_COMMAND(0x0100); // Set R/W bit to 1 (read access)
SEND_I2C_COMMAND(0x0100); // Set R/W bit to 1 (read access)
而(getword16(i2c_rxflr_reg)!= 2);//等待收到的数据

byte1 = 0xFF & GetWord16(I2C_DATA_CMD_REG); // Get received byte
byte2 = 0xff&getword16(i2c_data_cmd_reg);//获得收到的字节

GLOBAL_INT_RESTORE();
WAIT_UNTIL_I2C_FIFO_IS_EMPTY(); // Wait until Tx FIFO is empty
WAIT_UNTIL_NO_MASTER_ACTIVITY ();// wait until no master activity
*data = ((byte2 << 8) | byte1);
return I2C_NO_ERROR;
}

mt_dialog.
离线
最后一次露面:3 months 2 days ago
职员
加入:2015-06-08 11:34
你好Boydy1989,

你好Boydy1989,

The driver used for the eeprom is quite complete and tested, so one should be based on the structure of that driver and use it as a reference, regarding your observations.

  • I dont see a reason for changing if the WAIT_FOR_RECEIVED_BYTE, the macro is used in order to halt the code and wait for the device to receive data from the FIFO.
  • 从FIFO读取莫迪亚特利,有丢失的字节,不会响铃。
  • 关于停止条件,一旦FIFO为空,设备将自动发出停止条件,所以为了不看到停止条件,您将不得不保持FIFO完整,这就是驱动程序在批量中执行读取的原因32个字节(在第80页的第80页中的数据表中指示了14.2.1的启动和停止生成,允许发送FIFO为空,导致I2C控制器在I2C总线上生成停止条件)。
  • 关于您的最后一个观察,您是对的,如果您已将引脚配置为I2C的功能,则即使您不知道配置它们也将自动激活内部拉动UPS(这是从第21页的数据表中指示,I2C总线接口映射的PX引脚自动配置拉压电阻(25kΩ),以寄存器PX_PADPWR_CTRL_REG配置的电源)。

Thanks MT_dialog

Boydy1989
离线
最后一次露面:1 year 9 months ago
加入:2017-10-18 16:11
谢谢您的支持,

谢谢您的支持,all comments taken on board!