目录
1.前言
2.windows 串口通信API
3.C/C++封装 动态运行库
4.JAVA-JNI java程序调用C++程序
一、前言
&ensp ;写这个博客主要是因为自己想用java写一个小小的后端服务器,其中要处理由51单片机传送来的一些数据。单片机的数据由USB转串口发送至上位机,要处理这些数据,就会用到windows提供一些API( Application Programming Interface,应用程序接口 )。java在安装了相关的包后,比如JNative.jar,可以直接用该包提供的接口来进行调用windowsAPI。但是我才接触java。而且整个作业,我仅仅只要一部分来处理这个数据。安装一个java包,实在是大可不必,所以就用C/C++来写一个的终端,封装一下放在java程序里面。
二、windows串口通信API
2.1 工具:VC++6.0
2.2 概述:windows操作系统的设备无关性将所有的外设都当做文件来操作,那么我们写串口通信就直接将串口当做文件来读写。那么我们打开串口后一定要记得关闭,这个很重要
2.3 串口通信程序概述
2.3.1 打开/关闭串口
HANDLE WINAPI CreateFileW(
LPCWSTR lpFileName,
DWORD dwDesiredAccess,
DWORD dwShareMode, //共享模式
LPSECURITY_ATTRIBUTES lpSecurityAttributes, //安全属性
DWORD dwCreationDisposition, //指定文件的动作
DWORD dwFlagsAndAttributes, //文件属性---不指定就默认为同步IO
HANDLE hTemplateFile //模板文件
);
BOOL WINAPI CloseHandle(
HANDLE hObject
);
返回值:一个串口的句柄。
参数解释:
lpFileName——串口名字。 当为COM1~COM9的时候可以直接写入但是大于10会有另外的写法。以COM10为例:\.\COM10。
lpFileName——打开方式。 简单来说这个就是打开文件是读还是写。GENERIC_READ(读)|GENERIC_WRITE(写)。还有其它的两个值,详细请在编辑器中直接按下F12看看他们的定义。
如果我们要定义一个同步IO的话,我们的打开方式必须要有读动作。
dwShareMode指定该端口的共享属性。 对于不能共享的串口,它必须设置为0。这就是文件与通信设备之间的主要差异之一。如果在当前的应用程序调用CreateFile()时,另一个应用程序已经打开了串口,该函数就会返回错误代码,原因是两个应用程序不能共享一个端口。然而,同一个应用程序的多个线程可以共享由CreateFile()返回的端口句柄,并且根据安全性属性设置,该句柄可以被打开端口的应用程序的子程序所继承。
dwCreationDisposition指定文件的动作。 指定如果CreateFile()正在被已有的文件调用时应采取的动作。因为串口总是存在,fdwCreate必须设置成OPEN_EXISTING。该标志告诉Windows不用企图创建新端口,而是打开已经存在的端口。
调用该函数后,如果没有穿件成功将会返回INVALID_HANDLE_VALUE。
2.3.2 配置串口通信
- (1) 当我们设置同步IO通信的时候,需要设置一下通信超时。一般情况下,我们用GetCommTimeouts来获得COMMTIMEOUTS结构体,再利用SetCommTimeouts来写入。
BOOL WINAPI GetCommTimeouts(
HANDLE hFile,
LPCOMMTIMEOUTS lpCommTimeouts
);
BOOL WINAPI SetCommTimeouts(
HANDLE hFile,
LPCOMMTIMEOUTS lpCommTimeouts
);
COMMTIMEOUTS:
typedef struct _COMMTIMEOUTS {
DWORD ReadIntervalTimeout; /* 设置两个字符之前的最大读取时间 */
DWORD ReadTotalTimeoutMultiplier; /* 设置每个字符的读取时间 */
DWORD ReadTotalTimeoutConstant; /* 设置所有字符读取的最大时间 */
DWORD WriteTotalTimeoutMultiplier; /* 设置每个字符的写入时间 */
DWORD WriteTotalTimeoutConstant; /* 设置所有字符的写入时间 */
} COMMTIMEOUTS,*LPCOMMTIMEOUTS;
- (2) 设置波特率等相关参数
仍然先用GetCommState得到DCB结构,修改其中的某些参数后再用SetCommState写入DCB结构。
BOOL WINAPI GetCommState(
HANDLE hFile,
LPDCB lpDCB
);
BOOL WINAPI SetCommState(
HANDLE hFile,
LPDCB lpDCB
);
DCB数据结构我们初级学者需要关注:波特率、校验位、停止位、发送数据位数。
- (3) 设置缓冲区大小,根据程序要接收/发送的数据大小来决定。
BOOL WINAPI SetupComm(
HANDLE hFile,
DWORD dwInQueue,
DWORD dwOutQueue
);
- (4) 读取/写入数据
BOOL WINAPI ReadFile(
HANDLE hFile,
LPVOID lpBuffer, //存放数据的缓冲区
DWORD nNumberOfBytesToRead, //一次想要读入的数据长度
LPDWORD lpNumberOfBytesRead, //实际读入的数据长度
LPOVERLAPPED lpOverlapped
);
BOOL WINAPI WriteFile(
HANDLE hFile,
LPCVOID lpBuffer,
DWORD nNumberOfBytesToWrite,
LPDWORD lpNumberOfBytesWritten,
LPOVERLAPPED lpOverlapped
);