我是 PSoC 板的新手,我正在尝试从数字罗盘读取 x、y、z 值,但在使用罗盘本身开始传输时遇到问题。
我在这里在线找到了一些 Arduino 教程,但由于 PSoC 没有库,我无法复制代码。
另外我在这里阅读了 HMC5883L 数据表,我想将字节写入指南针并获取值,但我无法接收任何内容。我收到的所有值都是零,这可能是由于从错误地址读取值引起的。
希望尽快得到您的答复。
当您第一次开始使用 PSoC 时,它有点棘手。您需要仔细阅读要与之通信的设备和 i2c 模块本身的文档。
您链接的设备的数据表在第 18 页上说明了这一点:
所有总线事务都以主设备发出起始序列开始,然后是从地址字节。地址字节包含从机地址;高 7 位 (bits7-1) 和最低有效位 (LSb)。地址字节的 LSb 指定操作是读取 (LSb=1) 还是写入 (LSb=0)。在第 9 个时钟脉冲,接收从设备将发出 ACK(或 NACK)。在这些总线事件之后,主设备将发送数据字节进行写操作,或者从设备将通过读操作输出数据。所有总线事务都以主机发出停止序列而终止。
如果您使用 I2C_MasterWriteBuf 函数,它会包装上面 HMC 数据表中所述的所有内容。启动命令,处理该确认,数据处理等。您唯一需要指定的是如何传输它。
如果您参考 PSoC 的 I2C 模块数据表,MasterWriteBuf 函数接收设备地址、指向要发送的数据的指针、要发送的字节数和“模式”。它显示了文档中的各种传输模式。
I2C_MODE_COMPLETE_XFER 执行从 Start 到 Stop 的完整传输。
I2C_MODE_REPEAT_START 发送重复开始而不是开始。
I2C_MODE_NO_STOP 执行传输而不停止
如果我没记错的话,MODE_COMPLETE_XFRE 传输会为你发送启动和停止命令。
如果你愿意,你也可以“bit-bang”,但直接调用 I2C_MasterSendStart、WriteByte、SendStop 等。但调用它们的 writebuf 函数更容易。
您几乎需要编写如下代码:
// fill in your data or pass in the buffer of data you want to write
// if this is contained in a function call. I'm basing this off of HMC's docs
uint8 writeBuffer[3];
uint8 readBuffer[6];
writeBuffer[0] = 0x3C;
writeBuffer[1] = 0x00;
writeBuffer[2] = 0x70;
I2C_MasterWriteBuf(HMC_SLAVE_ADDRESS, &writeBuffer, 3, I2C_MODE_COMPLETE_XFER);
while((I2C_MasterStatus() & I2C_MSTAT_WR_CMPLT) == 0u)
{
// wait for operation to finish
}
writeBuffer[1] = 0x01;
writeBuffer[2] = 0xA0;
I2C_MasterWriteBuf(HMC_SLAVE_ADDRESS, &writeBuffer, 3, I2C_MODE_COMPLETE_XFER);
// wait for operation to finish
writeBuffer[1] = 0x02;
writeBuffer[2] = 0x00;
I2C_MasterWriteBuf(HMC_SLAVE_ADDRESS, &writeBuffer, 3, I2C_MODE_COMPLETE_XFER);
// wait for operation to finish
CyDelay(6); // docs state 6ms delay before you can start looping around to read
for(;;)
{
writeBuffer[0] = 0x3D;
writeBuffer[1] = 0x06;
I2C_MasterWriteBuf(HMC_SLAVE_ADDRESS, &writeBuffer, 2, I2C_MODE_COMPLETE_XFER);
// wait for operation to finish
// Docs don't state any different sort of bus transactions for reads.
// I'm assuming it'll be the same as a write
I2C_MasterReadBuf(HMC_SLAVE_ADDRESS, readBuffer, 6, I2C_MODE_COMPLETE_XFER);
// wait for operation to finish, wait on I2C_MSTAT_RD_CMPLT instead of WR_COMPLT
// You should have something in readBuffer to work with
CyDelay(67); // docs state to wait 67ms before reading again
}
我只是把它从头顶上写下来。我不知道这是否可行,但我认为这应该是一个开始尝试的好地方。我认为他们也有 I2C 示例项目可供查看。
另一件需要注意的事情是,WriteBuf 函数看起来不仅仅是一些神奇的命令,如果您右键单击 MasterWriteBuf 函数并单击“查找定义”(在您构建项目之后),它会告诉您它在做什么.
以下是 PSoC 上 I2C 读写操作的示例,
简单的写操作:
//Dumpy data values to write
uint8 writebuffer[3]
writebuffer[0] = 0x23
writebuffer[1] = 0xEF
writebuffer[2] = 0x0F
uint8 I2C_MasterWrite(uint8 slaveAddr, uint8 nbytes)
{
uint8 volatile status;
status = I2C_MasterClearStatus();
if(!(status & I2C_MSTAT_ERR_XFER))
{
status = I2C_MasterWriteBuf(slaveAddr, (uint8 *)&writebuffer, nbytes, I2C_MODE_COMPLETE_XFER);
if(status == I2C_MSTR_NO_ERROR)
{
/* wait for write complete and no error */
do
{
status = I2C_MasterStatus();
} while((status & (I2C_MSTAT_WR_CMPLT | I2C_MSTAT_ERR_XFER)) == 0u);
}
else
{
/* translate from I2CM_MasterWriteBuf() error output to
* I2C_MasterStatus() error output */
status = I2C_MSTAT_ERR_XFER;
}
}
return status;
}
读取操作:
void I2C_MasterRead(uint8 slaveaddress, uint8 nbytes)
{
uint8 volatile status;
status = I2C_MasterClearStatus();
if(!(status & I2C_MSTAT_ERR_XFER))
{
/* Then do the read */
status = I2C_MasterClearStatus();
if(!(status & I2C_MSTAT_ERR_XFER))
{
status = I2C_MasterReadBuf(slaveaddress,
(uint8 *)&(readbuffer),
nbytes, I2C_MODE_COMPLETE_XFER);
if(status == I2C_MSTR_NO_ERROR)
{
/* wait for reading complete and no error */
do
{
status = I2C_MasterStatus();
} while((status & (I2C_MSTAT_RD_CMPLT | I2C_MSTAT_ERR_XFER)) == 0u);
if(!(status & I2C_MSTAT_ERR_XFER))
{
/* Decrement all RW bytes in the EZI2C buffer, by different values */
for(uint8 i = 0u; i < nbytes; i++)
{
readbuffer[i] -= (i + 1);
}
}
}
else
{
/* translate from I2C_MasterReadBuf() error output to
* I2C_MasterStatus() error output */
status = I2C_MSTAT_ERR_XFER;
}
}
}
if(status & I2C_MSTAT_ERR_XFER)
{
/* add error handler code here */
}
}