#include <windows.h>
#include <stdio.h>
#include <stdint.h>
#include <mmsystem.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#pragma comment(lib, "winmm.lib")
#pragma comment(lib, "gdi32.lib")
#pragma comment(lib, "user32.lib")
#define UNICODE
#define _UNICODE
#define LOG_FILE L"vehicle_log.txt"
// ------------------ 全局变量定义 ------------------
uint16_t current_vehicle_speed = 0; // 当前速度(km/h)
uint8_t can_data[8] = {0}; // CAN 数据帧
uint64_t total_distance_mm = 0; // 累计行驶距离(mm)
uint32_t last_update_time = 0; // 上次更新状态的时间戳(ms)
const uint32_t delta_T = 20; // 目标刷新间隔(ms)
const uint32_t can_update_period = 100; // CAN 信号更新间隔(ms)
LARGE_INTEGER frequency, start_counter; // 高精度计时器
int is_paused = 0; // 暂停状态
// ------------------ 函数声明 ------------------
void ClearLogFile(const wchar_t* log_file);
void WriteLog(uint32_t current_time, uint16_t speed);
void GenerateCANMessage(uint16_t speed_msg, uint8_t frame[8]);
uint16_t ReadCANMessage(uint8_t frame[8]);
void UpdateVehicleState(uint32_t current_time);
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
// ------------------ 清空日志文件 ------------------
void ClearLogFile(const wchar_t* log_file) {
FILE* file = _wfopen(log_file, L"w");
total_distance_mm = 0;
if (file) {
fwprintf(file, L"Log initialized. Vehicle Logger started.\n");
fclose(file);
} else {
MessageBoxW(NULL, L"无法创建日志文件: vehicle_log.txt", L"错误", MB_ICONERROR);
}
}
// ------------------ 写入日志 ------------------
void WriteLog(uint32_t current_time, uint16_t speed) {
FILE* file = _wfopen(LOG_FILE, L"a");
if (!file) {
MessageBoxW(NULL, L"日志文件写入失败: vehicle_log.txt", L"错误", MB_ICONERROR);
return;
}
SYSTEMTIME st;
GetLocalTime(&st);
fwprintf(file, L"%02d:%02d:%02d.%03d - Speed: %d km/h, Total Distance: %llu mm\n",
st.wHour, st.wMinute, st.wSecond, st.wMilliseconds, speed, total_distance_mm);
fclose(file);
}
// ------------------ 生成 CAN 消息 ------------------
void GenerateCANMessage(uint16_t speed_msg, uint8_t frame[8]) {
memset(frame, 0, 8);
uint16_t mask = (1 << 13) - 1;
uint16_t encoded_speed = speed_msg & mask;
for (int i = 0; i < 13; i++) {
uint16_t bit_pos = 16 + i;
uint8_t byte_pos = bit_pos / 8;
uint8_t bit_in_byte = 7 - (bit_pos % 8);
if (encoded_speed & (1 << i)) {
frame[byte_pos] |= (1 << bit_in_byte);
}
}
}
// ------------------ 读取 CAN 消息 ------------------
uint16_t ReadCANMessage(uint8_t frame[8]) {
uint16_t speed = 0;
for (int i = 0; i < 13; i++) {
uint16_t bit_pos = 16 + i;
uint8_t byte_pos = bit_pos / 8;
uint8_t bit_in_byte = 7 - (bit_pos % 8);
if (frame[byte_pos] & (1 << bit_in_byte)) {
speed |= (1 << i);
}
}
return speed;
}
// ------------------ 更新车辆状态 ------------------
void UpdateVehicleState(uint32_t current_time) {
static uint32_t last_can_update_time = 0;
static uint32_t last_log_time = 0;
static int first_cycle_done = 0;
if (is_paused) return;
// 计算实际经过的时间(ms)
uint32_t elapsed_ms = (last_update_time == 0) ? delta_T : (current_time - last_update_time);
last_update_time = current_time;
if (!first_cycle_done) {
current_vehicle_speed = ReadCANMessage(can_data);
WriteLog(current_time, current_vehicle_speed);
first_cycle_done = 1;
return;
}
// 更新CAN信号
if ((current_time - last_can_update_time) >= can_update_period) {
uint16_t random_speed = rand() % 150;
GenerateCANMessage(random_speed, can_data);
current_vehicle_speed = random_speed;
last_can_update_time = current_time;
}
// 正确的距离计算公式
total_distance_mm += (uint64_t)((double)current_vehicle_speed * elapsed_ms / 3.6);
// 记录日志(每20ms)
if ((current_time - last_log_time) >= delta_T) {
WriteLog(current_time, current_vehicle_speed);
last_log_time = current_time;
}
}
// ------------------ 窗口处理函数 ------------------
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
static uint32_t last_display_update_time = 0;
switch (uMsg) {
case WM_CREATE: {
ClearLogFile(LOG_FILE);
// 创建控件
CreateWindowW(L"BUTTON", L"Pause", WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,
20, 20, 120, 40, hwnd, (HMENU)1, NULL, NULL);
CreateWindowW(L"STATIC", L"当前速度: 0 km/h\n总距离: 0 mm",
WS_VISIBLE | WS_CHILD | SS_LEFT,
20, 80, 350, 100, hwnd, (HMENU)2, NULL, NULL);
QueryPerformanceFrequency(&frequency);
QueryPerformanceCounter(&start_counter);
GenerateCANMessage(0, can_data);
srand((unsigned int)time(NULL)); // 初始化随机数生成器
// 初始显示
wchar_t buffer[256];
swprintf(buffer, 256, L"当前速度: %d km/h\n总距离: %llu mm", current_vehicle_speed, total_distance_mm);
SetWindowTextW(GetDlgItem(hwnd, 2), buffer);
break;
}
case WM_COMMAND: {
if (LOWORD(wParam) == 1) {
is_paused = !is_paused;
SetWindowTextW(GetDlgItem(hwnd, 1), is_paused ? L"Resume" : L"Pause");
}
break;
}
case WM_USER + 1: {
LARGE_INTEGER current_counter;
QueryPerformanceCounter(¤t_counter);
// 计算自程序启动以来的毫秒数
uint32_t elapsed_ms = (uint32_t)((current_counter.QuadPart - start_counter.QuadPart) * 1000 / frequency.QuadPart);
UpdateVehicleState(elapsed_ms);
// 更新显示(每100ms)
if (elapsed_ms - last_display_update_time >= 100) {
wchar_t buffer[256];
swprintf(buffer, 256, L"当前速度: %d km/h\n总距离: %llu mm", current_vehicle_speed, total_distance_mm);
SetWindowTextW(GetDlgItem(hwnd, 2), buffer);
last_display_update_time = elapsed_ms;
}
PostMessageW(hwnd, WM_USER + 1, 0, 0);
break;
}
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProcW(hwnd, uMsg, wParam, lParam);
}
return 0;
}
// ------------------ 主程序 ------------------
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow) {
// 确保正确注册窗口类
WNDCLASSW wc = {0};
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = L"VehicleLogger";
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
if (!RegisterClassW(&wc)) {
MessageBoxW(NULL, L"窗口类注册失败!", L"错误", MB_ICONERROR);
return 0;
}
HWND hwnd = CreateWindowW(
wc.lpszClassName,
L"CAN信号记录器",
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
CW_USEDEFAULT, CW_USEDEFAULT,
600, 400,
NULL,
NULL,
hInstance,
NULL
);
if (!hwnd) {
MessageBoxW(NULL, L"窗口创建失败!", L"错误", MB_ICONERROR);
return 0;
}
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
PostMessageW(hwnd, WM_USER + 1, 0, 0);
MSG msg;
while (GetMessageW(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
return (int)msg.wParam;
}
累计距离计算逻辑有点问题
最新发布