第30回 温湿度・気圧センサー(動作確認概要)

温湿度・気圧センサーから測定データを取得する前に、簡単なプログラムを作成してSPI通信できるか確認します。

目次

SPI通信確認方法

温湿度・気圧データを取得するプログラムは、データ校正部分がかなり複雑です。最初からそのプログラムを作成すると全体の見通しが悪くなってしまいます。

そこで、最初はSPI通信の動作確認を行うためのシンプルなプログラムを作成することにします。


このセンサーのメモリマップを見ると、0xD0番地にセンサのIDが保存されています

ここに保存されている値は0x60で固定となっています。

そこで、0xD0番地のデータをSPI通信で読み取るプログラムを作成し、0x60が正しく取得できるか確認することによりSPI通信の動作確認を行います


ところで、プログラムで0xD0番地のデータを読み取るのはいいとしても、その値を確認方法がありませんよね。

LCDモジュールを利用する方法がありますが、まだ動作させていませんので、読み取った値をLCDモジュールに表示して確認することはできません。

そこでセンサから取得した値を確認するために、MPLAB X IDEの「デバッグ機能」を使用します。

デバッグ機能については、実際に使用する際に詳しく説明しますので、ここでは「デバッグ機能」とはどのようなものか簡単に説明します。

今まで、PICマイコンを動作させる場合の手順は、MPLAB X IDE上でプログラムを作成→ビルド→PICマイコンに書き込み→動作、というステップでした。

このような手順では、PICマイコンが思った通りに動作する場合は問題ないですが、うまく動かない場合、PICマイコンの中で何が起こっているのか知りたいですよね。

MPLAB X IDEのデバッグ機能を使うと、PICマイコン内部で動作しているプログラムを指定した行で動作を止めて、変数の内容を確認しながらプログラムを1行ずつ動作させることができます。

このあとの説明は次のように進めます。

STEP
動作確認プログラム概要(今回の記事)

最初に動作確認プログラムでどのようなSPI通信を行うか、概要を説明します。

STEP
動作確認プログラム作成(次回第31回の記事)

実際にSPI通信の動作確認用のプログラムを作成します。

STEP
デバッグ機能による動作確認(第32回・第33回の記事)

デバッグ機能を利用して、SPI通信で取得したIDの値を確認します。
MPLAB X IDEのデバッグ機能の基本的な使い方も習得します。

使用するピンの確認

SPI通信を行うために、PICマイコンとセンサモジュールは以下のように接続しました。

このように接続すると、PICマイコン側のSPI通信用のピンは以下のように割り当てることになります。

ピン番号ポート名機能
15RC4CSB(チップセレクト)
16RC5MOSI(PICマイコン ➡︎ センサー)
17RC6MISO(センサー ➡︎ PICマイコン)
18RC7SCK(クロック)

SPI通信は、RC4 〜 RC7のピンをデジタル制御しながら行うことになります。

プログラムでは次のように記述して制御することになります。

LATCbits.LATC4 = 0;

ただ、このように記述すると、どのピンがどの信号線か分かりづらくなりますので、次のように名前定義することにします。

// SPI通信ピンの名前定義
#define SPI_SCK    LATCbits.LATC7  // SCK (クロック)
#define SPI_MISO   PORTCbits.RC6   // MISO (センサーからPICマイコン)
#define SPI_MOSI   LATCbits.LATC5  // MOSI (PICマイコンからセンサー)
#define SPI_CSB    LATCbits.LATC4  // CSB (チップセレクト)

なお、PICマイコンのピン入出力設定は次のようになります。

ポート名機能入出力
RC4CSB(チップセレクト)出力
RC5MOSI(PICマイコン ➡︎ センサー)出力
RC6MISO(センサー ➡︎ PICマイコン)入力
RC7SCK(クロック)出力

出力制御はLATレジスタ、入力値読み取りはPORTレジスタを使用しますので、上のように名前定義しています。

0xD0番地の読み出し手順

SPI通信で0xDO番地の読み出す場合、次のように通信を行います。

また、SPI通信手順は以下のようになります。(クリックすると拡大できます)

SPI通信の基本関数作成

SPI通信手順が確認できたところで、プログラムを作成します。

SPI通信を行うために、「8ビット送信」と「8ビット受信」の部分を関数として作成しておくことにします。(クリックすると拡大できます)

8ビット送信関数

8ビット送信関数として、次の部分をプログラム作成します。(クリックすると拡大できます)

この図のように、次の処理を8回繰り返せばSPIデータ送信ができます。

  1. SCKピンを0にする
  2. MOSIピンに送信するビットデータをセットする
  3. SCKピンを1にする

プログラムとしては以下のように作成してみました。

//
// SPIデータ8ビット書き込み
//   チップセレクト信号はこの関数の前後で制御する
//
void spiSend8bit(uint8_t data) {

    // 8ビット分繰り返す
    for (int8_t i=7; i>=0; i--) {

        // ❶SCKピンを0にする
        SPI_SCK = 0;
        
        // ❷MOSIに送信するビットデータをセットする
        if( data & (1<<i) ) {
            SPI_MOSI = 1;
        } else {
            SPI_MOSI = 0;
        }
      
        // ❸SCKピンを1にする
        SPI_SCK = 1;
    }

}

このプログラムについて、2点補足します。


1点目は変数型についてです。

基礎編と応用編では、変数を宣言するときの型指定はunsigned charなどを使用していました。

実践編では、変数のビット数が分かりやすいint_t型を使用することにしました。

なお、この変数型を使用する場合、stdint.hをインクルードする必要があります。

int_t型には次の型があります。

変数型意味
int8_t符号付き8ビット
uint8_t符号付き8ビット
int16_t符号付き16ビット
uint16_t符号なし16ビット
int32_t符号付き32ビット
uint32_t符号なし32ビット

符号付きが「int」(integer・整数)、符号なしが「uint」(unsigned integer・符号なしの整数)、数字がビット数を表しますので、分かりやすい変数型かなと思います。


2点目はビット演算についてです。

関数内では、data & (1<<i)として、iビット目の値を取り出しています。

(1<<i)という部分で、1をi回左にずらします。例えばiが3のとき、0b00001000になります。

さらに、この値をdataと論理積(&)を取ることによって、iビット目の値を取り出しています。

この結果をifで判定しますので、0であればfalse、1であればtrueとなり、送信するデータを設定しています。

(ちょっとわかりづらいですよね…。よく使われるテクニックですので、頭の片隅に置いておいていただければと思います)

8ビット受信関数

8ビット受信関数として、次の部分をプログラム作成します。(クリックすると拡大できます)

この図のように、次の処理を8回繰り返せばSPIデータ受信ができます。

  1. SCKピンを0にする
  2. SCKピンを1にする(この段階でセンサーのデータが読めるようになります)
  3. MISOのデータを読む

プログラムとしては以下のように作成してみました。

//
// SPIデータ8ビット読み込み
//   スレーブセレクト信号はこの関数の前後で制御する
//
uint8_t spiReceive8bit(void) {

    // 受信データ格納変数
    uint8_t read_data = 0;

    // 8ビット分繰り返す
    for (int8_t i=7; i>=0; i--) {

        // 受信データ変数を1ビット左シフト
        read_data << 1;

        // ❶SCKピンを0にする
        SPI_SCK = 0;
        
        // ❷SCKピンを1にする
        SPI_SCK = 1;

        // ❸MISOのピン状態を読む
        if(SPI_MISO){
            read_data |= 1;
        }
    }

    // 受信したデータを返す
    return read_data;

}

8ビットの送信と受信関数ができましたので、次回の記事で、これらの関数を利用して0xD0番地のデータを読み取るプログラムを作成します。

更新履歴

日付内容
2018.4.27新規投稿
2019.4.20ソースコード文字化け修正
2025.7.29「マスター」「スレーブ」を「ホスト」「デバイス」に変更
通知の設定
通知タイミング
guest
6 コメント
新しい準
古い順 一番投票が多い
本文中にフィードバック
全てのコメントを見る
aaa
aaa
3 年 前

お世話になります
// 受信データ変数を1ビット左シフト
        

read_data <<= 1;
の個所ですが
1ビットシフトしたら2番目に行くのではと思って
シフト無しで確認しても結果は同じでした
初期値は0でも1シフトでも同じという事で良いんですかね
デバックが使えだして理解が深まりそうです

aaa
aaa
返信  管理者
3 年 前

返信ありがとうございます
昨日やってたことが今日見たら分からない状況で
酒飲みながら朦朧としながらやってるんで
物凄い勘違いしてたような気がします

初学者
初学者
5 年 前

読んでいて自己解決しました。
ビット位置をずらすためですね。
申し訳ありませんでした。

初学者
初学者
5 年 前

上記プログラム(8ビット受信関数)で初歩的ではありますが質問があります。

14行名
// 受信データ変数を1ビット左シフト
read_data <<= 1; と記載がありますがこの理由を詳しく聞きたく。

目次