高级串口编程—C/C++打开串口、关闭串口和读串口函数
最近在做一个陀螺仪的原始数据读取遇到了串口数据读取问题,在网上查阅了一篇技术文档,觉得写的不错,分享一下!
1.1前言
通常使用以下函数来通过Windows系统来对外围设备进行通信,做串口方面的程序,使用CreatFile打开串口通信端口。在对串口进行操作之前,需要首先打开串口。使用C++进行串口编程,如果采用VS开发,则可以直接借助于串口通信控件来操作,其次,也可以直接调用Windows的底层API函数来控制串口通信。
在Windows的操作系统上,将串口(通信设备)作为文件来处理,所以串口的打开、关闭、读写所使用的API函数与文件操作一样。所以打开串口使用CreateFile函数,读写串口使用ReadFile、WriteFile函数,关闭串口使用CloseHandle函数。查看通信设备的串口,可以在设备管理器中查看。
1.2 CreateFile
这个函数的功能是创建或者打开一个文件或者I/O设备,通常使用的I/O形式有文件、文件流、目录、物理磁盘、卷、终端流等。如果执行成功,则返回文件句柄INVALID_HANDLE_VALUE表示出错,会设置GetLastError。
函数的声明定义:
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
)
参数列表:
部分参数Tips:
1. IpFileName:指定要打开的串口逻辑名,用字符串来表示。如COM1,COM2,分别表示串口1和串口2.
如果要确定工控机上有哪些串口,可以使用设备管理器查看,我的电脑,右键,属性,设备管理器,如下图:
2. dwDesiredAccess:端口属性的访问类型。
3. dwShareModel:指定端口的共享属性
该参数是由那些应用程序共享的文件提供。对于串口来说,是不能共享的,因此,必须设置为0,这是通信设备与文件的特殊差别。
如果当前的应用程序调用CreateFile打开一个串口,另外一个程序如果已经打开了该串口,此时CreateFile会返回一个错误代码。
然而,同一个应用程序的多个线程是可以共享CreateFile返回的端口句柄。并且根据安全属性设置,该句柄可以打开端口的应用程序的子程序来继承。
4. lpSecurityAttributes:安全属性,一般该参数为NULL,即该端口被设置为缺省的安全属性。缺省安全属性下,端口的句柄是不能继承的。
5. dwCreationDisposition:指定此端口正在被其他程序占用采取的动作,因为串口总是存在的,因此必须设置为OPEN_EXISTing, 该标志高速Windows不要创建新的端口。而是打开一个已经存在的端口。
6. dwFlagsAndSttributes:描述了端口的各种属性,对于文件来说有很多属性,但是对于串口来说,唯一的意义是FILE_FLAG _OVERLAPPED 属性,当设置该属性时,端口IO可以在后台进行,称为异步IO重叠结构。
7. hTemplateFile: 指定模板的文件句柄,对于串口来说,此参数必须设置为0;
用CreateFile函数打开串口COM1的例子如下:
HANDLE hCom;
DWORD dwError;
hCom=CreateFile("COM1", //文件名,这里是串口号
GENERIC_READ|GENERIC_WRITE, //允许读和写
0, //独占方式
NULL,
OPEN_EXISTING, //打开而不是创建
FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED, //异步I/O重叠结构
NULL
);
然后还应判断端口是否被正常打开,过程如下:
if(hCom==INVALID_HANDLE_VALUE)
{
dwErrow=GetLastError(); //取得错误代码
}
1.3 关闭串口
关闭串口,使用CloseHandle,函数声明为:
BOOL CloseHandle(
HANDLE hObject //handle to object
);
函数比较简单,参数是使用CreateFile打开的端口句柄。调用这个函数可以实现串口关闭。
示例如下:
if(CloseHandle(m_hCom)==0) //调用该函数关闭串口
{
CString strMsg;
str="关闭串口"+strSel_COM+"失败";
AfxMessageBox(strMsg);
}
else
{
CString strMsg;
strMsg="关闭"+strSel_COM+"成功";
}
1.4 ReadFile
从文件指针指向的位置(设备文件,通信)开始将数据读出到一个文件中, 且支持同步和异步操作,如果文件打开方式没有指明FILE_FLAG_OVERLAPPED的话,当程序调用成功时,它将实际读出文件的字节数保存到lpNumberOfBytesRead指明的地址空间中。FILE_FLAG_OVERLAPPED 允许对文件进行重叠操作。
BOOL WINAPI ReadFile(
__in HANDLE hFile, //文件局柄
__out LPVOID lpBuffer, //接收数据用的 buffer
__in DWORD nNumberOfBytesToRead, //要读取的字节数
__Out LPDWORD lpNumberOfBytesRead, //实际读取的字节数
__in LPOVERLAPPED lpOverlapped //OVERLAPPED结构,一般设定为NULL
);
代码示例:
1 BOOL Read(char *filePath)
2 {
3 HANDLE pFile;
4 DWORD fileSize;
5 char *buffer,*tmpBuf;
6 DWORD dwBytesRead,dwBytesToRead,tmpLen;
7
8 pFile = CreateFile(filePath,GENERIC_READ,
9 FILE_SHARE_READ,
10 NULL,
11 OPEN_EXISTING, //打开已存在的文件
12 FILE_ATTRIBUTE_NORMAL,
13 NULL);
14 // 创建设备文件,返回文件的位置
15 if ( pFile == INVALID_HANDLE_VALUE)
16 {
17 printf("open file error!\n");
18 CloseHandle(pFile);
19 return FALSE;
20 }
21
22 fileSize = GetFileSize(pFile,NULL); //得到文件的大小
23
24 buffer = (char *) malloc(fileSize);
25 ZeroMemory(buffer,fileSize);
26 dwBytesToRead = fileSize;
27 dwBytesRead = 0;
28 tmpBuf = buffer;
29
30 do{ //循环读文件,确保读出完整的文件
31
32 ReadFile(pFile,tmpBuf,dwBytesToRead,&dwBytesRead,NULL);
33
34 if (dwBytesRead == 0)
35 break;
36
37 dwBytesToRead -= dwBytesRead;
38 tmpBuf += dwBytesRead;
39
40 } while (dwBytesToRead > 0);
41
42 // TODO 处理读到的数据 buffer
43
44 free(buffer);
45 CloseHandle(pFile);
46
47 return TRUE;
48 }
1.5 WriteFile
将数据写入一个文件(设备文件,通信)。该函数比fwrite函数要灵活的多。也可以将这个函数应用于对通信设备、管道、套接字以及邮槽的处理。返回时,TRUE(非零)表示成功,否则返回零。会设置GetLastError。
函数声明定义:
BOOL WINAPI WriteFile(
__in HANDLE hFile, //文件句柄
__in LPCVOID lpBuffer, //要写入的数据
__in DWPRD nNumberOfBytesToWrite, //要写入的字节数
__out LPDWORD lpNumberOfBytesWritten, //实际写入的字节数
__in LPOVERLAPPED lpOverlapped //OVERLAPPED结构,一般设定为NULL
);
示例代码:
BOOL Write(char *buffer, DWORD contentLen)
{
HANDLE pFile;
char *tmpBuf;
DWORD dwBytesWrite,dwBytesToWrite;
pFile=CreateFile(filePath,
GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
)
if ( pFile == INVALID_HANDLE_VALUE)
{
printf("create file error!");
CloseHandle(pFile);
return FALSE;
}
dwBytesToWrite = contentLen;
dwBytewrite = 0;
tmpBuf = buffer;
do{
Write(pFile,tmpBuf,dwBytesToWrite,&dwBytesWrite,NULL);
dwBytesToWrite -= dwBytesWrite;
tmpBuf += dwBytesWrite;
} while(dwBytesToWrite > 0);
CloseHandle(pFile);
return TRUE;
}
参考:
1. http://www.cnblogs.com/findumars/p/5636108.html
2. https://www.cnblogs.com/icmzn/p/7155856.html?utm_source=itdadao&utm_medium=referral
3. https://blog.****.net/dongpanshan/article/details/7898583