#include <windows.h>
#include <stdio.h>
#include <stdint.h>
#include <mmsystem.h>
#include <string.h>
#include <stdlib.h>
#pragma comment(lib, "winmm.lib") // 连接多媒体库
#define UNICODE // 启用 Unicode 支持
#define _UNICODE
#define LOG_FILE "vehicle_log.txt"
// ------------------ 全局变量定义 ------------------
uint16_t current_vehicle_speed = 0; // 当前速度(初始化为 0)
uint8_t can_data[8] = {0}; // 初始 CAN 数据帧,速度为 0
uint64_t total_distance_mm = 0; // 累计行驶距离
uint32_t elapsed_time_ms = 0; // 已行驶时间(以毫秒为单位)
const uint32_t delta_T = 20; // 刷新间隔时间(20ms)
const uint32_t can_update_period = 100; // CAN 信号速度更新时间间隔(100ms)
LARGE_INTEGER frequency, start_counter; // 高精度计时器
// 修复:增加暂停变量
int is_paused = 0; // 是否暂停,0 为未暂停,1 为暂停
// ------------------ 函数声明 ------------------
void ClearLogFile(const char* 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 char* log_file) {
FILE* file = fopen(LOG_FILE, "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 = fopen(LOG_FILE, "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); // 清空 CAN 数据帧
uint16_t mask = (1 << 13) - 1; // 13 位掩码
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;
elapsed_time_ms += delta_T;
if (!first_cycle_done) {
current_vehicle_speed = ReadCANMessage(can_data);
WriteLog(current_time, current_vehicle_speed);
first_cycle_done = 1;
return;
}
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)(current_vehicle_speed * delta_T * 10) / 36;
if ((current_time - last_log_time) >= delta_T) {
WriteLog(current_time, current_vehicle_speed);
last_log_time = current_time;
}
}
// 添加全局变量
const uint32_t display_update_interval = 1000; // 窗口更新间隔为 500ms
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);
MessageBoxW(NULL, L"程序正在运行,日志已初始化。", L"提示", MB_OK);
// 创建控件
CreateWindowW(L"BUTTON", L"Pause", WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,
10, 10, 100, 30, hwnd, (HMENU)1, GetModuleHandle(NULL), NULL);
CreateWindowW(L"STATIC", L"当前速度: 0 km/h\n总距离: 0 mm", WS_VISIBLE | WS_CHILD,
10, 50, 300, 50, hwnd, (HMENU)2, GetModuleHandle(NULL), NULL);
QueryPerformanceFrequency(&frequency);
QueryPerformanceCounter(&start_counter);
GenerateCANMessage(0, can_data);
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);
if (elapsed_ms >= delta_T) {
uint32_t current_time = (uint32_t)((current_counter.QuadPart - start_counter.QuadPart) * 1000 / frequency.QuadPart);
UpdateVehicleState(current_time);
}
// 窗口内容更新逻辑
if (elapsed_ms - last_display_update_time >= display_update_interval) {
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 WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
WNDCLASSW wc = {0};
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = L"VehicleLogger";
RegisterClassW(&wc);
HWND hwnd = CreateWindowW(wc.lpszClassName, L"CAN Signal Logger",
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
400, 300, NULL, NULL, hInstance, NULL);
ShowWindow(hwnd, nCmdShow);
MSG msg;
PostMessageW(hwnd, WM_USER + 1, 0, 0);
while (GetMessageW(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
有一个问题,现在日志能按要求每20ms读取一次CAN信号,但是现在窗口为空