Embedded STM32F4 I2C从接收机

Embedded STM32F4 I2C从接收机,embedded,i2c,stm32,master-slave,stm32f4discovery,Embedded,I2c,Stm32,Master Slave,Stm32f4discovery,我使用STM32F4板作为从接收机,北欧板作为主发射机。我能够将从机地址发送为0x30,由从机确认,并将设备寄存器地址发送为0x10,然后使用 i2c_write(0x30, 0x10, data, 4); 我能够在中断服务例程中获取事件。我收到“I2C\u事件\u从\u接收器\u地址\u匹配”的0x00020002。然后,我收到0x00020044事件,时钟停止运行。谁能帮我一下吗。通过作用域,我在示波器上看到了从机地址、设备寄存器地址和我的第一个时钟数据。但在那之后,时钟停止了 我能够使用

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

i2c_write(0x30, 0x10, data, 4);
我能够在中断服务例程中获取事件。我收到“I2C\u事件\u从\u接收器\u地址\u匹配”的0x00020002。然后,我收到0x00020044事件,时钟停止运行。谁能帮我一下吗。通过作用域,我在示波器上看到了从机地址、设备寄存器地址和我的第一个时钟数据。但在那之后,时钟停止了

我能够使用STM32F4作为主发射机并读取一些传感器,但我发现很难使用STM32F4作为从接收机,使用北欧板作为主发射机

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;
            }
    }
}
void i2c_init2()
{
GPIO_InitTypeDef GPIO_init;
I2C_InitTypeDef I2C_init;
NVIC_InitTypeDef NVIC_InitStructure,NVIC_InitStructure2;
I2C_脱硝(I2C2);//脱硝并重置I2C以避免其锁定
I2C_软件重置指令(I2C2,启用);
I2C_软件重置指令(I2C2,禁用);
/*!SR1&=0x00FF;
}
}
无效I2C2_EV_IRQHandler(无效)
{
uint8_t数据接收;
事件=I2C_GetLastEvent(I2C2);
printf(“事件:0x%x\n”,事件);
开关(事件)
{
案例I2C\事件\从机\接收器\地址\匹配:
{
printf(“从属地址匹配\n”);
STM_EVAL_LEDOn(LED4);
I2C2->SR1;
I2C2->SR2;
打破
}
案例I2C_事件_从字节_接收:
{
printf(“接收到从属字节\n”);
dataRX=I2C_接收数据(I2C2);
打破
}
案例I2C事件从机确认故障:
{
STM_EVAL_LEDOn(LED3);
I2C2->SR1&=0x00FF;
打破
}
案例I2C\u事件\u从站\u停止\u检测到:
{
I2C2->SR1;
I2C2->CR1 |=0x1;
打破
}
}
}
然后,我收到0x00020044事件,时钟停止运行

术语“事件”的使用有点松散。ST的头文件所做的是将事件定义为特定的标志组合。你有一个稍微不同的组合。将其分解,设置以下位:

#define I2C_FLAG_BUSY                   ((uint32_t)0x00020000)
#define I2C_FLAG_RXNE                   ((uint32_t)0x10000040)
#define I2C_FLAG_BTF                    ((uint32_t)0x10000004)
(实际上,在不同的寄存器中有两个集合-根据已知事件的定义,后面一组的前导“1”在组合时似乎会被删除,但我不能100%确定这一点)

参考手册中有以下内容:

如果设置了RxNE,并且在下一个数据结束之前未读取DR寄存器中的数据 接收时,设置BTF位,接口等待,直到BTF被来自 I2C_DR寄存器,拉伸SCL低


这些条件似乎都满足了,这解释了STM32F4 I2C从机为何会延长(暂停)时钟。看起来您需要从数据寄存器中读取数据以允许其继续-实际上,将此作为事件进行匹配并执行此操作

我进一步怀疑,当您实际收到两个单词时,您会遇到这种情况——一个在接收缓冲区中,由RXNE表示,另一个在接收器中,由BTF表示。在这一点上,它被卡住了,不能再接受了——你可以考虑通过添加一个中断使能来捕获RXNE,这可能通过在第二个接收完成之前先声明第一个单词来提高效率。 如果你能完成的话