STM32F4挂在I2C_CheckEvent()中

时间:2014-07-15 21:21:06

标签: c i2c stm32 stm32f4discovery

我发现我的STM32F4和IMU设备之间的I2C通信随机挂起。 STM32F4是主设备,总线上唯一的其他设备是IMU6050 6轴加速度/陀螺仪。该程序最终会因陷入I2C_CheckEvent()函数内的循环而停止。

初始化如下:

RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);

GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_8 | GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;            
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;       
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;          
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;            
GPIO_Init(DATAPORT, &GPIO_InitStructure);                   
GPIO_PinAFConfig(DATAPORT, GPIO_PinSource8, GPIO_AF_I2C1);
GPIO_PinAFConfig(DATAPORT, GPIO_PinSource9, GPIO_AF_I2C1);

/* Set the I2C parameters, pretty much default except ack */
I2C_InitStructure.I2C_ClockSpeed = 100000;
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
I2C_InitStructure.I2C_OwnAddress1 = 0;
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_Init(I2C1, &I2C_InitStructure);

/* Enable the I2C peripheral */
I2C_Cmd(I2C1, ENABLE);

/* Config the IMU with defult settings */
IMUConfig(DEFAULTACCELRANGE, DEFAULTGYRORANGE);

IMU的初始化得到了解决,我确信所有工作都能正常工作,因为我获得了一段时间的有效数据。应用程序在运行几秒后随机崩溃。

读取功能:

void IMUReadBytes(uint8_t startAddress, uint8_t numOfBytes, uint8_t *location){
    I2C_GenerateSTART(I2C1, ENABLE);
    while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));

    I2C_Send7bitAddress(I2C1, IMU_ADDRESS << 1, I2C_Direction_Transmitter);
    while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));

    I2C_SendData(I2C1, startAddress);
    while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));

    I2C_GenerateSTART(I2C1, ENABLE);
    while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));

    I2C_Send7bitAddress(I2C1, IMU_ADDRESS << 1, I2C_Direction_Receiver);
    while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));

    int num = 0;
    for(num = 0; num <= numOfBytes; num++){
        if(num == numOfBytes){
            I2C_AcknowledgeConfig(I2C1, DISABLE);
            I2C_GenerateSTOP(I2C1, ENABLE);
        }

        while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED));
        location[num] = I2C_ReceiveData(I2C1);
    }
    I2C_AcknowledgeConfig(I2C1, ENABLE);
}

每次,应用程序似乎都会通过其中一个检查事件崩溃,每次都不同。

可能不相关,但在编译时,我收到警告:

source\application\source\imu.c:129:5: warning: passing argument 3 of 'IMUReadBytes' from incompatible pointer type [enabled by default]
source\application\source\imu.c:81:6: note: expected 'uint8_t *' but argument is of type 'uint8_t (*)[14]'

我不确定这与它有什么关系。

正如我所说,代码可以正常工作一段时间,有时甚至几分钟。我将陀螺仪和加速度值与某些电机联系起来,在它工作的时候,一切都运行得很好。不知道为什么会卡住

1 个答案:

答案 0 :(得分:0)

您没有包含如何调用IMUReadBytes(...)并且您有与此相关的编译器警告。如果没有实际代码,则无法查看是否超出location的范围。

然而,为了缩小问题,我建议将整个代码拆分为部分,并首先运行某种类型:

while(1)
 {
  while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED));
  unsigned char readbyte = I2C_ReceiveData(I2C1);
  printf("%x ",readbyte);
 }

这里的要点是有一个简单的健壮循环,它始终读取数据并将其输出给您。因此,你可以运行它,看看悬挂是否发生。这样的循环不会影响其他可能排除数据损坏和其他问题的内存,或多或少与I2C内容无关。

您是否有可以从系统打印出来的串口?它是调试的最大帮手。

另一种方法是在示波器上触发总线数据(如果有)。

否则,您只需要通过观察代码和文档来分析您的程序。