mbedのSerial通信要項


必要なこと

  • インクルード
#include "Serial.h"
  • インスタンス生成
Serial pc(USBTX, USBRX); // USBシリアルポートのインスタンス
Serial Cc(p28,p27);      // RX,TXでのシリアルポート生成
  • ボーレート調整
pc.baud(115200);
Cc.baud(115200);

*print

int data = 1;
pc.printf("hello %5d \r\n",data);

概要

mbedでの一番の利点は、受信割り込みがある事でしょう。Arduinoには有りません。さらにUSBも入れると4つもポートがあるので、センサー系統は全てSerialでまとめておくと通信失敗やよくわからないデーターの送信受信不一致を避けることができてとても楽です。mbedはSPI割り込みを持たないので、やはりSerialでしょう。
通信速度については、115200bpsも有れば、1秒に14400byte もデータが送れるので速度で困ることはほぼないでしょう。
ただし、送信処理printfに食われるmbedの処理時間はとてもながいです。これは、printfでは1byteで10進数の1桁のみを送ることになるためとても効率が悪いことも原因です。よって、送信する場合はprintfでなくputc(char)によってASCIIコードに変換せず送るのが良いと思われます。

受信

Serial pc(USBTX, USBRX); // USBシリアルポートのインスタンス生成
Serial Cc(p28,p27);
void getC(){
    //受信割り込み処理
}
int main() {
    pc.baud(115200);
    Cc.baud(115200);
    Cc.attach(getC,Serial::RxIrq);        //受信割り込み関数getC(名前は何でも良い)を設定
    while (1) {

    }
}

このようにattach(関数名,Serial::RxIrq);で割り込み関数を設定して、処理します。

void getC(){
    char receive = Cc.getc();
    int data = (int)receive;
    pc.printf("%5d \r\n",data);
}

getc()で1byte受け取り、int型に変換しPC側に表示させるプログラムです。
mbedに接続している、送信側は1byteデータを送信させます。
これだと、上位byte、下位byteの区別が付かないので1byteしか受け取れません。

void getR()
{
    //pc.printf("%c ",Ro.getc());
    char Rse = Ro.getc();
    if((Rse&0b10000000)==0b10000000) { //highByte
        high = Rse ;
        if((high&0b01000000)==0b01000000) {  //値は負なのでそのまま
            Polarity = true;
        } else {                              //値は正なので最上位を0にする
            high= high & 0b01111111;
            Polarity = false;
        }
        //pc.printf("%3x high",Rse);
    } else {                           //lowByte
        low = Rse;
        //pc.printf("%3x low",Rse);
        Rotate = (high <<7) | low ;
        if(Polarity ==true ) {                //負の時 int 2byte でないので
            Rotate = Rotate|0x8000;
        }
        //pc.printf("%6d \r\n",Rotate);
    }
}

14bit(+-8000程度)データの送受信、8bit目の数値を0,1で上位か下位かを区別してデータを変換し受け取っています。

送信

        int data = -3;
        char send = (char)data;
        Cc.putc(send);

これで、1byteまでなら送信できます。2byte以上のデータの場合、先頭を示すか、外部割り込みで指示するか一部bitを順番を指示するのに使用するか等の工夫が必要になります。
dataは-127 から+127までです。
int char
-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
扱いとなります。
よって、データを128 ~ -127 にしておいて、char型に変換し、送信すれば
受信側は
0~128まではそのまま
-1~-127までは 256 + int 
をすれば変換できます。

Serial受信割り込みとputcの併用の注意

2019/12/11:追記
受信割り込みを入れた場合、Cc.putc(5);の送信は割り込み関数内に入れないと、送信中に受信割り込みが入った場合エラーになります。USART,UARTの違いが影響しているかも知れません。CPUの説明ではUART4,5と有るのでUARTはSerial4,5のみです。
エラーはコンパイラではなく、mbedが動作を停止しているように見えます。

サンプルプログラム

#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を置いた方が良いかもしれません。