C++ C#自动获得特定串口 获得串口列表

2023-11-10

目的:自动获得特定串口。 

0、C++自动获得特定串口 读设备管理器 计算机管理 串口列表 

 

// PrintDeviceInfo.cpp : 定义控制台应用程序的入口点。
#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
#include <Windows.h>
#include <setupapi.h>
#pragma comment(lib, "setupapi.lib")
//获取特定串口号 示例Qualcomm HS-USB Diagnostics 9091 (COM20)
int getSpecialComNum(char *in)
{
	char out[100] = { 0 };
	sscanf_s(in, "Qualcomm HS-USB Diagnostics 9091 (COM%[0-9])", out,sizeof(out)); //不是%d哦
	return atoi(out);
}
//从设备信息中 获取特定串口号  @return <=0无效
int  getSpecialComNumFromDevInfo()
{
	HDEVINFO hDevInfo = SetupDiGetClassDevs(NULL, NULL, NULL, DIGCF_PRESENT|DIGCF_ALLCLASSES);
	if (hDevInfo == INVALID_HANDLE_VALUE)
	{
		printf("SetupDiGetClassDevs Err:%d", GetLastError());
		return -2;
	};

	SP_CLASSIMAGELIST_DATA _spImageData = { 0 };
	_spImageData.cbSize = sizeof(SP_CLASSIMAGELIST_DATA);
	SetupDiGetClassImageList(&_spImageData);

	SP_DEVINFO_DATA spDevInfoData = { 0 };
	spDevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
	for (DWORD i = 0; SetupDiEnumDeviceInfo(hDevInfo, i, &spDevInfoData); i++)	
	{
		char  szBuf[MAX_PATH] = { 0 };
		int  wImageIdx = 0;
		short  wItem = 0;
		if (!SetupDiGetDeviceRegistryPropertyA(hDevInfo, &spDevInfoData, SPDRP_CLASS, NULL, (PBYTE)szBuf, MAX_PATH, 0))
		{
			continue;
		};
		if (strcmp(szBuf, "Ports") != 0) //只取端口
		{
			continue;
		}
		printf("Class1:%s\r\n", szBuf);
		if (SetupDiGetClassImageIndex(&_spImageData, &spDevInfoData.ClassGuid, &wImageIdx))
		{
			char  szName[MAX_PATH] = { 0 };
			DWORD  dwRequireSize;
				
			if (!SetupDiGetClassDescription(&spDevInfoData.ClassGuid, (PWSTR)szBuf, MAX_PATH, &dwRequireSize))
			{
				continue;
			};
			wprintf(L"Class:%s\r\n", szBuf);

			if (SetupDiGetDeviceRegistryProperty(hDevInfo, &spDevInfoData, SPDRP_FRIENDLYNAME, NULL, (PBYTE)szName, MAX_PATH - 1, 0))
			{
				wprintf(L"FriendlyName:%s\r\n\r\n", szName);
				if (int comNum=getSpecialComNum(szName) > 0)
				{
					return comNum;
				}
			}
			else  if (SetupDiGetDeviceRegistryProperty(hDevInfo, &spDevInfoData, SPDRP_DEVICEDESC, NULL, (PBYTE)szName, MAX_PATH - 1, 0))
			{
				wprintf(L"Device:%s\r\n\r\n", szName);
			}
		}	
	}
	SetupDiDestroyClassImageList(&_spImageData);
	return - 1;
}

int  main(int  argc, char* argv[])
{
	printf("Locale is: %s\n", setlocale(LC_ALL, "chs"));
	printf("串口号:%d\n",getSpecialComNumFromDevInfo());
	//PrintDevicesInfo2();
	getchar();
	return  0;
}

1、C++注册表方式

#include <iostream>
#include <windows.h>
//***********************
// 枚举所有的串口,以及名称
//return 特定的串口号 或-1失败 
//***********************
int EnumAllComm()
{
	HKEY hkey;
	int result;
	int i = 0;
	result = RegOpenKeyEx(HKEY_LOCAL_MACHINE,"Hardware\\DeviceMap\\SerialComm", NULL, KEY_READ, &hkey);
	if (ERROR_SUCCESS == result)   //打开串口注册表   
	{
		do
		{
			TCHAR portName[0x100] = { 0 };//portName是注册表名称(不是设备管理器里的前缀),commName就是值 串口名字COMN
			TCHAR commName[0x100] = {0};
			DWORD dwSize = sizeof(portName) / sizeof(TCHAR);
			DWORD dwLong = dwSize;
			result = RegEnumValue(hkey, i, portName, &dwLong, NULL, NULL, (LPBYTE)commName, &dwSize);
			if (ERROR_NO_MORE_ITEMS == result)	{break;	}  			//   枚举串口				 	
			printf("%d %s %s\n", i, portName, commName); //显示名称及值

			if (strcmp(portName, "\\Device\\QCUSB_COM5_2") == 0) //特定串口
			{
				return atoi(commName + 3);//去掉COM只取号 正常返回
			}
			i++;
		} while (TRUE);
		RegCloseKey(hkey); //关闭注册表
	}
	return -1;//没找到特定串口
}
int main()
{
    std::cout << "Hello World!\n";
	std::cout << "**************************Special COM:"<<EnumAllComm()<<"\n";
	std::cout << "Hello World! end\n";
}

 注册表的key在不同的电脑上是否会变化?

2.C++直接打开试

//默认只找倒数第一个
int getCommNum()
{
	HANDLE hCom;
	int i;	
	BOOL flag;
	char str[100] = {0};
	flag = FALSE;
	for (i = 30; i >= 1; i--)//此程序支持N个串口
	{
		sprintf(str,"\\\\.\\COM%d",i);
		//printf("%s%s",str,"\n"); 
		hCom = CreateFile(str, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
		if (INVALID_HANDLE_VALUE != hCom)
		{//能打开该串口,则添加该串口
			CloseHandle(hCom);
			return i;
		}
	}
	return -1;
}

3、USB VID PID MI +串口前缀

#define MY_USB_PID_VID_F200	_T("VID_05C6&PID_9018")  //\\6&1DC4E91E&3
#define MY_USB_PID_VID_F210	_T("VID_18D1&PID_4001") //\\&MI_046&4592401&0&0004
#define MY_USB_PID_VID_F210_ELSE _T("VID_18D1&PID_4EE8")//这个在adb打开时存在
//获取特定串口号 示例Qualcomm HS-USB Diagnostics 9091 (COM20)
string getSpecialComNum(const char *in)
{
	logger.INFO_F(FUN_LINE+in);
	CString temp(in);
	if (StrStr(temp, "Qualcomm HS-USB Android GPS 9018") == NULL && StrStr(temp, "USB 串行设备") == NULL)
	{
		return "";
	}
	int ret=getContentInBracket(temp);
	if (ret != 0) { return ""; }
	temp.Replace("COM","");
	logger.INFO_F(FUN_LINE +" OK, COM"+ temp.GetBuffer());
	return temp;

	//char out[100] = { 0 };
	//sscanf_s(in, "Qualcomm HS-USB Android GPS 9018 (COM%[0-9])", out, sizeof(out)); //不是%d哦
	//return out;
}
//从设备信息中 获取特定串口号  @return <=0无效
int  getSpecialComNumFromDevInfo()
{
	HDEVINFO hDevInfo = SetupDiGetClassDevs(NULL, NULL, NULL, DIGCF_PRESENT | DIGCF_ALLCLASSES);
	if (hDevInfo == INVALID_HANDLE_VALUE)
	{
		printf("SetupDiGetClassDevs Err:%d", GetLastError());
		return -2;
	};

	SP_CLASSIMAGELIST_DATA _spImageData = { 0 };
	_spImageData.cbSize = sizeof(SP_CLASSIMAGELIST_DATA);
	SetupDiGetClassImageList(&_spImageData);

	SP_DEVINFO_DATA spDevInfoData = { 0 };
	spDevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
	for (DWORD i = 0; SetupDiEnumDeviceInfo(hDevInfo, i, &spDevInfoData); i++)
	{
		char  szBuf[MAX_PATH] = { 0 };
		int  wImageIdx = 0;
		short  wItem = 0;
		if (!SetupDiGetDeviceRegistryPropertyA(hDevInfo, &spDevInfoData, SPDRP_CLASS, NULL, (PBYTE)szBuf, MAX_PATH, 0))
		{
			continue;
		};
		if (strcmp(szBuf, "Ports") != 0) //只取端口
		{
			continue;
		}
		printf("Class1:%s\r\n", szBuf);


		// PID_VID 识别 筛选出实际串口
		DWORD nSize = 0;
		TCHAR				szDis[MAX_PATH] = { 0x00 };// 存储设备实例ID
		if (!SetupDiGetDeviceInstanceId(hDevInfo, &spDevInfoData, szDis, sizeof(szDis), &nSize)) { break; }
		// 根据设备信息寻找VID PID一致的设备
		CString strTemp;
		strTemp.Format(_T("%s"), szDis);
		logger.INFO_F(FUN_LINE+ szDis);
		//strTemp.MakeUpper();
		if ((strTemp.Find(MY_USB_PID_VID_F200, 0) == -1)  && (strTemp.Find(MY_USB_PID_VID_F210, 0) == -1)) //没找到
		{
			logger.INFO_F(FUN_LINE+"USB_PID_VID mismatch.");
			continue;
		}
		logger.INFO_F(FUN_LINE+"PID_VID Check OK.");


		if (SetupDiGetClassImageIndex(&_spImageData, &spDevInfoData.ClassGuid, &wImageIdx))
		{
			char  szName[MAX_PATH] = { 0 };
			DWORD  dwRequireSize;

			if (!SetupDiGetClassDescriptionW(&spDevInfoData.ClassGuid, (PWSTR)szBuf, MAX_PATH, &dwRequireSize))
			{
				continue;
			};
			wprintf(L"Class:%s\r\n", szBuf);

			if (SetupDiGetDeviceRegistryPropertyW(hDevInfo, &spDevInfoData, SPDRP_FRIENDLYNAME, NULL, (PBYTE)szName, MAX_PATH - 1, 0))
			{
				wprintf(L"FriendlyName:%s\r\n\r\n", szName);
				int comNum = atoi(getSpecialComNum(wideCharToMultiByte((wchar_t *)szName)).c_str()); //根据特殊前缀来识别
				if (comNum > 0)
				{
					return comNum;
				}
				logger.ERROR_F(FUN_LINE+" Com prefix mismatch.");
			}
			else  if (SetupDiGetDeviceRegistryProperty(hDevInfo, &spDevInfoData, SPDRP_DEVICEDESC, NULL, (PBYTE)szName, MAX_PATH - 1, 0))
			{
				wprintf(L"Device:%s\r\n\r\n", szName);
			}
			else
			{
				logger.ERROR_F(FUN_LINE);
			}
		}
		else
		{
			logger.ERROR_F(FUN_LINE);
		}
	}
	SetupDiDestroyClassImageList(&_spImageData);
	logger.ERROR_F(FUN_LINE);
	return -1;
}

//是否插了设备  @return <=0无效
int  isHaveDevice()
{
	HDEVINFO hDevInfo = SetupDiGetClassDevs(NULL, NULL, NULL, DIGCF_PRESENT | DIGCF_ALLCLASSES);
	if (hDevInfo == INVALID_HANDLE_VALUE)
	{
		printf("SetupDiGetClassDevs Err:%d", GetLastError());
		return -2;
	};

	SP_CLASSIMAGELIST_DATA _spImageData = { 0 };
	_spImageData.cbSize = sizeof(SP_CLASSIMAGELIST_DATA);
	SetupDiGetClassImageList(&_spImageData);

	SP_DEVINFO_DATA spDevInfoData = { 0 };
	spDevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
	for (DWORD i = 0; SetupDiEnumDeviceInfo(hDevInfo, i, &spDevInfoData); i++)
	{
		char  szBuf[MAX_PATH] = { 0 };
		int  wImageIdx = 0;
		short  wItem = 0;
		if (!SetupDiGetDeviceRegistryPropertyA(hDevInfo, &spDevInfoData, SPDRP_CLASS, NULL, (PBYTE)szBuf, MAX_PATH, 0))
		{
			continue;
		};
		if (strcmp(szBuf, "Ports") != 0) //只取端口
		{
			continue;
		}
		printf("Class1:%s\r\n", szBuf);


		// PID_VID 识别 筛选出实际串口
		DWORD nSize = 0;
		TCHAR				szDis[MAX_PATH] = { 0x00 };// 存储设备实例ID
		if (!SetupDiGetDeviceInstanceId(hDevInfo, &spDevInfoData, szDis, sizeof(szDis), &nSize)) { break; }
		// 根据设备信息寻找VID PID一致的设备
		CString strTemp;
		strTemp.Format(_T("%s"), szDis);
		logger.INFO_F(FUN_LINE + szDis);
		//strTemp.MakeUpper();
		if ((strTemp.Find(MY_USB_PID_VID_F200, 0) == -1) && (strTemp.Find(MY_USB_PID_VID_F210, 0) == -1) && (strTemp.Find(MY_USB_PID_VID_F210_ELSE, 0) == -1)) //没找到
		{
			logger.INFO_F(FUN_LINE + "USB_PID_VID mismatch.");
			continue;
		}
		logger.INFO_F(FUN_LINE + "PID_VID Check OK.");
		return 0;
	}
	SetupDiDestroyClassImageList(&_spImageData);
	logger.ERROR_F(FUN_LINE);
	return -1;
}

4、C#自动获得特定串口 枚举【计算机管理】表

 C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Management;
using System.Text;
using System.Threading.Tasks;

namespace FT_M20
{
    class MySerialPort
    {
        public static string strConvertToHexStr(string str)
        {
            string strHex = "";
            foreach (byte b in str)
            {
                strHex += String.Format("{0:X2} ", b);
            }
            return strHex;
        }
        public static byte[] hexConvertToByteArray(String str)
        {
            str = str.Replace(" ", "");
            byte[] b = new byte[str.Length / 2];
            for (int i = 0; i < str.Length; i = i + 2)
            {
                b[i / 2] = (byte)Convert.ToInt32(str.Substring(i, 2), 16);   //将十六进制“10”转换为十进制i
            }
            return b;
        }
        /// <summary>
        /// Get the target com num.
        /// </summary>
        /// <returns></returns>
        public static string GetComName()
        {
            string[] strArr = GetHarewareInfo(HardwareEnum.Win32_PnPEntity, "Name");
            foreach (string s in strArr)
            {
                //Quectel USB Serial - 1 Port(COM7)
                if (s.Contains("COM"))
                {
                    if (s.Contains("Quectel USB Serial-1"))
                    {
                        //Log(s);
                        return  return "COM"+ Regex.Match(s, @"\(COM(?<port>\d+)").Groups["port"].Value; //从(COM20)提取串口号
                    }
                }
            }
            return null;
        }

        /// <summary>
        /// Get the system devices information with windows api.
        /// </summary>
        /// <param name="hardType">Device type.</param>
        /// <param name="propKey">the property of the device.</param>
        /// <returns></returns>
        public static string[] GetHarewareInfo(HardwareEnum hardType, string propKey)
        {

            List<string> strs = new List<string>();
            try
            {
                using (ManagementObjectSearcher searcher = new ManagementObjectSearcher("select * from " + hardType))
                {
                    var hardInfos = searcher.Get();
                    foreach (var hardInfo in hardInfos)
                    {
                        if (hardInfo.Properties[propKey].Value != null)
                        {
                            String str = hardInfo.Properties[propKey].Value.ToString();
                            strs.Add(str);
                        }

                    }
                }
                return strs.ToArray();
            }
            catch
            {
                return null;
            }
            finally
            {
                strs = null;
            }
        }//end of func GetHarewareInfo().

        /// <summary>
        /// 枚举win32 api
        /// </summary>
        public enum HardwareEnum
        {
            // 硬件
            Win32_Processor, // CPU 处理器
            Win32_PhysicalMemory, // 物理内存条
            Win32_Keyboard, // 键盘
            Win32_PointingDevice, // 点输入设备,包括鼠标。
            Win32_FloppyDrive, // 软盘驱动器
            Win32_DiskDrive, // 硬盘驱动器
            Win32_CDROMDrive, // 光盘驱动器
            Win32_BaseBoard, // 主板
            Win32_BIOS, // BIOS 芯片
            Win32_ParallelPort, // 并口
            Win32_SerialPort, // 串口
            Win32_SerialPortConfiguration, // 串口配置
            Win32_SoundDevice, // 多媒体设置,一般指声卡。
            Win32_SystemSlot, // 主板插槽 (ISA & PCI & AGP)
            Win32_USBController, // USB 控制器
            Win32_NetworkAdapter, // 网络适配器
            Win32_NetworkAdapterConfiguration, // 网络适配器设置
            Win32_Printer, // 打印机
            Win32_PrinterConfiguration, // 打印机设置
            Win32_PrintJob, // 打印机任务
            Win32_TCPIPPrinterPort, // 打印机端口
            Win32_POTSModem, // MODEM
            Win32_POTSModemToSerialPort, // MODEM 端口
            Win32_DesktopMonitor, // 显示器
            Win32_DisplayConfiguration, // 显卡
            Win32_DisplayControllerConfiguration, // 显卡设置
            Win32_VideoController, // 显卡细节。
            Win32_VideoSettings, // 显卡支持的显示模式。

            // 操作系统
            Win32_TimeZone, // 时区
            Win32_SystemDriver, // 驱动程序
            Win32_DiskPartition, // 磁盘分区
            Win32_LogicalDisk, // 逻辑磁盘
            Win32_LogicalDiskToPartition, // 逻辑磁盘所在分区及始末位置。
            Win32_LogicalMemoryConfiguration, // 逻辑内存配置
            Win32_PageFile, // 系统页文件信息
            Win32_PageFileSetting, // 页文件设置
            Win32_BootConfiguration, // 系统启动配置
            Win32_ComputerSystem, // 计算机信息简要
            Win32_OperatingSystem, // 操作系统信息
            Win32_StartupCommand, // 系统自动启动程序
            Win32_Service, // 系统安装的服务
            Win32_Group, // 系统管理组
            Win32_GroupUser, // 系统组帐号
            Win32_UserAccount, // 用户帐号
            Win32_Process, // 系统进程
            Win32_Thread, // 系统线程
            Win32_Share, // 共享
            Win32_NetworkClient, // 已安装的网络客户端
            Win32_NetworkProtocol, // 已安装的网络协议
            Win32_PnPEntity,//all device
        }
    }
}

或者

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++ C#自动获得特定串口 获得串口列表 的相关文章

随机推荐

  • 机器学习西瓜书吃瓜笔记之(二)决策树分类 附一键生成决策树&可视化python代码实现

    决策树分类 附一键生成可视化python代码实现 决策树 决策树是用于分类任务的树结构 它的叶子结点为类别 其余节点为判断操作 决策树类似于日常中判断分类的方法 对某个样本进行分类时 从根节点开始 得到所处节点的判断结果 移动到满足结果的子
  • keil调试stm32无法退出debug

    keil调试stm32 debug之后有时会遇到这种情况 导致无法退出debug 只能任务管理器强制结束任务 原因 keil对中文的支持不够友好 工程路径过深或路径中有中文 调试过程中打了断电 解决方式 把工程的路径改浅 改成英文路径 例如
  • VS2015出现“在当前源文件目录或生成系统文件目录中未找到xxx.h”完美解决

    用VS打开一个项目 在编译的时候会出现 corecrt h Nosuchfileordirectory 这样一个问题 其实这就是找不到对应的头文件 这个是VS自带的 说白了就是路径的问题 后来 我在vc 包含目录和库目录添加了对应的头文件和
  • git提交新项目到github上

    博客引用处 以下内容在原有博客基础上进行补充或更改 谢谢这些大牛的博客指导 如何将idea本地已有的新项目完整提交到gitlab上 利用git提交代码 1 Idea的方式 使用idea开发工具新建了一个项目工程 此时该项目工程是没有任何的版
  • C++ 基本的输入输出

    C 标准库提供了一组丰富的输入 输出功能 我们将在后续的章节进行介绍 本章将讨论 C 编程中最基本和最常见的 I O 操作 C 的 I O 发生在流中 流是字节序列 如果字节流是从设备 如键盘 磁盘驱动器 网络连接等 流向内存 这叫做输入操
  • 5.27下周黄金行情走势预测及开盘操作策略

    近期有哪些消息面影响黄金走势 下周黄金多空该如何研判 黄金消息面解析 周五 5月26日 黄金大幅下跌 主要受到美国数据影响 美国公布的4月PCE和耐用品订单数据向好 再次强化市场对美联储的鹰派押注 现货黄金收报1946 63美元 盎司 目前
  • 联想拯救者2020R7000双系统装机记录_自用

    文章目录 材料 一 启动盘制作 1 下载ubuntu镜像文件 2 下载刻录工具UltralSO 3 使用UltralSO刻录Ubuntu镜像到U盘内 二 电脑设置 1 创建硬盘空白分区 2 设置BIOS 三 安装系统 1 重新开机的过程中摁
  • 【量化投资】离散傅里叶变换求数组周期

    好久没有更新量化分析相关的内容 本节将介绍如何通过傅里叶变换求解一组数据当中可能存在的周期性 后续将应用本节的结果实际在量化程序中进行应用 本文计算方法不一定正确 欢迎大家多多指正 并在评论区进行交流 1 离散傅里叶变换 离散傅里叶变换的公
  • C++版 - 剑指offer 面试题30:最小的K个数(topK问题) 题解

    剑指offer 面试题30 最小的K个数 题目 输入n个整数 找出其中最小的k个数 例如 例如输入4 5 1 6 2 7 3 8 这8 个数字 则最小的4 个数字是1 2 3 4 提交网址 http www nowcoder com pra
  • java——网络编程

    前言 作者主页 雪碧有白泡泡 个人网站 雪碧的个人网站 推荐专栏 java一站式服务 前端炫酷代码分享 uniapp 从构建到提升 从0到英雄 vue成神之路 解决算法 一个专栏就够了 架构咱们从0说 数据流通的精妙之道 文章目录 前言 网
  • Google C++编码规范(中文版)

    记录下Google C 编码规范 方便后面学习 网址如下 https zh google styleguide readthedocs io en latest
  • 显示器校正

    注意事项 1 显示器校准的环境应注意 防止外来强烈光线进入室内尤其室外强光 2 工作环境的物体 例如墙 地板 桌面等等要接近中性灰 防止环境影响视觉的判断 3 显示器要使用遮光罩 防止环境光和杂散光直接射到显示器的表面 4 操作者要穿深色衣
  • 多线程结合sprongboot事务(完善)

    避坑指南 1 Async Transactional不能在同一个方法上注解使用 原因Spring实现AOP的方法则就是利用了动态代理机制 正因如此 才会导致某些情况下 Async和 Transactional不生效 比如下面的将事务事务控制
  • 从Java到Go:使用Go语言实现OAuth2和JWT身份验证和授权服务

    目录 1 概述 2 OAuth2和JWT简介 2 1 OAuth2 2 2 JWT 3 从Java到Go 基本语法差异 3 1 变量声明和初始化
  • Echarts 桑基图的详细配置过程

    文章目录 桑基图 简介 配置步骤 简易示例 桑基图 简介 Echarts桑基图 Sankey Diagram 是一种数据可视化图表类型 用于展示流量 能量 资金等在各个节点之间的流动和转化关系 桑基图通过节点和曲线来表示不同元素之间的关系
  • centos7修改root用户密码

    一 如果知道旧密码 已经登录进去了 则 使用命令修改即可 修改即刻生效 不需要重启 1 修改系统用户root密码 root ITCATS 01 passwd 更改用户 root 的密码 新的 密码 2 修改系统非root用户密码 huazi
  • Flutter混合开发(二)Flutter 以 Module 形式 接入已经存在的Android原生项目中

    上一篇文章讲解了Flutter 打包AAR 嵌入的流程 这一篇就讲一下 module 的形式 做个简单的记录 也希望可以帮助到最近在学习Flutter混合开发的小伙伴 这里都是按最简单的方式进行载入的 来直接上图 如果已经有 Android
  • 异步FIFO的低水线判定

    最近做一个模块 需要用异步FIFO把链路层发来的局部不定时突发数据重建成连续稳定输出的视频流 输出要达到连续稳定的话 开始输出之前 需要在FIFO里攒够一定数量的数据 即FIFO的低水线 用于防止underflow 对应的还有高水线 即数据
  • 211院校计算机考研难度排名,全国211院校考研难度详细分析!建议收藏!

    原标题 全国211院校考研难度详细分析 建议收藏 很多考研的童鞋 都是为了提升自己的学历而来 梦想着考取名校 圆自己一个名校梦 希望是光明的 道路是曲折的 通向名校的道路 往往竞争十分惨烈 帮大家分析各大高校的考研难度 让小伙伴们能在考研之
  • C++ C#自动获得特定串口 获得串口列表

    目的 自动获得特定串口 0 C 自动获得特定串口 读设备管理器 计算机管理 串口列表 PrintDeviceInfo cpp 定义控制台应用程序的入口点 include