2

STM32F4ボードをスレーブレシーバーとして、ノルディックボードをマスタートランスミッターとして使用しています。スレーブによって確認応答される 0x30 としてスレーブ アドレスを送信でき、デバイス レジスタ アドレスを 0x10 として送信し、次を使用していくつかのデータを送信します。

i2c_write(0x30, 0x10, data, 4);

割り込みサービス ルーチンでイベントを取得できます。「I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED」で 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;
            }
    }
}
4

3 に答える 3

1

その後、0x00020044 イベントを受け取り、時計が停止しました。

「イベント」という用語は、少し大雑把に使用されています。ST のヘッダー ファイルが行うことは、イベントを特定のフラグの組み合わせとして定義することです。ちょっと変わった組み合わせです。分解すると、次のビットが設定されます。

#define I2C_FLAG_BUSY                   ((uint32_t)0x00020000)
#define I2C_FLAG_RXNE                   ((uint32_t)0x10000040)
#define I2C_FLAG_BTF                    ((uint32_t)0x10000004)

(実際には、異なるレジスタに 2 つのセットがあります。既知のイベントの定義によると、後者のグループの先頭の「1」は、それらを組み合わせると削除されるように見えますが、100% 確実ではありません)

リファレンスマニュアルを見ると、次のように書かれています。

RxNE が設定され、次のデータ受信が終了する前に DR レジスタのデータが読み取られない場合、BTF ビットが設定され、インタフェースは I2C_DR レジスタからの読み取りによって BTF がクリアされるまで待機し、SCL を Low にストレッチします。

これらの条件は満たされているように見え、STM32F4 I2C スレーブがクロックを伸ばしている (ストールしている) 理由を説明しています。続行できるようにするには、データレジスタから読み取る必要があるように見えます-実際には、これをイベントとして一致させ、それを実行します。

さらに、実際に 2 つのワードを受信したときにこの状態になると思われます。1 つは RXNE で示される受信バッファにあり、もう 1 つは BTF で示されます。その時点で、それはスタックしており、それ以上受け入れることができません - 2 番目の単語が受信を完了する前に最初の単語を要求することで効率を改善するために、そのための割り込みイネーブルを追加することで、RXNE を単独でキャッチすることを検討できます。

それを完全に機能させることができた場合は、あなたがしたこととまったく同じ答えを自由に書いて、それを受け入れてください。

于 2014-08-19T21:28:58.523 に答える
1

「これらの条件が満たされているように見え、STM32F4 I2C スレーブがクロックを伸ばしている (ストールしている) 理由を説明しています。継続できるようにするには、データ レジスタから読み取る必要があるようです。実際には、これをイベントとして一致させ、それを行う。"

私はあなたが言ったことを正確に行い、期待どおりに機能します。少し遅れてリファレンスマニュアルを読んでください。:)

于 2014-08-20T15:22:55.950 に答える