-1

我正在使用带有 HEW(高性能嵌入式工作台)编译器的 Renesas 16 bt MCU。

系统接收格式如下的 ACSII 数据:

<data><cc>

其中<cc>包含两个 ASCII 十六进制数字,对应于所有前面字符的 8 位按位异或。包含的字符串的最大长度<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

将此值转换为十六进制值 & xor 即(3F^30^31^53^52^57=68),如果我可以在程序中进行此计算

您从根本上不了解值和编码之间的区别。无论您将两者表示为“2”、“二”还是“X X”,二加三等于五。加法作用于,而不是表示。所以“转换为十六进制和异或”是没有意义的。你 XOR,而不是表示。十六进制是一种表示。

要保持运行 XOR,只需int running_xor=0;在顶部执行类似操作,然后 running_xor ^= rx_byte;每次收到一个字节。完成后它将包含正确的值。将其设置为零以将其重置。

完全忘记十六进制。这就是打印这些值以供使用的方式。这与仅处理值的程序的内部逻辑无关。

于 2013-01-28T12:14:51.107 回答
1

您最好将数据验证与数据接收分开,即使您不在中断处理程序中执行此操作;如果您使用的是 RTOS,最好在未检查的 ISR 中缓冲数据并将数据验证推迟到主代码线程或任务线程。您当然不想在 ISR 中调用重量级库函数,例如 sprintf() 或 strtol()!

无论哪种方式,这里都有一个函数,它将接收一个指向接收到的字符串的指针及其长度(以避免不必要的strlen()调用,因为您已经知道接收到了多少个字符),true如果校验和有效则返回,false否则返回。它对数据长度没有限制 - 这将由调用函数执行。

如果您知道校验和十六进制数字将始终为大写或小写,则可以简化该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 回答