I2C通信プログラムを作成する前にPICマイコンの「PPS機能」の使い方を説明します。
PPS機能とは?
突然「PPS機能」なんて用語がでてきて、どこ? I2C通信は?、という感じですが、I2Cプログラム作成の前にPPSの理解が必要になりますのでお付き合いください。
PICマイコンにはいろいろな機能モジュールが内蔵されていますよね。応用編ではPWMなどのPICマイコンに内蔵されている機能をいろいろと使ってタイマー機能を追加しました。実践編では、これからPIC16F18857に搭載されているI2C通信モジュールを使用してプログラムを作成していきます。
ところでこの機能モジュールですが、デフォルトでは特定のピンが割り当てられています。例えば、PIC16F18857には2個のI2C通信モジュールが内蔵されていますが、デフォルトでは以下のようにピンが割り当てられています。
モジュール | ピン |
---|---|
I2C通信モジュール1のSCL | RC3 |
I2C通信モジュール1のSDA | RC4 |
I2C通信モジュール2のSCL | RB1 |
I2C通信モジュール2のSDA | RB2 |
多くのPICマイコンでは、この機能モジュールのピンの割り当てを変更することができるようになっています。この機能のことを「PPS」機能と呼んでいます。「PPS」は「Peripheral Pin Select」の略で、「周辺機能のピン選択」という意味です。意味合いとしては「内蔵機能モジュールのピン割り当て機能」という感じです。
実践編ではI2C通信モジュール1を使用することにしますが、このモジュールのデフォルトの割り当てピンは、SCLがRC3、SDAがRC4となっています(上の表参照)。作成した回路図は、SCLがRC3、SDAがRC2に接続していますので、割り当てピンを変更する必要があります。
そこで、I2C通信プログラムの作成に入る前にPPSの使い方を確認します。
PPSの使い方概要
機能モジュールは以下のように入力部と出力部を持っています。
機能モジュールのピンの割り当ては、以下のように1つの機能モジュールに対して入力部と出力部のピンの割り当てを行います。
なお、図中では任意のピンと記載していますが、機能モジュールにより設定できないピンもありますので注意してください。詳しい内容はこの記事の後半で説明します。
PICマイコンのI2C機能モジュールは、一つの機能モジュールではなく、I2C通信のSCLのモジュールとSDAのモジュールの2つの機能モジュールから構成されています。そのため、以下のように、SCLとSDAのそれぞれに対して、入力ピンと出力ピンを割り当てます。
次にPPSの設定の流れを説明します。PPSのピン割り当て機能はデフォルトではロックされています。そのため、以下のようにロックを解除してからPPSの設定を行い、設定後再度ロックします。
- PPSロック解除
- 機能モジュールの入力部とピンの割り当て
- 機能モジュールの出力部とピンの割り当て
- PPSロック
それでは、この番号順に対応するプログラムを順番に説明します。
1. PPSロック解除
PPSのロックを解除するには、PPSLOCKレジスタのPPSLOCKEDビットを0に設定します。ただ、このビットを変更するには、おまじないが必要になります。
そのおまじないとは、ちょっと不思議なのですがPPSLOCKレジスタに0x55を代入した後、0xAAを代入します。2進数では0b01010101を代入した後に0b10101010を代入することになります。「アリババと40人の盗賊」の話に「開け、ゴマ」という呪文が出てきますが、そんな感じでしょうか。同じレジスタに0x55、0xAAという順番に代入するとPPSLOCKEDビットを変更することができるようになります。
PPSロック解除のプログラムは以下のようになります。
PPSLOCK = 0x55; PPSLOCK = 0xAA; PPSLOCKbits.PPSLOCKED = 0;
2. 機能モジュールの入力部とピンの割り当て
PPSロックの解除ができたら、機能モジュールの入力部にピンを割り当てます。割り当て方は回路図から以下のようになります。
機能モジュール | 割り当てピン |
---|---|
I2C通信モジュール1のSDAの入力部 | RC2 |
I2C通信モジュール1のSCLの入力部 | RC3 |
プログラムでは、以下のように設定することになります。
[機能モジュール名] = [ピン名];それでは、モジュール名とピン名はどのような名称になるのかデータシートの読み方を説明します。
以下の表は、入力部の設定を行うための機能モジュール名の表です。この表は機能モジュール名の他に、デフォルトで割り当てられているピン、設定可能なピンの表になっています。
I2C通信モジュール1の機能モジュール名は、赤枠で囲んだ部分に記載されています。SDAの機能モジュール名は「SSP1DATPPS」、SCLは「SSP1CLKPPS」です。つまり、
SSP1DATPPS = [RC2のピン名];
SSP1CLKPPS = [RC3のピン名];
というように記載することになります。
次にピン名です。ピン名は文字列ではなく数値で指定します。以下は入力部の割り当てピンを設定するための各ピンの設定値の表です。
表中、赤枠で囲んだ部分がRC2とRC3の設定値です。RC2は0x12、RC3は0x13を設定することになります。
以上をまとめると、機能モジュールの入力部の設定は以下のようになります。
SSP1DATPPS = 0x12; // SDA入力部をRC2に設定する SSP1CLKPPS = 0x13; // SCL入力部をRC3に設定する
3. 機能モジュールの出力部とピンの割り当て
次にI2C通信モジュール1のSDA、SCLの出力部の設定を行います。先ほどの入力部と同様、以下のように設定することになります。
機能モジュール | 割り当てピン |
---|---|
I2C通信モジュール1のSDAの出力部 | RC2 |
I2C通信モジュール1のSCLの出力部 | RC3 |
プログラムでは、以下のように設定することになります。
[ピン名] = [機能モジュール名];最初にピン名です。ピン名はフォーマットが決まっていて、以下のように記述します。
ピン名PPS
例えば、RC2であれば「RC2PPS」、RC3であれば「RC3PPS」と記述します。ここまでの説明で、出力部の設定は以下のようになります。
RC2PPS = [SDAのモジュール名];
RC3PPS = [SCLのモジュール名];
次に機能モジュール名の設定です。モジュール名は数値で指定することになります。
以下の表は、出力部の設定を行うための表です。この表は機能名とその設定値が書かれています。またデフォルトで割り当てられているピンも記載されていますが、入力部の表と同じ内容になります。
I2C通信モジュール1のSDAとSCLは赤枠で囲んである部分にあるように、それぞれ0x15、0x14です。プログラムでは以下のように設定することになります。
RC3PPS = 0x14; // RC3をSCLに設定 RC2PPS = 0x15; // RC2をSDAに設定
これで入力部と出力部の設定が完了しました!
4. PPSロック
PPSの設定が終わったら、PPSを変更できないようにロックします。ロックするにはPPSLOCKEDに1をセットすればOKですが、ロック解除の時と同様に呪文が必要になります。
PPSLOCK = 0x55; PPSLOCK = 0xAA; PPSLOCKbits.PPSLOCKED = 1;
I2C通信機能モジュールのPPS設定
今までの設定をまとめると以下のようになります。
// PPS設定ロックの解除 PPSLOCK = 0x55; PPSLOCK = 0xAA; PPSLOCKbits.PPSLOCKED = 0; // I2C通信モジュール1のSCL、SDA入力部のピン割り当て SSP1DATPPS = 0x12; // SDA入力部をRC2に設定する SSP1CLKPPS = 0x13; // SCL入力部をRC3に設定する // I2C通信モジュール1のSCL、SDA出力部のピン割り当て RC3PPS = 0x14; // RC3をSCLに設定 RC2PPS = 0x15; // RC2をSDAに設定 // PPS設定ロック PPSLOCK = 0x55; PPSLOCK = 0xAA; PPSLOCKbits.PPSLOCKED = 1;
これで回路図に合ったI2C通信モジュールのピン割り当てができました。次回はI2C通信モジュールのプログラムを関数として作成します!
更新履歴
日付 | 内容 |
---|---|
2018.6.10 | 新規投稿 |