我正在使用带有HEW(高性能嵌入式工作台)编译器的瑞萨16 bt MCU。
系统接收以下形式的ACSII数据:
<data><cc>
其中<cc>
包括两个 ASCII 十六进制数字,对应于前面所有字符的 8 位按位 XOR。包括<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
}
}
}
将此值转换为十六进制值和xor it,即(3F^30^31^53^52^57=68),如果我可以在程序中进行此计算
您从根本上不了解值和编码之间的区别。二加三等于五,无论您将两者表示为"2"、"二"还是"X X"。加法作用于值,而不是表示。因此,"转换为十六进制和xor它"是没有意义的。您是异或值,而不是表示。十六进制是一种表示形式。
要保持正在运行的 XOR,只需在顶部执行类似 int running_xor=0;
的操作,然后在每次收到字节时running_xor ^= rx_byte;
。完成后,它将包含正确的值。将其设置为零以重置它。
完全摆脱十六进制。这就是打印这些值以供您使用的方式。这与程序的内部逻辑无关,程序只处理值。
您最好将数据验证与数据接收分开,即使您不在中断处理程序中执行此操作; 如果您使用的是 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 ;
}