C/C++编写一个定时往串口(虚拟串口)发送数据的程序

时间:2022-11-25 07:58:20

利用C/C++来设计一个定时往串口(虚拟串口)发送数据的程序,包括虚拟串口的配置与串口的接收显示数据:

程序如下:

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

using namespace std;

int main()
{
HANDLE hcom;
hcom = CreateFile("COM3",GENERIC_READ | GENERIC_WRITE,0,NULL,OPEN_EXISTING
,FILE_ATTRIBUTE_NORMAL,NULL);
if (hcom == INVALID_HANDLE_VALUE)
{

fprintf(stderr, "打开串口失败!\n");
exit(0);
}
SetupComm(hcom,1024,1024);
DCB dcb;
GetCommState(hcom,&dcb);
dcb.BaudRate = 9600;
dcb.ByteSize = 8;
dcb.Parity = 0;
dcb.StopBits = 1;
SetCommState(hcom,&dcb);
char data[]={0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
DWORD dwWrittenLen = 0;
int k=0;
for (;;) {
if(!WriteFile(hcom,data,8,&dwWrittenLen,NULL))
{
fprintf(stderr, "发送数据失败!\n");
}

k++;

printf("往串口发送数据成功!第%d次\n" ,k);
Sleep(10*1000); //10s发送一次
}

return 0;
}
程序中用到的一些函数说明如下:

HANDLE CreateFile(
LPCTSTR  lpFileName
DWORD   dwDesiredAccess
DWORD   dwSharedMode
LPSECURITY_ATTRIBUTES  lpSecurityAttributes
DWORD   dwCreationDisposition
DWORD   dwFlagsAndAttributes
HANDLE   hTemplateFile
);
在调用成功时,CreateFile返回打开文件的句柄,该句柄将在以后与该串口相关的各个调用函数中使用。如果调用失败,则CreateFile返回INVALID_HANDLE_VALUE。

获取串行口当前状态:

windows系统使用GetCommState函数获取串行口的当前配置,GetCommState的声明如下:
BOOL  GetCommState(
      HANDLE hFile
      LPDCB  lpDCB
);
GetCommState函数的第一个参数hFile是由CreateFile函数返回指向已打开串行口的句柄。第二个参数指向设备控制块DCB。DCB是一个非常重要的数据结构,几乎所有的串行口属性和状态都存储在该结构的成员变量中。
对串口进行设置:
windows系统利用SetCommState函数修改串行口的当前参数配置。SetCommState函数声明如下:
BOOL  SetCommState(
      HANDLE hFile
      LPDCB  lpDCB
);
GetCommState函数的第一个参数hFile是由CreateFile函数返回指向已打开串行口的句柄。第二个参数指向设备控制块DCB。如果函数调用成功,则返回值为非0;若函数调用失败,则返回值为0。当应用程序仅仅需要修改一部分串行口的配置值时,可以通过GetCommState函数获得当前的DCB结构,然后更改参数,再调用SetCommState函数设置修改过的DCB来配置串行口。

为串口分配接收和发送缓冲区:

当一个串行口打开时,可以为该串口分配一个发送缓冲区和一个接收缓冲区。串行口发送缓冲区和接收缓冲区的配置可以由函数SetupComm实现。如果不调用SetupComm,系统会为该串口分配默认的发送缓冲区和接收缓冲区。但是为了保证缓冲区的大小与实际需要的一致,最好调用该函数进行设置。SetupComm函数原型如下:

BOOL  SetupComm(

     HANDLE hFile

     DWORD dwInQueue

     DWORD dwOutQueue

);

其中hFile是由CreateFile函数返回指向已打开串行口的句柄。参数dwInQueue和dwOutQueue分别指定应用程序推荐使用的接收缓冲区和发送缓冲区的大小。

 串行数据的发送
利用WriteFile函数可以向串行口写入数据。WriteFile函数原型如下:
BOOL  WriteFile(
HANDLE  hFile
LPVIOD   lpBuffer
DWORD   nNumberOfBytesToWrite
LPDWORD   lpNumberOfBytesWritten
LPOVERLAPPED  lpOverlapped
);

其中参数hFile指向已经打开的串行口句柄;lpBuffer指向一个发送数据缓冲区;nNumberOfBytesToWrite指定要从串行设备中发送的字节数;lpNumberOfBytesWritten指明实际从串行口中发送的字节数;lpOverlapped指向一个OVERLAPPED结构变量,该结构变量中包含一个同步事件。
通常如果调用成功,WriteFile返回非0值;否则返回值为0。但是对于发送操作在后台进行的串口来说,返回值为0不一定说明函数调用失败。此时可以调用GetLastError函数获取进一步的信息。如果GetLastError返回值为ERROR_IO_PENDING,则说明该写入串口的操作仍然处于后台等待状态,而非一个真正意义上的错误。

接收数据是会用到:

 串行数据的接收

利用ReadFile函数可以读取将串行口接收到的数据。ReadFile函数原型如下:

BOOL  ReadFile(

HANDLE  hFile

LPVIOD   lpBuffer

DWORD   nNumberOfBytesToRead

LPDWORD   lpNumberOfBytesRead

LPOVERLAPPED  lpOverlapped

);

其中参数hFile指向已经打开的串行口句柄;lpBuffer指向一个读取数据缓冲区;nNumberOfBytesToRead指定要从串行设备中读取的字节数;lpNumberOfBytesRead指明实际从串行口中读出的字节数;lpOverlapped指向一个OVERLAPPED结构变量,该结构变量中包含一个同步事件。

通常如果调用成功,ReadFile返回非0值;否则返回值为0。但是对于接收操作在后台进行的串口来说,返回值为0不一定说明函数调用失败。此时可以调用GetLastError函数获取进一步的信息。如果GetLastError返回值为ERROR_IO_PENDING,则说明该读取串口的操作仍然处于后台等待状态,而非一个真正意义上的错误。


下面开始测试:

(1)首先下载虚拟串口vsdp,安装后添加两个串口COM3和COM4:

 C/C++编写一个定时往串口(虚拟串口)发送数据的程序

(2)下载一个串口调试工具:由于程序中选择的串口为COM3,而虚拟串口中COM3和COM4是相通的,所以串口调试工具应该选择COM4来显示程序往COM3发送的数据,如下:

C/C++编写一个定时往串口(虚拟串口)发送数据的程序

(3)运行程序,结果如下:

C/C++编写一个定时往串口(虚拟串口)发送数据的程序


 到此,成功!