-1

HEW (High-performance Embedded Workbench) コンパイラを搭載した Renesas 16 bt MCU を使用しています。

システムは、次の形式の ACSII データを受け取ります。

<data><cc>

ここで<cc>、先行するすべての文字の 8 ビット ビットごとの XOR に対応する 2 つの ASCII 16 進数で構成されます。含む文字列の最大長<cc>は 14 です。

これが私の試みです:

#pragma INTERRUPT Interrupt_Rx0
void Interrupt_Rx0 (void)
{
    unsigned char   rx_byte, rx_status_byte,hex;
    char buffer[15],test[5];
    int r,k[15];
    char * pEnd;
    unsigned char dat,arr[14],P3;
    unsigned int i,P1[10];

    rx_byte = u0rbl;    //get rx data
    rx_status_byte = u0rbh;

    if ((rx_status_byte & 0x80) == 0x00)        //if no error
    {
        if ((bf_rx0_start == 0) && (rx_byte == '?') && (bf_rx0_ready == 0))
        {


            byte_rx0_buffer[0]=rx_byte;
            bf_rx0_start = 1;                                    
            byte_rx0_ptr = 1;       
        }

        else
        {
            if (rx_byte == '?')
            {
                bf_rx0_start = 1;
                byte_rx0_ptr = 0;
            }
            if(bf_rx0_start == 1)
            {
                byte_rx0_buffer[byte_rx0_ptr++] = rx_byte;          

                sprintf(buffer,"%X",rx_byte); //ASCII CONVERSION
                dat=strtol(buffer,&pEnd,16);
                //  P1=(int)dat;
                //  sprintf(P1,"%s",dat);
                delay_ms(2000);
                k[byte_rx0_ptr++]=dat;  
            }                       

            if ((byte_rx0_ptr == 14))               
                bf_rx0_start = 0;//end further rx until detect new STX

        }
    }
}   
4

2 に答える 2

2

この値を 16 進数値に変換し、xor it (3F^30^31^53^52^57=68) をプログラムで計算できる場合

値とエンコーディングの違いを根本的に理解していません。2 を「2」、「2」、「X X」のいずれで表現しても、2 たす 3 は 5 です。加算は、表現ではなく、値に対して作用します。したがって、「16 進数に変換して xor する」ことは意味がありません。表現ではなく、値をXORします。16 進数は表現です。

実行中の XOR を維持するには、最初のようなことをint running_xor=0;行い running_xor ^= rx_byte;、バイトを受信するたびに行います。終了すると、正しい値が含まれます。ゼロに設定してリセットします。

頭から完全に 16 進数を取得します。それが、これらの値があなたの消費のために印刷されている方法です。これは、値のみを扱うプログラムの内部ロジックとは関係ありません。

于 2013-01-28T12:14:51.107 に答える
1

割り込みハンドラーでそれを行わないという点でも、データの検証をデータの受信から分離することをお勧めします。RTOS を使用している場合は、チェックされていない ISR にデータをバッファリングし、データの検証をメイン コード スレッドまたはタスク スレッドに委ねる方がよい可能性があります。ISR で sprintf() や strtol() などの重いライブラリ関数を呼び出したくないのは確かです!

いずれにせよ、受信した文字列へのポインターとその長さ (strlen()受信した文字数は既にわかっているため、不要な呼び出しを避けるため) を受け取りtrue、チェックサムが有効かどうかを返す関数を次に示しfalseます。データ長に制限はありません。これは、呼び出し元の関数によって実行されます。

チェックサムの 16 進数が常に大文字または小文字であることがわかっている場合は、decodeHexNibble()関数を単純化できます。

#include <stdint.h>
#include <stdbool.h>

uint8_t decodeHexNibble() ;
uint8_t decodeHexByte( char* hexbyte ) ;
uint8_t decodeHexNibble( char hexdigit ) ;

bool checkData( char* data, int length )
{
    int data_len = length - 2 ;
    char* bcc_ptr = &data[data_len] ;
    uint8_t rx_bcc_val = 0 ;
    uint8_t actual_bcc_val = 0 ;
    int i = 0 ;

    // Convert <cc> string to integer
    rx_bcc_val = decodeHexByte( bcc_ptr ) ;

    // Calculate XOR of <data>
    for( i = 0; i < data_len; i++ )
    {
        actual_bcc_val ^= data[i] ;
    }

    return actual_bcc_val == rx_bcc_val  ;
}

uint8_t decodeHexNibble( char hexdigit )
{
    uint8_t nibble ;

    if( hexdigit >= '0' && hexdigit <= '9' )
    {
        nibble = hexdigit - '0' ;
    }
    else if( hexdigit >= 'a' && hexdigit <= 'f' )
    {
        nibble = hexdigit - 'a' + 10 ;
    }
    else if( hexdigit >= 'A' && hexdigit <= 'F' )
    {
        nibble = hexdigit - 'A' + 10 ;
    }
    else
    {
        // Do something 'sensible' with invalid digits
        nibble = 0 ;
    }

    return nibble ;
}

uint8_t decodeHexByte( char* hexbyte )
{
    uint8_t byte = hexbyte[0] << 4 ;
    byte |= hexbyte[1] ;

    return byte ;
}
于 2013-01-28T21:34:50.280 に答える