QtでRaspberryPi/GUI開発(9)-SPI通信をしてみた
公開日:
:
最終更新日:2019/01/30
C言語, pigpio, RaspberryPi, 開発
どもです。
えー。
「Qtで…」とか書いておきながら、今回はQtは出てきません。
今回のエントリでは、RaspberryPi3とpigpio(ライブラリ)を使用してSPI通信をしてみました。
SPI通信に触るのが久しぶり、pigpioを使ってのSPI通信については初めてになります。
また、調べた範囲ではpigpioを使用したRaspberryPi3のSPI通信についての情報は、あまり見つかりません。
なので、同じように困ってる(?)方の助けになればと思い、エントリを書いてみます。
最初は「ループバック」から挑戦です。
1.SPI通信って?
はい。
そもそも、という話です。
「Serial Peripheral Interface」の略称で、同期式シリアル通信の1つです。
細かい説明は、ネットや書籍の情報に任せることにして、ここでは詳細な説明はしません。
今回のエントリでは、「同期式の通信方法」くらいに覚えておけばよいかと考えます。
2.RaspberryPi3でのピン配置は?
SPI通信で使用するピンについて、RaspberryPi3では下記のように配置されています。
- SCLK → 23番(GPIO-11)
- MOSI → 21番(GPIO-9)
- MISO → 19番(GPIO-10)
- CE0 → 24番(GPIO-8)
- CE1 → 26番(GPIO-7)
各ピンの配置についてSCLK、MOSI、およびMISOについては、「ALT0」モードでの動作になります。
なお、これらのピン配置については、RaspberryPi3のコマンドライン上で
1 |
gpio readall |
と入力することで、確認できます。
分かりやすい表が、コマンドライン上に表示されます。
3.pigpioの設定
前の段で、RaspberryPi3のピン配置が分かりました。
次は、pigpioを用いてピンの設定をする必要があります。
と思ったら、pigpioでは「spiOpen()」を実行することで、必要なピン設定は行われるようです。
ただし、この関数では別の設定が必要なようです。
即ち、「通信速度」と「モード」です。
「通信速度」については[bits per second]単位の値を、「モード」については極性とかフェーズとかによって、「0」から「3」まで選択されます。
このモードの設定に従って、信号の出力と読込みのタイミングが変化します。
この「モード」とデータの振る舞いについてはココの内容が詳しくて、分かりやすいかと思います。
少し具体的にすると、以下の手順で設定します。
①:gpioInitialise() – ライブラリを初期化する。
②:spiOpen() – SPI通信の設定を行いつつ、通信ハンドラを取得する。
なお、終了時は
①:spiClose() – SPI通信の設定を解除する。
②:gpioTerminate() – ライブラリを終了する。
の順番で関数を呼び出す必要があります。
4.pigpioでの送受信
pigpioを使用して実際にデータの送受信を行う場合、を使用します。
この関数では、指定されたバッファの規定されたサイズ(バイト)のデータを送信し、また受信したデータを指定されたバッファに格納します。
即ち、データの送受信を一気に実施してくれます。
pigpioには、送信/受信それぞれのためにspiReadやspiWriteが用意されています。
spiXferという関数も用意されています。
この関数は、データの送受信を1つの関数の中で実施してくれます。
今回は、この「spiXfer」を使用します。
5.実装してみた
今回のループバックの実験では、下記のコードを実装しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
/* * main.c * * Created on: 2019/01/27 * Author: CountrySideEngineer */ #include <stdio.h> #include "pigpio.h" #define BUFFER_SIZE (1024) #define TX_BUFF_SIZE BUFFER_SIZE #define RX_BUFF_SIZE BUFFER_SIZE //Declare data type. typedef uint8_t BYTE; typedef uint16_t WORD; typedef uint32_t DWORD; typedef int8_t SBYTE; typedef int16_t SWORD; typedef int32_t SDWORD; /** * @brief Initialize buffer by the value passed via argument, * the variable "value". * @param value The value to initialize the buffer. * @parma bufferSize Size of buffer. */ void initBuffer( BYTE *buffer, BYTE value, int bufferSize) { int index = 0; for (index = 0; index < bufferSize; index++) { *buffer = value; buffer++; } } /** * @brief Show buffer in 16 bytes per line format. * @param[in] messageHeader Message to be shown in top of message; * @param[in] buffer Pointer to buffer to show. * @param bufferSize size of buffer. */ void showBuffer( char *messageHeader, BYTE *buffer, int bufferSize) { int index = 0; if (NULL != messageHeader) { printf("%s : ", messageHeader); } else { printf("NO MESSAGE HEADER : "); } for (index = 0; index < bufferSize; index++) { if ((0 == index) || (0 == (index % 16))) { printf("\n"); } else { printf(" "); } printf("0x%02x", *buffer); buffer++; } printf("\n"); } /** * @brief Main function of SPI sample program of raspberry pi3 * using pigpio library. */ #define SND_RCV_DATA_SIZE (10) int main() { int spiHandler = 0; int index = 0; int subIndex = 0; WORD rcv = 0; BYTE txBuf[TX_BUFF_SIZE] = { 0 }; BYTE rxBuf[RX_BUFF_SIZE] = { 0 }; printf("Start SPI sample\n"); if (gpioInitialise() < 0) { printf("gpioInitialise() failed\n"); return 0; } /* * The unit of second argument is bits per second, and it corresponds * heltz. * It means that, if the value is 10 * 1000 * 1000 = 10,000,000, * it is 10MHz. */ spiHandler = spiOpen(0, 10 * 1000 * 1000, 0); //10M bits per seconds. if (spiHandler < 0) { printf("spiOpen() failed.\n"); gpioTerminate(); return 0; } for (index = 0; index < 100; index++) { initBuffer(txBuf, 0xFF, SND_RCV_DATA_SIZE); initBuffer(txBuf, 0xAA, SND_RCV_DATA_SIZE); for (subIndex = 0; subIndex < SND_RCV_DATA_SIZE; subIndex++) { txBuf[subIndex] = subIndex | 0x80; } spiXfer(spiHandler, (char*)txBuf, (char*)rxBuf, SND_RCV_DATA_SIZE); showBuffer("SND", txBuf, SND_RCV_DATA_SIZE); showBuffer("RCV", rxBuf, SND_RCV_DATA_SIZE); showBuffer("DATA", (unsigned char *)&rcv, 1); } printf("Stop SPI sample\n"); spiClose(spiHandler); gpioTerminate(); return 0; } |
このコードは、下記のようにビルドします。
1 |
gcc -o SPIgpio main.o -lpigpio -lpthread |
H/W的には、19番(GPIO-10)と21番(GPIO-9)のピンを短絡しておいて下さい。
ピンを短絡した状態でビルドしたファイルを実行すると、送信したデータをそのまま受信する、という動作になります。
今回のエントリでは、ループバックテストになりますが、RaspberryPi3でのSPI通信の手順および方法について記載しました。
次回は、SPI通信で実際に他のデバイス/センサーなんかと通信をしてみようと思います。
またQtを使わない…可能性が大いにあります。
ではっ!
参考にしたサイト
・pigpio – http://abyz.me.uk/rpi/pigpio/index.html
・ArduinoでSPI通信を行う方法 – http://stupiddog.jp/note/archives/976
2019/01/30 更新
文言を色々修正しました。
関連記事
-
-
VisualStudioCommunityでのPython開発環境構築
どもです。 最近、VisualStudioでのPython開発を始めました。 その際の環境構築に
-
-
C言語でEV3開発(5)
どもです。 今回のエントリーは、前回のエントリーでちくっと触れた、「単体テスト」について、です。
-
-
QtでRaspberryPi/GUI開発(2):ためしに時計を作ってみた(其の弐)
どもです。 前回のエントリーでは、ラジオボタンのグループ化と、選択されたボタンの特定方法まで記載し
-
-
QtでRaspberryPi/GUI開発(7):pigpioを使用したチャタリング対策の問題
どもです。 前回のエントリーで、pigpioを使用したチャタリング対策について記載しました。 今
-
-
RaspberryPiで物体検出(2)-白線検出への挑戦(2):輪郭検出による白線検出(実機編)
どもです。 今回は、前回に引き続きOpenCvを用いて道路の白線検出について、です。 1.今
-
-
eclipse/CDTにおけるgdbでのデバッグ中に発生するpythonのエラー
どもです。 今回のエントリーは、Eclipse上でのデバッグの際に「pythonのエンコードエラー
-
-
C言語でEV3開発(8)-opOUTPUT_POWERコマンド
どもです。 今回のエントリーでは、EV3でモーターを動かします。 なお、今回のエントリーでも
-
-
C言語でEV3開発(11)-opOUTPUT_STEP_POWERコマンド
どもです。 今回のエントリーでは、再びモーターを動かすためのコマンドについて書きます。 コマンド
-
-
C言語でEV3開発(26)-EV3で機械学習(1)-QLearningをC#に委譲してみた
どもです。 前回の投稿では、Q-LearningをEV3本体に実装してみたら、メモリが足りなくて動
-
-
C言語でEV3開発(27)-EV3にヒステリシス処理を実装してみた
どもです。 今回は、モーターから読み出した値に対するヒステリシス・フィルター処理です。 0.