You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

138 lines
11 KiB

  1. # I2C マスタドライバ :id=i2c-master-driver
  2. <!---
  3. grep --no-filename "^[ ]*git diff" docs/ja/*.md | sh
  4. original document: 0.10.33:docs/i2c_driver.md
  5. git diff 0.10.33 HEAD -- docs/i2c_driver.md | cat
  6. -->
  7. QMK で使われる I2C マスタドライバには、MCU 間のポータビリティを提供するための一連の関数が用意されています。
  8. ## I2C アドレスについての重要なメモ :id=note-on-i2c-addresses
  9. このドライバが期待する全てのアドレスは、アドレスバイトの上位7ビットにプッシュする必要があります。最下位ビットの設定(読み込み/書き込みを示す)は、それぞれの関数によって行われます。データシートやインターネットで列挙されているほとんど全ての I2C アドレスは、下位7ビットを占める7ビットとして表され、1ビット左(より上位)にシフトする必要があります。これは、ビット単位のシフト演算子 `<< 1` を使用して簡単に実行できます。
  10. これは、呼び出しごとに以下の関数を実行するか、アドレスの定義で1度だけ実行するかどちらかで行うことができます。例えば、デバイスのアドレスが `0x18` の場合:
  11. `#define MY_I2C_ADDRESS (0x18 << 1)`
  12. I2C アドレスと他の技術詳細について、さらなる情報を得るためには https://www.robot-electronics.co.uk/i2c-tutorial を見てください。
  13. ## 使用できる関数 :id=available-functions
  14. | 関数 | 説明 |
  15. |-------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
  16. | `void i2c_init(void);` | I2C ドライバを初期化します。他のあらゆるトランザクションを開始する前に、この関数を一度だけ呼ぶ必要があります。 |
  17. | `i2c_status_t i2c_start(uint8_t address, uint16_t timeout);` | I2C トランザクションを開始します。アドレスは方向ビットのない7ビットスレーブアドレスです。 |
  18. | `i2c_status_t i2c_transmit(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout);` | I2C 経由でデータを送信します。アドレスは方向ビットのない7ビットスレーブアドレスです。トランザクションのステータスを返します。 |
  19. | `i2c_status_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout);` | I2C 経由でデータを受信します。アドレスは方向ビットのない7ビットスレーブアドレスです。 `length` で指定した長さのバイト列を `data` に保存し、トランザクションのステータスを返します。 |
  20. | `i2c_status_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout);` | `i2c_transmit` と同様ですが、 `regaddr` でスレーブのデータ書き込み先のレジスタを指定します。 |
  21. | `i2c_status_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout);` | `i2c_receive` と同様ですが、 `regaddr` でスレーブのデータ読み込み先のレジスタを指定します。 |
  22. | `i2c_status_t i2c_stop(void);` | I2C トランザクションを終了します。 |
  23. ### 関数の戻り値 :id=function-return
  24. `void i2c_init(void)` を除く上にあるすべての関数は、次の真理値表にある値を返します。
  25. |戻り値の定数 |値 |説明 |
  26. |--------------------|---|----------------------------|
  27. |`I2C_STATUS_SUCCESS`|0 |処理が正常に実行されました。|
  28. |`I2C_STATUS_ERROR` |-1 |処理に失敗しました。 |
  29. |`I2C_STATUS_TIMEOUT`|-2 |処理がタイムアウトしました。|
  30. ## AVR :id=avr
  31. ### 設定 :id=avr-configuration
  32. I2Cマスタドライバを設定するために、次の定義が使えます。
  33. | 変数 | 説明 | 既定値 |
  34. |---------|---------------------|--------|
  35. | `F_SCL` | クロック周波数 (Hz) | 400KHz |
  36. AVR は通常 I2C ピンとして使う GPIO が設定されているので、これ以上の設定は必要ありません。
  37. ## ARM :id=arm
  38. ARM の場合は、内部に ChibiOS I2C HAL ドライバがあります。この節では STM32 MCU を使用していると仮定します。
  39. ### 設定 :id=arm-configuration
  40. ARM MCU 用の設定はしばしば非常に複雑です。これは、多くの場合複数の I2C ドライバをさまざまなポートに対して割り当てられるためです。
  41. 最初に、必要なハードウェアドライバを有効にするために `mcuconf.h` ファイルをセットアップします。
  42. | 変数 | 説明 | 既定値 |
  43. |-------------------------------|------------------------------------------------------------------------------------------------|--------|
  44. | `#STM32_I2C_USE_XXX` | ハードウェアドライバ XXX の有効化/無効化(すべてのドライバを明示的にリストアップする必要あり) | FALSE |
  45. | `#STM32_I2C_BUSY_TIMEOUT` | レスポンスの受信がない場合に I2C コマンドを中断するまでの時間 (ms) | 50 |
  46. | `#STM32_I2C_XXX_IRQ_PRIORITY` | ハードウェアドライバ XXX の割り込み優先度(上級者向けの設定) | 10 |
  47. | `#STM32_I2C_USE_DMA` | MCU がデータ送信を DMA ユニットにオフロードする機能の有効化/無効化 | TRUE |
  48. | `#STM32_I2C_XXX_DMA_PRIORITY` | ハードウェアドライバ XXX に使用する DMA ユニットの優先度(上級者向けの設定) | 1 |
  49. 次に `halconf.h` ファイル内で `#define HAL_USE_I2C``TRUE` にします。これにより ChibiOS が I2C ドライバを読み込みます。
  50. 最後に、使用したい I2C ハードウェアドライバに応じて正しい GPIO ピンを割り当てます。
  51. 標準では I2C1 ハードウェアドライバが使われます。もし他のハードウェアドライバを使う場合、 `config.h` ファイルに `#define I2C_DRIVER I2CDX` を追加します( X は使用するハードウェアドライバの番号です)。例えば I2C3 を有効化する場合、`config.h` ファイルに `#define I2C_DRIVER I2CD3` と定義します。これにより QMK I2C ドライバと ChibiOS I2C driver が同期されます。
  52. STM32 MCU では、使用するハードウェアドライバにより、さまざまなピンを I2C ピンとして設定できます。標準では `B6`, `B7` ピンが I2C 用のピンです。 I2C 用のピンを設定するために次の定義が使えます:
  53. | 変数 | 説明 | 既定値 |
  54. |-----------------------|--------------------------------------------------------------------------------------------------|---------|
  55. | `I2C1_SCL_BANK` | SCL に使うピンのバンク (`GPIOA`, `GPIOB`, `GPIOC`) | `GPIOB` |
  56. | `I2C1_SDA_BANK` | SDA に使うピンのバンク (`GPIOA`, `GPIOB`, `GPIOC`) | `GPIOB` |
  57. | `I2C1_SCL` | SCL のピン番号 (0-15) | `6` |
  58. | `I2C1_SDA` | SDA のピン番号 (0-15) | `7` |
  59. | `I2C1_BANK`(非推奨) | 使用するピンのバンク (`GPIOA`, `GPIOB`, `GPIOC`)。後継は `I2C1_SCL_BANK`, `I2C1_SDA_BANK` です。 | `GPIOB` |
  60. ChibiOS I2C ドライバの設定項目は STM32 MCU の種類に依存します。
  61. STM32F1xx, STM32F2xx, STM32F4xx, STM32L0xx, STM32L1xx では I2Cv1 が使われます。
  62. STM32F0xx, STM32F3xx, STM32F7xx, STM32L4xx では I2Cv2 が使われます。
  63. #### I2Cv1 :id=i2cv1
  64. STM32 MCU の I2Cv1 では、クロック周波数とデューティ比を次の変数で変更できます。詳しくは <https://www.playembedded.org/blog/stm32-i2c-chibios/#I2Cv1_configuration_structure> を参照してください。
  65. | 変数 | 既定値 |
  66. |--------------------|------------------|
  67. | `I2C1_OPMODE` | `OPMODE_I2C` |
  68. | `I2C1_CLOCK_SPEED` | `100000` |
  69. | `I2C1_DUTY_CYCLE` | `STD_DUTY_CYCLE` |
  70. #### I2Cv2 :id=i2cv2
  71. STM32 MCU の I2Cv2 では、信号のタイミングパラメータを次の変数で変更できます。詳しくは <https://www.st.com/en/embedded-software/stsw-stm32126.html> を参照してください。
  72. | 変数 | 既定値 |
  73. |-----------------------|--------|
  74. | `I2C1_TIMINGR_PRESC` | `15U` |
  75. | `I2C1_TIMINGR_SCLDEL` | `4U` |
  76. | `I2C1_TIMINGR_SDADEL` | `2U` |
  77. | `I2C1_TIMINGR_SCLH` | `15U` |
  78. | `I2C1_TIMINGR_SCLL` | `21U` |
  79. STM32 MCU では GPIO ピンを設定するとき、別の「代替機能」モードを使うことができます。これは I2Cv2 モードで使われるピンを変更するために必要です。適切な設定値は、使用している MCU のデータシートを参照してください。
  80. | 変数 | 既定値 |
  81. |---------------------|--------|
  82. | `I2C1_SCL_PAL_MODE` | `4` |
  83. | `I2C1_SDA_PAL_MODE` | `4` |
  84. #### その他 :id=other
  85. `void i2c_init(void)` 関数は `weak` 属性が付いており、オーバーロードすることができます。この場合、上記で設定した変数は使用されません。可能な GPIO の設定については、 MCU のデータシートを参照してください。次に示すのは初期化関数の例です:
  86. ```c
  87. void i2c_init(void)
  88. {
  89. setPinInput(B6); // Try releasing special pins for a short time
  90. setPinInput(B7);
  91. wait_ms(10); // Wait for the release to happen
  92. palSetPadMode(GPIOB, 6, PAL_MODE_ALTERNATE(4) | PAL_STM32_OTYPE_OPENDRAIN | PAL_STM32_PUPDR_PULLUP); // Set B6 to I2C function
  93. palSetPadMode(GPIOB, 7, PAL_MODE_ALTERNATE(4) | PAL_STM32_OTYPE_OPENDRAIN | PAL_STM32_PUPDR_PULLUP); // Set B7 to I2C function
  94. }
  95. ```