Windows下用C语言识别Standard Serial over Bluetooth Link的Outgoing COM端口
用C语言实现蓝牙串口识别与数据读取(Windows平台)
核心思路
可以用C语言结合Windows API实现需求:通过SetupAPI枚举系统串口设备,筛选出描述为Standard Serial over Bluetooth Link的设备,再读取注册表信息区分Outgoing端口,最后用Win32串口API打开端口并读取数据。
步骤拆解与关键实现
1. 枚举并筛选蓝牙串口设备
Windows将蓝牙串口归类到Ports (COM & LPT)设备类,需借助以下API遍历设备:
SetupDiGetClassDevs:获取指定设备类的所有已连接设备列表SetupDiEnumDeviceInfo:遍历设备列表中的每个设备SetupDiGetDeviceRegistryProperty:读取设备的描述信息,匹配Standard Serial over Bluetooth Link
2. 识别Outgoing端口
蓝牙串口的方向信息存储在设备注册表的Device Parameters子键下,通过RegQueryValueEx读取Direction值,筛选出值为Outgoing的端口,同时读取PortName获取COM端口号。
3. 打开串口并读取数据
用CreateFile打开目标COM端口,通过DCB结构体配置串口参数(匹配HC-05默认的9600波特率、8位数据位、无校验、1位停止位),最后用ReadFile循环读取数据。
完整代码示例
#include <windows.h> #include <setupapi.h> #include <initguid.h> #include <devguid.h> #include <stdio.h> #define BLUETOOTH_SERIAL_DESC "Standard Serial over Bluetooth Link" #define OUTGOING_DIRECTION "Outgoing" // 查找目标蓝牙Outgoing串口 BOOL FindBluetoothOutgoingPort(char* outPortName, DWORD maxLen) { HDEVINFO hDevInfo = SetupDiGetClassDevs(&GUID_DEVCLASS_PORTS, NULL, NULL, DIGCF_PRESENT); if (hDevInfo == INVALID_HANDLE_VALUE) { printf("SetupDiGetClassDevs failed: %lu\n", GetLastError()); return FALSE; } SP_DEVINFO_DATA devInfoData = {0}; devInfoData.cbSize = sizeof(SP_DEVINFO_DATA); for (DWORD i = 0; SetupDiEnumDeviceInfo(hDevInfo, i, &devInfoData); i++) { // 读取设备描述 TCHAR desc[256] = {0}; if (!SetupDiGetDeviceRegistryProperty(hDevInfo, &devInfoData, SPDRP_DEVICEDESC, NULL, (PBYTE)desc, sizeof(desc), NULL)) { continue; } // 匹配蓝牙串口描述 if (_tcscmp(desc, TEXT(BLUETOOTH_SERIAL_DESC)) != 0) { continue; } // 打开设备注册表项 HKEY hDeviceKey = SetupDiOpenDevRegKey(hDevInfo, &devInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_READ); if (hDeviceKey == INVALID_HANDLE_VALUE) { continue; } // 读取端口方向 TCHAR direction[32] = {0}; DWORD dataSize = sizeof(direction); if (RegQueryValueEx(hDeviceKey, TEXT("Direction"), NULL, NULL, (LPBYTE)direction, &dataSize) == ERROR_SUCCESS) { if (_tcscmp(direction, TEXT(OUTGOING_DIRECTION)) == 0) { // 读取端口名称 TCHAR portName[32] = {0}; dataSize = sizeof(portName); if (RegQueryValueEx(hDeviceKey, TEXT("PortName"), NULL, NULL, (LPBYTE)portName, &dataSize) == ERROR_SUCCESS) { _tcscpy_s((TCHAR*)outPortName, maxLen, portName); RegCloseKey(hDeviceKey); SetupDiDestroyDeviceInfoList(hDevInfo); return TRUE; } } } RegCloseKey(hDeviceKey); } SetupDiDestroyDeviceInfoList(hDevInfo); return FALSE; } // 打开串口并读取数据 BOOL ReadSerialPort(const char* portName) { HANDLE hSerial = CreateFile(portName, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hSerial == INVALID_HANDLE_VALUE) { printf("CreateFile failed: %lu\n", GetLastError()); return FALSE; } // 配置串口参数(匹配HC-05默认设置) DCB dcbSerialParams = {0}; dcbSerialParams.DCBlength = sizeof(dcbSerialParams); if (!GetCommState(hSerial, &dcbSerialParams)) { printf("GetCommState failed: %lu\n", GetLastError()); CloseHandle(hSerial); return FALSE; } dcbSerialParams.BaudRate = CBR_9600; dcbSerialParams.ByteSize = 8; dcbSerialParams.StopBits = ONESTOPBIT; dcbSerialParams.Parity = NOPARITY; if (!SetCommState(hSerial, &dcbSerialParams)) { printf("SetCommState failed: %lu\n", GetLastError()); CloseHandle(hSerial); return FALSE; } // 设置读取超时 COMMTIMEOUTS timeouts = {0}; timeouts.ReadIntervalTimeout = 50; timeouts.ReadTotalTimeoutConstant = 50; timeouts.ReadTotalTimeoutMultiplier = 10; if (!SetCommTimeouts(hSerial, &timeouts)) { printf("SetCommTimeouts failed: %lu\n", GetLastError()); CloseHandle(hSerial); return FALSE; } // 循环读取数据 char buffer[256] = {0}; DWORD bytesRead = 0; printf("Reading data from %s...\n", portName); while (TRUE) { if (ReadFile(hSerial, buffer, sizeof(buffer)-1, &bytesRead, NULL)) { if (bytesRead > 0) { buffer[bytesRead] = '\0'; printf("Received: %s", buffer); } } else { printf("ReadFile failed: %lu\n", GetLastError()); break; } } CloseHandle(hSerial); return TRUE; } int main() { char portName[32] = {0}; if (FindBluetoothOutgoingPort(portName, sizeof(portName))) { printf("Found Bluetooth Outgoing Port: %s\n", portName); ReadSerialPort(portName); } else { printf("No Bluetooth Outgoing Port found.\n"); } return 0; }
编译与运行说明
- 使用MSVC编译器编译时,需链接
setupapi.lib库:cl bluetooth_serial.c setupapi.lib - 程序需以管理员权限运行,否则可能无法读取设备注册表信息
- 确保HC-05已与电脑配对并建立串口连接
内容的提问来源于stack exchange,提问作者Vagabond4761
相关产品推荐
相关产品推荐

