你好,
我试着与传感器通信。传感器数据表上说我需要写一个测量命令。它的值(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_peripher_setup .h中配置。为大小
我有2个字节。
我能做什么来接收两个字节?它是如何储存的?我需要值存储在一个变量的大小是2Bytes。在发送“read”命令后,传感器发送“most_signant_byte”_ACK_“least_signant_byte”_ACK_(可能校验和)_NACK_ STOP_CONDITION。
为了更好地描述它,我也尝试了i2c_eeprom_read_byte
获取第一个字节。但这也不起作用。同时,ble连接丢失,我无法重新连接。整个系统只是在“等待循环”中。我必须取消,重置和重启系统才能让蓝牙再次工作。我想通过将1写入特征值的ble命令来触发测量。当将1写入char-value时,应该触发用于测量的触发器命令(1字节长度)。之后,我想要读出值(2字节),这将存储在另一个特征。
当一切正常时,我想使用通知来更新我手机上的传感器的新值。
谢谢!
简
设备:
嗨,詹菲尔德,
如果你被困在WAIT_FOR_RECEIVE_BYTE(),那么是的580没有从另一边收到任何东西。我不认为这是由于代码实现,但由于与580和传感器的连接,或传感器从不回复你发送的命令的某种原因。在这种情况下,逻辑分析仪捕获会有很大帮助。
对于BLE, I2C驱动轮询I2C接口以获取一些数据,因为没有数据可返回,驱动就一直等待,并且由于M0粘在I2C轮询上,所以BLE连接丢失。您必须获取I2C总线的捕获信息,并查看580在总线上发送的信息是否正确(传感器获取他想要的命令),以及是否有来自传感器的回复。
对于I2C驱动的读取过程,可以使用read_data_single()函数设置要读取的传感器的地址(传感器的某个内部地址),并将大小设置为2。这将迫使驱动程序发送两个时钟周期,以便从您声明的指定地址读取数据。然后,驱动程序将把你接收到的数据放在你作为参数传递给函数的指针中。
由于MT_dialog
谢谢你的回答。我没有任何关于传感器内部地址的信息。有了arduino,它工作得很好。我发送“测量CMD”到传感器,等待几毫秒,而它的测量,然后我发送读请求。之后,我将读取两个字节的数据。没有传感器的内部地址。我认为是这样的:
µC: _____ S___ADDR + WR_BIT_____Meas_CMD_____ADDR + RD_BIT______ACK_____ACK ____________ NACK___P
传感器:______________________Ack__________________________MSB______LSB_____CHECKSUM__________
这是传感器数据表中描述的。没有特定的指针地址可用。是否有其他方式接收值?也许是像“听”这样的功能?
我会尽快使用示波器分析传输。但也许你有一个想法我能做什么。
谢谢,
简
嗨,詹菲尔德,
似乎您必须将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
嗨,它仍然不起作用。我试图将meas_cmd发送为地址参数。
我附上了传感器数据表中的方案。它显示了传感器工作的通信序列。到目前为止,我无法在i2c_eeprom文件中看到能够提供这种通信流的可能性。
在尝试接收字节时,我仍然会卡住。
在我的理解中,我必须用写函数发送测量命令。我没有内存地址,而是只有传感器的I2C地址。测量后(20-80μs之间的某些东西),我可以发送read-command(i2c_address +读取位)。然后传感器开始发送数据。起初最重要的字节。当收到它时,DA14580必须提供ACK。然后将发送第二个字节(LSB)(然后是来自DA14580的ACK)。校验和将最后发送。
我是否弄错了关于它如何工作的原因,或者是我看不到的东西?
对于通信,两条通信线路必须有上拉。我使用了我在“configurepin(...... input_pullup .....)上设置的内部上拉?那是错的吗?我也尝试过外部上拉。(
configurepin(.....输入.....)
)。也没有工作。谢谢,
简
嗨,詹菲尔德,
正如我提到的,如果没有捕获,就没有容易的方法来调试这个,您将不得不检查总线上的信号,只是推测我们无法跟踪问题的原因。您必须检查在I2C总线上输出的是什么。I2C功能当执行一个读将执行写第一次(最后一点I2C奴隶地址设置为0),为了写设备的内部地址,或者一个命令在你的情况中,然后将读取命令(奴隶地址最后位设置为1)为了从传感器开始阅读,在写和读命令之间不发出延迟。您可以检查的是传感器I2C的配置,如果它对应于初始化时I2C模块的设置。但你必须捕捉到巴士才能解决这个问题。
由于MT_dialog
你好再次,
我检查了与示波器的通信,发现了
send_i2c_command.
不正常工作。当我想编写一个命令时,它在命令后发送addr + wr_bit后,该命令将一位向右移动。(大多数时候,不是所有的时间..有时它有效)例如:
SEND_I2C_COMMAND (0 xf3)
将发送:ADDR+WR_BIT和0x71作为命令。(1000'0000作为7位addr。+ wr位0和0111'1001而不是1111'0011)。地址是正确的,有时它能工作,传感器也能工作。但大多数情况下它都不起作用,并发送错误的值。我读东西的时候也是这样。我想发送
SEND_I2C_COMMAND (0 x0100)
.它发送:ADDR+WR_BIT(而不是RD_BIT)以及之后的一些随机值。有时它会发送ADDR+RD_BIT。(1000'0001)但大多数时候它不能正常工作。我的另一个问题是,ACK后收到的字节设置自动或我必须手动设置它ACK第一个字节,所以传感器可以发送第二个?
谢谢,
简
嗨,詹菲尔德,
关于SEND_I2C_COMMAND(),我不认为命令必须做什么与你面临的,如果有时它工作和其他它不我认为它必须做一些与你的连接。
当I2C控制器自动获得接收到的数据时,它将生成ACK,您不需要从代码中做任何额外的事情。
由于MT_dialog
你好,
我有同样的问题,即在I2C总线上读取多字节时陷入了卡。我从“i2c_eeprom.c”之一修改了I2C-Multi-Read Fucntioin。该功能如下所述。
而问题是,当我试图从我的传感器(加速计MMA8652)读取192字节时,程序将停止在“WAIT_FOR_RECEIVED_BYTE();',其中已经读取的数据的索引总是66(dec)。
我从逻辑信号分析仪得到了通信图,看起来DA14580和加速度计之间的通信是正确的,信号持续了192字节的周期!当我消除代码“WAIT_FOR_RECEIVED_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 (0 x0100);//设置读取次数
}
//读取数据{
for(index = 0;索引
WAIT_FOR_RECEIVED_BYTE ();
data[index] = (uint8_t)(uint8_t)(GetWord16(I2C_DATA_CMD_REG) & 0xFF);
}
}
以及I2C控制器的初始化:
i2cinitparam_t param;
param.periAdrr=0x1D;
参数。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 0 x0);//关闭I2C控制器
SetWord16(I2C_CON_REG, I2C_MASTER_MODE | I2C_SLAVE_DISABLE | I2C_RESTART_EN);//禁用Slave
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控制器
while((GetWord16(I2C_STATUS_REG) & 0x20) != 0); / /返回一个状态//等待I2C主FSM空闲
}
你好,
我有同样的问题,即在I2C总线上读取多字节时陷入了卡。我从“i2c_eeprom.c”之一修改了I2C-Multi-Read Fucntioin。该功能如下所述。
而问题是,当我试图从我的传感器(加速计MMA8652)读取192字节时,程序将停止在“WAIT_FOR_RECEIVED_BYTE();',其中已经读取的数据的索引总是66(dec)。
我从逻辑信号分析仪得到了通信图,看起来DA14580和加速度计之间的通信是正确的,信号持续了192字节的周期!当我消除代码“WAIT_FOR_RECEIVED_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 (0 x0100);//设置读取次数
}
//读取数据{
for(index = 0;索引
WAIT_FOR_RECEIVED_BYTE ();
data[index] = (uint8_t)(uint8_t)(GetWord16(I2C_DATA_CMD_REG) & 0xFF);
}
}
以及I2C控制器的初始化:
i2cinitparam_t param;
param.periAdrr=0x1D;
参数。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 0 x0);//关闭I2C控制器
SetWord16(I2C_CON_REG, I2C_MASTER_MODE | I2C_SLAVE_DISABLE | I2C_RESTART_EN);//禁用Slave
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控制器
while((GetWord16(I2C_STATUS_REG) & 0x20) != 0); / /返回一个状态//等待I2C主FSM空闲
}
我有一个为我工作的解决方案,但我认为这可能不足以一行的大量字节。但也许你可以尝试..
我通过删除
WAIT_FOR_RECEIVED_BYTE ();
并尝试直接获取该值并通过指针将其保存到数组。我的函数现在是这样的:
空白i2c_cust_read_bytes (uint8_t * val_ptr)
{
val_ptr [0] = 0x00;
val_ptr [1] = 0 x00;
wait_until_no_master_actity();
SEND_I2C_COMMAND (0 x0100);
WAIT_WHILE_I2C_FIFO_IS_FULL ();
val_ptr[1]=GetWord16(I2C_DATA_CMD_REG);
SEND_I2C_COMMAND (0 x0100);
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()不适合我..
希望我能帮到你。
干杯,
简
你好,
您是否尝试过按原样使用I2C驱动程序(i2c_eeprom_read_data)。捕捉你的高度我看到没有停止条件从580年为了读取数据(FIFO满-32时钟周期emmited和32字节的数据已收到,所以proccessor应该开始阅读FIFO和把数据从I2C FIFO缓冲区),当FIFO是满的时候,你正在读取数据吗?WAIT_FOR_RECEIVED_BYTE检查I2C_RX_FLR_REG,这个寄存器包含有效的数据,已经接收到,并且位于FIFO中,如果在FIFO中没有数据,它将被卡在while中,因为它被指示读取。在你的代码中作为输入的大小的值是多少?如果您正在调用您提到的超过32的函数,那么您的FIFO是满的,并且FIFO中的数据被下一个传入的数据重写。如果你检查I2C_eeprom司机你会看到i2c_eeprom_read_data是阅读的数据使用read_data_single eepm在32的倍数()函数和当FIFO满32字节I2C模块将停止时钟读取32个字节的数据。
Thansk mt_dialog.
你好。
我有一个同样的问题并得到解决方案。
您可以使用此代码读取两个字节。
关键是I2C_CON_REG的I2C_RESTART_EN位禁用。
空白init_i2c(空白)
{
setbits16(clk_per_reg,i2c_enable,1);//为i2c启用时钟
SetWord16 (I2C_ENABLE_REG 0 x0);//关闭I2C控制器
//这是关键解决方案。
//SetWord16(I2C_CON_REG, I2C_MASTER_MODE | I2C_SLAVE_DISABLE | I2C_RESTART_EN);//禁用Slave
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控制器
while((GetWord16(I2C_STATUS_REG) & 0x20) != 0); / /返回一个状态//等待I2C主FSM空闲
}
无符号短读短I2C(无效)
{
无符号短v v1 v2;
WAIT_WHILE_I2C_FIFO_IS_FULL ();//设置R/W位为1(读访问)
SEND_I2C_COMMAND (0 x0100);//设置次次读取访问。所以2次来电
WAIT_WHILE_I2C_FIFO_IS_FULL ();
SEND_I2C_COMMAND (0 x0100);
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;
拱形打印(“\r\nV%04X:%04X=%04X(%d)”,v1,v2,v,v);
返回v;
}
谢谢你!