10
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

mbedのSerial通信

Last updated at Posted at 2019-10-08

必要なこと

  • インクルード
#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);

概要

mbedSerial通信を利用する一番の利点は、Serial受信割り込みがある事でしょう。
Arduinoには有りません。

さらにUSBも入れると$4$つもポートがあるので、センサーとの通信を全てSerialでまとめておくと、I2CSPIでの通信失敗やデータの送信受信不一致を避けることができてとても楽です。特にmbedSPI割り込みを持たないので、やはり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を置いた方が良いかもしれません。

10
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?