BCM2835ライブラリ その6 [Raspberry Pi]
BCM2835ライブラリの日本語解説の最終回。サンプルコードをまとめておしまいにする。せっかくなので、今回の記事をまとめてLaTeXで整形したpdfをここに置いておく。BCM2835ライブラリを使おうという人のために。
このイベントという機能はbcm2835ライブラリ特有の考え方らしく、結局ポーリングしないといけないので、ちょっと中途半端。できればコールバックのような仕組みにしてもらったらよかった。
でも想定している使い方はおそらく、いわゆるイベントドリブンな、例えば細いパルスが入るとそれを合図に何かの作業をする、というのではないのだろう。主となる作業中に、ある条件が満たされないと先に進めないというような、初めから淡々と手順を進めていく途中での段階制御に使う、みたいな感じに思える。
組み込みにはよくあるパターンなのかもしれない。
データ転送の前に幾つかの設定が必要だけど、それは実際に接続されるスレーブデバイスに合わせることになる。設定の詳細は英語版のWikipediaを参照するのが手っ取り早い(残念だけど日本語版に情報はない)。
1バイトとやりかたは同じだけど、バッファが使い回されてスレーブからのデータで上書きされることに注意を要する。
コマンドラインからgpio、あるいはi2cを読んだり書いたり設定したりできる。ハイフン('-')に続いてこれが顔文字みたいになったけどそうではなくて、コマンドキャラクタを続ける、というunixによくあるスタイルになっている。
引数無しでとりあえず動かしてみると、usageが表示されるので、それを参考に試してみればいい。
ソースは順に読んでいけばわかるようになっている。
i2cのほうには、ファイルの先頭のコメント部分にA/DコンバータのADC1015とD/AのMCP4725をi2cにつないだ場合に読み書きするためのコマンドラインシーケンスが書いてある。
ライブラリそのものは見てきたように非常にシンプルなもので、自分で書いてもそれほど手間はかからないようなものだけど、他のライブラリを使っていないなら
僕はこのままでありがたく使わせてもらうことにする。
4 サンプルコード
僕が使ったコードを入れようと思ったけど、いろいろなことをやるせいで回りくどくて長いので、もともとbcm2835の配布についているexamplesを解説することにする。 examplesには- blink
- event
- gpio
- i2c
- input
- pwm
- spi
- spin
% cc example.c -o example -l bcm2835 % sudo ./exampleで実行できる。もちろんライブラリ本体とヘッダが読めるパスの上にインストールされていることが前提である。
4.1 blink
Raspberry PiのP1コネクタの11番ピンを0.5秒ごとにオン/オフするサンプルコード。#include <bcm2835.h> #define PIN RPI_GPIO_P1_11 int main(int argc, char **argv) { // これを実行してGPIOにアクセスできていなかったら // これを読んでテストする // bcm2835_set_debug(1); if (!bcm2835_init()) return 1; // ピンを出力に設定する bcm2835_gpio_fsel(PIN, BCM2835_GPIO_FSEL_OUTP); // Blink while (1) { // オン bcm2835_gpio_write(PIN, HIGH); // ちょっと待って bcm2835_delay(500); // オフ bcm2835_gpio_write(PIN, LOW); // また待って bcm2835_delay(500); } bcm2835_close(); return 0; }解説不要のコードである。本体は無限ループでプロセスを殺さないと止まらないので、とうぜんソースにあるclose()関数は呼ばれることはない。
4.2 input
これはRaspberry PiのP1コネクタの15番ピンを読み込む。#include <bcm2835.h> #include <stdio.h> #define PIN RPI_GPIO_P1_15 int main(int argc, char **argv) { if (!bcm2835_init()) return 1; // P1の15ピンを入力にセットする bcm2835_gpio_fsel(PIN, BCM2835_GPIO_FSEL_INPT); // ついでにプルアップ bcm2835_gpio_set_pud(PIN, BCM2835_GPIO_PUD_UP); // Blink while (1) { // データを読む uint8_t value = bcm2835_gpio_lev(PIN); printf("read from pin 15: %d\n", value); // ちょっと待つ delay(500); } bcm2835_close(); return 0; }
4.3 event
このサンプルはGPIOのイベントの使い方。15ピンがLOWに落ちたらイベントが発生する。#include <bcm2835.h> #include <stdio.h> #define PIN RPI_GPIO_P1_15 int main(int argc, char **argv) { if (!bcm2835_init()) return 1; // P1の15ピンを入力に設定 bcm2835_gpio_fsel(PIN, BCM2835_GPIO_FSEL_INPT); // プルアップする bcm2835_gpio_set_pud(PIN, BCM2835_GPIO_PUD_UP); // LOWの検出ができるようにする bcm2835_gpio_len(PIN); while (1) { if (bcm2835_gpio_eds(PIN)) { // 次のイベントを待つためにフラグをセットしなおす bcm2835_gpio_set_eds(PIN); printf("low event detect for pin 15\n"); } // ちょっと待つ delay(500); } bcm2835_close(); return 0; }ちょっとだけ注意が必要なのは、イベントが検出された状態はeds関数でチェックしたあとも変化しないらしい。従ってedsでチェックしたあとはset_edsでイベント検出をセットしなおす(検出済みであることを知らせる)必要がある。
このイベントという機能はbcm2835ライブラリ特有の考え方らしく、結局ポーリングしないといけないので、ちょっと中途半端。できればコールバックのような仕組みにしてもらったらよかった。
でも想定している使い方はおそらく、いわゆるイベントドリブンな、例えば細いパルスが入るとそれを合図に何かの作業をする、というのではないのだろう。主となる作業中に、ある条件が満たされないと先に進めないというような、初めから淡々と手順を進めていく途中での段階制御に使う、みたいな感じに思える。
組み込みにはよくあるパターンなのかもしれない。
4.4 spi
spiを使って1バイト送って1バイト読み込む。このサンプルではRaspberry Piのspi入力(MISO)をspi出力(MOSI)にそのままつないで、ループバックさせることを想定している。データ転送の前に幾つかの設定が必要だけど、それは実際に接続されるスレーブデバイスに合わせることになる。設定の詳細は英語版のWikipediaを参照するのが手っ取り早い(残念だけど日本語版に情報はない)。
#include <bcm2835.h> #include <stdio.h> int main(int argc, char **argv) { if (!bcm2835_init()) return 1; bcm2835_spi_begin(); bcm2835_spi_setBitOrder(BCM2835_SPI_BIT_ORDER_MSBFIRST); // The default bcm2835_spi_setDataMode(BCM2835_SPI_MODE0); // The default bcm2835_spi_setClockDivider(BCM2835_SPI_CLOCK_DIVIDER_65536); // The default bcm2835_spi_chipSelect(BCM2835_SPI_CS0); // The default bcm2835_spi_setChipSelectPolarity(BCM2835_SPI_CS0, LOW); // the default // 1バイトスレーブに送って同時にスレーブから返ってくる1バイトを読みこむ // MISOをMISOに接続してあったら、送ったものがそのまま読まれる uint8_t send_data = 0x23; uint8_t read_data = bcm2835_spi_transfer(send_data); printf("Sent to SPI: 0x%02X. Read back from SPI: 0x%02X.\n", send_data, read_data); if (send_data != read_data) printf("Do you have the loopback from MOSI to MISO connected?\n"); bcm2835_spi_end(); bcm2835_close(); return 0; }
4.5 spin
このサンプルはspiでマルチバイト転送する場合のもの。1バイトとやりかたは同じだけど、バッファが使い回されてスレーブからのデータで上書きされることに注意を要する。
#include <bcm2835.h> #include <stdio.h> int main(int argc, char **argv) { if (!bcm2835_init()) return 1; bcm2835_spi_begin(); bcm2835_spi_setBitOrder(BCM2835_SPI_BIT_ORDER_MSBFIRST); // The default bcm2835_spi_setDataMode(BCM2835_SPI_MODE0); // The default bcm2835_spi_setClockDivider(BCM2835_SPI_CLOCK_DIVIDER_65536); // The default bcm2835_spi_chipSelect(BCM2835_SPI_CS0); // The default bcm2835_spi_setChipSelectPolarity(BCM2835_SPI_CS0, LOW); // the default // 複数バイトをスレーブに送って同時に読む // たいていのSPIデバイスは1、2バイトのコマンドに対してそのあとデータを送り返すようになっている // そのような場合は、バッファの先頭にコマンドを書いて、残りに送り返されるデータバイト数の分だけ0を埋めておく // 転送が終わったら、送り返されたバイトをバッファから読み出すことができる // MISOをMOSIに直接つないてあったら、書いたものがそのまま読み込まれるはずである char buf[] = { 0x01, 0x02, 0x11, 0x33 }; // 送り出すデータ bcm2835_spi_transfern(buf, sizeof(buf)); // bufにはスレーブから読み込まれたデータで書き換えられる printf("Read from SPI: %02X %02X %02X %02X \n", buf[0], buf[1], buf[2], buf[3]); bcm2835_spi_end(); bcm2835_close(); return 0; }
4.6 もうすこし実用的なサンプルコード
gpioとi2cのふたつのサンプルは、これまでとちがって実用的なコードになっている。長いのでここにはあげないけど、それほど難しいコードではない。コマンドラインからgpio、あるいはi2cを読んだり書いたり設定したりできる。ハイフン('-')に続いてこれが顔文字みたいになったけどそうではなくて、コマンドキャラクタを続ける、というunixによくあるスタイルになっている。
引数無しでとりあえず動かしてみると、usageが表示されるので、それを参考に試してみればいい。
ソースは順に読んでいけばわかるようになっている。
i2cのほうには、ファイルの先頭のコメント部分にA/DコンバータのADC1015とD/AのMCP4725をi2cにつないだ場合に読み書きするためのコマンドラインシーケンスが書いてある。
5 まとめ
spiだけはもとからあるspidevモジュールを停止させないといけないけど、それ以外は他のモジュールと共存可能らしい(もちろん一つのピンを二つのプロセスから使ったりはできない)。ライブラリそのものは見てきたように非常にシンプルなもので、自分で書いてもそれほど手間はかからないようなものだけど、他のライブラリを使っていないなら
- BCM2835のレジスタ配置を調べる手間がない
- ちゃんと動作確認がされてる
- 機種ごとに異なるレジスタアドレスやピン配置を隠蔽してくれる
- 整理されていて一貫している
僕はこのままでありがたく使わせてもらうことにする。
2015-09-05 20:16
nice!(0)
コメント(1)
トラックバック(0)
沒有醫生的處方
cialis 20 mg cut in half http://kawanboni.com/ Tadalafil 20mg
by Cialis 20mg (2018-04-14 02:43)