arm-linuxシリアルポート受信エラー


1フレームデータの受信では、1フレームデータは、2回に分けて受信され、以下のように、1回目は一部を受信し、2回目は一部を受信する.
recv  data   from downline:   0x66   0x17   0x0   0xc1   0x0   0x1   0x0   0x0   0x0   0x0   0x11   0x1   0x0   0x0   0x1   0x41   0x33   0x0   0x1   0x0  the length of data  : 20 16:43:6 16:48:53 recv data  downline:      0xff   0x4d   0x16  the length of data :3
私はモジュールの送信が終わった後、受信状態に入って、設備の速度が追いつかないため、送信データが遅くなり、受信の速いデータが半分送信されて読み出されたのではないでしょうか.データが半分に分かれたのか?しかし、後にsleep(1)を追加した後、すべて1フレームに読まれた.
その後、投稿を参照してループします.一度に16バイトを読むと、シリアルポートから20回読むとエラーが発生します.その後8バイトでテストも理想的ではありません.やはりフレームを2回に分けて受信する場合がある.
では、シリアル関数を実現する際に、どのようにして安定したデータの読み取りを行うことができますか?
その後,シリアルポートの読み出し動作は7層ネットワークモデルにおける物理層動作であり,フレームの完全な受信を実現するにはシリアルポート数値だけでなく容易であるという投稿を見た.シリアルポートはデータを受信するだけなので、完全なフレームデータが到来するか否かを判断するのではなく、データ伝送が終了するか否かに基づいている.データ転送が中止されると、システムが読み出した情報にread()を呼び出してデータを読み出す.しかし、完全なフレームデータは上位層に必要であり、下位層は処理しない.これにより、完全なフレームの受信を制御するために上位層が必要となる.
これにより,上記の作業はシリアルポートデータの数行のコードを読み取るだけではない.受信したデータが完全なデータフレームであるか否かを判断し、もしそうであれば受信に成功し、受信関数を飛び出して他の操作を実行する.受信されたデータが完全なフレームでない場合、受信されたデータが私たちが必要とする完全なデータフレームに合致するまで、シリアルポートデータを受信し続ける必要があります.これは、読み終わった後に一度判断するという煩わしさがあるが、フレームデータの受信精度はずっと高い.
しかし、読み取ったデータが完全なデータフレームではない場合、どうすればいいのかという問題も避けなければなりません.上記のように受信を続けると、シリアル受信で死ぬ可能性が高い.正しいデータフレームがずっとないので、シリアルポートデータの受信を続けます.しかし、読み続けても正しいフレームデータはありません.だからここでは回数判断を加えて、耐えられる回数を超えたら退出します.これにより、プログラムがここに詰まっている可能性が回避されます.
修正したコードを使用した場合、再度テストした場合、上の2フレームは表示されません.最初の受信エラーが発生しても、完全なフレームデータが受信されるまで受信を続けます.受信関数から飛び出すと、必ず完全なデータフレームになります.
int Read_Com3(unsigned char * Data)
{
#define TTY_READ_SIZE       8

    short int length=0;
    unsigned char route;
    unsigned char data[256];
    unsigned char *p_data = data;
    unsigned char start;
    struct timeval tv = {8, 0};
    fd_set serialfd;
    unsigned int u32Ret = FALSE;
    unsigned char u8ReadSize;
    FD_ZERO(&serialfd);
    FD_SET(fd3,&serialfd);
do{
	u32Ret = select(fd3 + 1,&serialfd,NULL,NULL,&tv))
        if(u32Ret < 1)
        {   
            break;
        }
        
        u32Ret = FD_ISSET(fd3, &serialfd) ;
        if(u32Ret < 1)
        {
            break;
        }
        
        bzero(data, 256);
        
        #if 0
        length = read(fd3, data, 256);
        #else
        while(1)
        {
            u8ReadSize = read(fd3, p_data, TTY_READ_SIZE);
            if(TTY_READ_SIZE != u8ReadSize)
            {
                length += u8ReadSize;
                break;
            }
            p_data += TTY_READ_SIZE;
            length += TTY_READ_SIZE;
        }
        #endif
        
#ifdef DEBUG
        printf("
"); printf("recv data downline: "); for(i=0; i<length; i++) printf(" 0x%x ",data[i]); printf("
"); printf("the length of data: %d
",length); #endif if(length > 0) { u32Ret = length; } else { u32Ret = FALSE; //error handle } }while(0); tcflush(fd3,TCIOFLUSH); //clear the rest of the data in the fd3 return u32Ret; }

修正されたコード:
int Read_Com3(unsigned char * Data)
{
#define READ_DATA_SIZE   256

    unsigned char u8CycleTime = 0;
    short int length=0;
    unsigned char route;
    unsigned char data[256];
    unsigned char *p_data = data;
    unsigned char start;
    unsigned char u8ReadSize;
    unsigned char u8Ret = FALSE;

    struct timeval tv = {.tv_sec = 10,
                        .tv_usec = 0};

do{
        if(FALSE == is_ready_read(fd3, &tv))
            break;
        bzero(data, 256);
        
        while(1)
        {
            u8ReadSize = read(fd3, p_data, READ_DATA_SIZE);
            
            if(READ_DATA_SIZE != u8ReadSize)
            {
                length += u8ReadSize;
                p_data += u8ReadSize;
                
                tcflush(fd3,TCIOFLUSH);  //clear the rest of the data  in the fd3

                if(TRUE == judge(&start, data, length))
                {
                    //store the number
                    length = length - start;
                    /*===Copy the data after A===*/
                    memcpy(Data, &data[start],length);
                    u8Ret = length;
                    break;
                }
                
                u8CycleTime++;
                if(u8CycleTime & 0x11)
                {
                    break;
                }
                
                tv.tv_sec = 1;
                tv.tv_usec = 0;
                if(FALSE == is_ready_read(fd3, &tv))
                {
                    
                    break;
                }
                else
                {
                    printf_str_int("####/***read continue*****/####", TRUE);
                    continue;
                }
            }
            else
            {
                p_data += READ_DATA_SIZE;
                length += READ_DATA_SIZE;
            }
        }
        
        printf_str_int("judeg_end", NULL);
    }   while(0);
     //tcflush(fd3,TCIOFLUSH);  //clear the rest of the data  in the fd3
     
    return u8Ret;
}

参考ブログ:
http://justwinit.cn/post/2856/