亲爱的对话支持团队,
最近,我们在DA14580平台上移植LIS2DS / LIS3DH驱动程序,但在I2C操作中陷入困境。
LISX传感器具有来自其他参考I2C传感器的不同读取序列(如MC3410)/ I2C EEPROM。
这是从奴隶读取一个字节的序列
--------------
掌握|st |悲伤+ w |... ... |次... ... |SR |悲伤+ r |... ... |...... ...... | NMAK | SP
奴隶|... ... |...... ...... |萨克|... ... |萨克|... ... |...... ...... |萨克|数据| .... ... | ...
ST:启动条件
SR:重复开始条件
SP:停止条件
SAK:奴隶承认
子:从属子地址,LISXDX中的寄存器地址
SAD:从地址,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)|特殊| gc_or_start);
如下:
void i2c_master_init(uint16_t dev_address,uint8_t速度,uint8_t地址_mode,uint8_t地址_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);//启用I2C控制器
而((getword16(i2c_status_reg)&0x20)!= 0);//等待I2C主FSM闲置
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)|特殊| gc_or_start);
等待_while_i2c_fifo_is_full();//等待TX FIFO已满
send_i2c_command(0x0100);//将R / W位设置为1(读取访问)
wait_until_i2c_fifo_is_empty();//等到I2C TX FIFO空
wait_for_received_byte();//等待收到的数据
返回(0xff&getword16(i2c_data_cmd_reg));//获得收到的字节
}
但是,它不起作用,并且程序在“wait_for_received_byte()”中被阻止。
我还审查了关于I2C操作的以前的讨论,但似乎没有人可以谈论重复的SR。
请帮助提前谢谢您!
嗨霍勒斯,
您不必默认的任何内容,以便在580的I2C模块上发出重新启动条件。当从读成写命令或相对(写入读取命令)时,I2C模块将发出重启命令(启动命令)。请检查附件,是580与I2C EEPROM闪光的交互。
谢谢mt_dialog.
亲爱的,
非常感谢回复。
>>当从读取写入命令或相对时,I2C模块将发出重启命令(启动命令)(写入读取命令
好的,所以我只是改变了如下所示的代码:
- //发送重复的启动条件和设置从设备地址
- // setword16(i2c_tar_reg,((i2c_dev_address + 1)和ic_tar)|特殊| gc_or_start);
+ //设置从设备地址
+ setword16(i2c_tar_reg,((i2c_dev_address + 1)和ic_tar));
但它仍然变得止血
wait_for_received_byte();//等待收到的数据
传感器所需的序列与附带的图片有点不同,
安装后,只有1个数据在LISXDX传感器中写入CMD,而不是EEPROM闪存中的2。
我不知道为什么以下代码不起作用:(
......
setword16(i2c_tar_reg,(i2c_dev_address和ic_tar));//设置从设备地址
setword16(i2c_enable_reg,0x1);//启用I2C控制器
而((getword16(i2c_status_reg)&0x20)!= 0);//等待I2C主FSM闲置
send_i2c_command(register&0xff);//设置地址LSB,写访问
//设置悲伤+ r
setword16(i2c_tar_reg,((i2c_dev_address + 1)和ic_tar));
等待_while_i2c_fifo_is_full();//等待TX FIFO已满
send_i2c_command(0x0100);//将R / W位设置为1(读取访问)
wait_until_i2c_fifo_is_empty();//等到I2C TX FIFO空
wait_for_received_byte();//等待收到的数据
请帮助指出问题的位置,再次感谢!
嗨霍勒斯,
为了产生上面的序列,我使用了以下代码:
i2c_eeprom_init(i2c_slave_address,i2c_speed_mode,i2c_address_mode,i2c_address_size);//初始化I2C,在I2C地址大小中放置设备的地址大小 times的读取访问
send_i2c_command(0x03&0xff);//设备具有的地址大小为两个字节长度,如果您的设备需要一个字节长度,则可以使用此指令从0x03地址或所需的任何地址读取。
等待_while_i2c_fifo_is_full();//等待TX FIFO已满
send_i2c_command(0x0100);//设置
上面的片段产生下面附上的波形,当然当然从内存响应的数据是错误的,但我想这就是你要找的东西。
谢谢mt_dialog.
亲爱的,
非常感谢您的帮助。
但是,该案例比您写的方案更复杂
在您的情况下,从地址保持在0x50不变。
但作为所附规范,LIS传感器具有以下要求。
1)
与LIS2DS12相关联的从地址(SAD)是XX位的00111xxb
由SA0 / SDO引脚修改,以修改设备地址。
如果SA0 / SDO引脚连接到电源电压,则地址为0011101B
2)
从地址以读/写位完成。如果该位是'1'(读取),则重复
开始(SR)条件必须在两个子地址字节后发出。如果该位是'0'(写)
主人将以方向向奴隶与方向不变
因此,SAD + R = 0x3B,而SAD + W = 0x3A(如果SA0连接到VCC)
这意味着我必须在i2c_tar_reg中的值进行两次更改值以在表20中生成序列(请检查附件或我的第一个注释)
我尝试了多种组合,但所有尝试都失败了,如:
i2c_eeprom_init(0x3a,i2c_fast,i2c_7bit_addr,i2c_1byte_addr);//初始化i2c,sad + w,fast_mode,7bit,1byte
send_i2c_command(0x0f);// who_am_i_reg地址 - 0xF
等待_while_i2c_fifo_is_full();//等待TX FIFO已满
1)setword16(i2c_tar_reg,(0x3a + 1));//重复SR +(SAD + R)
2)setword16(i2c_enable_reg,0);
setword16(i2c_tar_reg,(0x3a + 1));//重复SR +(SAD + R)
setword16(i2c_enable_reg,1);
等待_while_i2c_fifo_is_full();//等待TX FIFO已满
send_i2c_command(0x0100);
......
有什么建议么?
嗨霍勒斯,
我没有在那个特定的传感器上看到任何不同的东西,就我所能理解,一个定义传感器地址的一个引脚应该连接到VCC或GND,以便定义传感器7bit地址0x1d或0x1e,这是什么您应该在I2C_TAR_REG中设置,之后您不必在要执行读取或写操作时更改I2C_TAR_REG的值,I2C模块将自动添加“0”或“1”,就像捕捉我送你了。在捕获I VE附上仪器的仪器解码地址和读写操作,如果检查时钟和SDA上的脉冲和SCL上的脉冲,您将看到写入写入[0x50]是0x50加上的8位序列额外的0表示写入(如果将其读取为8位数,则在0xA0中导致的8位数),并且在读取操作中读取[0x50]是0x50的8位序列加上额外的1才能声明读取(如果您读取)它是am 8位的数字,这将导致0xA1的结果。请尝试用作目标Addres而不是0x3a但0x1d,它是设备的实际地址,当您执行读取或写入时,将放置附加位(“1”或“0”)通过i2c_data_cmd_reg。如果将从i2c_data_cmd_reg写入从站的子地址的值(仅写入寄存器的0:7位),则模块将发送设备的地址,后跟写命令(因此1d(11101)+0 - > 0x3A)后跟您在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.
嗨MT,
虽然它仍然不起作用,但仍然感谢您的耐心和善良的指导。
我猜剩下的问题可能与时序相关,并将稍后捕获SDA&SCL的信号。
嗨MT,
司机现在运作,在硬件家伙用新的电路板上替换后。
请关闭机票,再次谢谢您拯救我们的时间!