MachiKaniaでI2C接続 技術編
2017年3月12日
「MachiKaniaでI2C接続」の技術的なことに関するメモ。なお、この記事はver 0.5に基づいて記述されている。
I2C接続のBASICコードのSVNレポジトリーは、こちら。
https://osdn.net/users/kmorimatsu/pf/kmbasic/scm/tree/head/applications/trunk/i2c/
主に、I2Cnauplia.txtで記述しているコードについて、解説したい。以下の図の黒字で記述された部分は、I2C仕様書からの引用である。
このシグナルを、BASICコードでどの様にして扱っているかについて(赤字での記述)、述べる。
PIC32ペリフェラルへのBASICコードからのアクセス
コード中で、コメントを以下のように書いた。
PORTBからの読み込みも、以下の例のように、「B(4)」の値を読み込むことで可能である。
I2Cシグナル作成
I2Cで1ビットのデーター部分処理部分をピックアップすると、以下のようになる。
I2Cの接続速度を100 kHzとする実装にした。1クロックに10 μ秒の時間を掛けることになる。上図で赤点線の部分でシグナルのやりとりを行なうので、2.5 μ秒と5 μ秒の待ち時間を儲ける必要がある。この時間待ちルーチンを、以下のように記述した。
これに従い、Lシグナルを1ビット送出するルーチン(I2CWL)は、以下のような仕様にした。
1. SDA=L
2. 2.6 μ秒待ち
3. SCL=H
4. 5.2 μ秒待ち
5. SCL=L
6. 2.6 μ秒待ち
また、Hシグナルを1ビット送出するルーチン(I2CWHR)は、以下のような仕様。ただし、1ビット読み込みも兼ねている。
1. SDA=H
2. 2.6 μ秒待ち
3. SCL=H
4. 5.2 μ秒待ち
5. データー読み取り
6. SDA=Lなら、L出力
7. SCL=L
8. 2.6 μ秒待ち
これらのルーチンが、完全なI2Cシグナルにどう対応するのかは、最初の図を参照して頂きたい。StartシグナルとStopシグナルも、同様に、I2CSとI2CPで作成される。なお、I2CSは、Repeated Startにも対応している。
I2C通信の例
記述が簡潔な、Zoea用のコードを取り上げて説明する。出力は、例えば次のコードのように実装している。
入力は、次のコードのように実装している。
通信速度
MachiKaniaではNTSCビデオシグナルの作成にCPUのリソースをかなり取られるので、実際の速度は100 kHzよりも落ちる。SYSTEMステートメントでビデオ出力を停止すれば、最大速度で接続する事が出来る。
I2C接続のBASICコードのSVNレポジトリーは、こちら。
https://osdn.net/users/kmorimatsu/pf/kmbasic/scm/tree/head/applications/trunk/i2c/
主に、I2Cnauplia.txtで記述しているコードについて、解説したい。以下の図の黒字で記述された部分は、I2C仕様書からの引用である。
このシグナルを、BASICコードでどの様にして扱っているかについて(赤字での記述)、述べる。
PIC32ペリフェラルへのBASICコードからのアクセス
コード中で、コメントを以下のように書いた。
REM PIX32MX peripheral: REM TRISB =0xBF886110 REM TRISBCLR=0xBF886114 (TRISB+4*1) REM TRISBSET=0xBF886118 (TRISB+4*2) REM PORTB =0xBF886120 (TRISB+4*4) REM LATBCLR =0xBF886134 (TRISB+4*9)TRISBのアドレスは0xBF886110で、TRISBCLR, TRISBSET, PORTB, LATBCLRはそれぞれ、TRISBより1, 2, 4, 9 ワード先にある。BASICのコード中では、配列を記述する方法で、以下の例のようにアクセスすることが可能である。
B=0xBF886110 B(2)=gosub(I2CCLK)+gosub(I2CDAT) B(9)=gosub(I2CCLK)+gosub(I2CDAT)この例では、TRISBSETに0x0480を、LATBCLRに0x0480を出力している(gosub(I2CCLK)は0x0400を、gosub(I2CDAT)は0x0080を返す)。RB7とRB10の両方を読み込みに設定し、LATB7とLATB10をLに設定するためのコードである。
PORTBからの読み込みも、以下の例のように、「B(4)」の値を読み込むことで可能である。
if B(4) and gosub(I2CDAT) then I2CWH2PORTB10からの読み込み値に従って、分岐している。
I2Cシグナル作成
I2Cで1ビットのデーター部分処理部分をピックアップすると、以下のようになる。
I2Cの接続速度を100 kHzとする実装にした。1クロックに10 μ秒の時間を掛けることになる。上図で赤点線の部分でシグナルのやりとりを行なうので、2.5 μ秒と5 μ秒の待ち時間を儲ける必要がある。この時間待ちルーチンを、以下のように記述した。
REM Wait for 2.6 usec exec 0x34020090,0x1440FFFF,0x2442FFFF REM Wait for 5.2 usec exec 0x34020120,0x1440FFFF,0x2442FFFF2.6 μ秒待ちのコードのアセンブリは、以下のようなものである。
ORI $zero,$v0,0x0090 BNE $v0,$zero,0xffff ADDIU $v0,$v0,0xffff2倍の時間待ちのルーチンも、同様の物である。
これに従い、Lシグナルを1ビット送出するルーチン(I2CWL)は、以下のような仕様にした。
1. SDA=L
2. 2.6 μ秒待ち
3. SCL=H
4. 5.2 μ秒待ち
5. SCL=L
6. 2.6 μ秒待ち
また、Hシグナルを1ビット送出するルーチン(I2CWHR)は、以下のような仕様。ただし、1ビット読み込みも兼ねている。
1. SDA=H
2. 2.6 μ秒待ち
3. SCL=H
4. 5.2 μ秒待ち
5. データー読み取り
6. SDA=Lなら、L出力
7. SCL=L
8. 2.6 μ秒待ち
これらのルーチンが、完全なI2Cシグナルにどう対応するのかは、最初の図を参照して頂きたい。StartシグナルとStopシグナルも、同様に、I2CSとI2CPで作成される。なお、I2CSは、Repeated Startにも対応している。
I2C通信の例
記述が簡潔な、Zoea用のコードを取り上げて説明する。出力は、例えば次のコードのように実装している。
gosub I2CZ,0x40,0x00,0xFE,-1I2CZサブルーチンが呼ばれると、まずI2CSサブルーチンによりStartシグナルが送出され、続けて0x40, 0x00, 0xFEの3バイトのコードが送出される。なお、1バイトごとにACKシグナルが返されることを確認している。最後に、-1のところでI2CPサブルーチンが呼ばれて、Stopシグナルが送出される。
入力は、次のコードのように実装している。
gosub(I2CZ,0x40,0x13,-3,0x41,-2)まず、0x40, 0x13を続けて出力し、次に-3でRepeated Startシグナルを送る。続けて0x41で読み込みモードに指定し、最後に-2でNAKモードの1バイト読み込みを行なう。
通信速度
MachiKaniaではNTSCビデオシグナルの作成にCPUのリソースをかなり取られるので、実際の速度は100 kHzよりも落ちる。SYSTEMステートメントでビデオ出力を停止すれば、最大速度で接続する事が出来る。