大致就是以下代码,,串口读写
#include <iostream>
#include "stdlib.h"
#include <string>
#include <Windows.h>
//#include <afx.h>
using namespace std;
HANDLE hcom = 0;//端口
HANDLE tThread;
DWORD threadId = 0;
//连接端口
void connectPort(char* portName){
/*
CreateFileA(
__in LPCSTR lpFileName,
__in DWORD dwDesiredAccess,
__in DWORD dwShareMode,
__in_opt LPSECURITY_ATTRIBUTES lpSecurityAttributes,
__in DWORD dwCreationDisposition,
__in DWORD dwFlagsAndAttributes,
__in_opt HANDLE hTemplateFile
);*/
hcom =CreateFile( portName,//串口名字
GENERIC_READ|GENERIC_WRITE,//读写权限
0, //独占的方式打开
NULL,//安全参数,默认就行
OPEN_EXISTING,//打开已经存在的
0 ,
NULL
);
DCB dcb;//串口通讯中的DCB结构
memset(&dcb,0,sizeof(dcb));
GetCommState(hcom,&dcb);
dcb.DCBlength= sizeof(dcb);//调用setcomm必须要的值
dcb.BaudRate=9600;//这个必须要和设备那边匹配好;
dcb.Parity= NOPARITY;//端口数据的校验方法,无校验
SetCommState(hcom,&dcb);
}
//写数据
void writeData(){
char datas[] ="往串口里写的数据";
DWORD lpNumOfByteToWrite;//实际写入的字符数
WriteFile(hcom,datas,sizeof(datas),&lpNumOfByteToWrite,NULL);
}
//接收串口数据的线程
DWORD WINAPI readThread(LPVOID lpParam ){
char buff[1024] = {0};
DWORD ret;
DWORD byteRead = -1;
/*
ReadFile(
__in HANDLE hFile, //文件句柄
__out_bcount_part_opt(nNumberOfBytesToRead, *lpNumberOfBytesRead) __out_data_source(FILE) LPVOID lpBuffer//接收数据用的buff
__in DWORD nNumberOfBytesToRead, //读取的数据量
__out_opt LPDWORD lpNumberOfBytesRead, //实际读取的数据
__inout_opt LPOVERLAPPED lpOverlapped //OVERLAPPED 结构,一般设定为 NULL
);
*/
ret = ReadFile(hcom,buff,sizeof(buff),&byteRead,NULL);
}
//读取数据
void readData(){
tThread = CreateThread(NULL,0,readThread,hcom,0,&threadId);
}
//关闭线程和端口句柄
void closeHandleAndTimer(){
CloseHandle(hcom);
TerminateThread(tThread , 0);
CloseHandle(tThread);
}
获取所有可用串口,下方打印里面的commNam就是我们平时需要的串口名
int main()
{
HKEY hkey;
/*打开一个指定的注册表键
RegOpenKeyExA (
__in HKEY hKey, //需要打开的主键的名字
__in_opt LPCSTR lpSubKey, //需要打开的子健的名字
__in_opt DWORD ulOptions, //无用
__in REGSAM samDesired, // 安全访问标记,也就是权限,读或者写
__out PHKEY phkResult //得到的将要打开键的句柄
);
*/
LONG retVal = RegOpenKeyEx(HKEY_LOCAL_MACHINE,"Hardware\\DeviceMap\\SerialComm",NULL, KEY_READ, &hkey);
if (retVal == ERROR_SUCCESS)
{
DWORD comm_index =0;
char portName[256] = {0};
char commNam[256]= {0};
DWORD dLong,dSize ;
dLong=dSize=sizeof(portName);
while (1)
{
//枚举结果 返回0标识成功
/*egEnumValueA (
__in HKEY hKey,//句柄
__in DWORD dwIndex,//索引 0开始
__out_ecount_part_opt(*lpcchValueName, *lpcchValueName + 1) LPSTR lpValueName, //用于装载位于指定索引处值名的一个缓冲区
__inout LPDWORD lpcchValueName, //指定索引处值名的字符长度
__reserved LPDWORD lpReserved, //无
__out_opt LPDWORD lpType, //装载值的类型代码的变量 无
__out_bcount_part_opt(*lpcbData, *lpcbData) __out_data_source(REGISTRY) LPBYTE lpData,串口名
__inout_opt LPDWORD lpcbData 串口名字的长度
*/
retVal = RegEnumValue(hkey,comm_index,portName,&dLong,NULL,NULL,(LPBYTE)commNam,&dSize);
if (retVal == ERROR_NO_MORE_ITEMS)
{
break;
}
//我电脑的结果 index =0, portname = \Device\Serial2, dLong = 15 ,commNam=COM3 ,dSize= 5
printf("index =%d, portname = %s, dLong = %d ,commNam=%s ,dSize= %d ",comm_index,portName,dLong, commNam , dSize);
comm_index++;
dLong=dSize=100;
}
RegCloseKey(hkey);
}
system("pause");
return 0;
}
2022/1/18 更新
串口读取有时会停在readfile,就不往下执行了,导致线程直接卡死,串口这个时候在等待读取数据,readFile是阻塞的状态。出现这样的情况可以设置一个超时。
SetupComm(hCom, 1024, 1024); //输入缓冲区和输出缓冲区的大小都是1024
COMMTIMEOUTS TimeOuts;
TimeOuts.ReadIntervalTimeout = 1000; //设定读超时
TimeOuts.ReadTotalTimeoutMultiplier = 2;
TimeOuts.ReadTotalTimeoutConstant = 500;
TimeOuts.WriteTotalTimeoutMultiplier = 20; //设定写超时
TimeOuts.WriteTotalTimeoutConstant = 30;
SetCommTimeouts(hCom, &TimeOuts); //设置超时
读取的时候,buff定的1024,所以在readFile的时候,超时的时间就是2*1024+500,也就是上面的
ReadTotalTimeoutMultiplier*1024 +ReadTotalTimeoutConstant ,大概两秒多的时间,debug一下看到,确实是3秒内就返回了