Windows使用串口API函数串口编程

2023-11-03

前言

本文介绍了Windows上用串口api进行软件开发的步骤,其大致分为4步:(1)打开串口 (2)配置串口(3)串口通讯(4)关闭串口。接下来,会用C++代码示例来详细介绍具体的开发流程。

1. 打开串口

调用CreateFile()函数来打开串口,函数执行成功返回串口句柄,出错返回INVALID_HANDLE_VALUE。

HANDLE WINAPI CreateFile(
_In_ LPCTSTR lpFileName,
_In_ DWORD dwDesiredAccess,
_In_ DWORD dwShareMode,
_In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes,
_In_ DWORD dwCreationDisposition,
_In_ DWORD dwFlagsAndAttributes,
_In_opt_ HANDLE hTemplateFile
);

1.1 参数详解

lpFileName表示要打开的串口逻辑名,如“COM1”;注意当串口号大于9时,字符串前需加上"\\.\"的前缀;

dwDesiredAccess指定类型的访问对象。如果为 GENERIC_READ 表示允许对设备进行读访问;如果为 GENERIC_WRITE 表示允许对设备进行写访问(可组合使用);如果为零,表示只允许获取与一个设备有关的信息 ;

dwShareMode打开串口时,该参数只能为0,表示独占方式;

lpSecurityAttributes设置为NULL即可;

dwCreationDisposition打开串口时必须设置为OPEN_EXISTING;

dwFlagsAndAttributes对于串口而言,唯一有意义的设置时FILE_FLAG_OVERLAPPED,创建时指定该设置,串口可执行异步操作;否则只能执行同步操作;

hTemplateFile串口操作时必须设置为NULL.

1.2 代码示例

1.2.1 获取串口号

若使用的是沁恒微的CH34X USB转串口芯片产品,可通过调用CH341PT.DLL库中的接口,识别出为其分配的串口和监测串口设备的插拔行为。
下面给出一段调用示例以供参考:

// 方法1 : 通过串口句柄来识别串口, 使用的库函数CH341PtHandleIsCH341()
...
 for (j=1;j<21;j++) 
 {
 	// fullportname为完整的串口名字符串,格式为"\\\\.\\COMxx"
	porthandle=CreateFile((CHAR *)fullportname, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL );
	if ( porthandle != INVALID_HANDLE_VALUE )
	{
		if(CH341PtHandleIsCH341(porthandle))
			// ... 识别到位CH34X串口
		CloseHandle(porthandle);
	}
}
...
// 方法2 : 通过串口名称来识别串口, 使用的库函数CH341PtNameIsCH341()
...
 for (j=0;j<20;j++) 
 {
	// fullportnamebuf数组中元素为完整的串口名字符串,从COM1开始枚举
	if(CH341PtNameIsCH341(fullportnamebuf[j]))
	{							
		// ... 	识别到位CH34X串口
	}
}
...

1.2.2 打开串口(同步通信)

HANDLE m_hCom;
m_hCom = CreateFile("COM1",                     //串口名,COM10及以上的串口名格式应为:"\\\\.\\COM10"
					GENERIC_READ|GENERIC_WRITE, //允许读或写
					0,							//独占方式
					NULL,
					OPEN_EXISTING,				//打开而不是创建
					NULL,						//同步方式
					NULL );

1.2.3 打开串口(异步通信)

HANDLE m_hCom;
m_hCom = CreateFile("\\\\.\\COM11",             //串口名,COM10及以上的串口名格式应为:"\\\\.\\COM10"
					GENERIC_READ|GENERIC_WRITE, //允许读或写
					0,							//独占方式
					NULL,
					OPEN_EXISTING,				//打开而不是创建
					FILE_FLAG_OVERLAPPED,		//异步方式
					NULL );

2. 关闭串口

调用CloseHandle()函数来关闭串口,函数参数为串口句柄。

BOOL WINAPI CloseHandle(HANDLE hObject);

3. 配置串口

串口成功打开后,就可以开始对串口属性进行配置。

3.1 配置输入输出缓冲区

我们可以根据需求用SetupComm()来配置输入输出缓冲区:

BOOL WINAPI SetupComm(
    __in HANDLE hFile,		//串口句柄
    __in DWORD dwInQueue,	//输入缓冲区大小
    __in DWORD dwOutQueue	//输出缓冲区大小
    );

其中缓冲区大小以字节为单位,也可以不调用该函数,Windows系统也会分配默认的发送和接收缓冲区

3.2 配置超时时间

超时有两种,一个叫间隔超时,另一个叫总超时。

读端口有间隔超时和总超时设置,写端口只有总超时设置。

要查询当前的超时设置应调用GetCommTimeouts函数,该函数会填充一个COMMTIMEOUTS结构。调用SetCommTimeouts可以用某一个COMMTIMEOUTS结构的内容来设置超时。

COMMTIMEOUTS结构介绍:

typedef struct _COMMTIMEOUTS {
    DWORD ReadIntervalTimeout;          /* Maximum time between read chars. */
    DWORD ReadTotalTimeoutMultiplier;   /* Multiplier of characters.        */
    DWORD ReadTotalTimeoutConstant;     /* Constant in milliseconds.        */
    DWORD WriteTotalTimeoutMultiplier;  /* Multiplier of characters.        */
    DWORD WriteTotalTimeoutConstant;    /* Constant in milliseconds.        */
} COMMTIMEOUTS,*LPCOMMTIMEOUTS;

ReadIntervalTimeout为读操作时两个字符间的间隔超时;

ReadTotalTimeoutMultiplier为读操作在读取每个字符时的超时;

ReadTotalTimeoutConstant为读操作的固定超时;

WriteTotalTimeoutMultiplier为写操作在写每个字符时的超时;

WriteTotalTimeoutConstant为写操作的固定超时;

读操作的间隔超时 = ReadIntervalTimeout
读操作的总超时 = ReadTotalTimeoutConstant + ReadTotalTimeoutMultiplier*要读的字符数
写操作的总超时 = WriteTotalTimeoutConstant + WriteTotalTimeoutMultiplier*要写的字符数

需要注意的是,对于异步读写时,SetCommTimeouts()仍然是起作用的,在这种情况下,超时规定的是I/O操作的完成时间,而不是ReadFile和WriteFile的返回时间。

3.3 串口的属性配置

在配置串口波特率,数据位,奇偶校验,停止位等属性时,首先调用GetCommState获取一个DCB结构:

DCB dcb;
GetCommState(m_hCom, &dcb); // m_hCom是串口句柄

然后对dcb结构体中的成员进行赋值:

dcb.BaudRate = 115200; 		// 波特率
dcb.ByteSize = 8; 	   		// 8位数据位
dcb.StopBits = ONESTOPBIT;	// 1位停止位
							// | ONESTOPBIT | 1位停止位 |
							// | ONE5STOPBITS | 1.5位停止位 |
							// | TWOSTOPBITS | 2位停止位 |
dcb.Parity = NOPARITY; 	    // 无校验 
							// | EVENPARITY | 偶校验 |
							// | MARKPARITY | 标号校验 |
							// | NOPARITY | 无校验 |
							// | ODDPARITY | 奇校验 |
							// | SPACEPARITY | 空格校验 |

其中:

BaudRate用于指定串口设备通信的数据传输速率。

ByteSize指定端口当前使用的数据位数。

Parity用于指定端口当前使用的奇偶校验方式。

StopBits用于指定串口当前使用的停止位数。

如想查看完整DCB结构说明,请点击https://docs.microsoft.com/en-us/windows/win32/api/winbase/ns-winbase-dcb

4. 同步方式读写串口

4.1 函数介绍

在串口打开并配置好之后,可以开始读写串口,读写之前,需要清空串口缓冲区和清除错误,代码参考如下:

PurgeComm(m_hCom, PURGE_TXCLEAR|PURGE_RXCLEAR|PURGE_TXABORT|PURGE_RXABORT);	// 清空串口缓冲区,终止发送接收异步操作
DWORD dwError;
if (!ClearCommError(g_hCom, &dwError, NULL))
{
	...
}

完成后,可以调用ReadFile和WriteFile来对串口进行读写操作,API原型如下:

BOOL ReadFile(
  HANDLE       hFile,					// 串口句柄
  LPVOID       lpBuffer,				// 读缓冲区
  DWORD        nNumberOfBytesToRead,	// 要求读入的字节数
  LPDWORD      lpNumberOfBytesRead,		// 实际读入的字节数
  LPOVERLAPPED lpOverlapped				// 重叠结构
); 
BOOL WriteFile(
  HANDLE  hFile,						//文件句柄
  LPCVOID lpBuffer,						//数据缓存区指针
  DWORD   nNumberOfBytesToWrite,		//你要写的字节数
  LPDWORD lpNumberOfBytesWritten,		//用于保存实际写入字节数的存储区域的指针
  LPOVERLAPPED lpOverlapped				//OVERLAPPED结构体指针
) ;

4.2 代码示例

下面给出一个简单的同步通信的控制台程序示例:

// ComDemo.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include "pch.h"
#include <windows.h>
#include <iostream>

// 全局变量
HANDLE h_Com; // 串口句柄

// 打开串口
void ConnectCom(LPCTSTR ComName)
{
	COMMTIMEOUTS TimeOuts; //串口设置超时结构体
	DCB		dcb;

	//打开一个串口设备
	h_Com = CreateFile(ComName, GENERIC_READ | GENERIC_WRITE, 0, NULL,OPEN_EXISTING, NULL, NULL); 

	if (h_Com == INVALID_HANDLE_VALUE)
	{
		std::cout << "串口无法打开" << std::endl;
		return;
	}

	SetupComm(h_Com, 4096, 4096); //设置输入输出缓冲
	// 超时设置
	TimeOuts.ReadIntervalTimeout = 100;
	TimeOuts.ReadTotalTimeoutMultiplier = 500;
	TimeOuts.ReadTotalTimeoutConstant = 0;

	TimeOuts.WriteTotalTimeoutMultiplier = 0;
	TimeOuts.WriteTotalTimeoutConstant = 0;
	
	SetCommTimeouts(h_Com, &TimeOuts);
	// 设置串口属性
	GetCommState(h_Com, &dcb); //串口属性配置
	dcb.BaudRate = 115200;
	dcb.ByteSize = 8;
	dcb.StopBits = ONESTOPBIT;
	dcb.Parity = NOPARITY;

	if (!SetCommState(h_Com, &dcb))
	{
		CloseHandle(h_Com);
		std::cout << "串口配置失败" << std::endl;
		return ;
	}
	PurgeComm(h_Com, PURGE_TXCLEAR | PURGE_RXCLEAR | PURGE_TXABORT | PURGE_RXABORT);//清空串口缓冲区
}

int main()
{
	ConnectCom(L"COM7"); // 打开指定串口并进行配置
	
	// 发送
	DWORD dwError;
	DWORD dwSend = 0;
	const char* pSendBuf = "test send";
	
	if (ClearCommError(h_Com, &dwError, NULL))
	{
		PurgeComm(h_Com, PURGE_TXABORT | PURGE_TXCLEAR);
	}
	if (!WriteFile(h_Com, pSendBuf, strlen(pSendBuf), &dwSend,NULL))
	{
		std::cout << "发送失败" << std::endl;
	}

	std::cout << "已发送: ";
	std::cout << dwSend << "个字节" << std::endl;

	// 数据接收
	DWORD dwWantRead = 100;
	DWORD dwRead = 0;
	char* pReadBuf = new char[100];
	memset(pReadBuf, 0, 100);

	if (ClearCommError(h_Com, &dwError, NULL))
	{
		PurgeComm(h_Com, PURGE_RXABORT | PURGE_RXCLEAR);
	}

	if (!ReadFile(h_Com, pReadBuf, dwWantRead, &dwRead, NULL))
	{
		std::cout << "读取失败" << std::endl;
	}
	std::cout << "读取的内容: ";
	std::cout << pReadBuf << std::endl;
	delete[] pReadBuf;
}


5. 异步读写数据

异步(重叠)I/O操作指的是应用程序可以在后台读或是写数据,需要使用OVERLAPPED结构。
接下来,会重点介绍异步操作的具体步骤。

5.1 异步操作介绍

1.首先要使用OVERLAPPED结构,CreateFile()函数的dwFlagsAndAttributes参数必须设为FILE_FLAG_OVERLAPPED,调用读写串口时,也必须在参数中指定OVERLAPPED结构。

2.OVERLAPPED结构类型说明如下:

typedef struct _OVERLAPPED {
  ULONG_PTR Internal;
  ULONG_PTR InternalHigh;
  union {
    struct {
      DWORD Offset;
      DWORD OffsetHigh;
    } DUMMYSTRUCTNAME;
    PVOID Pointer;
  } DUMMYUNIONNAME;
  HANDLE    hEvent;
} OVERLAPPED, *LPOVERLAPPED;

其中,hEvent表示I/O操作完成后触发的事件(信号),其余完整参数说明请参考:https://docs.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-overlapped

3.设置了异步I/O操作后,I/O操作和函数返回有以下两种情况:

① 函数返回时I/O操作已完成

② 函数返回时I/O操作还未完成:此时一方面,函数返回值为FALSE,并且GetLastError函数返回ERROR_IO_PENDING;另一方面,系统把OVERLAPPED中的信号事件设为无信号状态。当I/O操作完成时,系统要把它设为信号状态。

4.异步I/O操作可以由GetOverLappedResult()函数来获取结果,也可以使用等待函数来查询事件当前状态或等待Windows状态信号。

关于GetOverLappedResult()详细说明,请参看以下链接:https://docs.microsoft.com/en-us/windows/win32/api/ioapiset/nf-ioapiset-getoverlappedresult

5.2 代码示例

下面给出一个简单的异步通讯的控制台程序作为参考:

// ComDemo.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include "pch.h"
#include <windows.h>
#include <iostream>

// 全局变量
HANDLE h_Com; // 串口句柄

// 打开串口
void ConnectCom(LPCTSTR ComName)
{
	COMMTIMEOUTS TimeOuts; //串口设置超时结构体
	DCB		dcb;

	//打开一个串口设备
	h_Com = CreateFile(ComName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL); // 重叠方式

	if (h_Com == INVALID_HANDLE_VALUE)
	{
		std::cout << "串口无法打开" << std::endl;
		return;
	}

	SetupComm(h_Com, 4096, 4096); // 设置输入输出缓冲

	// 超时设置
	TimeOuts.ReadIntervalTimeout = 100;
	TimeOuts.ReadTotalTimeoutMultiplier = 500;
	TimeOuts.ReadTotalTimeoutConstant = 0;

	TimeOuts.WriteTotalTimeoutMultiplier = 0;
	TimeOuts.WriteTotalTimeoutConstant = 0;

	SetCommTimeouts(h_Com, &TimeOuts);

	// 设置串口属性
	GetCommState(h_Com, &dcb);	//串口属性配置
	dcb.BaudRate = 115200;
	dcb.ByteSize = 8;
	dcb.StopBits = ONESTOPBIT;
	dcb.Parity = NOPARITY;

	if (!SetCommState(h_Com, &dcb))
	{
		CloseHandle(h_Com);
		std::cout << "串口配置失败" << std::endl;
		return ;
	}


	PurgeComm(h_Com, PURGE_TXCLEAR | PURGE_RXCLEAR | PURGE_TXABORT | PURGE_RXABORT);//清空串口缓冲区
}

int main()
{
	ConnectCom(L"COM7"); // 打开指定串口并进行配置

	// 建立一个重叠结构
	OVERLAPPED wrOverlapped;
	ZeroMemory(&wrOverlapped, sizeof(wrOverlapped));
	if (wrOverlapped.hEvent != NULL)
	{
		ResetEvent(wrOverlapped.hEvent);
		wrOverlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
	}

	// 发送
	DWORD dwError;
	DWORD dwSend = 0;
	const char* pSendBuf = "test send";
	
	if (ClearCommError(h_Com, &dwError, NULL))
	{
		PurgeComm(h_Com, PURGE_TXABORT | PURGE_TXCLEAR);
	}
	if (!WriteFile(h_Com, pSendBuf, strlen(pSendBuf), &dwSend, &wrOverlapped))
	{
		if (GetLastError() == ERROR_IO_PENDING)
		{
			while (!GetOverlappedResult(h_Com, &wrOverlapped, &dwSend, FALSE))
			{
				if (GetLastError() == ERROR_IO_INCOMPLETE)
				{
					continue;
				}
				else
				{
					std::cout << "发送失败" << std::endl;
					ClearCommError(h_Com, &dwError, NULL);
					break;
				}
			}
		}
	}

	std::cout << "已发送: ";
	std::cout << dwSend << "个字节" << std::endl;

	// 数据接收
	DWORD dwWantRead = 100;
	DWORD dwRead = 0;
	char* pReadBuf = new char[100];
	memset(pReadBuf, 0, 100);

	if (ClearCommError(h_Com, &dwError, NULL))
	{
		PurgeComm(h_Com, PURGE_RXABORT | PURGE_RXCLEAR);
	}

	if (!ReadFile(h_Com, pReadBuf, dwWantRead, &dwRead, &wrOverlapped))
	{
		if (dwError = GetLastError() == ERROR_IO_PENDING)
		{
			while (!GetOverlappedResult(h_Com, &wrOverlapped, &dwRead, FALSE))
			{
				if (GetLastError() == ERROR_IO_INCOMPLETE)
				{
					continue;
				}
				else
				{
					std::cout << "接收失败" << std::endl;
					ClearCommError(h_Com, &dwError, NULL);
					return 0;
				}
			}
		}
	}
	std::cout << "读取的内容: ";
	std::cout << pReadBuf << std::endl;
	delete[] pReadBuf;
}


6. 通信事件

Windows进程中监视发生在通信资源中的一组事件,这样应用程序可以不检查端口状态就可以知道某些条件何时发生。
Windows通信事件列表如下:

描述
EV_BREAK 检测到输入的终止
EV_CTS CTS(清除发送)信号改变状态
EV_DSR DSR(数据设置就绪)信号改变状态
EV_ERR 发生了线路状态错误,线路状态错误时CE_FRAME(帧错误),CE_OVERRUN(接收缓冲区超限)和CE_RXPARITY(奇偶校验错误)
EV_RING 检测到振铃
EV_RLSD RLSD(接收线路信号检测)信号改变状态
EV_RXCHAR 接收到一个字符,并放入输入缓冲区
EV_RXFLAG 接收到事件字符(DCB结构的EvtChar成员),并放入输入缓冲区
EV_TXEMPTY 输出缓冲区中最后一个字符发送出去

1. 操作通信事件
应用程序可以通过SetCommMask()函数建立事件掩模来监视指定通信资源上的事件。SetCommMask()函数的声明如下:

BOOL SetCommMask(
  HANDLE hFile,
  DWORD  dwEvtMask
);

其中 dwEvtMask标识被监视的通信事件,其值可以是上表中的任意通信事件组合。

如果想获取特定通信资源的当前事件掩模,可以使用GetCommMask()函数。其函数声明如下:

BOOL GetCommMask(
  HANDLE  hFile,
  LPDWORD lpEvtMask
);

2. 监视通信事件
在用SetCommMask()指定了有用的事件后,应用程序就调用WaitCommEvent()函数来等待其中一个事件发生。其函数声明如下:

BOOL WaitCommEvent(
  HANDLE       hFile,
  LPDWORD      lpEvtMask,
  LPOVERLAPPED lpOverlapped
);

其参数的详细说明,请参见:https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-waitcommevent

当lpOverlapped参数指向了一个OVERLAPPED结构,并且打开hfile参数标识的通信设备时指定了FILE_FLAG_OVERLAPPED标志,则WaitCommEvent()函数以异步操作实现。

这种情况下,OVERLAPPED结构体必须含有一个人工复位事件的句柄,当异步操作不能立即实现时,WaitCommEvent()返回false,且GetLastError()函数返回ERROR_IO_PENDING。此时,在该函数返回前,系统将OVERLAPPED结构中的hEvent参数设置为无信号状态;当指定事件发生后,再置为有信号状态。

操作通信事件的具体代码见下章节–API串口通讯示例。

7. API串口通讯代码示例

接下来我们提供了一个完整的API串口通讯的控制台程序示例。
https://download.csdn.net/download/WCH_TechGroup/12228991
也可在github上下载我们的示例程序。
https://github.com/WCHSoftGroup/SerialPortDemo-Win

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

Windows使用串口API函数串口编程 的相关文章

  • 无法在 Angular 10 中的“pdf-viewer”=>“ng2-pdf-viewer”中显示 blob url

    我有一个 API 它将上传的文件作为 blob 返回 当我尝试绑定时src如果使用 blob URL 则它不会显示任何内容 但是 当我尝试绑定直接 URL 时 它可以显示 PDF 文件 这是我下面给出的代码 我的 TS 代码 downloa
  • Twitter Streaming API 使用的官方编码?是UTF-8吗?

    Twitter 流 API 的官方编码是什么 根据我所看到的 我最好的猜测是 UTF 8 但我想避免做出假设 我见过的 Twitter 网站上唯一暗示他们使用什么作为官方编码的部分是在这里 Twitter 不想因为我们使用 UTF 8 或相
  • Streamlabs API 405 响应代码

    我正在尝试使用Streamlabs API https dev streamlabs com Streamlabs API 使用 Oauth2 来创建应用程序 因此 首先我将使用我的应用程序的用户发送到一个授权链接 其中包含我的应用程序的客
  • SSDT SQL Server 数据库项目中用于架构比较的命令行/API?

    在 Visual Studio 2012 中 我们有Schema Compare http msdn microsoft com en us library hh272690 28v vs 103 29 aspx in SSDT http
  • 更改API数据输出的布局

    我是 API 集成和 PHP 的新手 我最近将 VIN 解码器集成到我的应用程序中 在输入框中输入车辆的 VIN 选择提交 然后就会显示 API 数据库中有关该车辆的所有信息 数据存储为关联数组 其中包含类别及其相应元素 例如 对于 VIN
  • 使用 PHP 和 OAuth 访问 SkyDrive

    我想使用 PHP 访问 skyDrive 我想检索文件和文件夹列表 下载 上传和删除文件 我有一个 microsoft dev clientID 和 clientSecret 有人可以帮助我开始使用 OAuth 连接到 skyDrive 并
  • 注册期间现有电子邮件的 422 或 409 状态代码

    我正在构建 RESTful API 遇到了一种情况 在用户注册期间 如果电子邮件已存在 则在422 and 409哪个http响应代码有意义 我浏览过类似的one https stackoverflow com questions 9269
  • 使用 Instagram Basic Display API 时出现“无效平台应用程序”错误

    我正在尝试使用 Instagram Basic 显示 API 但是当我发布授权代码以获取访问令牌时 我不断收到以下错误 error type OAuthException 代码 400 error message 平台应用无效 我正在遵循此
  • 如何获取Postgres当前的可用磁盘空间?

    在开始在数据库中进行某些工作之前 我需要确保至少有 1Gb 的可用磁盘空间 我正在寻找这样的东西 select pg get free disk space 是否可以 我在文档中没有找到任何相关内容 PG 9 3 操作系统 Linux Wi
  • SQLAPI++ 的免费替代品? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 是否有任何免费 也许是开源 的替代品SQLAPI http www sqlapi com 这个库看起来
  • 如何按名称杀死进程? (Win32 API)

    基本上 我有一个将启动多次的程序 因此 该程序将启动两个或多个进程 我想使用 Win32 API 并终止 终止具有特定名称的所有进程 我见过杀死一个进程的例子 但没有看到多个具有完全相同名称 但参数不同 的进程 尝试下面的代码 killPr
  • iTunes Lookup API,获取iPhone 5应用程序截图

    I use iTunes API 查找通过 App ID 获取应用数据 即使应用程序是为iPhone5 在 JSON 中我得到3 5 inch屏幕截图 下截图网址 array 有什么办法可以得到4 inch 截图 可以使用非官方的 iTun
  • 如何共享 Swagger 文档

    我最近开始使用 Swagger 来编写文档 但有一些事情我仍然不清楚 我创建了 YAML 文档 现在我希望能够与团队的其他成员共享 pdf 或 HTML Javascript 页面中的文档 我无法使用 SwaggerHub 因为它们没有私有
  • 从 Delphi 访问 TRAKT API - 承载身份验证问题

    使用 TOauth2Authenticator TRESTClient TRESTRequest TRESTResponseDataSet TRESTResponse TFDmemtable 和 TDataSource 我成功连接到 Tra
  • React + Redux 和 REST API?

    我在 Node 中构建了一个简单的 CRUD 应用程序 并已在 Express 中完成了其余 API 的创建 我现在正在寻求添加前端功能 并希望使用 React Redux 作为学习练习 然而 似乎所有围绕此的教程都直接使用 Redux 访
  • cURL 命令在 git bash 中有效,但在 cmd 和 powershell 中无效

    以下命令在 git bash 中有效 但在 cmd 和 powershell 中无效 curl X POST http localhost 5678 api findgen H Content Type application json d
  • RESt api:根据身份验证对资源和内容进行识别

    我正在设计一个遵循 HATEOAS REST 原则的 API 但我不确定这个基本点 资源识别 假设这个网址 images它公开了用户 向该用户 上传的所有图像 假设我使用 oauth 访问令牌进行身份验证 images 的内容将根据授权标头
  • 在 Java 中处理视频(DVD、.avi .mkv)

    在寻找了一个像样的 Java 视频播放库之后 我发现了问题 周围的每个人都在尖叫不要使用 JMF 因为它已经过时 过时并且需要用户安装它 其他替代方案 例如 VLCJ 如果可以工作的话似乎不错 但仍然相对不稳定并且依赖大量本机代码 并且至于
  • 你可以拥有你的 API 并在 Laravel 中使用它吗?

    我制作了一个在 Laravel 中返 回 json 的 API 路线 api php 现在我想在我的内部使用所述APIweb项目的一侧 路线 web php 包括中间件 刀片视图 etc 我当前的解决方案是这样的 public functi
  • 使用 Swagger 的 Spring REST API 文档 [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我正在寻找一个可以帮助我生成 RESTful API 文档的工具 我的服务器是用Java编写的并使用S

随机推荐

  • 单元测试和白盒测试相关总结

    一 软件测试方法 1 软件测试方法包括 白盒测试 White Box Testing 黑盒测试 Black Box Testing 灰盒测试 静态测试 动态测试 2 白盒测试 是一种测试用例设计方法 在这里盒子指的是被测试的软件 白盒 顾名
  • 如何在桌面上显示我的计算机,Win10如何将我的电脑(此电脑)显示到桌面上?

    win10和之前两个版本Windows一样安装好以后就一个回收站 我的电脑还有网络这两个图标都没有 那么Win10如何将我的电脑 此电脑 显示到桌面上 下面小编就为大家详细介绍一下 来看看吧 方法 步骤 1 使用原版镜像安装完系统后 进入系
  • C语言数据结构之树(保姆级讲解)

    前言 树是 一对多 的非线性存储结构 较链表 队列那些 树的概念会多点 涵盖的范围也较广 C语言数据结构之单链表 C语言数据结构之双向链表 c语言数据结构之栈 c语言数据结构之队列 1 树概念 1 1 树基本术语 图1 双亲节点 以A B
  • fileupload ajax ie,ajaxfileupload.js IE兼容问题

    IE9和IE10都无法上传 这是由于IE浏览器的版本升级问题 修改方法如下 if window ActiveXObject var io document createElement if typeof uri boolean io src
  • Spring依赖注入

    内容主要来自 Spring实战 第二章 区别在于自己写了一个测试类 对于初学者更容易理解依赖注入 先定义两个接口 1 CompactDisc java package soundsystem public interface Compact
  • 把pdf转为高清jpg图片,其dpi为300以上

    把pdf转为高清jpg图片 其dpi为300以上 在用latex写好伪代码后生成的pdf 想生成jpg格式 可以用如下方法 工具 Adobe Acrobat Pro DC 如果是 文件 gt 导出到 gt 图像 这样的图像dpi较小 有很重
  • 【无人机】无人机平台的非移动 GPS 干扰器进行位置估计的多种传感器融合算法的性能分析(Matlab代码实现)

    欢迎来到本博客 博主优势 博客内容尽量做到思维缜密 逻辑清晰 为了方便读者 座右铭 行百里者 半于九十 本文目录如下 目录 1 概述 2 运行结果 3 参考文献 4 Matlab代码 数据 详细文章 1 概述 诸如美国全球定位系统 GPS
  • xml入门

    什么是 XML XML 即可扩展标记语言 Extensible Markup Language 是一种平台无关的表示数据的方法 简单地说 使用 XML 创建的数据可以被任何应用程序在任何平台上读取 甚至可以通过手动编码来编辑和创建 XML
  • python爬虫需要学哪些东西_Python爬虫需要学习那些东西?

    一个教程让你学会爬虫 Python爬虫实战8天速成 验证码识别 数据解析 Scrapy框架 实战案例 2020全套 哔哩哔哩 干杯 bilibili www bilibili com 学Python爬虫需要学习的八个知识点 1 HTML H
  • 最新dns大全

    公共DNS服务器IP地址大全 名称 各省公共DNS服务器IP大全 114 DNS 114 114 114 114 114 114 115 115 阿里 AliDNS 223 5 5 5 223 6 6 6 百度 BaiduDNS 180 7
  • wincap问题之一(丢包)

    最近开发一个项目 发现wincap会有丢包现象 与wincap的具体应用是这样的 一个接收线程 采用pcap loop接收网络中的数据包 一个发送线程 采用pcap sendqueue transmit的方式发送数据包 pcap loop接
  • 重新赋能Web3域名,Dmail让ESN域名不再单一

    Dmail独特的NFT账号不仅提供了全新的概念 还为用户提供了参与平台上各种信息和资产服务的权利 以及体验Web3 0时代各种应用的可能性 一般来说 NFT域账户除了基本的应用之外 还具有三个有价值的方面 即收集投资 奖励赎回和一般身份 首
  • 数据结构-顺序表(c++)含全代码

    顺序表的原理及实现 文章目录 前言 一 顺序表是什么 二 创建顺序表 三 顺序表的初始化及销毁 1 顺序表的初始化 2 顺序表的销毁 四 顺序表的基本操作 1 顺序表的添加元素 2 顺序表的插入元素 3 顺序表的删除元素 4 打印顺序表的元
  • error: Store update, insert, or delete statement affected an unexpected number of rows (0). Entities

    Store update insert or delete statement affected an unexpected number of rows 0 Entities may have been modified or delet
  • 计算机中数的存储形式(原码,反码,补码的表示)

    原码 反码和补码知识点 1 原码 10进制转换成2进制是原码 只不过正数的原码是本身符号位为0 负数的原码符号位为1 例 单字节的1 10进制1的原码是0000 0001 10进制 1的原码是1000 0001 2 反码 正数的反码是它本身
  • Ueditor设置默认字体、字号、行间距,添加字体种类

    Ueditor默认字体 字号 行间距的修改 ueditor默认字号是16号 默认字体为sans serif 默认行间距为5px 如下图所示 首先 修改ueditor all js文件中如上图红框中对应的字体 字号 行间距的值 其次 uedi
  • 查询三方jar包漏洞

    安全检测的时候一般会对第三方的jar包扫描 下面的地址可以根据artifactId 或者漏洞查询相应的不同版本漏洞 然后自己做相应的处理 一般都是升级包 或者直接用功能类似的包替换 避免重大事故 nvd漏洞查询
  • MySQL数据库——数据库和表的基本操作(一)

    目录 第1关 查看表结构与修改表名 一 本关任务 修改表名 并能顺利查询到修改后表的结构 查看数据表基本结构 查看数据表详细结构 修改表名 二 编程要求 三 预期输出 四 代码 第2关 修改字段名与字段数据类型 一 本关任务 修改表中的字段
  • 2020牛客暑期多校训练营(第八场)E Enigmatic Partition —— 找规律,差分上差分,有丶东西

    This way 题意 定义合法序列 n a1 a2 am m的大小是你自己构造的 m gt 3 并且满足以下条件 定义f n 为构造n的合法序列的情况数 然后每次问你n为l r中所有数的f的和是多少 题解 其实就相当于要预处理每个数有多少
  • Windows使用串口API函数串口编程

    Windows使用串口API函数串口编程 前言 1 打开串口 1 1 参数详解 1 2 代码示例 1 2 1 获取串口号 1 2 2 打开串口 同步通信 1 2 3 打开串口 异步通信 2 关闭串口 3 配置串口 3 1 配置输入输出缓冲区