STM32CubeIDE 7 (I2C with DMA)

SeeedのBMI088ボードから加速度と角速度を取得します。
DMA転送させます。

先に確認しておくこと

Coreより上でctags -Rしておいて、I2C用のHALの中を見ておきます。
関数一覧を確認します。
API内部で最初にREADYのチェックをしているので、自分でREADYのチェックを実装するべきではないとわかります。

001

002

このあたりをざっと読むと、「やっぱりevent interruptにチェックが必要そう。」と気付けると思います。

I2C with DMA

DMAとNVICの設定は前回で済ませてあります。
これが完了していれば、後は簡単です。

main.cpp

void
i2c_write( uint16_t addr, uint8_t *tx_buf, uint16_t len )
{
    /// without DMA

    // while (HAL_I2C_Master_Transmit(&hi2c1, addr, tx_buf, len, 10000) != HAL_OK)
    // {
    //     if (HAL_I2C_GetError(&hi2c1) != HAL_I2C_ERROR_AF)
    //     {
    //         error_type = I2C_ERROR;
    //         Error_Handler();
    //     }
    // }

    /// with DMA

    if (HAL_I2C_Master_Transmit_DMA(&hi2c1, addr, tx_buf, len) != HAL_OK)
    {
        sprintf( uart_message, "\r\n HAL_I2C_Master_Transmit_DMA \r\n" );
        p_( uart_message );
        error_type = I2C_ERROR;
        Error_Handler();
    }

    while (HAL_I2C_GetState(&hi2c1) != HAL_I2C_STATE_READY)
    {
        sprintf( uart_message, "\r\n WRITE HAL_I2C_STATE_BUSY \r\n" );
        p_( uart_message );
        HAL_Delay(1);
    }
}

void
i2c_read( uint16_t addr, uint8_t reg, uint8_t *rx_buf, uint16_t len )
{
    /// without DMA

    // while (HAL_I2C_Master_Receive(&hi2c1, addr, rx_buf, len, 10000) != HAL_OK)
    // {
    //     if (HAL_I2C_GetError(&hi2c1) != HAL_I2C_ERROR_AF)
    //     {
    //         error_type = I2C_ERROR;
    //         Error_Handler();
    //     }
    // }

    /// with DMA

    if (HAL_I2C_Master_Receive_DMA(&hi2c1, addr, rx_buf, len) != HAL_OK)
    {
        sprintf( uart_message, "\r\n HAL_I2C_Master_Receive_DMA \r\n" );
        p_( uart_message );
        error_type = I2C_ERROR;
        Error_Handler();
    }

    while (HAL_I2C_GetState(&hi2c1) != HAL_I2C_STATE_READY)
    {
        sprintf( uart_message, "\r\n READ HAL_I2C_STATE_BUSY \r\n" );
        p_( uart_message );
        HAL_Delay(1);
    }

    // if (HAL_I2C_Mem_Read_DMA(&hi2c1, addr, (uint16_t)reg, 1, rx_buf, len) != HAL_OK)
    // {
    //     sprintf( uart_message, "\r\n HAL_I2C_Mem_Read_DMA \r\n" );
    //     p_( uart_message );
    //     error_type = I2C_ERROR;
    //     Error_Handler();
    // }
}

自分が動かしている範囲内では、READY以外だったことは一度もありません。

まとめ

HAL_I2C_Mem_Read_DMAの仕込みが入っています。リピートスタートコンディションできます。きっと、いつか、やります。
readの前のwriteもやってくれるみたいなので、#ifdefの整理された設計が必要と思います。割と面倒かな。

スレーブアドレスの1ビット上にビットシフトは昔から変わっていないそうです。STのGitHubのサンプルコードは完全にバグですが。
バグは仕方ないとしても、仕様理解不備で、それを放置はありえないです。

7bitアドレスと1bitでREAD/WRITEのどちらかという構成のようですが、LLレイヤーで意識させることはあっても、HALレイヤーでこれだけレジスタを意識しなくていいのだし、1bitのREAD/WRITEは自動でやっているのだから、アドレスのビットシフトも自動でやっておくべきです。

GitHubでも手順書にしてほしいです。
.iocファイルも見ないといけないのは厳しい。

広告

IT開発関連書とビジネス書が豊富な翔泳社の通販『SEshop』
さくらのレンタルサーバ
ムームードメイン
Oisix(おいしっくす)
らでぃっしゅぼーや
珈琲きゃろっと
エプソムソルト




«       »