長らく疑問に思っていたことがあるが、今のところ理解できているわけじゃない。
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を利用した。
コメントを追加