我有一个连接到 Arduino 模块的动物标签阅读器,并且由于用户 red_car 成功读取了数据,但我遇到了标签 ID 不正确的问题,它似乎通过了校验和并提供了给定标签的正确国家/地区代码。但标签数据解码错误。该系统有一个手册(附照片),它似乎与 red_car 示例中的结构匹配,但标签 ID 始终是错误的。
因此,为了隔离问题,我更改了从手动设置的代码中读取的代码,并输入了手册中的示例。
例子是:
02 31 37 31 41 39 32 35 33 41 33 34 38 33 30 30 31 30 30 30 30 30 30 30 30 30 30 07 f8 03 通过 ASICII 转换时:171A9253A34830010000000000
其中包含: 标签ID:1-10字节(10长) 国家代码字节 11-14(4 个长)
171A9253A3 483 0010000000000
应生成:国家/地区:900 标签:250000023921
byte buffer[30] = {0x02, 0x31, 0x37, 0x31, 0x41, 0x39, 0x32, 0x35, 0x33, 0x41, 0x33, 0x34, 0x38, 0x33, 0x30, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x07, 0xf8, 0x03};
byte b;
uint8_t idx;
boolean started = false;
byte XOR;
byte inverted;
uint32_t value;
void setup() {
// Initialize serial communication at 9600 baud
Serial.begin(9600);
delay(1000);
Serial.println("start:");
}
void loop() {
// Print the contents of the buffer to Serial Monitor for verification
for (int i = 0; i < sizeof(buffer); i++) {
Serial.print(buffer[i], HEX);
Serial.print(" ");
}
Serial.println();
// Check we received the message ok. XOR checksum on bytes 01-26 should match byte 27.
XOR = buffer[1];
for (int x = 2; x <= 26; x++)
{
XOR ^= buffer[x];
}
Serial.print("Calculated checksum: ");
Serial.print(XOR, HEX);
if (XOR == buffer[27])
Serial.println(" (Correct)");
else
Serial.println(" (Error)");
// Check the inverted XOR checksum
inverted = ~XOR;
Serial.print("Inverted checksum: ");
Serial.print(inverted, HEX);
if (inverted == buffer[28])
Serial.println(" (Correct)");
else
Serial.println(" (Error)");
// Extract the card number from bytes 01 (LSB) - 10 (MSB).
value = 0;
for (int x = 10; x >= 1; x--)
{
if(buffer[x] <= '9')
value = (value<<4) + buffer[x] - '0';
else
value = (value<<4) + buffer[x] - '7';
}
Serial.print("Card number: ");
Serial.println(value);
// Extract the country number from bytes 11 (LSB) - 14 (MSB).
value = 0;
for (int x = 14; x >= 11; x--)
{
if(buffer[x] <= '9')
value = (value<<4) + buffer[x] - '0';
else
value = (value<<4) + buffer[x] - '7';
}
Serial.print("Country number: ");
Serial.println(value);
// Extract the Data Block from byte 15.
Serial.print("Data block: ");
Serial.println(buffer[15] - '0');
// Extract the Animal Flag from byte 16.
Serial.print("Animal flag: ");
Serial.println(buffer[16] - '0');
Serial.println("\r");
delay(100000);
}
返回卡 ID:891920753
2 31 37 31 41 39 32 35 33 41 33 34 38 33 30 30 31 30 30 30 30 30 30 30 30 30 30 7 F8 3
Calculated checksum: 7 (Correct)
Inverted checksum: F8 (Correct)
Card number: 891920753
Country number: 900
Data block: 0
Animal flag: 1
这是将您的输入转换为实际值的方法。 我把校验和计算留给你:)
#include <array>
#include <cstdint>
#include <iostream>
std::array<std::uint8_t, 30> buffer = { 0x02, 0x31, 0x37, 0x31, 0x41, 0x39, 0x32, 0x35, 0x33, 0x41, 0x33, 0x34, 0x38, 0x33, 0x30,
0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x07, 0xf8, 0x03 };
// helper function to convecrt ascii hex character to a decimal number
std::uint64_t from_hex(const char c)
{
if(c >= '0' && c <= '9')
return c - '0';
return c - 'A' + 10;
}
struct tag_info_t
{
tag_info_t(const std::array<std::uint8_t, 30>& buffer)
{
// copy the data from the buffer to the struct
std::memcpy(&m_data, buffer.data(), sizeof(tag_info_t));
// then convert the ascii hex values to a single integer
// start at last digit and work forwards
for(int i = static_cast<int>(m_data.tag_id.size()-1); i >= 0; --i)
{
// each time we get to a new character the current
// value is shifted left by 4 bits (multiplied by 16)
m_tag_id = (m_tag_id << 4);
// then we convert the current character in the input buffer
// to a number and add it to the current value
m_tag_id += from_hex(m_data.tag_id[i]);
}
for(int i = static_cast<int>(m_data.country_id.size()-1); i >= 0; --i)
{
m_country_id = (m_country_id << 4);
m_country_id += from_hex(m_data.country_id[i]);
}
}
bool validate()
{
if(m_data.start_byte != 0x02)
return false;
if(m_data.end_byte != 0x03)
return false;
//TODO checksum
return true;
}
std::uint64_t get_tag_id() const noexcept
{
return m_tag_id;
}
std::uint64_t get_country_id() const noexcept
{
return m_country_id;
}
private:
// not strictly needed
// you can index into the raw array directly
// but this lets me show you a bit more clearly
// where I am getting the bytes from
struct data_block_t
{
std::uint8_t start_byte;
std::array<std::uint8_t, 10> tag_id;
std::array<std::uint8_t, 4> country_id;
std::uint8_t data_block;
std::uint8_t animal_flag;
std::array<std::uint8_t, 4> reserved4;
std::array<std::uint8_t, 6> reserved6;
std::uint8_t crc1;
std::uint8_t crc2;
std::uint8_t end_byte;
};
data_block_t m_data;
std::uint64_t m_country_id{};
std::uint64_t m_tag_id{};
};
int main()
{
tag_info_t tag_info{ buffer };
if(tag_info.validate())
{
std::cout << "Country ID: " << tag_info.get_country_id() << "\n";
std::cout << "Tag ID: " << tag_info.get_tag_id() << "\n";
}
return 0;
}