I2C从传感器接收2个字节

13个职位/ 0新
最后一篇
Janfeld.
离线
最后一次露面:4年7个月前
加入:2016-03-08 14:38
I2C从传感器接收2个字节

你好,

我尝试与传感器进行通信。传感器数据表说我需要编写测量命令。它的值(12或14位)存储在其内存中。要获取此数据,我必须读出2个字节。但每当我尝试用“I2C_EEPROM_READ_DATA(UINT8_T * RD_DATA_PTR,UINT32_T地址,UINT32_T大小)“我陷在”read_data_single()“ 在里面 ”wait_for_received_byte();“循环。看来,DA14580没有收到东西。

为了* rd_data_ptr我得到一个指针到一个值可变uint32_t的mes_val。对于我使用的地址I2C_SLAVE_ADDRESS在user_periph_setup.h中配置。为了尺寸我有2个两个字节。

我能做些什么来得到两个字节?它是如何存储?我需要储存在一个变量伟驰大小为2个字节的值。发送后“读”命令传感器发送“MOST_SIGNIFICANT_BYTE” _ACK_“LEAST_SIGNIFICANT_BYTE” _ACK_(也许校验和)_NACK_ STOP_CONDITION。

要更好地描述它,我也尝试过i2c_eeprom_read_byte拿到第一个字节。但是,这并不工作。另外,BLE连接丢失,我无法重新连接。整个系统只在“等待循环”。我不得不取消,重新设置并重新启动系统,以获得再次蓝牙工作。我想写入1的特征值,以触发经由BLE-命令测量。上写1到炭值触发命令(1字节长度),用于测量应该被解雇。之后,我想读出的将被存储在另一特征的值(2个字节)。
当一切工作时,我想使用通知来更新手机上的值,以传感器的新值。

谢谢!

1月

设备:
mt_dialog.
离线
最后一次露面:4个月2个星期前
职员
加入:2015-06-08 11:34
嗨Janfeld,

嗨Janfeld,

如果您被困在Wait_for_receive_Byte()中,则是,580不会从另一侧收到任何内容。我不认为这是由于代码实现而发生的,但由于与580和传感器的连接,或传感器出于某种原因,从不回复您发送的命令。在这种情况下,逻辑分析仪捕获将有很多帮助。

关于BLE的I2C驱动民调I2C接口,以获得一些数据,因为没有数据返回驱动器仍然在等待和BLE连接丢失,因为M0粘在I2C投票。您将获得I2C总线的捕获,看看580总线上发送,如果是正确的(传感器能得到他想要的命令),如果有来自传感器的答复。

关于I2C驱动程序的阅读过程中,你可以使用read_data_single()函数设置传感器,你想读(传感器的一些内部地址)的地址和值2,这将迫使驾驶员设定的尺寸,以便从指定的地址读取数据,你声明发送两个时钟周期。然后司机将会把你的指针收到你已经在函数作为参数传递的数据。

谢谢mt_dialog.

Janfeld.
离线
最后一次露面:4年7个月前
加入:2016-03-08 14:38
感谢您的回答。我不

感谢您的回答。我没有任何形式的关于传感器的内部地址信息。有了一个Arduino它工作正常。我送“测量CMD”到传感器,等待几毫秒,而它的测量,然后我送读请求。从那以后,我会读两个字节的数据。没有什么与传感器的内部地址。我认为它的工作原理是这样的:

μC:_____ S___ADDR + WR_BIT_____Meas_CMD_____ADDR + RD_BIT______ACK_____ACK____________NACK___P

传感器:______________________Ack__________________________MSB______LSB_____CHECKSUM__________

这就是如何在传感器数据表中描述的。没有可用的特定指针探针地址。是否有另一种接收价值的方法?也许像“听”的功能一样?

我会尽快使用示波器分析传输。但也许你有一个想法我能做什么。

谢谢,

1月

mt_dialog.
离线
最后一次露面:4个月2个星期前
职员
加入:2015-06-08 11:34
嗨Janfeld,

嗨Janfeld,

似乎您必须将meas_cmd作为read_data_single()中的地址参数发送为2,以便执行两个读数。为了使I2C传感器提供一些值,需要了解EMIT和哪些设备或通常做的数据的数据,因此您必须向I2C总线提供您想要的设备的地址要与传感器进行通信并写入传感器(I2C的写命令)您想要哪些值(MEAM_CMD)。因此,当您尝试使用read_data_single()函数访问总线时,i2c将自动提供在I2C模块初始化期间的从设备的地址(在I2C_INIT())和写入位置在从总线上遵循的从地址(MEAS_CMD)之后,执行I2C_SEND_ADDRESS(MEAM_CMD),然后I2C模块将提供从传感器采用两个字节的时钟。我希望我足够清楚。

谢谢mt_dialog.

Janfeld.
离线
最后一次露面:4年7个月前
加入:2016-03-08 14:38
嗨,它仍然没有

嗨,它仍然不起作用。我试图将meas_cmd发送为地址参数。

我连接从传感器的数据表的方案。它示出了通信序列中的传感器的工作原理与。现在我看不到在i2c_eeprom文件,可以提供这种通信流的可能性。

我仍然在尝试接收字节时被困住。

在我的理解中,我必须用写函数发送测量命令。我没有内存地址,而是只有传感器的I2C地址。测量后(20-80μs之间的某些东西),我可以发送read-command(i2c_address +读取位)。然后传感器开始发送数据。起初最重要的字节。当收到它时,DA14580必须提供ACK。然后将发送第二个字节(LSB)(然后是来自DA14580的ACK)。校验和将最后发送。

我是否弄错了关于它如何工作的原因,或者是我看不到的东西?

对于通信,两条通信线路必须有上拉。我使用了我在“configurepin(...... input_pullup .....)上设置的内部上拉?那是错的吗?我也尝试过外部上拉。(configurepin(.....输入.....))。也没有工作。

谢谢,

1月

依恋:
mt_dialog.
离线
最后一次露面:4个月2个星期前
职员
加入:2015-06-08 11:34
嗨Janfeld,

嗨Janfeld,

正如我所提到的,没有捕获,没有简单的方式调试这一点,你必须检查总线上的信号,只是通过猜测我们无法跟踪问题的原因。您必须检查I2C总线上的内容。执行读取时I2C的功能将执行写入第一(设置为0的I2C从地址的最后一位),以便在案例中写入设备的内部地址,或者将发送一个读取命令(使用最后一位设置为1的从站地址为1),以便从传感器开始读取,您不会在Write和Read命令之间发出延迟。如果在初始化期间对应于I2C模块的设置,您可以检查的是传感器的I2C的配置。但是你真的必须捕获公共汽车以解决这个问题。

谢谢mt_dialog.

Janfeld.
离线
最后一次露面:4年7个月前
加入:2016-03-08 14:38
你好,我们又见面了,

你好,我们又见面了,

我检查了与示波器的通信,发现了send_i2c_command.不正常工作。当我想编写一个命令时,它在命令后发送addr + wr_bit后,该命令将一位向右移动。(大多数时候,不是所有的时间..有时它有效)

例如:SEND_I2C_COMMAND(0xF3)将发送:ADDR + WR_BIT和0x71的命令。(1000'0000 7位地址。+ WR位0和0111'1001代替1111'0011)。地址是正确的,有时它的工作原理和传感器是这样做的工作。但大多数的时候它不工作,并发送错误的价值观。

当我尝试读一些同样的事情。我想送send_i2c_command(0x0100)。它发送:Addr + WR_BIT(而不是RD_BIT)以及之后的某些随机值。有时它有效,它发送addr + rd_bit。(1000'0001)但大部分时间它都无法正常工作。

另一个问题我有是,是接收到的字节组自动后的ACK或我必须手动将它设置为ACK的第一个字节,因此传感器可以发送第二?

谢谢,

1月

mt_dialog.
离线
最后一次露面:4个月2个星期前
职员
加入:2015-06-08 11:34
嗨Janfeld,

嗨Janfeld,

关于SEND_I2C_COMMAND(),我不认为该命令有跟你面对什么事情,如果有时它的工作原理和其他人不我想它有与你联系的东西。

该I2C控制器将产生ACK的时候,他自动获得接收到的数据,你没有从你的代码做任何额外的东西。

谢谢mt_dialog.

章程
离线
最后一次露面:1年6个月前
加入:2016-07-12 07:10
你好,

你好,

我有同样的问题,即在I2C总线上读取多字节时陷入了卡。我从“i2c_eeprom.c”之一修改了I2C-Multi-Read Fucntioin。该功能如下所述。

问题是,当我尝试从传感器(Accelerometer MMA8652)中读取192字节时,该程序将停止在“wait_for_received_byte();”如果已读取数据的索引始终为66(DEC)。

并且我从逻辑信号分析仪获得了通信图表,似乎DA14580和加速度计之间的通信正确,信号持续到192字节期间!当我消除代码“wait_for_receive_byte”时,整个时期的时间是相同的。根据图表的I2C-STOP信号前甚至有可用数据。

因此,似乎DA14580和加速度计之间的“连接问题”不是正确的原因。

希望你的帮助。

void i2c_readmultibyte(uint8_t regaddr,uint8_t data [],uint8_t大小)
{
uint8_t索引;

wait_until_i2c_fifo_is_empty();

wait_until_no_master_actity();

//注册地址阅读
send_i2c_command(regaddr);

for(index = 0;索引{
WAIT_WHILE_I2C_FIFO_IS_FULL();//等待TX FIFO已满
send_i2c_command(0x0100);//设置次次读取访问
}

//数据读取
for(index = 0;索引{
wait_for_received_byte();
数据[index] =(uint8_t)(getword16(i2c_data_cmd_reg)&0xff);
}

}

和I2C contorler的初始化:

i2cinitparam_t param;
param.periadrr = 0x1d;
param.addressmode = i2c_7bit_addr;
param.speedmode = i2c_fast;

void i2c_init(const i2cinitparam_t * param)
{
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,param-> speedMode);//设置速度
setBits16(i2c_con_reg,i2c_10bitaddr_master,param-> addressmode);//设置寻址模式
setword16(i2c_tar_reg,param-> periadrr&0x3ff);//设置从设备地址
setword16(i2c_enable_reg,0x1);//启用I2C控制器
而((GetWord16(I2C_STATUS_REG)&0×20)!= 0);//等待I2C主FSM为IDLE
}

章程
离线
最后一次露面:1年6个月前
加入:2016-07-12 07:10
你好,

你好,

我有同样的问题,即在I2C总线上读取多字节时陷入了卡。我从“i2c_eeprom.c”之一修改了I2C-Multi-Read Fucntioin。该功能如下所述。

问题是,当我尝试从传感器(Accelerometer MMA8652)中读取192字节时,该程序将停止在“wait_for_received_byte();”如果已读取数据的索引始终为66(DEC)。

并且我从逻辑信号分析仪获得了通信图表,似乎DA14580和加速度计之间的通信正确,信号持续到192字节期间!当我消除代码“wait_for_receive_byte”时,整个时期的时间是相同的。根据图表的I2C-STOP信号前甚至有可用数据。

因此,似乎DA14580和加速度计之间的“连接问题”不是正确的原因。

希望你的帮助。

void i2c_readmultibyte(uint8_t regaddr,uint8_t data [],uint8_t大小)
{
uint8_t索引;

wait_until_i2c_fifo_is_empty();

wait_until_no_master_actity();

//注册地址阅读
send_i2c_command(regaddr);

for(index = 0;索引{
WAIT_WHILE_I2C_FIFO_IS_FULL();//等待TX FIFO已满
send_i2c_command(0x0100);//设置次次读取访问
}

//数据读取
for(index = 0;索引{
wait_for_received_byte();
数据[index] =(uint8_t)(getword16(i2c_data_cmd_reg)&0xff);
}

}

和I2C contorler的初始化:

i2cinitparam_t param;
param.periadrr = 0x1d;
param.addressmode = i2c_7bit_addr;
param.speedmode = i2c_fast;

void i2c_init(const i2cinitparam_t * param)
{
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,param-> speedMode);//设置速度
setBits16(i2c_con_reg,i2c_10bitaddr_master,param-> addressmode);//设置寻址模式
setword16(i2c_tar_reg,param-> periadrr&0x3ff);//设置从设备地址
setword16(i2c_enable_reg,0x1);//启用I2C控制器
而((GetWord16(I2C_STATUS_REG)&0×20)!= 0);//等待I2C主FSM为IDLE
}

Janfeld.
离线
最后一次露面:4年7个月前
加入:2016-03-08 14:38
我有一个解决方案,

我有一个为我工作的解决方案,但我认为这可能不足以一行的大量字节。但也许你可以尝试..

我通过删除它来解决它wait_for_received_byte();并尝试直接获取该值并通过指针将其保存到数组。

我的函数现在看起来是这样的:


无效i2c_cust_read_bytes(uint8_t * val_ptr)
{
val_ptr [0] = 0x00;
val_ptr [1] = 0×00;

wait_until_no_master_actity();
send_i2c_command(0x0100);
WAIT_WHILE_I2C_FIFO_IS_FULL();

val_ptr [1] = getword16(i2c_data_cmd_reg);

send_i2c_command(0x0100);
WAIT_WHILE_I2C_FIFO_IS_FULL();

val_ptr [0] = getword16(i2c_data_cmd_reg)&0xfc;

}

这个对我有用。我对我数组的第二个元素有第一个值的原因只是我希望它在那里。您可以选择要点的哪个元素。

我认为这是这样的:

起初:没有主活动。
然后发送“read_cmd”..等待直到FIFO为空,以接收新字节(在将地址+读取位和0x00写入I2C_DATA_CMD_REG时清除)。
然后保存到您想要的变量。再次发送READ_CMD,这将覆盖在I2C_DATA_CMD_REG中保存的值,并为您要连续接收的每个字节重复该值。

对于它可能工作的两个值,但我不知道是否可以在没有错误或更改位的行中保存以接收多个或两个字节。

可悲的是,我仍然不知道为什么wait_for_received_byte()不适合我..

希望我可以帮助你有点。

干杯,

1月

mt_dialog.
离线
最后一次露面:4个月2个星期前
职员
加入:2015-06-08 11:34
你好,

你好,

您是否尝试过使用I2C驱动程序(I2C_EEPROM_READ_DATA)。从您所附的捕获,我看到,从580没有停止条件,以便读取数据(FIFO是完整的-32时钟周期,并且已经收到了32个字节的数据 - 所以Proccessor应该开始阅读FIFO并将数据从I2C FIFO放入缓冲区),在FIFO已满时读出数据吗?wait_for_received_byte检查i2c_rx_flr_reg,此寄存器包含已接收的有效数据,并且如果FIFO中没有数据,则会陷入困境,因为它将被困在其指示读取。所以在你的代码中你用作输入的大小的值是什么?如果您正在调用超过32的函数,则FIFO已满,并且FIFO中的数据由下一个InComming数据写入。如果检查I2C_EEPROM驱动程序,您将看到i2c_eeprom_read_data使用read_data_single()函数在32的倍数中从EEPROM读取数据,并且当FIFO满32个字节时,I2C模块将停止时钟读取32数据字节。

Thansk mt_dialog.

naracontrol
离线
最后一次露面:3年7个月前
加入:2016-04-14 10:22
你好。

你好。
我有一个同样的问题并得到解决方案。

您可以使用此代码读取两个字节。
关键是I2C_CON_REG的I2C_RESTART_EN位禁用。

空隙init_i2c(无效)
{
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);//从站被禁用
SetWord16(I2C_CON_REG,I2C_MASTER_MODE | I2C_SLAVE_DISABLE);

setBits16(i2c_con_reg,i2c_speed,i2c_standard);//设置速度
setbits16(i2c_con_reg,i2c_10bitaddr_master,i2c_7bit_addr);//设置寻址模式

// I2C设备地址设置。
setword16(i2c_tar_reg,地址);//设置从设备地址

setword16(i2c_enable_reg,0x1);//启用I2C控制器
而((GetWord16(I2C_STATUS_REG)&0×20)!= 0);//等待I2C主FSM为IDLE
}

无符号短readshorti2c(无效)
{
无符号短V,V1,V2;

WAIT_WHILE_I2C_FIFO_IS_FULL();//将R / W位设置为1(读取访问)
send_i2c_command(0x0100);//设置次次读取访问。所以2次来电
WAIT_WHILE_I2C_FIFO_IS_FULL();
send_i2c_command(0x0100);

wait_for_received_byte();//等待收到的数据
v1 = 0xff&getword16(i2c_data_cmd_reg);//获得收到的字节,MSB
wait_for_received_byte();//等待收到的数据
v2 =(0xff&getword16(i2c_data_cmd_reg));//获得收到的字节,LSB

v = v1 << 8 |v2;
ARCH_PRINTF(“\ r \ nv%04x:%04x =%04x(%d)”,v1,v2,v,v);
返回v;
}

谢谢你。