1.03日更新
在使用I2C2的过程中发现读取数据下图的问题。
这是读取bno055的结果,如果摆动传感器会获得数据,但是如果静止或者过了一会就只剩下yaw方向的结果。同时pitch 方向的数据基本上的读不到的。经常出现-1的结果。
而使用I2C1的结果如下:
原因未知!!!
在尝试使用软件I2C与BNO055通讯失败后(该软件I2C代码此前与MPU6050或其他传感器通讯均没问题,但是用在BNO055 上在发送从地址并收到应答后时序就乱了,不接传感器下测出来的时序是正确的),使用STM32 自带的I2C,并且使用的是库函数操作。当读函数在main函数内是正常的,但是一旦在把它封装到别的函数,时序就乱了,并且卡在EV6事件的循环等待。
此前一直没使用过硬件的I2C,所有这次认真查看参考手册再比较库函数的实现,其实在每个事件的等待中,库函数比较的不止一个寄存器的位,基本上每个事件都是几个位的比较
下列是事件掩码的定义
/* --EV6 */
#define I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED ((uint32_t)0x00070082) /* BUSY, MSL, ADDR, TXE and TRA flags */
#define I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED ((uint32_t)0x00030002) /* BUSY, MSL and ADDR flags */
/* --EV9 */
#define I2C_EVENT_MASTER_MODE_ADDRESS10 ((uint32_t)0x00030008) /* BUSY, MSL and ADD10 flags */
/* --EV5 */
#define I2C_EVENT_MASTER_MODE_SELECT ((uint32_t)0x00030001) /* BUSY, MSL and SB flag */
使用库函数的代码很容易就卡在死循环了,而且也不知道是哪里出错。所以果断使用另外一个官方的实现。
根据参考手册的介绍,其实只要检查某一位标志就可以确定外设的状态。
下面这个实现根据参考手册去实现。并且在文档中也对代码进行了阐述:
Status I2C_Master_BufferRead(I2C_TypeDef* I2Cx, uint8_t* pBuffer, uint32_t NumByteToRead, I2C_ProgrammingModel Mode, uint8_t SlaveAddress)
{
__IO uint32_t temp = 0;
__IO uint32_t Timeout = 0;
/* Enable I2C errors interrupts (used in all modes: Polling, DMA and Interrupts */
I2Cx->CR2 |= I2C_IT_ERR;
......
else if (Mode == Polling) /* I2Cx Master Reception using Polling */
{
if (NumByteToRead == 1)
{
Timeout = 0xFFFF;
/* Send START condition */
I2Cx->CR1 |= CR1_START_Set;
/* Wait until SB flag is set: EV5 */
while ((I2Cx->SR1&0x0001) != 0x0001)
{
if (Timeout-- == 0)
return Error;
}
/* Send slave address */
/* Reset the address bit0 for read */
SlaveAddress |= OAR1_ADD0_Set;
Address = SlaveAddress;
/* Send the slave address */
I2Cx->DR = Address;
/* Wait until ADDR is set: EV6_3, then program ACK = 0, clear ADDR
and