必要なこと
- インクルード
#include "Serial.h"
- インスタンス生成
Serial pc(USBTX, USBRX); // USBシリアルポートのインスタンス
Serial インスタンス名(p28,p27); // RX,TXでのシリアルポート生成
- ボーレート調整
pc.baud(115200);
インスタンス名.baud(115200);
- pcに送る
int data = 1;
pc.printf("hello %5d \r\n",data);
概要
mbed
でSerial
通信を利用する一番の利点は、Serial受信割り込みがある事でしょう。
Arduino
には有りません。
さらにUSB
も入れると$4$つもポートがあるので、センサーとの通信を全てSerial
でまとめておくと、I2C
やSPI
での通信失敗やデータの送信受信不一致を避けることができてとても楽です。特にmbed
はSPI
割り込みを持たないので、やはりSerial
でしょう。
通信速度については、$115200bps$も有れば、$1$秒に$14400byte$もデータが送れるので速度で困ることはほぼないでしょう。
ただし、送信処理printf
に食われるmbedの処理時間はとても長いです。これは、printf
では$1byte$で$10$進数の$1$桁のみを送ることになるためです。よって、送信する場合はprintf
でなくputc(char)
を使って、ASCIIコード
に変換せず$1$byte$データとして送信するのが良いと思われます。
受信方法
受信する方法は、Serial受信割り込み処理
をセットして
Serialインスタンス.attach(受信割り込み関数,Serial::RxIrq);
割り込み処理内で
char receive = Serialインスタンス.getc();
をすることで$1$byteデータを読むことができます。
受信サンプルプログラム
Serial pc(USBTX, USBRX); // USBシリアルポートのインスタンス生成
Serial Cc(p28,p27);
void getC(){
//受信割り込み処理
char receive = Cc.getc();
}
int main() {
pc.baud(115200);
Cc.baud(115200);
Cc.attach(getC,Serial::RxIrq); //受信割り込み関数getC(名前は何でも良い)を設定
while (1) {
}
}
受信したデータをpcに送る場合は次のように受信割り込み関数を変更します。
void getC(){
char receive = Cc.getc();
int data = (int)receive;
pc.printf("%5d \r\n",data);
}
送信側は$1$byteデータを送信させます。
送信
基本的には
Serialインスタンス.putc(char);
で1byte送信できます。
数値データの場合はchar
型への変換が要ります。
int data = 3;
char send = (char)data;
Cc.putc(send);
これで1byteまでなら送信できます。
data
は$0$から$255$までです。
char send = (char)data;
の変換は
-256 -> 0
-255 -> 1
-127 -> 129
-126 -> 130
-125 -> 131
-1 -> 255
0 -> 0
1 -> 1
125 -> 125
126 -> 126
127 -> 127
128 -> 128
255 -> 255
256 -> 0
に変わります。つまり、
send =
\left\{
\begin{array}{ll}
data & (255 \geq data \geq 0)\\
256+data &( 0 \geq data \geq -256)
\end{array}
\right.
となっています。
負の値を送るのは面倒そうですね。
2byte以上送るのも面倒です。
昔の自分は最上位ビットで頑張って送ってますが、たぶんそれ用のライブラリがあると思うので探してみてください。ArduinoにはPacket Serial
という超便利なライブラリがあります。
mbed
にもあれば教えて下さい。
Serial受信割り込みとputcの併用の注意
2019/12/11:追記
受信割り込みを入れた場合、putc(5);
のようなSerial送信は割り込み関数内に入れないと動作が不安定になります。
自動で再起動したりして、最初は困惑しました。
mbedにはUSART
,UART
の二つがあり、この違いが影響しているかも知れません。CPUの説明ではUART4,5
とあるのでUART
はSerial4,5のみです。
失敗するサンプルプログラム
#include "mbed.h"
Serial pc(USBTX, USBRX); // USBシリアルポートのインスタンス
Serial moterDriver(PC_10,PC_11);
void geCC(){
int k2=moterDriver.getc();
}
int main() {
pc.baud(115200);
moterDriver.baud(115200);
moterDriver.attach(geCC,Serial::RxIrq);
while(1) {
moterDriver.putc(3); //送信を受信割り込み外で行う
pc.printf("moving\r\n");
}
}
このプログラムを動かしている時に、PC_10,PC_11
ピンにSerial
データを送信すると、常時送信していた文字列"moving"が停止します。
恐らく、送信中に受信割り込みが入るのは想定外なんでしょう。
tx,rx
電圧レベルの問題ではない事は、オシロで計測して確認しました。Nucleo F446RE
で確認しました。LPC1768
でも、似たプログラムを使っている際に頻繁に落ちて困ってしまったので仕様だと思われます。
putc
を利用する際は安全のため、そのSerial
受信割り込み処理内にputc
を置いた方が良いかもしれません。