Browse Source

添加 温度485数据解析程序

master
zhaohe 1 year ago
parent
commit
7bf53491a5
  1. 4
      .gitignore
  2. 4
      .settings/language.settings.xml
  3. 1
      tools/build.bat
  4. 368
      tools/temperature_sensor_data_parse.cpp
  5. BIN
      tools/黄金温度485数据解析程序V2.exe

4
.gitignore

@ -1,2 +1,4 @@
Debug
Release
Release
tools/log.txt
tools/.vscode

4
.settings/language.settings.xml

@ -5,7 +5,7 @@
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
<provider class="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" console="false" env-hash="-1298583211825695533" id="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" keep-relative-paths="false" name="MCU ARM GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
<provider class="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" console="false" env-hash="336939840050793459" id="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" keep-relative-paths="false" name="MCU ARM GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
<language-scope id="org.eclipse.cdt.core.gcc"/>
<language-scope id="org.eclipse.cdt.core.g++"/>
</provider>
@ -16,7 +16,7 @@
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
<provider class="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" console="false" env-hash="-1249455055963968572" id="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" keep-relative-paths="false" name="MCU ARM GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
<provider class="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" console="false" env-hash="386067995912520420" id="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" keep-relative-paths="false" name="MCU ARM GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
<language-scope id="org.eclipse.cdt.core.gcc"/>
<language-scope id="org.eclipse.cdt.core.g++"/>
</provider>

1
tools/build.bat

@ -0,0 +1 @@
g++ -static -static-libgcc -static-libstdc++ -lwsock32 -lstdc++ .\temperature_sensor_data_parse.cpp -o temperature_sensor_data_parse.exe

368
tools/temperature_sensor_data_parse.cpp

@ -0,0 +1,368 @@
#pragma comment(lib, "ws2_32.lib")
#include <winsock2.h>
#include <fstream>
#include <functional>
#include <iostream>
#include <list>
#include <map>
#include <memory>
#include <mutex>
#include <set>
#include <sstream>
#include <string>
#include <thread>
#include <vector>
//
#include <Windows.h>
//
using namespace std;
/***********************************************************************************************************************
* *
***********************************************************************************************************************/
#define RX_OVERTIME_MS 30 // 之所以设置成10ms,目的是为了能够监听到回执包
/***********************************************************************************************************************
* *
***********************************************************************************************************************/
ofstream* logfile;
/**
* @brief
*/
bool log_file_init() {
// 创建日志文件
logfile = new ofstream("log.txt", ios::app);
if (logfile == NULL) {
printf("创建日志文件失败\n");
return false;
}
return true;
}
void log(const char* fmt, ...) {
char buf[1024] = {0};
va_list args;
va_start(args, fmt);
vsprintf(buf, fmt, args);
va_end(args);
cout << buf;
}
void logd(const char* fmt, ...) {
char buf[1024] = {0};
va_list args;
va_start(args, fmt);
vsprintf(buf, fmt, args);
va_end(args);
if (logfile) {
*logfile << buf;
logfile->flush();
}
cout << buf;
}
#define LOG(fmt, ...) log("[%08d] INFO : " fmt "\n", GetTickCount(), ##__VA_ARGS__);
#define LOGD(fmt, ...) logd("[%08d] INFO : " fmt "\n", GetTickCount(), ##__VA_ARGS__);
string hextostr(const char* data, size_t len) {
string ret;
for (size_t i = 0; i < len; i++) {
char buf[20] = {0};
sprintf(buf, "%02x", (uint8_t)data[i]);
ret += buf;
}
return ret;
}
/***********************************************************************************************************************
* MODBUS *
***********************************************************************************************************************/
static const uint8_t auchCRCHi[] = {0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81,
0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01,
0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40};
// CRC低位字节值表
static const uint8_t auchCRCLo[] = { // CRC_16低8位数据区
0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF,
0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3, 0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F,
0x3E, 0xFE, 0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26, 0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0,
0x60, 0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E, 0x7F, 0xBF,
0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5, 0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C, 0x5D, 0x9D, 0x5F, 0x9F, 0x9E,
0x5E, 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C, 0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83, 0x41, 0x81, 0x80, 0x40};
/*CRC16查表计算函数*/
uint16_t modbus_gen_crc16(uint8_t* puckMsg, uint8_t usDataLen) {
volatile uint8_t uchCRCHi = 0xFF; // 高CRC字节初始化
volatile uint8_t uchCRCLo = 0xFF; // 低CRC 字节初始化
volatile uint32_t uIndex; // CRC循环中的索引
// 传输消息缓冲区
while (usDataLen--) {
// 计算CRC
uIndex = uchCRCLo ^ *puckMsg++;
uchCRCLo = uchCRCHi ^ auchCRCHi[uIndex];
uchCRCHi = auchCRCLo[uIndex];
}
// 返回结果,高位在前
return (uchCRCLo << 8 | uchCRCHi);
}
void modbus_pack_crc_to_packet(uint8_t* puckMsg, uint8_t packetlen) {
uint16_t crc = modbus_gen_crc16(puckMsg, packetlen - 2);
puckMsg[packetlen - 2] = crc >> 8;
puckMsg[packetlen - 1] = crc;
}
bool modbus_checkcrc16(uint8_t* message, uint8_t length) { return (modbus_gen_crc16(message, length) == 0x00) ? true : false; }
/***********************************************************************************************************************
* *
***********************************************************************************************************************/
unique_ptr<thread> serial_listen_thread;
unique_ptr<thread> serial_parse_thread;
mutex rx_lock_;
uint8_t serial_rxcache[1024] = {0};
uint8_t serial_rxlen = 0;
HANDLE serial_CommHandler;
uint32_t serial_last_rx_data_ticket;
static void serial_on_data(const char* data, size_t len);
int serial_receive(uint8_t* rxbuf, int rxbufsize) {
COMMTIMEOUTS TimeOuts;
GetCommTimeouts(serial_CommHandler, &TimeOuts);
TimeOuts.ReadIntervalTimeout = 0; // 读间隔超时
TimeOuts.ReadTotalTimeoutMultiplier = 0; // 读时间系数
TimeOuts.ReadTotalTimeoutConstant = 1; // 读时间常量
SetCommTimeouts(serial_CommHandler, &TimeOuts);
DWORD wCount = rxbufsize; // 成功读取的数据字节数
BOOL bReadStat = ReadFile(serial_CommHandler, // 串口句柄
rxbuf, // 数据首地址
wCount, // 要读取的数据最大字节数
&wCount, // DWORD*,用来接收返回成功读取的数据字节数
NULL);
return wCount;
}
bool serial_send(const uint8_t* data, size_t len) {
DWORD dwBytesWrite = len;
BOOL bWriteStat = WriteFile(serial_CommHandler, // 串口句柄
(char*)data, // 数据首地址
dwBytesWrite, // 要发送的数据字节数
&dwBytesWrite, // DWORD*,用来接收返回成功发送的数据字节数
NULL); // NULL为同步发送,OVERLAPPED*为异步发送
return dwBytesWrite;
}
bool serial_open(string serial, string baudrate) {
char portnamebuf[256] = {0};
sprintf(portnamebuf, "\\\\.\\%s", serial.c_str());
serial_CommHandler = CreateFileA(portnamebuf, // port name
GENERIC_READ | GENERIC_WRITE, // Read/Write
0, // No Sharing
NULL, // No Security
OPEN_EXISTING, // Open existing port only
0, // Non Overlapped I/O
NULL); // Null for Comm Devices
if (serial_CommHandler == INVALID_HANDLE_VALUE) {
LOG("Error in opening serial port");
return false;
}
DCB p;
memset(&p, 0, sizeof(p));
p.DCBlength = sizeof(p);
p.BaudRate = atoi(baudrate.c_str()); // 波特率
p.ByteSize = 8;
// 设置校验位
p.Parity = NOPARITY;
p.StopBits = ONESTOPBIT;
if (!SetCommState(serial_CommHandler, &p)) {
CloseHandle(serial_CommHandler);
LOG("Error in setting serial port state");
return false;
}
serial_listen_thread.reset(new thread([]() {
while (true) {
uint8_t rx[1024] = {0};
int rx_cnt = serial_receive(rx, 1024);
// LOG("接收到串口数据: %d", rx_cnt);
if (rx_cnt != 0) {
lock_guard<mutex> lock(rx_lock_);
// LOG("接收到串口数据: %s", hextostr((char*)rx, rx_cnt).c_str());
if (rx_cnt + serial_rxlen > sizeof(serial_rxcache)) {
memset(serial_rxcache, 0, sizeof(serial_rxcache));
serial_rxlen = 0;
}
memcpy(serial_rxcache + serial_rxlen, rx, rx_cnt);
serial_rxlen += rx_cnt;
serial_last_rx_data_ticket = GetTickCount();
}
this_thread::sleep_for(chrono::microseconds(1));
}
return 0;
}));
serial_parse_thread.reset(new thread([]() {
while (true) {
this_thread::sleep_for(chrono::milliseconds(1));
{
lock_guard<mutex> lock(rx_lock_);
if (serial_rxlen == 0) continue;
if (GetTickCount() - serial_last_rx_data_ticket > RX_OVERTIME_MS) {
serial_on_data((const char*)serial_rxcache, serial_rxlen);
memset(serial_rxcache, 0, sizeof(serial_rxcache));
serial_rxlen = 0;
}
}
}
return 0;
}));
return true;
}
typedef struct {
vector<uint8_t> data;
} data_t;
list<data_t> data_list;
#pragma pack(1)
typedef struct {
uint8_t slaveAdd;
uint8_t modbusCmd;
uint8_t regAdd_H;
uint8_t regAdd_L;
uint8_t nregH;
uint8_t nregL;
uint8_t nbyte;
uint8_t data[];
} modbus_data_t;
typedef struct {
uint8_t slaveAdd;
uint8_t modbusCmd;
uint8_t regAdd_H;
uint8_t regAdd_L;
uint8_t nregH;
uint8_t nregL;
uint8_t check[2];
} modbus_receipt_data_t;
#pragma pack()
typedef struct {
uint8_t slaveAdd;
uint8_t modbusCmd;
uint16_t regAdd;
uint16_t nreg;
uint8_t nbyte;
uint16_t t1[5];
bool hasReceipt;
} temperature_data_t;
bool parse_temperature_data(const char* rx, size_t len, temperature_data_t* temperaturedata) {
modbus_data_t* mdbusdata = (modbus_data_t*)rx;
if (mdbusdata->nbyte != 10) {
return false;
}
int cmdlen = mdbusdata->nbyte + 7 + 2;
int receiptlen = 8;
bool check = modbus_checkcrc16((uint8_t*)mdbusdata, cmdlen);
if (!check) {
return false;
}
temperaturedata->slaveAdd = mdbusdata->slaveAdd;
temperaturedata->modbusCmd = mdbusdata->modbusCmd;
temperaturedata->regAdd = (mdbusdata->regAdd_H << 8) | mdbusdata->regAdd_L;
temperaturedata->nreg = (mdbusdata->nregH << 8) | mdbusdata->nregL;
temperaturedata->nbyte = mdbusdata->nbyte;
for (int i = 0; i < 5; i++) {
temperaturedata->t1[i] = (mdbusdata->data[i * 2] << 8) | mdbusdata->data[i * 2 + 1];
}
if (len == cmdlen + receiptlen) {
temperaturedata->hasReceipt = true;
}else{
temperaturedata->hasReceipt = false;
}
return true;
}
float I2T(int32_t I) {
int32_t temperature001 = (I / 1000.0 - 4) / (20 - 4) * 350 * 100.0; // 0.01度
if (temperature001 < 0) {
temperature001 = 0;
}
return temperature001 / 100.0;
}
static void serial_on_data(const char* data, size_t len) { //
// LOG("接收到串口数据: %s", hextostr(data, len).c_str());
temperature_data_t td;
bool suc = parse_temperature_data(data, len, &td);
if (!suc) {
LOGD("解析失败 %s", hextostr(data, len).c_str());
} else {
LOGD("TO:%d CMD[0x%x] [%x: nreg:%d nbyte:%d] Receipt[%s] || %.2f %.2f %.2f %.2f %.2f ||", td.slaveAdd, td.modbusCmd, td.regAdd, td.nreg, td.nbyte, //
td.hasReceipt ? "YES" : "NO", I2T(td.t1[0]), I2T(td.t1[1]), I2T(td.t1[2]), I2T(td.t1[3]), I2T(td.t1[4]));
}
// data_list.push_back({vector<uint8_t>(data, data + len)});
}
int _main(int argc, char const* argv[]) {
bool loginit = log_file_init();
if (!loginit) {
LOGD("日志文件初始化失败");
return -1;
}
// WSADATA wsaData;
// WSAStartup(MAKEWORD(2, 2), &wsaData);
LOGD("黄金温度消息解析程序 v2.0");
// 请输串口号
string serial;
cout << "请输入串口号:";
cin >> serial;
// 请输波特率
string baudrate;
cout << "请输入波特率:";
cin >> baudrate;
bool suc = serial_open(serial, baudrate);
if (!suc) {
cout << "串口打开失败" << endl;
return -1;
}
LOGD("串口打开成功: %s(%d)", serial.c_str(), atoi(baudrate.c_str()));
LOGD("开始监听数据");
while (true) {
Sleep(1000);
}
return 0;
}
int main(int argc, char const* argv[]) {
_main(argc, argv);
while (true) {
Sleep(1000);
}
}

BIN
tools/黄金温度485数据解析程序V2.exe

Loading…
Cancel
Save