パソコンとmbed間でシリアル通信を行う際の、mbed(NUCLEO-L152RE )側のプログラムについて簡単に説明します。
基本的にはパソコンのシリアル通信と同様です。ただデータ受信時に割り込みを発生させるなど、組み込みならではの処理が必要になります。
シリアル通信を行う際の大きな流れは以下の通りです。
- mbedでシリアル通信に使用するピンを決め、クラス作成を行う
- シリアル通信を行うための各種設定を行う(ボーレートなど)
- 受信割り込みの登録
- 受信処理
- 送信処理(送信割り込みの登録)
- 送信完了(送信割り込みの解除)
とても簡単ですが、大きい流れは上記の通りです。この流れに沿って簡単に説明します。
注:異常処理はほとんど触れません。説明が複雑になり量が増えてしまうためです。とりあえず使ってみるというレベルです。
mbedでシリアル通信に使用するピンを決め、クラス作成を行う
今回はパソコンとmbed(NUCLEO-L152RE )はUSBで接続することにします。
#include "mbed.h" #include "Serial.h" int main() { Serial usbSerial(USBTX, USBRX); return 0; }
2行目がシリアル通信を行うために必要なヘッダーのインクルードです。今回は「Serial.h」を使用していますが、「RawSerial.h」もほぼ同様に使用できます。通信方法によっては「RawSerial.h」でないとうまく動かないことがあるようなので、頭の片隅にでも置いておいてください。
6行目がシリアル通信のクラス(オブジェクト)作成部分になります。ピンの名前は「USBTX」と「USBRX」です。オンラインコンパイラであれば使用するmbedを選択するだけど、簡単にUSB接続するピンを指定できます。
ちなみにNUCLEO-L152REの場合、 USBTXがPA_2、USBRXがPA_3を使用します。なので以下のような書き方も可能です。
Serial usbSerial(PA_2, PA_3);
シリアル通信を行うための各種設定を行う(ボーレートなど)
シリアル通信の各種設定を行います。色々設定できますが、今回は通信速度のみ変更します。
#include "mbed.h" #include "Serial.h" int main() { Serial usbSerial(USBTX, USBRX); // シリアル通信の速度設定 usbSerial.baud(57600); return 0; }
8行目が通信速度を設定しているところです。baud()関数の引数に設定したい数値を入れるだけです。
受信割り込みの登録と受信
ここからがパソコンと処理が大きく違う所です。パソコンはメモリなどが潤沢なため、受信タイミングなどシビアに考えなくても動くは動きます。しかし組み込み系の場合、きちんと処理しないとデータが消えてしまったりしてしまいます。
#include "mbed.h" #include "Serial.h" Serial usbSerial(USBTX, USBRX); void ISR_Serial_Rx() { // シリアルの受信処理 char data = usbSerial.getc(); } int main() { // シリアル通信の速度設定 usbSerial.baud(57600); // シリアル通信受信の割り込みイベント登録 usbSerial.attach(ISR_Serial_Rx, Serial::RxIrq); while (1) { // メイン処理 } }
まず4行目、データを受信した際、割り込み処理にて受信したデータを取得します。
メイン関数内で宣言してしまうと他の関数で使用できないので、手っ取り早く簡単にするために、シリアルクラスのオブジェクト作成をグローバル領域にて行います。こうすることでファイル内であれば自由にアクセスできます。
個人的には、新たなクラスを作成し、メンバー変数にして扱うのが安全でいいと思います。
18行目がデータを受信した際に割り込みを発生させる処理になります。
作成したクラス(オブジェクト)において、割り込み「Serial::RxIrq」が発生した際(データを受信した時)、「ISR_Serial_Rx」関数を呼び出しなさいよ。という意味になります。
6~10行目の関数がデータを受信した際に実行される関数です。この中でデータの取得処理を行います。
9行目が1バイトデータを取得している部分になります。
今回はデータを取得して終わっていますが、実際は配列に入れるなどの処理を行うことになると思います。
送信処理(送信割り込みの登録と解除)
送信処理は少し注意が必要になります。送信時の割り込みは、送信データのバッファが空の状態の時に発生します。
受信の場合、データを受信した際に発生するだけなので、何も受信していなければ割り込みは発生しません。
しかし送信の場合、先ほど書いたように、送信データのバッファが空の状態だと発生します。となるとデータを送信していない時は常に割り込みが発生することになります。処理をすぐに抜けるようにしておけばそれほどの問題はないのですが、常に割り込みが発生している状態というのは良い状態とは言えません。
なので、送信時に使用する割り込みは、データを送信する際に登録し、送信完了したら割り込み処理の解除、という流れをお勧めします。
今回はサンプル程度なので1回送信したら割り込み解除を行います。
#include "mbed.h" #include "Serial.h" Serial usbSerial(USBTX, USBRX); void ISR_Serial_Rx() { // シリアルの受信処理 char data = usbSerial.getc(); } void ISR_Serial_Tx() { // シリアルのs送信処理 usbSerial.attach(NULL, Serial::TxIrq); } int main() { // シリアル通信の速度設定 usbSerial.baud(57600); // シリアル通信受信の割り込みイベント登録 usbSerial.attach(ISR_Serial_Rx, Serial::RxIrq); // シリアル通信のデータ送信 usbSerial.attach(ISR_Serial_Tx, Serial::TxIrq); usbSerial.putc(5); while (1) { // メイン処理 } }
27行目が送信データのバッファが空になった際に割り込みを発生させる処理になります。
作成したクラス(オブジェクト)において、割り込み「Serial::TxIrq」が発生した際、「ISR_Serial_Tx」関数を呼び出しなさいよ。という意味になります。
28行目が1バイトのデータ送信になります。今回は数値の「5」を送信しています。
12~16行目の関数の処理が、送信データのバッファが空になった際の処理です。今回は1バイトのデータ送信だけなので、割り込み解除のみ行っていますが、通常は次のデータ送信をここで行います。そして、送信データがなくなったら割り込み解除を行います。
15行目が送信時に使用する割り込みの解除処理です。
他(Tickerなど)の割り込み登録の場合、「attach」で登録、「detach」で解除なのですが、シリアル通信の場合は違います。
シリアル通信の場合、「attach」で登録は同じなのですが、「detach」はありません。なので、「attach」で呼び出す関数なしという意味で「NULL」を登録します。
まとめ
さてC#に続いてmbedでのシリアル通信について簡単にまとめましたが、どうでしたでしょうか?
どちらもクラスなどがよくできているため、簡単にプログラムを作成することができたと思います。
ただ、ここでは最低限の処理についてのみまとめているので、これを足掛かりに自分の作りたい処理を作成して頂けたらと思います。C#やmbedの仕様や説明サイトなどに関してはどちらも沢山あるので、是非色々と調べてプログラムを作成してみてください。
更新履歴
版 | 更新日 | フォームバージョン | mbedライブラリ | 説明 |
新規作成 | 2017/6/9 | V2.J28.M16 | 124:2241e3a39974 |