I2C driver of LISxDx sensor

8 posts / 0 new
最后一篇
Horace Hsieh.
离线
最后一次露面:2年7个月前
加入:2016-05-05 16:34
I2C driver of LISxDx sensor

亲爱的对话支持团队,

最近,我们在DA14580平台上移植LIS2DS / LIS3DH驱动程序,但在I2C操作中陷入困境。

LISx sensor has different read sequence from other reference i2c sensor (like mc3410)/i2c eeprom.

Here is the sequence of reading one byte from slave
---------------
掌握|st |悲伤+ w |... ... |次... ... |SR |悲伤+ r |... ... |...... ...... | NMAK | SP
奴隶|... ... |...... ...... |萨克|... ... |萨克|... ... |...... ...... |萨克|数据| .... ... | ...

ST:启动条件
SR:重复开始条件
SP:停止条件
SAK:奴隶承认
SUB: Slave Sub-Address, register address in LISxDx
SAD: Slave Address, 0x3a, 0011 1010
SAD + W:从地址+ W,0x3A,0011 1010
SAD + R:从地址+ R,0x3B,0011 1011
NMAK:没有主人承认
----
我的问题是如何实现SR +(SAD + R),我试图使用
//发送重复的SR和SED SAD + R
SetWord16(I2C_TAR_REG, ((i2c_dev_address + 1) & IC_TAR)|SPECIAL|GC_OR_START);
如下:

void i2c_master_init(uint16_t dev_address, uint8_t speed, uint8_t address_mode, uint8_t address_size)
{
mem_address_size = 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);//从站被禁用
setBits16(i2c_con_reg,i2c_speed,speed);//设置速度
setbits16(i2c_con_reg,i2c_10bitaddr_master,address_mode);//设置寻址模式
setword16(i2c_tar_reg,(dev_address&ic_tar));//设置从设备地址
SetWord16(I2C_ENABLE_REG, 0x1); // Enable the I2C controller
while( (GetWord16(I2C_STATUS_REG) & 0x20) != 0 ); // Wait for I2C master FSM to be IDLE
i2c_dev_address = dev_address;
}
UINT8_T I2C_READ_BYTE(UINT32_T地址)
{
send_i2c_command(地址&0xff);//设置地址LSB,写访问
//发送重复的SR和SED SAD + R
SetWord16(I2C_TAR_REG, ((i2c_dev_address + 1) & IC_TAR)|SPECIAL|GC_OR_START);

WAIT_WHILE_I2C_FIFO_IS_FULL(); // Wait if Tx FIFO is full
send_i2c_command(0x0100);// Set R/W bit to 1 (read access)
WAIT_UNTIL_I2C_FIFO_IS_EMPTY(); // Wait until I2C Tx FIFO empty
WAIT_FOR_RECEIVED_BYTE(); // Wait for received data
返回(0xff&getword16(i2c_data_cmd_reg));//获得收到的字节
}
However, it doesn't work, and the program is blocked at "WAIT_FOR_RECEIVED_BYTE()".
I also reviewed the previous discussions about i2c operations, but it seems there is nobody to talk about the repeated SR.

Please help on this topic, thank you in advance!

Device:
mt_dialog.
离线
最后一次露面:2个月4天前
职员
加入:2015-06-08 11:34
Hi Horace,

Hi Horace,

您不必默认的任何内容,以便在580的I2C模块上发出重新启动条件。当从读成写命令或相对(写入读取命令)时,I2C模块将发出重启命令(启动命令)。请检查附件,是580与I2C EEPROM闪光的交互。

谢谢mt_dialog.

附件:
Horace Hsieh.
离线
最后一次露面:2年7个月前
加入:2016-05-05 16:34
亲爱的,

亲爱的,

非常感谢回复。

>>当从读取写入命令或相对时,I2C模块将发出重启命令(启动命令)(写入读取命令

好的,所以我只是改变了如下所示的代码:
- //发送重复的启动条件和设置从设备地址
- // setword16(i2c_tar_reg,((i2c_dev_address + 1)和ic_tar)|特殊| gc_or_start);
+ // Set Slave device address
+ SetWord16(I2C_TAR_REG, ((i2c_dev_address + 1) & IC_TAR));

But it still gets dead-loop in
WAIT_FOR_RECEIVED_BYTE(); // Wait for received data

The sequence that required by sensor is a little different from the picture that you attached,
安装后,只有1个数据在LISXDX传感器中写入CMD,而不是EEPROM闪存中的2。

I have no idea why the following code doesn't work :(
......
SetWord16(I2C_TAR_REG, (i2c_dev_address & IC_TAR)); // Set Slave device address
SetWord16(I2C_ENABLE_REG, 0x1); // Enable the I2C controller
while( (GetWord16(I2C_STATUS_REG) & 0x20) != 0 ); // Wait for I2C master FSM to be IDLE
SEND_I2C_COMMAND(register & 0xFF); // Set address LSB, write access
// Set SAD + R
SetWord16(I2C_TAR_REG, ((i2c_dev_address + 1) & IC_TAR));

WAIT_WHILE_I2C_FIFO_IS_FULL(); // Wait if Tx FIFO is full
send_i2c_command(0x0100);// Set R/W bit to 1 (read access)
WAIT_UNTIL_I2C_FIFO_IS_EMPTY(); // Wait until I2C Tx FIFO empty
WAIT_FOR_RECEIVED_BYTE(); // Wait for received data

请帮助指出问题的位置,再次感谢!

mt_dialog.
离线
最后一次露面:2个月4天前
职员
加入:2015-06-08 11:34
Hi Horace,

Hi Horace,

为了产生上面的序列,我使用了以下代码:

i2c_eeprom_init(i2c_slave_address,i2c_speed_mode,i2c_address_mode,i2c_address_size);//初始化I2C,在I2C地址大小中放置设备的地址大小
SEND_I2C_COMMAND(0x03 & 0xFF); // the address size that device has is two bytes length, if your device takes one byte length you can use this instruction to read from 0x03 address or whatever address you need.
WAIT_WHILE_I2C_FIFO_IS_FULL(); // Wait if Tx FIFO is full
send_i2c_command(0x0100);// Set read access for times

上面的片段产生下面附上的波形,当然当然从内存响应的数据是错误的,但我想这就是你要找的东西。

谢谢mt_dialog.

附件:
Horace Hsieh.
离线
最后一次露面:2年7个月前
加入:2016-05-05 16:34
亲爱的,

亲爱的,

Thank you very much for kind help.
但是,该案例比您写的方案更复杂

In your case, the slave address is kept at 0x50 unchanged.
但作为所附规范,LIS传感器具有以下要求。
1)
与LIS2DS12相关联的从地址(SAD)是XX位的00111xxb
由SA0 / SDO引脚修改,以修改设备地址。
If the SA0/SDO pin is connected to the supply voltage, the address is 0011101b
2)
从地址以读/写位完成。如果该位是'1'(读取),则重复
START (SR) condition must be issued after the two sub-address bytes. If the bit is ‘0’ (Write)
主人将以方向向奴隶与方向不变

Therefore, SAD + R = 0x3b, while SAD + W = 0x3a (if SA0 is connected to VCC)
这意味着我必须在i2c_tar_reg中的值进行两次更改值以在表20中生成序列(请检查附件或我的第一个注释)

I tried several combinations, but all attempts failed, like:

i2c_eeprom_init(0x3A, I2C_FAST, I2C_7BIT_ADDR, I2C_1BYTE_ADDR); //initialize the i2c, SAD + W, FAST_MODE, 7BIT, 1BYTE
SEND_I2C_COMMAND(0x0F); // WHO_AM_I_REG address -- 0xF
WAIT_WHILE_I2C_FIFO_IS_FULL(); // Wait if Tx FIFO is full

1)SetWord16(I2C_TAR_REG, (0x3A + 1)); // Repeat SR + (SAD + R)
2)setword16(i2c_enable_reg,0);
SetWord16(I2c_TAR_REG, (0x3A + 1)); // Repeat SR + (SAD + R)
setword16(i2c_enable_reg,1);

WAIT_WHILE_I2C_FIFO_IS_FULL(); // Wait if Tx FIFO is full
send_i2c_command(0x0100);
......

有什么建议么?

mt_dialog.
离线
最后一次露面:2个月4天前
职员
加入:2015-06-08 11:34
Hi Horace,

Hi Horace,

我不看到任何不同的特定sensor, as far as i can understand, the one pin that defines the address of the sensor should be connected either to vcc or gnd in order to define the sensors 7bit address 0x1D or 0x1E, this is what you should set in the I2C_TAR_REG, after that you dont have to change the value of the I2C_TAR_REG when you want to perform a read or a write operation, the I2C module will add a "0" or a "1" automatically, just like the captures i ve sent you. In the captures i ve attached the instrument decodes the address and the read and write operation, if you check the clocks and the pulses on SDA and SCL you will see that the write is Write [0x50] is an 8-bit sequence of 0x50 plus an extra 0 to declare write (if you read it as an 8-bit number this results in 0xA0) and in the read operation Read [0x50] is an 8-bit sequence of 0x50 plus an extra 1 to declare read (if you read it as am 8-bit number this wil result to a 0xA1). Please try using as a target addres NOT 0x3A but 0x1D which is the actual address of your device, the additional bit will be placed (either a "1" or a "0") when you perform a read or write, and that is done via the I2C_DATA_CMD_REG. If you write to the I2C_DATA_CMD_REG the value of the sub-address of the slave (write only the 0:7 bits of the register) the module will send out the address of the device followed by the Write command (hence 1D(11101) + 0 -> 0x3A) followed by the data that you ve written in the I2C_DATA_CMD_REG. After that when you want to read, by writting the value 0x100 the module will understand that you want to perform a read (since you have set the 9th bit of thei2c_data_cmd_reg.)并且将提供它想要读取的设备的地址,然后是读取命令(因此1d(11101)+1-> 0x3b)和scl行上的时钟,以便从先前写入的地址从从器件时钟数据在公共汽车上,只要在总线上没有停止条件并且您将I2C_DATA_CMD_REG与0x100保持馈送,模块将继续提供时钟(而不会使从地址暴露从地址)。

谢谢mt_dialog.

Horace Hsieh.
离线
最后一次露面:2年7个月前
加入:2016-05-05 16:34
嗨MT,

嗨MT,

虽然它仍然不起作用,但仍然感谢您的耐心和善良的指导。
I guess the remaining issue might be related to timing, and will capture the signals of SDA & SCL later.

Horace Hsieh.
离线
最后一次露面:2年7个月前
加入:2016-05-05 16:34
嗨MT,

嗨MT,

司机现在运作,在硬件家伙用新的电路板上替换后。
Please close the ticket, thank you again for saving our hours!

主题锁定