人気ブログランキング | 話題のタグを見る

[PC-G850V] ポケコンでI2C通信 実機確認 - ピンのON/OFFを見直し 図解 (6/13)

(5/16追記)
間違っている旧4=SCL、5=SDAの回路図だけは修正済み。
これに伴うChatGPTの回答は、4を5、5を4に置き換えて読む事。
(5/16追記おわり)

つまり、どういうことかと言うと、

マスタ側データ送信は、次のようになる。
データ1を送信する例を4ピンで、
データ0を送信する例を5ピンで説明する。

[マスタ側データ送信]

[PC-G850V] ポケコンでI2C通信 実機確認 - ピンのON/OFFを見直し 図解 (6/13)_a0034780_03442748.png

(5/16追記)4、5ピンの役割を取り違えたのでSCLとSDAをSDAとSCLに修正済み(おわり)
【SDA/SCLへの出力の場合】
(4,5)=(SDA 0,SCL 0):pioset(0),pioput(0)
(4,5)=(SDA 1,SCL 0):pioset(1),pioput(1)
(4,5)=(SDA 0,SCL 1):pioset(2),pioput(2)
(4,5)=(SDA 1,SCL 1):pioset(3)
(5/16追記修正ココまで)
と設定する。

マスタから0を送りたい時は、ポートを出力モードにして0を出力し、
マスタから1を送りたい時はポートを解放すると、入力に自然となるのだ。

オープンドレイン方式(回路的にはワイヤードAND構成)というやつだ。

※ マスタからデータを送りたいのと、ポート(ピン)の出力モードは別物だという事!
電気理論は奥が深いな~


で、このオープンドレイン方式で、マスタ側データ入力は、以下のようにする。

[マスタ側データ入力]
[PC-G850V] ポケコンでI2C通信 実機確認 - ピンのON/OFFを見直し 図解 (6/13)_a0034780_03443648.png

(5/16追記)4、5ピンの役割を取り違えたのでSCLとSDAをSDAとSCLに修正済み(おわり)
【SDA/SCLからの入力の場合】
(5/16追記修正ココまで)
(4,5)=(0,0):pioset(3),w=pioget(),(w & 0x03)==0
(4,5)=(1,0):pioset(3),w=pioget(),(w & 0x01)==1→0x03
(4,5)=(0,1):pioset(3),w=pioget(),(w & 0x02)==10x03,2
(4,5)=(1,1):pioset(3),w=pioget(),(w & 0x03)==3

となるという事。

ここで、以下のようにChatGPTにチェックをかけてもらったら、取り消し線の指摘が的確にあったので、修正した。

素晴らしい事に、「クロスストレッチ」による、ACK受信待ちの方法もついでに教えてくれた。感謝。


(5/16追記 ここからは修正できないのでそのままにしてある。↑上のピンとpio関数の関係とSDA/SCLで読み解く事。)
[ChatGPTとのやり取り]
~~~~~
質問:
これで合っていますか?
【両4,5ピン出力の場合】
(4,5)=(SCL 0,SDA 0):pioset(0),pioput(0)
(4,5)=(SCL 1,SDA 0):pioset(1),pioput(1)
(4,5)=(SCL 0,SDA 1):pioset(2),pioput(2)
(4,5)=(SCL 1,SDA 1):pioset(3) と設定
【両4,5ピン入力の場合】
(4,5)=(0,0):pioset(3),w=pioget(),(w & 0x03)==0
(4,5)=(1,0):pioset(3),w=pioget(),(w & 0x01)==1
(4,5)=(0,1):pioset(3),w=pioget(),(w & 0x02)==1
(4,5)=(1,1):pioset(3),w=pioget(),(w & 0x03)==3
回答:
はい、基本的な考え方は合っています。

ただし、**I2Cとしては「1を出力する」のではなく、「1は入力(Hi-Z)にする」**という考え方になるので、少し整理すると分かりやすくなります。

出力
SCL SDA 設定
0 0 pioset(0), pioput(0)
1 0 pioset(1), pioput(1)
0 1 pioset(2), pioput(2)
1 1 pioset(3)

ここで、

pioset(0):4,5ピンとも出力
pioset(1):4ピン入力、5ピン出力
pioset(2):4ピン出力、5ピン入力
pioset(3):4,5ピンとも入力

だとすると、

(SCL,SDA)=(0,0)
→両方を出力にして0を出力

(SCL,SDA)=(1,0)
→SCLを入力(解放)
→SDAを出力0

(SCL,SDA)=(0,1)
→SCLを出力0
→SDAを入力(解放)

(SCL,SDA)=(1,1)
→両方入力(解放)

となり、I2Cとして理想的です。

入力

ここは少し修正した方がよいです。

pioset(3); // 両方入力
w = pioget();

として、

(w & 0x03)==0 // (0,0)
(w & 0x03)==1 // (1,0)
(w & 0x03)==2 // (0,1)
(w & 0x03)==3 // (1,1)

と判定するのが自然です。

質問の

(w & 0x02)==1

は、

w & 0x02

の結果が取り得る値は

0
2

なので、

(w & 0x02)==1

は常に偽になります。

したがって

(0,1):(w & 0x03)==2

または

(w & 0x02)!=0

とする必要があります。

ACK受信

例えば、

// SDA解放
(5/16追記 下からここも意味がわかったので修正できる - ↑上から、解放は入力モードにする事)
pioset(1); // SCLDA入力、SDACL出力0
pioput(
);

// SCL解放
pioset(3);

// クロックストレッチ待ち
do{
  w = pioget();
(5/16追記 下からここも意味がわかったので修正できる)
}while((w & 0x01)==0); // SCL=1待ち

// SDA読む
(5/16追記 ここは意味がはっきりしてるので修正できる)
if((w & 0x02
1)==0)
  ACK;
else
  NAK;

のようにすると、クロックストレッチ対応のI2Cになります。


この pioset() と pioput() の仕様が、

bit0 = 4ピン(SCL)←(5/16追記 残念。ここ以降ChatGPTの誤回答がわからなくなるので残す)
bit1 = 5ピン(SDA)
pioset():1=入力、0=出力
pioput():出力時の値

であるなら、PC-G850VのソフトウェアI2Cとしてかなり美しい実装になっていると思います。特に (1,1)=pioset(3) だけで両線を解放できるので、START、STOP、ACK、クロックストレッチの処理が非常に書きやすそうです。
~~~~~(ChatGPTの回答おわり)

これで、メインである旧出力pioput(n)をそれぞれ書き換えると、
マスタ側データ送信の上から順に対応するので、

☆ 次の記事でやらかしたので、逆と勘違いしやすいのであえてここに書く。
(これより上の内容にも間違いがありそうなので見直すように!)

(5/16追記やっと追いついた。ここからは逆だったことに気が付いている)
☆ bit 0が4ピンでSDA、bit 1が5ピンでSCLであるので、

旧pioput(0)→pioset(0),pioput(0) /* bit 0:SDA 0,bit 1:SCL 0 */
旧pioput(1)→pioset(1),pioput(1) /* bit 0:SDA 1(入力モードで1を出力しても無効なのがポイント), bit 1;SCL 0 */
旧pioput(2)→pioset(2),pioput(2) /* bit 0:SDA 0,bit 1:SCL 1 */
旧pioput(3)→pioset(3) /* bit 0,1:SDA 1,SCL 1(入力モードにするとオープンドレインでHiになる) */

に書き換えればよい。

そして、ACK受信処理は、
例えばの後のSDA解放・SCL解放・クロックストレッチ待ち・SDA読むをそのまま採用する。

Cソースを書き換えよう。出力側のコメントも、1をxxx入力、0をxxx解放、に修正しよう。

by k1segawa | 2026-06-13 22:28 | ポケコン | Comments(0)