MinGW C 测试 - 读取蓝牙光电头电池电压

MinGW C 测试 - 读取蓝牙光电头电池电压

1.环境准备

2.编译和使用说明

  • 使用Visual Studio或MinGW编译此程序:
gcc -o opbt_battery.exe opbt_battery_voltage.c
  • 运行程序(可选择指定COM口和波特率):
opbt_battery.exe COM3 9600
  • 运行结果
    Using COM port: com3, Baud rate: 9600
    

Entering command mode… Response: {“OK”:true} Querying battery voltage… Response: {“BatteryVoltage”:4011}

Battery voltage: 4011 mV (4.01 V) Exiting command mode… Response: {“OK”:false}


## 3.程序说明
**程序功能:**
   
   - 通过串口连接OP-BT设备
   - 发送命令进入命令模式
   - 查询设备配置信息(包含电池电压)
   - 解析并显示电池电压
   - 退出命令模式

**关键步骤:**
 
   - 使用Windows API (CreateFile, WriteFile, ReadFile等)操作串口
   - 发送JSON格式命令: {"AtCommandMode":true} 进入命令模式
   - 发送 {"BatteryVoltage":"?"} 查询设备信息
   - 解析返回的JSON数据获取电池电压
   - 发送 {"AtCommandMode":false} 退出命令模式

**注意事项:**
   - 需要根据实际情况修改串口号和波特率
   - 程序中有500ms的等待时间,可能需要根据设备响应速度调整
   - 解析JSON使用了简单的字符串查找方法,在实际应用中可能需要使用更健壮的JSON解析库
这个程序提供了一个基本框架,你可以根据需要扩展它来查询其他参数或执行其他命令。

## 4. 示例代码
```c
// opbt_battery_voltage.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>

#define BUFFER_SIZE 1024
#define DEFAULT_COM "COM3"  // Default COM port, can be modified as needed
#define DEFAULT_BAUDRATE 9600  // Default baud rate, can be modified as needed

// Send command and receive response
int sendCommand(HANDLE hSerial, const char* command, char* response, int responseSize) {
    DWORD bytesWritten = 0;
    DWORD bytesRead = 0;
    BOOL status;
    
    // Clear receive buffer
    PurgeComm(hSerial, PURGE_RXCLEAR | PURGE_TXCLEAR);
    
    // Send command
    status = WriteFile(hSerial, command, strlen(command), &bytesWritten, NULL);
    if (!status || bytesWritten != strlen(command)) {
        printf("Failed to send command\n");
        return -1;
    }
    
    // Wait for device response
    Sleep(500);  // Wait 500ms, can be adjusted based on device response time
    
    // Read response
    memset(response, 0, responseSize);
    status = ReadFile(hSerial, response, responseSize - 1, &bytesRead, NULL);
    if (!status) {
        printf("Failed to read response\n");
        return -1;
    }
    
    response[bytesRead] = '\0';  // Ensure string is null-terminated
    return bytesRead;
}

// Parse battery voltage from JSON response
int parseBatteryVoltage(const char* jsonResponse) {
    char* batteryStr = strstr(jsonResponse, "\"BatteryVoltage\":");
    if (batteryStr == NULL) {
        return -1;  // Battery voltage field not found
    }
    
    // Move pointer to value position
    batteryStr += strlen("\"BatteryVoltage\":");
    
    // Skip spaces
    while (*batteryStr == ' ') {
        batteryStr++;
    }
    
    // Parse value
    return atoi(batteryStr);
}

int main(int argc, char* argv[]) {
    HANDLE hSerial;
    DCB dcbSerialParams = {0};
    COMMTIMEOUTS timeouts = {0};
    char response[BUFFER_SIZE];
    char comPort[20] = DEFAULT_COM;
    int baudRate = DEFAULT_BAUDRATE;
    
    // Process command line arguments
    if (argc >= 2) {
        strcpy(comPort, argv[1]);
    }
    if (argc >= 3) {
        baudRate = atoi(argv[2]);
    }
    
    printf("Using COM port: %s, Baud rate: %d\n", comPort, baudRate);
    
    // Open serial port
    hSerial = CreateFile(comPort,
                         GENERIC_READ | GENERIC_WRITE,
                         0,
                         NULL,
                         OPEN_EXISTING,
                         FILE_ATTRIBUTE_NORMAL,
                         NULL);
    
    if (hSerial == INVALID_HANDLE_VALUE) {
        printf("Failed to open COM port %s, error code: %d\n", comPort, GetLastError());
        return 1;
    }
    
    // Configure serial port parameters
    dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
    if (!GetCommState(hSerial, &dcbSerialParams)) {
        printf("Failed to get COM port status\n");
        CloseHandle(hSerial);
        return 1;
    }
    
    dcbSerialParams.BaudRate = baudRate;
    dcbSerialParams.ByteSize = 8;
    dcbSerialParams.StopBits = ONESTOPBIT;
    dcbSerialParams.Parity = NOPARITY;
    
    if (!SetCommState(hSerial, &dcbSerialParams)) {
        printf("Failed to set COM port parameters\n");
        CloseHandle(hSerial);
        return 1;
    }
    
    // Set timeouts
    timeouts.ReadIntervalTimeout = 50;
    timeouts.ReadTotalTimeoutConstant = 1000;
    timeouts.ReadTotalTimeoutMultiplier = 10;
    timeouts.WriteTotalTimeoutConstant = 1000;
    timeouts.WriteTotalTimeoutMultiplier = 10;
    
    if (!SetCommTimeouts(hSerial, &timeouts)) {
        printf("Failed to set COM port timeouts\n");
        CloseHandle(hSerial);
        return 1;
    }
    
    // 1. Enter command mode
    printf("Entering command mode...\n");
    if (sendCommand(hSerial, "{\"AtCommandMode\":true}\r\n", response, BUFFER_SIZE) > 0) {
        printf("Response: %s\n", response);
        if (strstr(response, "{\"OK\":true}") == NULL) {
            printf("Failed to enter command mode\n");
            CloseHandle(hSerial);
            return 1;
        }
    } else {
        printf("Failed to send command\n");
        CloseHandle(hSerial);
        return 1;
    }
    
    // 2. Query battery voltage directly
    printf("Querying battery voltage...\n");
    if (sendCommand(hSerial, "{\"BatteryVoltage\":\"?\"}\r\n", response, BUFFER_SIZE) > 0) {
        printf("Response: %s\n", response);
        
        // Parse battery voltage
        int batteryVoltage = parseBatteryVoltage(response);
        if (batteryVoltage > 0) {
            printf("\nBattery voltage: %d mV (%.2f V)\n", batteryVoltage, batteryVoltage / 1000.0);
        } else {
            printf("Unable to parse battery voltage\n");
        }
    } else {
        printf("Failed to send command\n");
    }
    
    // 3. Exit command mode
    printf("Exiting command mode...\n");
    if (sendCommand(hSerial, "{\"AtCommandMode\":false}\r\n", response, BUFFER_SIZE) > 0) {
        printf("Response: %s\n", response);
    }
    
    // Close serial port
    CloseHandle(hSerial);
    
    return 0;
}