本文使用C/C++语言,对windows下串口读写进行操作。
一、## 函数解释:
1.###CreateFile函数
CreateFile函数是Windows系统中的一个函数,用于创建或打开一个文件或设备。它可以在应用程序中使用,通过指定文件名、文件属性和访问权限来创建或打开文件。
CreateFile函数的语法如下:
HANDLE CreateFile(
LPCSTR lpFileName,
DWORD dwDesiredAccess,
DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreationDisposition,
DWORD dwFlagsAndAttributes,
HANDLE hTemplateFile
);
参数说明:
- lpFileName: 文件名或设备名的字符串指针。
- dwDesiredAccess: 文件或设备的访问权限,例如GENERIC_READ、GENERIC_WRITE等。
- dwShareMode: 文件或设备的共享模式,例如FILE_SHARE_READ、FILE_SHARE_WRITE等。
- lpSecurityAttributes: 指向SECURITY_ATTRIBUTES结构的指针,用于指定文件或设备的安全属性。
- dwCreationDisposition: 指定创建新文件的方式,例如CREATE_ALWAYS、OPEN_EXISTING等。
- dwFlagsAndAttributes: 指定文件或设备的属性和标志,例如FILE_ATTRIBUTE_NORMAL、FILE_FLAG_OVERLAPPED等。
- hTemplateFile: 指定一个用于复制文件属性的句柄。
返回值:
如果函数执行成功,则返回一个有效的文件句柄;如果函数执行失败,则返回INVALID_HANDLE_VALUE。
通过使用CreateFile函数,我们可以创建或打开文件,并获取一个用于后续文件操作的句柄。句柄可以用于读取、写入、修改文件属性等操作。CreateFile函数是Windows系统中的一个函数,用于创建或打开一个文件或设备。它可以在应用程序中使用,通过指定文件名、文件属性和访问权限来创建或打开文件。
2.###WriteFile函数
WriteFile函数是Windows系统中的一个函数,它用于将数据写入打开的文件或设备。
WriteFile函数的语法如下:
BOOL WriteFile(
HANDLE hFile,
LPCVOID lpBuffer,
DWORD nNumberOfBytesToWrite,
LPDWORD lpNumberOfBytesWritten,
LPOVERLAPPED lpOverlapped
);
参数说明:
- hFile: 文件或设备的句柄,通过CreateFile函数获取。
- lpBuffer: 指向包含要写入文件的数据的缓冲区的指针。
- nNumberOfBytesToWrite: 要写入文件的字节数。
- lpNumberOfBytesWritten: 指向接收实际写入字节数的变量的指针。
- lpOverlapped: 指向一个OVERLAPPED结构的指针,用于指定异步I/O操作的参数。如果不需要使用异步I/O,可以将该参数设置为NULL。
返回值:
如果函数执行成功,则返回非零值,表示写入操作成功;如果函数执行失败,则返回零。
通过使用WriteFile函数,我们可以将数据从缓冲区写入打开的文件或设备。可以指定要写入的字节数,同时也可以获取实际写入的字节数。这个函数通常与CreateFile函数一起使用,用于向已经打开的文件中写入数据。WriteFile函数是Windows系统中的一个函数,它用于将数据写入打开的文件或设备。
3.###ReadFile函数
ReadFile函数是Windows系统中的一个函数,用于从一个打开的文件或设备中读取数据。
ReadFile函数的语法如下:
BOOL ReadFile(
HANDLE hFile,
LPVOID lpBuffer,
DWORD nNumberOfBytesToRead,
LPDWORD lpNumberOfBytesRead,
LPOVERLAPPED lpOverlapped
);
参数说明:
- hFile: 文件或设备的句柄,通过CreateFile函数获取。
- lpBuffer: 指向接收读取数据的缓冲区的指针。
- nNumberOfBytesToRead: 要读取的字节数。
- lpNumberOfBytesRead: 指向接收实际读取字节数的变量的指针。
- lpOverlapped: 指向一个OVERLAPPED结构的指针,用于指定异步I/O操作的参数。如果不需要使用异步I/O,可以将该参数设置为NULL。
返回值:
如果函数执行成功,则返回非零值,表示读取操作成功;如果函数执行失败,则返回零。
通过使用ReadFile函数,我们可以从已经打开的文件或设备中读取指定字节数的数据。可以指定要读取的字节数,同时也可以获取实际读取的字节数。这个函数通常与CreateFile函数一起使用,用于从已经打开的文件中读取数据。ReadFile函数是Windows系统中的一个函数,用于从一个打开的文件或设备中读取数据。
4.###CloseFile函数
CloseFile函数是用来关闭已打开的文件的函数。在程序中,当我们打开一个文件进行读取或写入操作后,必须通过调用CloseFile函数来关闭文件,以释放文件资源。
CloseFile函数的定义可能会因编程语言和操作系统的不同而有所差异,但其基本功能是相同的:将文件指针指向的文件关闭,并释放相关资源。
在使用CloseFile函数时,需要将要关闭的文件的文件句柄作为参数传递给函数。文件句柄是一个用于标识文件的整数或指针。
关闭文件后,程序将不能再对该文件进行读写操作。因此,在调用CloseFile函数之前,必须确保已完成对文件的读写操作。
关闭文件是一个良好的编程习惯,可以避免文件资源的浪费和潜在的错误。CloseFile函数是用来关闭已打开的文件的函数。在程序中,当我们打开一个文件进行读取或写入操作后,必须通过调用CloseFile函数来关闭文件,以释放文件资源。
CloseFile函数的定义可能会因编程语言和操作系统的不同而有所差异,但其基本功能是相同的:将文件指针指向的文件关闭,并释放相关资源。
在使用CloseFile函数时,需要将要关闭的文件的文件句柄作为参数传递给函数。文件句柄是一个用于标识文件的整数或指针。
关闭文件后,程序将不能再对该文件进行读写操作。因此,在调用CloseFile函数之前,必须确保已完成对文件的读写操作。
关闭文件是一个良好的编程习惯,可以避免文件资源的浪费和潜在的错误。
5.###SetCommState函数
SetCommState函数是用于设置串口的状态参数的函数。在程序中,当我们需要使用串口进行数据通信时,需要设置串口的一些参数,如波特率、数据位数、停止位、奇偶校验等。
SetCommState函数的定义和使用可能会因编程语言和操作系统的不同而有所差异,但其基本功能是相同的:根据传入的参数设置串口的状态。
在使用SetCommState函数时,需要创建一个DCB(Device Control Block)结构体,并将需要设置的串口参数赋值给该结构体。然后,将该结构体作为参数传递给SetCommState函数。
SetCommState函数会根据传入的参数,将指定的串口的状态参数设置为所需的值。如果设置成功,函数将返回一个非零值;如果设置失败,函数将返回零。
使用SetCommState函数设置串口的状态参数是进行串口通信的关键步骤之一。正确设置串口参数可以确保数据的正常传输和接收。因此,在使用串口进行数据通信前,必须先调用SetCommState函数设置串口的状态参数。
6.###GetCommState函数
GetCommState函数用于获取串口的当前状态参数。在进行串口通信时,有时候需要获取串口的当前状态参数,以便进行一些判断或设置其他相关参数。
GetCommState函数的定义和使用可能会因编程语言和操作系统的不同而有所差异,但其基本功能是相同的:获取指定串口的当前状态参数。
在使用GetCommState函数时,需要创建一个DCB(Device Control Block)结构体,并将该结构体作为参数传递给GetCommState函数。
GetCommState函数会获取指定串口的当前状态参数,并将结果保存在传入的DCB结构体中。如果获取成功,函数将返回一个非零值;如果获取失败,函数将返回零。
通过GetCommState函数获取串口的当前状态参数,可以帮助我们了解串口的当前设置情况,以及对应的波特率、数据位数、停止位、奇偶校验等参数。这些参数可以用于判断当前串口的工作状态,或对其他相关参数进行设置。
7.###CloseHandle函数
CloseHandle函数用于关闭一个已打开的对象句柄。在Windows操作系统中,访问系统资源(例如文件、串口、线程等)需要通过句柄(Handle)来进行。当我们不再需要使用一个已打开的句柄时,应当调用CloseHandle函数来关闭该句柄,以释放系统资源。
CloseHandle函数的定义和使用可能会因编程语言和操作系统的不同而有所差异,但其基本功能是相同的:关闭指定的句柄。
在使用CloseHandle函数时,需要将需要关闭的句柄作为参数传递给CloseHandle函数。
CloseHandle函数会根据传入的句柄关闭对应的系统资源,并释放相关的内存和资源。如果关闭成功,函数将返回一个非零值;如果关闭失败,函数将返回零。
使用CloseHandle函数关闭一个已打开的对象句柄,可以帮助我们及时释放系统资源,避免资源泄漏和浪费。同时,关闭句柄还可以提高系统性能,减少系统资源的占用。因此,在不再需要使用一个句柄时,应当及时调用CloseHandle函数关闭该句柄。
二、## 示例代码
以下是使用C/C++语言,并使用CreateFile、WriteFile和ReadFile函数读写串口数据的示例代码:
#include <windows.h>
#include <stdio.h>
int main()
{
// 打开串口
HANDLE hSerial = CreateFile("COM1", GENERIC_READ | GENERIC_WRITE, 0, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hSerial == INVALID_HANDLE_VALUE)
{
printf("Failed to open serial port\n");
return 1;
}
// 配置串口参数
DCB dcbSerialParams = { 0 };
dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
if (!GetCommState(hSerial, &dcbSerialParams))
{
printf("Failed to get serial port parameters\n");
CloseHandle(hSerial);
return 1;
}
dcbSerialParams.BaudRate = CBR_9600; // 根据实际情况修改波特率
dcbSerialParams.ByteSize = 8;
dcbSerialParams.StopBits = ONESTOPBIT;
dcbSerialParams.Parity = NOPARITY;
if (!SetCommState(hSerial, &dcbSerialParams))
{
printf("Failed to set serial port parameters\n");
CloseHandle(hSerial);
return 1;
}
// 循环读写数据
char buffer[100];
DWORD bytesRead, bytesWritten;
while (true)
{
// 写入串口
char key;
if (_kbhit())
{
key = _getch();
WriteFile(hSerial, &key, 1, &bytesWritten, NULL);
}
// 读取串口数据
if (ReadFile(hSerial, buffer, sizeof(buffer) - 1, &bytesRead, NULL))
{
if (bytesRead > 0)
{
buffer[bytesRead] = '\0';
printf("Received: %s\n", buffer);
}
}
}
// 关闭串口
CloseHandle(hSerial);
return 0;
}
这段代码首先使用CreateFile
函数打开串口,返回一个句柄hSerial
,表示成功打开的串口。如果打开串口失败,则会返回INVALID_HANDLE_VALUE
。
然后,通过GetCommState
函数获取串口的当前参数,并使用DCB
结构体来设置波特率、数据位、停止位和校验位等参数。然后使用SetCommState
函数将新的参数应用于串口。
接下来,在一个无限循环中,通过_kbhit
和_getch
函数来检测键盘输入并写入串口,使用WriteFile
函数进行写入。然后使用ReadFile
函数从串口读取数据,并使用printf
函数打印出来。
最后,在程序结束前需要使用CloseHandle
函数关闭串口句柄。
请注意,以上代码中的COM1
是一个示例串口号,你需要将其替换为实际连接设备的串口号。另外,为了能够使用 _kbhit
和 _getch
函数来实现键盘输入的检测和获取,需要包含conio.h
头文件,并在编译时链接conio.lib
库文件。
希望以上能帮助到您,感谢阅读!!