EXCEL通过WindowsAPI操作串口

2016.08.24 18:14 Wed| 267 visits it手札| Text

工作需要时常和串口打交道,诚然有各种各样好用的串口调试工具可以使用,但收集的数据经常要复制到EXCEL进行分析,这一来二去,总会觉得些许的麻烦,索性用VBA写个读写串口的程序,岂不省去不少力气。

代码

下面的代码为VBA,主要实现了打开串口,配置串口,写串口和读取串口等关键步骤。API有详细的注释。

Sub COMtest()

Dim StrDataIn As String
Dim ASCDataIn(10) As Byte  '接受10个字符

Dim StrDataOut As String
Dim ASCDataOut() As Byte
StrDataOut = "test" & vbNewLine       '上位机写入本体的字符串
lenOfStrDataOut = Len(StrDataOut)           '写入字符串的长度
ASCDataOut() = StrConv(StrDataOut, vbFromUnicode) '转换为ASC数组
'======================================================
'打开端口COM2,获得句柄comm ,CreateFile 原型
'HANDLE CreateFile( LPCTSTR lpFileName,
'                  DWORD dwDesiredAccess,
'                  DWORD dwShareMode,
'                  LPSECURITY_ATTRIBUTES lpSecurityAttributes,
'                  DWORD dwCreationDistribution,
'                  DWORD dwFlagsAndAttributes,
'                  HANDLE hTemplateFile);
'lpFileName:将要打开的串口逻辑名,如“COM1”
'dwDesiredAccess:指定串口访问的类型,可以是读取、写入或二者并列;
'dwShareMode:指定共享属性,由于串口不能共享,该参数必须置为0;
'lpSecurityAttributes:引用安全性属性结构,缺省值为NULL;
'dwCreationDistribution:创建标志,对串口操作该参数必须置为OPEN_EXISTING;
'dwFlagsAndAttributes:属性描述,用于指定该串口是否进行异步操作,该值为'FILE_FLAG_OVERLAPPED,表示使用异步的I/O;该值为0,表示同步I/O操作;
'hTemplateFile:对串口而言该参数必须置为NULL;
comm = CreateFile("COM2", GENERIC_READ Or GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0)

'======================================================
'配置串口
'1.SetupComm配置I/O缓冲区的大小
'2.SetCommState配置DCB结构
'3.GetCommTimeouts,SetCommTimeouts配置超时时间
'======================================================
'SetupComm函数原型:
'BOOL SetupComm(
'    HANDLE hFile,  // 通信设备的句柄
'    DWORD dwInQueue, // 输入缓冲区的大小(字节数)
'    DWORD dwOutQueue // 输出缓冲区的大小(字节数)
' );
SetupComm comm, 1024, 1024

'=====================================================
'typedef struct _DCB {
'   //………
'   //波特率,指定通信设备的传输速率。这个成员可以是实际波特率值或者下面的常量值之一:
'   DWORD BaudRate;
'   //CBR_110,CBR_300,CBR_600,CBR_1200,CBR_2400,CBR_4800,CBR_9600,CBR_19200, 'CBR_38400,
'   //CBR_56000, CBR_57600, CBR_115200, CBR_128000, CBR_256000, CBR_14400

'   DWORD fParity; // 指定奇偶校验使能。若此成员为1,允许奇偶校验检查
'   //…
'   BYTE ByteSize; // 通信字节位数,4—8
'   BYTE Parity; //指定奇偶校验方法。此成员可以有下列值:
'   //EVENPARITY 偶校验     NOPARITY 无校验
'   //MARKPARITY 标记校验   ODDPARITY 奇校验
'   BYTE StopBits; //指定停止位的位数。此成员可以有下列值:
'   //ONESTOPBIT 1位停止位   TWOSTOPBITS 2位停止位
'   //ONE5STOPBITS   1.5位停止位
'   //………
' } DCB;
GetCommState comm, fDCB
With fDCB
    .BaudRate = 9600
    .fBitFields = 0
    .ByteSize = 8
    .StopBits = 1
End With
SetCommState comm, fDCB

'======================================================
'COMMTIMEOUTS结构的定义为:
'typedef struct _COMMTIMEOUTS {
'    DWORD ReadIntervalTimeout; //读间隔超时
'    DWORD ReadTotalTimeoutMultiplier; //读时间系数
'    DWORD ReadTotalTimeoutConstant; //读时间常量
'    DWORD WriteTotalTimeoutMultiplier; // 写时间系数
'    DWORD WriteTotalTimeoutConstant; //写时间常量
'} COMMTIMEOUTS,*LPCOMMTIMEOUTS;
GetCommTimeouts comm, fCOMMTIMEOUTS
With fCOMMTIMEOUTS
    .ReadIntervalTimeout = 1000
    .ReadTotalTimeoutConstant = 5000
    .ReadTotalTimeoutMultiplier = 1000
    .WriteTotalTimeoutMultiplier = 1000
    .WriteTotalTimeoutConstant = 1000
End With
SetCommTimeouts comm, fCOMMTIMEOUTS

''======================================================
'WriteFile上位机发送
'WriteFile函数原型
'BOOL WriteFile(
'    HANDLE hFile,  //串口的句柄
'
'    // 写入的数据存储的地址,
'    // 即以该指针的值为首地址的nNumberOfBytesToWrite
'   // 个字节的数据将要写入串口的发送数据缓冲区。
'   LPCVOID lpBuffer,
'    DWORD nNumberOfBytesToWrite, //要写入的数据的字节数
'
'    // 指向指向一个DWORD数值,该数值返回实际写入的字节数
'    LPDWORD lpNumberOfBytesWritten,
'
'    // 重叠操作时,该参数指向一个OVERLAPPED结构,
'    // 同步操作时,该参数为NULL。
'    LPOVERLAPPED lpOverlapped
');
'
WriteFile comm, ASCDataOut(0), lenOfStrDataOut, num, 0

'======================================================
'ReadFile上位机读取
'ReadFile函数原型
'BOOL ReadFile(
'   HANDLE hFile, //串口的句柄
'
'    // 读入的数据存储的地址,
'    // 即读入的数据将存储在以该指针的值为首地址的一片内存区
'    LPVOID lpBuffer,
'    DWORD nNumberOfBytesToRead,  // 要读入的数据的字节数
'
'    // 指向一个DWORD数值,该数值返回读操作实际读入的字节数
'    LPDWORD lpNumberOfBytesRead,
'
'    // 重叠操作时,该参数指向一个OVERLAPPED结构,同步操作时,该参数为NULL。
'    LPOVERLAPPED lpOverlapped
');
ReadFile comm, ASCDataIn(0), 10, lenth, 0&

StrDataIn = StrConv(ASCDataIn, vbUnicode) '将读取的ASC转换为字符串
Debug.Print StrDataIn
CloseHandle (comm)
End Sub

这便是码代码的乐趣吧,自己动手让程序为己所用,让事情变得越来越简单,油然而生的成就感。