#define NOMINMAX
#include <windows.h>
#include <stdio.h>
#include <stdint.h>
#include <mmsystem.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <math.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"
#define TARGET_INTERVAL 20 // 20ms目标间隔
#define LOG_BUFFER_SIZE 4096 // 日志缓冲区大小
#define MAX_ACCEPTABLE_INTERVAL 40 // 最大可接受间隔40ms
// ------------------ 全局变量定义 ------------------
volatile uint16_t current_vehicle_speed = 0;
uint8_t can_data[8] = {0};
volatile uint64_t total_distance_mm = 0;
volatile uint32_t last_update_time = 0;
const uint32_t can_update_period = 100; // CAN信号每100ms更新一次
LARGE_INTEGER frequency;
volatile int is_paused = 0;
HWND hStatic = NULL;
HANDLE hExitEvent = NULL;
HANDLE hLogThread = NULL;
HANDLE hLogEvent = NULL;
MMRESULT hTimerID = 0;
// 日志缓冲区和索引
static wchar_t log_buffer[LOG_BUFFER_SIZE];
static size_t log_index = 0;
static CRITICAL_SECTION log_cs; // 日志缓冲区临界区
// ------------------ 函数声明 ------------------
void ClearLogFile(const wchar_t* log_file);
void BufferLog(uint32_t current_time, uint16_t speed, uint32_t actual_interval);
void FlushLogBuffer();
void GenerateCANMessage(uint16_t speed_msg, uint8_t frame[8]);
uint16_t ReadCANMessage(uint8_t frame[8]);
void UpdateVehicleState(uint32_t current_time, uint32_t actual_interval);
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
DWORD WINAPI LogThread(LPVOID lpParam);
void CALLBACK TimerCallback(UINT uTimerID, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2);
// ------------------ 清空日志文件 ------------------
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 {
OutputDebugStringW(L"无法创建日志文件: vehicle_log.txt\n");
}
}
// ------------------ 缓冲日志(简化版) ------------------
void BufferLog(uint32_t current_time, uint16_t speed, uint32_t actual_interval) {
SYSTEMTIME st;
GetLocalTime(&st);
EnterCriticalSection(&log_cs);
// 计算总距离(米),四舍五入
uint64_t total_distance_m = (total_distance_mm + 500) / 1000;
// 计算剩余缓冲区空间
size_t remaining = LOG_BUFFER_SIZE - log_index - 1;
// 只记录时间、速度和距离(米)
int written = swprintf_s(log_buffer + log_index, remaining,
L"%02d:%02d:%02d.%03d - Speed: %d km/h, Total Distance: %llu m\n",
st.wHour, st.wMinute, st.wSecond, st.wMilliseconds,
speed, total_distance_m);
if (written > 0 && written < (int)remaining) {
log_index += written;
} else {
// 缓冲区不足,触发日志刷新
SetEvent(hLogEvent);
swprintf_s(log_buffer + log_index, LOG_BUFFER_SIZE - log_index - 1,
L"%02d:%02d:%02d.%03d - Speed: %d km/h, Total Distance: %llu m\n",
st.wHour, st.wMinute, st.wSecond, st.wMilliseconds,
speed, total_distance_m);
log_index = wcslen(log_buffer);
}
// 如果缓冲区接近满,触发日志刷新
if (log_index > LOG_BUFFER_SIZE - 512) {
SetEvent(hLogEvent);
}
LeaveCriticalSection(&log_cs);
}
// ------------------ 刷新日志缓冲区 ------------------
void FlushLogBuffer() {
if (log_index == 0) return;
FILE* file = _wfopen(LOG_FILE, L"a");
if (file) {
fwrite(log_buffer, sizeof(wchar_t), log_index, file);
fclose(file);
log_index = 0;
}
}
// ------------------ 日志线程 ------------------
DWORD WINAPI LogThread(LPVOID lpParam) {
while (1) {
// 等待日志事件或退出事件
HANDLE handles[2] = { hLogEvent, hExitEvent };
DWORD waitResult = WaitForMultipleObjects(2, handles, FALSE, 1000); // 1秒超时
if (waitResult == WAIT_OBJECT_0) {
// 日志事件触发
EnterCriticalSection(&log_cs);
FlushLogBuffer();
LeaveCriticalSection(&log_cs);
}
else if (waitResult == WAIT_OBJECT_0 + 1) {
// 退出事件触发
break;
}
else if (waitResult == WAIT_TIMEOUT) {
// 超时,定期刷新日志
EnterCritical极速Section(&log_cs);
if (log_index > 0) {
FlushLogBuffer();
}
LeaveCriticalSection(&log_cs);
}
}
// 退出前确保所有日志都写入
EnterCriticalSection(&log_cs);
FlushLogBuffer();
LeaveCriticalSection(&log_cs);
return 0;
}
// ------------------ 生成 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, uint32_t actual_interval) {
static uint32_t last_can_update_time = 0;
static uint16_t last_speed = 0; // 保存上次速度
static int speed_change_counter = 0; // 速度变化计数器
const int SPEED_CHANGE_INTERVAL = 5; // 每5次CAN更新改变速度
if (is_paused) return;
// 更新CAN信号(每100ms更新一次)
if ((last_can_update_time == 0) || (current_time - last_can_update_time) >= can_update_period) {
// 每5次CAN更新改变一次速度(约0.5秒)
if (last_speed == 0 || speed_change_counter >= SPEED_CHANGE_INTERVAL) {
// 生成更合理的随机速度(0-120km/h)
last_speed = 10 + (rand() % 110);
speed_change_counter = 0;
} else {
speed_change_counter++;
}
GenerateCANMessage(last_speed, can_data);
current_vehicle_speed = last_speed;
last_can_update_time = current_time;
}
// 使用实际间隔时间计算距离
// 单位转换:km/h -> m/s: /3.6, 毫秒->秒: /1000
double distance_m = (double)current_vehicle_speed * actual_interval / (3.6 * 1000.0);
total_distance_mm += (uint64_t)(distance_m * 1000); // 转换为毫米
}
// ------------------ 定时器回调函数(修复窗口更新) ------------------
void CALLBACK TimerCallback(UINT uTimerID, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2) {
static uint32_t start_time = 0;
static uint32_t last_time = 0;
static LARGE_INTEGER start_counter;
static LARGE_INTEGER last_counter;
HWND hwnd = (HWND)dwUser;
// 初始化计时器
if (start_time == 0) {
start_time = timeGetTime();
QueryPerformanceCounter(&start_counter);
last_counter = start_counter;
last_time = 0;
}
// 获取当前时间(毫秒)
uint32_t current_time = timeGetTime() - start_time;
// 使用高精度计数器计算实际间隔
LARGE_INTEGER current_counter;
QueryPerformanceCounter(¤t_counter);
uint32_t actual_interval = (uint32_t)((current_counter.QuadPart - last_counter.QuadPart) * 1000 / frequency.QuadPart);
last_counter = current_counter;
// 更新车辆状态(使用实际间隔时间)
UpdateVehicleState(current_time, actual_interval);
// 缓冲日志(简化版)
BufferLog(current_time, current_vehicle_speed, actual_interval);
// 实时更新UI
// 计算总距离(米),四舍五入
uint64_t total_distance_m = (total_distance_mm + 500) / 1000;
wchar_t buffer[256];
swprintf_s(buffer, 256,
L"速度: %d km/h\n距离: %llu m",
current_vehicle_speed, total_distance_m);
// 直接更新UI(使用SendMessage确保立即更新)
SendMessageW(hStatic, WM_SETTEXT, 0, (LPARAM)buffer);
}
// ------------------ 窗口处理函数 ------------------
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
static UINT timerResolution = 0; // 保存定时器分辨率
switch (uMsg) {
case WM_CREATE: {
// 初始化日志临界区
InitializeCriticalSection(&log_cs);
// 创建事件对象
hExitEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
hLogEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
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);
// 创建静态文本控件
hStatic = CreateWindowW(L"STATIC", L"速度: 0 km/h\n距离: 0 m",
WS_VISIBLE | WS_CHILD | SS_LEFT | SS_NOTIFY,
20, 80, 350, 100, hwnd, (HMENU)2, NULL, NULL);
// 确保静态文本控件创建成功
if (!hStatic) {
MessageBoxW(hwnd, L"无法创建静态文本控件", L"错误", MB_ICONERROR);
}
QueryPerformanceFrequency(&frequency);
GenerateCANMessage(0, can_data);
srand((unsigned int)time(NULL));
// 创建日志线程
hLogThread = CreateThread(
NULL,
0,
LogThread,
NULL,
CREATE_SUSPENDED, // 先挂起线程
NULL
);
// 设置日志线程优先级
SetThreadPriority(hLogThread, THREAD_PRIORITY_BELOW_NORMAL);
ResumeThread(hLogThread);
// 设置系统定时器精度
TIMECAPS tc;
timeGetDevCaps(&tc, sizeof(tc));
timerResolution = std::min(std::max(tc.wPeriodMin, 1), tc.wPeriodMax);
timeBeginPeriod(timerResolution);
// 提升进程优先级
SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);
// 创建多媒体定时器
hTimerID = timeSetEvent(
TARGET_INTERVAL,
timerResolution,
TimerCallback,
(DWORD_PTR)hwnd,
TIME_PERIODIC | TIME_CALLBACK_FUNCTION
);
if (!hTimerID) {
MessageBoxW(hwnd, L"无法创建定时器", L"错误", MB_ICONERROR);
}
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_DESTROY: {
// 通知线程退出
SetEvent(hExitEvent);
SetEvent(hLogEvent);
// 等待日志线程退出
WaitForSingleObject(hLogThread, 1000);
// 关闭句柄
CloseHandle(hLogThread);
CloseHandle(hExitEvent);
CloseHandle(hLogEvent);
// 清理日志临界区
DeleteCriticalSection(&log_cs);
// 停止定时器
if (hTimerID) {
timeKillEvent(hTimerID);
hTimerID = 0;
}
// 恢复系统定时器精度
timeEndPeriod(timerResolution);
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);
wc.style = CS_HREDRAW | CS_VREDRAW;
if (!RegisterClassW(&wc)) {
MessageBoxW(NULL, L"窗口类注册失败!", L"错误", MB_ICONERROR);
return 0;
}
HWND hwnd = CreateWindowExW(
0,
wc.lpszClassName,
L"CAN信号记录器",
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
CW_USEDEFAULT, CW_USEDEFAULT,
400, 300,
NULL,
NULL,
hInstance,
NULL
);
if (!hwnd) {
MessageBoxW(NULL, L"窗口创建失败!", L"错误", MB_ICONERROR);
return 0;
}
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
MSG msg;
while (GetMessageW(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
return (int)msg.wParam;
}
修改上述代码的错误,以C语言输出
最新发布