embedded - STM32F4 I2C 从接收器

标签 embedded i2c stm32 master-slave stm32f4discovery

我使用 STM32F4 板作为从接收器,使用 Nordic 板作为主发送器。我能够将从机地址发送为 0x30,该地址由从机确认,并将设备寄存器地址发送为 0x10,然后使用

发送一些数据
i2c_write(0x30, 0x10, data, 4);

我能够在中断服务例程中获取事件。我收到“I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED”的 0x00020002。然后我收到 0x00020044 事件并且时钟停止运行。谁能帮我解决这个问题吗?通过范围界定,我在示波器上看到了从地址、设备寄存器地址和带有时钟的第一个数据。但在那个时钟停止之后。

我可以使用 STM32F4 作为主发送器并读取一些传感器,但我发现很难使用 STM32F4 作为从接收器并使用 Nordic 板作为主发送器

void i2c_init2()
{
    GPIO_InitTypeDef gpio_init;
    I2C_InitTypeDef i2c_init;
    NVIC_InitTypeDef NVIC_InitStructure, NVIC_InitStructure2;

    I2C_DeInit(I2C2 );       //Deinit and reset the I2C to avoid it locking up
    I2C_SoftwareResetCmd(I2C2, ENABLE);
    I2C_SoftwareResetCmd(I2C2, DISABLE);

        /*!< I2C Periph clock enable */
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE);
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);

        /* setup SCL and SDA pins
         * SCL on PB10 and SDA on PB11
         */
    gpio_init.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;     // we are going to use PB10 and PB11
    gpio_init.GPIO_Mode = GPIO_Mode_AF;                                 // set pins to alternate function
    gpio_init.GPIO_Speed = GPIO_Speed_50MHz;                        // set GPIO speed
    gpio_init.GPIO_PuPd = GPIO_PuPd_UP;                                 //Pull up resistor
    gpio_init.GPIO_OType = GPIO_OType_OD;                               //Open Drain
    GPIO_Init(GPIOB, &gpio_init);

        // Connect I2C2 pins to AF  
    GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_I2C2 ); // SCL
    GPIO_PinAFConfig(GPIOB, GPIO_PinSource11, GPIO_AF_I2C2 ); // SDA

        /* Configure the Priority Group to 1 bit */
        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

    NVIC_InitStructure.NVIC_IRQChannel = I2C2_EV_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    NVIC_InitStructure2.NVIC_IRQChannel = I2C2_ER_IRQn;
    NVIC_InitStructure2.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure2.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure2.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure2);

    I2C_ITConfig(I2C2, I2C_IT_EVT, ENABLE);
    I2C_ITConfig(I2C2, I2C_IT_ERR, ENABLE);
    I2C_ITConfig(I2C2, I2C_IT_BUF, ENABLE);


    i2c_init.I2C_ClockSpeed = 100000;
    i2c_init.I2C_Mode = I2C_Mode_I2C;
    i2c_init.I2C_DutyCycle = I2C_DutyCycle_2;
    i2c_init.I2C_OwnAddress1 = 0x30;
    i2c_init.I2C_Ack = I2C_Ack_Enable;
    i2c_init.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
    I2C_Init(I2C2, &i2c_init);

    I2C_StretchClockCmd(I2C2, ENABLE);
    I2C_Cmd(I2C2, ENABLE);
}

void I2C2_ER_IRQHandler(void)
{
        /* Read SR1 register to get I2C error */
    if ((I2C_ReadRegister(I2C2, I2C_Register_SR1 ) & 0xFF00) != 0x00)
    {
            STM_EVAL_LEDOn(LED6);
        /* Clears error flags */
        I2C2 ->SR1 &= 0x00FF;
    }
}

void I2C2_EV_IRQHandler(void)
{
    uint8_t dataRX;
    Event = I2C_GetLastEvent(I2C2 );
    printf("Event: 0x%x\n", Event);
    switch (Event)
    {

            case I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED :
            {
                    printf("Slave Address Matched\n");
                    STM_EVAL_LEDOn(LED4);
                    I2C2 ->SR1;
                    I2C2 ->SR2;
                    break;
            }
            case I2C_EVENT_SLAVE_BYTE_RECEIVED :
            {
                    printf("Slave Byte Received\n");
                    dataRX = I2C_ReceiveData(I2C2 );
                    break;
            }
            case I2C_EVENT_SLAVE_ACK_FAILURE :
            {
                    STM_EVAL_LEDOn(LED3);
                    I2C2 ->SR1 &= 0x00FF;
                    break;
            }
            case I2C_EVENT_SLAVE_STOP_DETECTED :
            {
                    I2C2 ->SR1;
                    I2C2 ->CR1 |= 0x1;
                    break;
            }
    }
}

最佳答案

“这些条件似乎得到满足,解释了为什么 STM32F4 I2C 从机延长(停止)时钟。看来您需要从数据寄存器中读取以允许其继续 - 实际上,将其匹配为一个事件并执行该操作。”

我完全按照你说的做了,效果符合预期。阅读引用手册有点晚了。 :)

关于embedded - STM32F4 I2C 从接收器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25392572/

相关文章:

java - 在 Eclipse 中同时构建和上传

android - 从哪里开始使用 I2C 的 Android 驱动程序

c++ - ATMega328P 和 ESP8266ex 之间的 I2c 通信只能发送 8 个字节,bug?

c - Atmega168 I2C 作为主机

stm32 - STM32的外设寄存器在哪里?它们是在 cortex-m 内核中还是在外围单元中?

c - 延迟如何在stm32l152RC上工作?

python - 用日志数量而不是 %asctime 标记 python 记录器文件

c - 如何使用嵌入式 C 启动 ARM Cortex 编程?

c - AUTH 命令时 Hotmail/Outlook.com 连接失败

c - STM32F0使用GCC编程arm-none-eabi : hardfault in __libc_init_array