メインコンテンツに移動

シリアル通信

長らく疑問に思っていたことがあるが、今のところ理解できているわけじゃない。

CDCクラスの仮想COMシリアルは、実際の通信自体はUSBだ。しかし、仮想COMということで、ボーレート設定があり、実際ボーレート設定が間違っていると、通信ができず文字化けになったりして、通常のシリアル通信と同じ挙動を示す。

シリアル通信をどんな速度設定にしようと、実際の通信はFull-Speed以上であり、どうやってもそれ以上だ。また仮想COMで使用する通信にはハンドシェークがない。通常のシリアルならハードハンドシェーク(RTS/CTSあるいは、DTR/DSR、あるいはその両方)の設定があって結線が必要になるという事実がある。

実際、ボーレート設定などあるがUSBの最高速度で通信していて、ならパケットロストなど通常起こりえないなら、うまく出来ている(つまり速度は関係ない)のではないかという疑問だ。

ある業務で、1ms間隔でデータを取得してCDCでPCに送りたいということがあった。普通のシリアル通信であれば、115.2kbpsに設定しても(通常、特殊なことがない限りこれが最高速になる)、1byte送信するのに86μs要する(Start、Stopビットはともに1として)。例えば36byteを毎回送信したいとする。要する時間は、連続で通信できたとして3.125ms要する。つまり1ms間隔で送信できない。しかし、実際の通信はUSBなので、十分に間に合う。

実際のところどうなのか?

まず、16byteのデータを1ms間隔で送信することを考える。

Serial usbserial(USBTX,USBRX);
Ticker tbase;

void tbase_t(void){
    tb_reach=0;
    tb++;
}

main(){
    usbserial.format(8,SerialBase::None,1);
    usbserial.baud(115200);
    tb_reach = 1;
    tbase.attach( &tbase_t , INTERVAL );

    while(1){
        while( tb_reach );
        tb_reach=1;

        dcnt++;
        usbserial.printf("%06d,%06d\n\r",tb,dcnt);
        
        val = usbserial.readable();
        if( val != 0 ){
            //tbase.detach();
            break;
        }
    }
}

コードは一部抜粋であるがtimebaseであるtbも、whie文中のdcntも同じ数で数落ちしてなければすべて送れていることになるが、実際のところ、tbの数はdcntより少なかった。つまりこれは、usbserial.printfにおける送信が、仮想COMの速度をシミュレートしているということになるのではないか。

結論として、仮想シリアルCOMの通信速度を超えた間隔でデータ通信を行おうとすると、データの欠落が生じるため注意が必要ということだと思う。この場合のデータの欠落は通信自体(USB通信)でhなく、プログラム側で発生するということだと認識した。

他のデータも含めて、excelファイルを添付しておく。データはteratermのlogを利用した。​​​​
​​​​

添付

Tags

コメントを追加

Plain text

  • HTMLタグは利用できません。
  • ウェブページのアドレスとメールアドレスは自動的にリンクに変換されます。
  • 行と段落は自動的に折り返されます。