I2C STM32F0 HALライブラリを使用したレジスターのアドレス指定


12

私はSTMのCUBEおよびHAL_librariesを使用するのが非常に初めてです。32ピンのSTM32F0マイクロコントローラを使用しています。I2Cの回路図は正しいです。ここで少し助けが必要です。

I2C通信を使用する静電容量センサー(FDC1004)があります。データを読み取るには、これらのレジスタに書き込む必要があります。

STARTリクエストフォームマスターをスレーブに正しく送信するにはどうすればよいですか(スレーブアドレスはA0)。

ポインタを0x0Cレジスタに設定する方法は?

  • データシートでは、(レジスタ0x0C:bit [7:4])から1を参照しています。)どうすればよいですか?そして最後に、同じレジスタから読み取る方法は?
  • さらに、DONE_xフィールド(レジスタ0x0C:bits [3:0])を読み取ってから、それを読み取る必要がありますか?

しかし、私が適切なレジスタに対応しているかどうかはわかりません!センサーからデータが返されないからです!

これが私のコードです:

int I2Ccomm ()
{

    HAL_I2C_Master_Transmit(&hi2c1,0xA1,0x0C, 10, 100); //start bit and pointer to register
    HAL_Delay(50);
    HAL_I2C_Master_Transmit(&hi2c1,0xA1,0x054, 10, 100); // setting the register
    HAL_Delay(50);

    HAL_I2C_Master_Receive(&hi2c1, 0xA0, 0x0C, 10, 100); //read from this register
    HAL_Delay(50);
    HAL_I2C_Master_Receive(&hi2c1, 0xA0, 0x02, 10, 100); //read data from register

    return ReadREG[1];
}

より具体的な質問をしてください。Xレジスタを適切にアドレス指定するにはどうすればよいですか?これはひどい言葉の質問です。詳細なガイドラインについては、electronics.stackexchange.com
to

それでは、新しい質問を書いたり、これを編集したりする方が良いでしょうか?
yest111

編集した方がよいし、質問も少なくなります。これを閉じる必要はありません。
電圧スパイク

回答:


16

HAL_I2C_Master_Transmit()関数から始めましょう。その宣言を確認すると:

 HAL_StatusTypeDef HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout);
  1. 2番目のパラメータの軽微な問題、スレーブデバイスのアドレス。スレーブデバイスのアドレスはb1010000、8ビット形式に完成させると0xA0、あなたが言ったようにになります。これを渡すとHAL_I2C_Master_Transmit()、R / Wビットを手動で設定する必要がなくなり、HALが代わりに設定します。したがってHAL_I2C_Master_Transmit()、送信されたR / Wビットを呼び出すと自動的に0にHAL_I2C_Master_Receive()なり、送信されたR / Wビットを呼び出すと自動的に1になり、書き込み操作を示します。R / W値を混在させましたが、これは関数のドントケアビットであるため、コードの実際のエラーではありません。

  2. 3番目のパラメータは、( uint8_t *pData)でバッファへのポインタ含まれて送信されるデータを。さて、あなたの呼び出しで3番目のパラメータ0x0Cはあなたの実際のデータ、レジスタアドレスです。問題は、HAL_I2C_Master_Transmit()未定義のデータが見つかる可能性のあるメモリ位置へのポインタとして(によって)解釈されることです。

  3. 4番目のパラメータであり、バッファのサイズ、送信されるバイトの数。1バイトを送信する場合、このパラメーターは10ではなく1にする必要があります。

使用する場合は、スレーブデバイスのデータシートを取得し、書き込みおよび読み取り操作のドキュメントを調べることが最善の方法です。I2C

レジスターの書き込み

これは、データシートの対応する図です。

ここに画像の説明を入力してください

したがって、スレーブアドレスをバスに送信した後、レジスタポインタMSBバイトLSBバイトの 3バイトを送信する必要があります。HALが16ビットレジスタを書き込む一般的な実装:

void write_register(uint8_t register_pointer, uint16_t register_value)
{
    uint8_t data[3];

    data[0] = register_pointer;     // 0x0C in your example
    data[1] = register_value>>8;    // MSB byte of 16bit data
    data[2] = register_value;       // LSB byte of 16bit data

    HAL_I2C_Master_Transmit(&hi2c1, 0xA0, data, 3, 100);  // data is the start pointer of our array
}

あなたの値の例: write_register(0x0C, 0x0054);

あるいは、HA​​L定義のレジスタ書き込み関数も使用できます。これには、レジスタアドレスとアドレスサイズを渡すための追加のパラメータがあります。

void write_register(uint8_t register_pointer, uint16_t register_value)
{
    HAL_StatusTypeDef status = HAL_OK;

    status = HAL_I2C_Mem_Write(&hi2c1, 0xA0, (uint16_t)register_pointer, I2C_MEMADD_SIZE_8BIT, (uint8_t*)(&register_value), 2, 100); 

    /* Check the communication status */
    if(status != HAL_OK)
    {
        // Error handling, for example re-initialization of the I2C peripheral
    }
}

これで、HAL_I2C_Master_Receive()機能はほぼ同じになります。

HAL_StatusTypeDef HAL_I2C_Master_Receive(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout);

唯一の違いは、3番目のパラメータが、受信したデータが格納されるバッファへのポインタであることです。それは0x02あなたのコードにあり、あなたの目的が何であったかはわかりませんが、ポインタとして解釈されます(残念ながらランダムなメモリ位置への)。

レジスタを読み取る

ここに画像の説明を入力してください

レジスタを読み取るには、適切なレジスタポインタを送信して、書き込み操作でそのレジスタを選択する必要があります(このレジスタを読み取りの直前に書き込んだ場合、そのアドレスをポインタに再度送信する必要はありません。レジスタ、書き込み時に設定済みです)。次に、読み取り操作で、16ビットデータを読み取ります。I2CI2C

void read_register(uint8_t register_pointer, uint8_t* receive_buffer)
{
    // first set the register pointer to the register wanted to be read
    HAL_I2C_Master_Transmit(&hi2c1, 0xA0, &register_pointer, 1, 100);  // note the & operator which gives us the address of the register_pointer variable

    // receive the 2 x 8bit data into the receive buffer
    HAL_I2C_Master_Receive(&hi2c1, 0xA0, receive_buffer, 2, 100);   
}

例:

uint8_t reg_ptr = 0x0C;
uint8_t buffer[2];

read_register(reg_ptr, buffer);

// the register content available in the buffer

また、HALで定義されたレジスタ読み取り関数もあります。

uint16_t read_register(uint8_t register_pointer)
{
    HAL_StatusTypeDef status = HAL_OK;
    uint16_t return_value = 0;

    status = HAL_I2C_Mem_Read(&hi2c1, 0xA0, (uint16_t)register_pointer, I2C_MEMADD_SIZE_8BIT, &return_value, 2, 100);

    /* Check the communication status */
    if(status != HAL_OK)
    {

    }

    return return_value;
}

詳細については、データシートの「8.5プログラミング」セクションをお読みください。


回答ありがとうございます。ようやく動作しました。しかし、もう1つ質問がありますか?読むのに数ミリ秒待つ必要がありますか、それとも遅滞なく読むことができますか?
yest111 2016

私は遅延が必要だとは思わない、あなたは最初なしで試すことができます。
Bence Kaulics 16

1
待機する必要はありません。I2Cには、スレーブが完了するまでクロック信号のループが含まれます。
Mahmoud Al-Qudsi
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.