ジャンル不定の日記です。

I2C-cm3-USB

STM32F042用のI2C-Tiny-USB互換ファームウェアです。
標準のI2C-Tiny-USBドライバで認識します。
libopencm3を利用するのでcm3にしてますがSTM32F0はCortex-M0です。
libopencm3以外のAPIは使用していないので、libopencm3が対応するUSB搭載マイコンなら移植は難しくないんじゃないかと思います。

I2Cの機能フラグは確認したもの以外はコメントアウトしているのでI2C-Tiny-USBの全機能に対応していません。
無効機能の中にはフラグの追加だけで機能するものもあるかもしれません。

標準でSWDIO(PA13)とSWCLK(PA14)を使用する様になっています。
DFUが利用できない場合は変更が必要です。
標準だとPF0とPF1以外は全ピン使用します。

USB to I2C以外に、
USARTブリッジ
仮想PCF8574(GPIOエクスパンダ)
仮想PCA9685(PWM LEDコントローラ)
仮想MCP3221(ADコンバータ)
の機能があります。

USARTブリッジUSART1(PA9とPA10)とUSART2(PA2とPA3)を繋ぎます。
PA9とPA10は5V入力対応なので、5V専用のシリアルケーブル(中華PL2303等)を母艦とUSART1に接続して3.3V専用デバイスに中継する用途を想定しています。
5V駆動のPL2303は3.3Vの信号でHになります。
PA2とPA3は5V入力非対応です。
バッファ(標準で1024byte)が溢れた場合は消えます。
USART1のTXに向かうデータのバッファはデバッグ出力と共通です。
USARTに対してUSBはかなり速いので、USBコマンドに対してデバッグ出力しているような場合は簡単にバッファを使い切ります。

I2C-Tiny-USB 本家はAVRマイコンを使用したUSB to I2Cアダプタです。
ドライバが有効ならUSBケーブルを接続すれば利用できます。

$ i2cdetect -l
I2Cバスの一覧が表示されます。

$ sudo i2cdetect -F 13
利用可能なI2C機能が確認できます。(13のところは環境による)

$ sudo i2cdetect -y 13
バスに接続されたI2Cデバイスのアドレス一覧が表示されます。

仮想PCF8574I2C接続の8ピンGPIOエクスパンダです。
標準でアドレス0x1Fに設定しています。
本物のPCF8574は電源電圧の出力が行なえますが、5V入力を考慮して標準で内部プルアップOFFのオープンドレインに設定しているため回路に接続しないとHになりません。
Nch-MOSFETを使うならプッシュプルに変更すればHで押せると思います。
リードオンリーのピンを設定できます。
PA8に直列抵抗と外部プルアップをつけたうえで本物のI2CデバイスのINTピンを接続することを想定した設定になっています。

$ sudo sh -c 'echo pcf8574 0x1f > /sys/bus/i2c/devices/i2c-13/new_device'
でlibgpiodが利用できます。(libgpiod2と旧libgpiodで仕様が大きく違うらしいです。)

$ sudo gpioinfo
ピンの一覧が表示されます。
CPUがgpiochip0にあると思うのでgpiochip1以降になります。

$ sudo gpioinfo -c gpiochip1
対象gpiochip1のみのピンの一覧が表示されます。

$ sudo gpioset -c gpiochip1 -t 0 0=1
1番目のピンがHになります。-t 0を指定しない場合、コマンドは終了しません。

$ sudo gpioget -c gpiochip1 0
1番目のピンの状態が表示されます。
この際gpiogetコマンドは対象ピンに1をwriteしてからreadするため、仮想ピンの場合は必ずHになります。
リアルピンの場合は回路状況によります。

仮想PCA9685I2C接続の16ch PWM LEDコントローラです。
標準でアドレス0x1Eに設定しています。
本物は所有してないので本物との差異は確認できません。
HでLEDを光らせる場合はN-MOS等のスイッチが必要です。Lで直接光らせる場合は電圧と電流に注意。
標準設定は内部プルアップOFFのオープンドレインで、L=ONでH=OFFを想定した設定になっています。
標準設定のピンは5V入力非対応です。5V入力対応のピンを割り当てることも可能です。

$ sudo sh -c 'echo pca9685 0x1E > /sys/bus/i2c/devices/i2c-13/new_device'
で/sys/class/pwm/pwmchip0などが出現します。

$ sudo sh -c 'echo 0 > /sys/class/pwm/pwmchip0/export'
で/sys/class/pwm/pwmchip0/pwm0が出現します。
本物はこの時点でenable=0じゃないかと思うのですが、どういうわけかこの時点でenable=1になります。

$ sudo sh -c 'echo 1000000 > /sys/class/pwm/pwmchip0/pwm0/period'
周期1000000(1000000ns=1000Hz)を設定します。

$ sudo sh -c 'echo 500000 > /sys/class/pwm/pwmchip0/pwm0/duty_cycle'
periodの半分の値でデューティー比50%になります。
exportした時点でenable=1ならここで始動します。

$ sudo sh -c 'echo 1 > /sys/class/pwm/pwmchip0/pwm0/enable'
停止中の場合はデューティー比が送信されて始動します。

$ sudo sh -c 'echo 0 > /sys/class/pwm/pwmchip0/pwm0/enable'
停止します。

仮想MCP3221I2C接続の1ch 12bit ADコンバータです。
標準ではアドレス0x10から0x15の6デバイスを設定しています。
本物は所有してないので本物との差異は確認できません。
要求時に前回変換値を渡して1回AD変換を行うので、初回要求時は0が返されます。
I2Cの速度的にありえないかもですが、AD変換中に次の要求がきた場合は変換がスキップされます。
ADC対応ピンはすべて5V入力非対応です。
標準ドライバは基準電圧(電源電圧)を設定する機能がないようなので補正する必要があるかもしれません。(手元では3.3V基準で表示されました。)

$ sudo sh -c 'echo mcp3221 0x10 > /sys/bus/i2c/devices/i2c-13/new_device'
で/sys/class/i2c-dev/i2c-13/device/13-0010/hwmonが出現します。

$ cat /sys/class/i2c-dev/i2c-13/device/13-0010/hwmon/hwmon5/in0_input
などで対象chの電圧が取得できます。(ADC_CHANNEL_TEMPの場合は電圧ではなく温度です。)


配布物
i2c-cm3-usb.202611-1.tar.xz