3

Linux のシリアル ポートからデータを読み取るプログラムを作成しています。データは、次のフレーム形式で別のデバイスから送信されます。

|start | Command | Data               | CRC  | End |
|0x02  | 0x41    | (0-127 octets)     |      | 0x03|
----------------------------------------------------

Data フィールドには、示されているように 127 オクテットが含まれており、オクテット 1,2 には 1 つのタイプのデータが含まれています。オクテット 3,4 には別のデータが含まれています。これらのデータを取得する必要があります

Linux でシリアル ポートとの間でデータを読み書きする方法は知っていますが、単純な文字列 (「ABD」など) を読み書きするだけです。

私の問題は、上記のようにフォーマットされたデータフレームを解析する方法がわからないため、次のことができることです。

  • データ フィールドのオクテット 1,2 のデータを取得する
  • データ フィールドのオクテット 3,4 のデータを取得する
  • データの一貫性をチェックするために CRC フィールドの値を取得します

Linux のシリアル ポートとの間で単純な文字列を読み書きするサンプル コードは次のとおりです。

int writeport(int fd, char *chars) {
    int len = strlen(chars);
    chars[len] = 0x0d; // stick a <CR> after the command
    chars[len+1] = 0x00; // terminate the string properly
    int n = write(fd, chars, strlen(chars));
    if (n < 0) {
        fputs("write failed!\n", stderr);
        return 0;
    }
    return 1;                                                                                                           
}

int readport(int fd, char *result) {
    int iIn = read(fd, result, 254);
    result[iIn-1] = 0x00;
    if (iIn < 0) {
        if (errno == EAGAIN) {
            printf("SERIAL EAGAIN ERROR\n");
            return 0;
        } else {
            printf("SERIAL read error %d %s\n", errno, strerror(errno));
            return 0;
        }
    }                    
    return 1;
}

誰かアイデアを教えてください。

4

2 に答える 2

5

resultcharは1オクテット幅のsの配列です。

オクテットnを読み取るには、次を使用します。

char octet_n = result[n];

だからあなたが必要なことをするために:

// skip the start and command fields
char *data_field = result + 2; 

int octet_1_2 = data_field[1] | (data_field[2] << 8);
int octet_3_4 = data_field[3] | (data_field[4] << 8);

// crc is at byte 128 + 2 = 130
int crc = result[130];

編集:この行の説明:

int octet_1_2 = data_field[1] | (data_field[2] << 8);

2つの連続するオクテットを1つの16ビットワードに読み込みたい場合:

            1
       bits 5        8 7       0
            --------------------
octet_1_2 = | octet 2 | octet 1|
            --------------------

したがって、オクテット1のビット7:0を取得し、それらを:のビット7:0に配置しますoctet_1_2

octet_1_2 = data_field[1];

次に、オクテット2のビット7:0を取得し、それらをのビット15:8に配置しoctet_1_2ます。これを行うには、オクテット2を8ビット左にシフトしOR、結果を次のように変換しoctet_1_2ます。

octet_1_2 |= data_field[2] << 8;

上記のように、これら2つの行を1つにマージできます。

于 2010-03-23T14:18:55.953 に答える
0

C でフォーマットされたデータを読み取る最善の方法は、構造体を読み取ることです。あなたが持っているフレーム形式を考えると、私は次のことをします。


typedef struct special_data
{
    char first_data[2];
    char second data[2];
} special_data_t;

union data_u
{
    special_data_t my_special_data;
    char           whole_data[128];
};

typedef struct data_frame
{
    unsigned char start;
    unsigned char cmd;
    union data_u  data;
    unsigned char crc;
    unsigned char end;
} data_frame_t;

void func_read(int fd)
{
    data_frame_t my_data;

    if (read(fd, &my_data, sizeof(my_data)) != -1)
    {
        // Do something
    }
    return;
}

このようにして、構造フィールドを介して必要なデータにアクセスできます。最初の構造体と共用体は、フレームのデータ フィールドで必要なバイトにアクセスするための単なるヘルパーです。

于 2010-03-23T14:41:08.257 に答える