Raspberry Pi の IOは3.3Vなので、5V TTL - USB変換アダプタに抵抗分圧してつなごうかと思いましたが、 ランニングエレクトロニクスさんのSBDBTがあったので、これを使って、一気にUARTの無線(Bluetooth)化です。
しかし、当初、単純に配線するだけでは上手く動いてくれませんでした。そこで、Google先生に助けを求め、先人の知恵を借りる事にしました。こちらのClick Labさんのサイトに解決方法が掲載されていました。Click LabさんはInterfaceにRaspberry Piのラジコンカーの記事を書かれた方のようです。丸々転載で申し訳ないですが、
/boot/cmdline.txt の
dwc_otg.lpm_enable=0 console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 rootwait
記述を
dwc_otg.lpm_enable=0 rpitestmode=1 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 rootwait
のように変更し、
/etc/inittab の
TO:23:respawn:/sbin/getty -L ttyAMA0 115200 vt100
の先頭に#を付けてコメントアウトします。
#TO:23:respawn:/sbin/getty -L ttyAMA0 115200 vt100
設定変更後リブートすることで、UARTが利用可能になりました。デフォルトではUARTはシリアルコンソールに割り当てられているそうです。
これらの設定をすることで、UARTを(Bluetooth経由で)利用できるようになりました。
配線はこんな感じ。Raspberry Pi の拡張端子のピン配置はこちらを参照して下さい。
動作確認用のプログラムは、せっかくなので、先日用意したクロス開発・デバッグ環境です。
Eclipse 上で、ブレークポイントを設定して、Bluetooth接続でコンソールに接続、"Hello~"のメッセージをコンソール側に表示後、コンソールに文字を入力すると、UART受信関数が文字を取得してブレークがかかります。変数にマウスを当てると、変数の値も表示されます。Raspberry Pi上でGeanyを使えばいいんですが、何気にクロス開発環境でeclipseも便利かも。
以下、テストに使ったソース。
#define _POSIX_SOURCE 1 #include <stdio.h> #include <stdlib.h> #include <termios.h> #include <sys/signal.h> #include <unistd.h> #include <fcntl.h> // グローバル変数宣言。 int fd; struct termios old_term_io; // 現在の設定の退避用。 // 関数プロトタイプ宣言。 int UART_open_port(char *serial_dev); void UART_close_port(void); int UART_put_char(unsigned char c); int UART_put_string(char *s); int UART_get_char(void); int main() { char uart_rBuffer[1024]; char uart_sBuffer[256]; char *uart_dev = "/dev/ttyAMA0"; int c; // シリアル通信用バッファの初期化。NULL終端文字で埋める。 memset(uart_rBuffer, '\0', 1024); memset(uart_sBuffer, '\0', 256); // テスト送信データの設定。 sprintf(uart_sBuffer, "Hello,UART!!\r\n"); // UARTの初期化。 UART_open_port(uart_dev); // UART送信。 UART_put_string(uart_sBuffer); // メインループ。 while(1) { c = 0; /// 1バイト受信。データが来るまでブロックされる。 c = UART_get_char(); if (c != 0) UART_put_char((unsigned char)c); } return 0; } int UART_open_port(char *serial_dev) { struct termios new_term_io; // デバイスをオープン。 fd = open(serial_dev, O_RDWR | O_NOCTTY); if (fd < 0) { /// デバイスオープンに失敗。 perror(serial_dev); exit(-1); } // 既存の設定を取得・保存。 tcgetattr(fd, &old_term_io); // new_term_ioの制御文字の初期化。 new_term_io.c_iflag = 0; new_term_io.c_oflag = 0; new_term_io.c_cflag = 0; new_term_io.c_lflag = 0; new_term_io.c_line = 0; //bzero(new_term_io.c_cc, sizeof(new_term_io.c_cc)); memset(new_term_io.c_cc, '\0', sizeof(new_term_io.c_cc)); // ポートの設定。 // B9600 = 9600bps // CS8 = 8bit, no parity, 1 stopbit // CLOCAL = ローカル接続(モデム制御なし) // CREAD = 受信文字有効。 new_term_io.c_cflag = B9600 | CS8 | CLOCAL | CREAD; // パリティデータエラーは無視に設定。 new_term_io.c_iflag = IGNPAR; // Rawモード出力。 new_term_io.c_oflag = 0; // 入力モード設定。non-canonical, no echo, new_term_io.c_lflag = 0; // inter-character timer new_term_io.c_cc[VTIME] = 0; // 1文字来るまで読み込みをブロック。 new_term_io.c_cc[VMIN] = 1; // モデムラインのクリア。 tcflush(fd, TCIFLUSH); // 新しい設定を適用。 tcsetattr(fd, TCSANOW, &new_term_io); return(0); } void UART_close_port(void) { tcsetattr(fd, TCSANOW, &old_term_io); close(fd); } int UART_put_char(unsigned char c) { if (write(fd, &c, 1) != 1) return(-1); return(0); } int UART_put_string(char *s) { if (write(fd, s, strlen(s)) != 1) return(-1); return(0); } int UART_get_char(void) { unsigned char c; int res; res = read(fd, (char *)&c, 1); return(c); }
0 件のコメント:
コメントを投稿