日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

基于C語言的java串口通信程序

 山峰云繞 2022-05-24 發(fā)布于貴州

目錄

1.前言

2.windows ?串口通信API

3.JAVA-JNI ?java程序調(diào)用C++程序

4.C/C++封裝 ?動態(tài)運行庫

一、前言

??

https://www.cnblogs.com/kadcyh/p/14389710.html



寫這個博客主要是因為自己想用java寫一個小小的后端服務(wù)器,其中要處理由51單片機(jī)傳送來的一些數(shù)據(jù)。單片機(jī)的數(shù)據(jù)由USB轉(zhuǎn)串口發(fā)送至上位機(jī),要處理這些數(shù)據(jù),就會用到windows提供一些API( Application Programming Interface,應(yīng)用程序接口 )。java在安裝了相關(guān)的包后,比如JNative.jar,可以直接用該包提供的接口來進(jìn)行調(diào)用windowsAPI。但是我才接觸java。而且整個作業(yè),我僅僅只要一部分來處理這個數(shù)據(jù)。安裝一個java包,實在是大可不必,所以就用C/C++來寫一個的終端,封裝一下放在java程序里面。

二、windows串口通信API

??2.1 ? 工具VC++6.0

??2.2 ? 概述:windows操作系統(tǒng)的設(shè)備無關(guān)性將所有的外設(shè)都當(dāng)做文件來操作,那么我們寫串口通信就直接將串口當(dāng)做文件來讀寫。那么我們打開串口后一定要記得關(guān)閉,這個很重要

??2.3 ? 串口通信程序概述

2.3.1 打開/關(guān)閉串口

HANDLE WINAPI CreateFileW(
    LPCWSTR lpFileName,                 
    DWORD dwDesiredAccess,                        
    DWORD dwShareMode,                              //共享模式
    LPSECURITY_ATTRIBUTES lpSecurityAttributes,    //安全屬性
    DWORD dwCreationDisposition,                  //指定文件的動作
    DWORD dwFlagsAndAttributes,                  //文件屬性---不指定就默認(rèn)為同步IO 
    HANDLE hTemplateFile                        //模板文件
    );

BOOL WINAPI CloseHandle(
       HANDLE hObject
    );

返回值:一個串口的句柄。
參數(shù)解釋:
lpFileName——串口名字。?當(dāng)為COM1~COM9的時候可以直接寫入但是大于10會有另外的寫法。以COM10為例:\.\COM10。
lpFileName——打開方式。?簡單來說這個就是打開文件是讀還是寫。GENERIC_READ(讀)|GENERIC_WRITE(寫)。還有其它的兩個值,詳細(xì)請在編輯器中直接按下F12看看他們的定義。
如果我們要定義一個同步IO的話,我們的打開方式必須要有讀動作。
dwShareMode指定該端口的共享屬性。?對于不能共享的串口,它必須設(shè)置為0。這就是文件與通信設(shè)備之間的主要差異之一。如果在當(dāng)前的應(yīng)用程序調(diào)用CreateFile()時,另一個應(yīng)用程序已經(jīng)打開了串口,該函數(shù)就會返回錯誤代碼,原因是兩個應(yīng)用程序不能共享一個端口。然而,同一個應(yīng)用程序的多個線程可以共享由CreateFile()返回的端口句柄,并且根據(jù)安全性屬性設(shè)置,該句柄可以被打開端口的應(yīng)用程序的子程序所繼承。
dwCreationDisposition指定文件的動作。?指定如果CreateFile()正在被已有的文件調(diào)用時應(yīng)采取的動作。因為串口總是存在,fdwCreate必須設(shè)置成OPEN_EXISTING。該標(biāo)志告訴Windows不用企圖創(chuàng)建新端口,而是打開已經(jīng)存在的端口。
調(diào)用該函數(shù)后,如果沒有穿件成功將會返回INVALID_HANDLE_VALUE。

2.3.2 配置串口通信

  • (1)?當(dāng)我們設(shè)置同步IO通信的時候,需要設(shè)置一下通信超時。一般情況下,我們用GetCommTimeouts來獲得COMMTIMEOUTS結(jié)構(gòu)體,再利用SetCommTimeouts來寫入。

BOOL WINAPI GetCommTimeouts(
    HANDLE hFile,
    LPCOMMTIMEOUTS lpCommTimeouts
    );

BOOL WINAPI SetCommTimeouts(
    HANDLE hFile,
    LPCOMMTIMEOUTS lpCommTimeouts
    );

COMMTIMEOUTS

typedef struct _COMMTIMEOUTS {
    DWORD ReadIntervalTimeout;          /* 設(shè)置兩個字符之前的最大讀取時間 */
    DWORD ReadTotalTimeoutMultiplier;   /* 設(shè)置每個字符的讀取時間        */
    DWORD ReadTotalTimeoutConstant;     /* 設(shè)置所有字符讀取的最大時間    */
    DWORD WriteTotalTimeoutMultiplier;  /* 設(shè)置每個字符的寫入時間       */
    DWORD WriteTotalTimeoutConstant;    /* 設(shè)置所有字符的寫入時間      */
} COMMTIMEOUTS,*LPCOMMTIMEOUTS;
  • (2)?設(shè)置波特率等相關(guān)參數(shù)
    仍然先用GetCommState得到DCB結(jié)構(gòu),修改其中的某些參數(shù)后再用SetCommState寫入DCB結(jié)構(gòu)。

BOOL WINAPI GetCommState(
    HANDLE hFile,
    LPDCB lpDCB
    );
BOOL WINAPI SetCommState(
    HANDLE hFile,
    LPDCB lpDCB
    );

DCB數(shù)據(jù)結(jié)構(gòu)我們初級學(xué)者需要關(guān)注:波特率、校驗位、停止位、發(fā)送數(shù)據(jù)位數(shù)。

  • (3)?設(shè)置緩沖區(qū)大小,根據(jù)程序要接收/發(fā)送的數(shù)據(jù)大小來決定。

BOOL WINAPI SetupComm(
    HANDLE hFile,
    DWORD dwInQueue,
    DWORD dwOutQueue
    );
  • (4)?讀取/寫入數(shù)據(jù)

BOOL WINAPI ReadFile(
    HANDLE hFile,
    LPVOID lpBuffer,                  //存放數(shù)據(jù)的緩沖區(qū)
    DWORD nNumberOfBytesToRead,       //一次想要讀入的數(shù)據(jù)長度
    LPDWORD lpNumberOfBytesRead,      //實際讀入的數(shù)據(jù)長度
    LPOVERLAPPED lpOverlapped      
    );

BOOL WINAPI WriteFile(
    HANDLE hFile,
    LPCVOID lpBuffer,
    DWORD nNumberOfBytesToWrite,
    LPDWORD lpNumberOfBytesWritten,
    LPOVERLAPPED lpOverlapped
    );

2.3.3 串口緩沖區(qū)配置

在程序運行的時候,應(yīng)該保證設(shè)置的緩沖區(qū)是“干凈”的。所以在讀數(shù)據(jù)或者寫數(shù)據(jù)之前,可以先清空一下緩沖區(qū)。

//清空緩沖區(qū)
BOOL WINAPI PurgeComm(
    HANDLE hFile,
    DWORD dwFlags
    );

//清除錯誤
BOOL WINAPI ClearCommError(
    HANDLE hFile,
    LPDWORD lpErrors,
    LPCOMSTAT lpStat
    );

2.4完整的讀串口代碼

#include <stdio.h>`
#include <windows.h>
int Comm(int nBaud,int parity,int bytesize,int stopbits,int accdatalength,char rBuf[])
{								//緩沖區(qū)
	DWORD rSize = 0;
	DWORD dwError;										//清除錯誤
	COMSTAT cs;				
	COMMTIMEOUTS timeouts;								//超時數(shù)據(jù)結(jié)構(gòu)
	DCB dcb;											//串口通信配置文件---用LPDCB類型會報錯
	HANDLE hCom;										//串口的句柄(實例)| the instance of com
	hCom = CreateFile("COM3",							//串口的名字
					   GENERIC_READ | GENERIC_WRITE,    //串口打開方式
					   0,								//共享方式					
					   NULL,							//安全屬性
					   OPEN_EXISTING,					//指定文件的動作
					   0,								//文件屬性---不指定就默認(rèn)為同步IO
					   NULL								//指向模板文件的句柄
					   );
	if(hCom == INVALID_HANDLE_VALUE)
	{
		return -1;
	}
///////////////////////////////////////
//同步IO需要設(shè)置讀數(shù)據(jù)超時
//////////////////////////////////////
	if(!(GetCommTimeouts(hCom,&timeouts)))		//獲的COMMTIMEOUTS結(jié)構(gòu)失?。?	{
		CloseHandle(hCom);
	}
	timeouts.ReadIntervalTimeout = 1000;			//讀取每個字符之間的超時
	timeouts.ReadTotalTimeoutMultiplier = 500;		//讀取一個字符的超時
	timeouts.ReadTotalTimeoutConstant=5000;			//固定總超時
	timeouts.WriteTotalTimeoutConstant = 0;			//寫入字符之間超時
	timeouts.WriteTotalTimeoutMultiplier = 0;		//寫入字符總超時
	if(!(SetCommTimeouts(hCom,&timeouts)))			//設(shè)置COMMTIMEOUTS結(jié)構(gòu)失敗
	{
		CloseHandle(hCom);
	}
////////////////////////////////////////
//設(shè)置緩沖區(qū)大小
///////////////////////////////////////
	if(!SetupComm(hCom,500,500))				//設(shè)置讀寫緩沖區(qū)失敗
	{
		CloseHandle(hCom);
	}
//////////////////////////////////////
//設(shè)置波特率等其它讀文件配置
/////////////////////////////////////
	if(GetCommState(hCom,&dcb)==0)			//獲得DCB數(shù)據(jù)失敗
	{
		CloseHandle(hCom);
	}
	//dcb.DCBlength = sizeof(DCB);
	dcb.BaudRate = nBaud;					//波特率為4800
	dcb.Parity = parity;					//校驗方式為無校驗
	dcb.ByteSize = bytesize;						//數(shù)據(jù)位為8位
	dcb.StopBits = stopbits;				//停止位為1位
	if (!SetCommState(hCom,&dcb))			//設(shè)置串口通信配置項失敗
	{
		CloseHandle(hCom);
	}

//////////////////////////////////////
//清除緩沖區(qū)
/////////////////////////////////////
	PurgeComm(hCom,PURGE_RXCLEAR|PURGE_TXCLEAR);
///////////////////////////////////////
//清除錯誤
///////////////////////////////////////
	if(!(ClearCommError(hCom,&dwError,&cs)))
	{
		CloseHandle(hCom);
	}
////////////////////////////////////////////
//開始讀取緩沖口的數(shù)據(jù)
///////////////////////////////////////////

	//讀取串口數(shù)據(jù)
	if(INVALID_HANDLE_VALUE != hCom)
	{
		WriteFile
		ReadFile(hCom,rBuf,accdatalength,&rSize,NULL);
		printf("%d \n",rSize);
		if(rSize)
		{
			CloseHandle(hCom);
			return 1;
			
		}
		else
		{
			CloseHandle(hCom);
			return 0;
		}
	}
	else
	{
		CloseHandle(hCom);
		return 2;
	}	
}
void main()
{
	int i;
	char buf[18] = {0};
	int a,b,c,d,e;
	printf("請輸入相關(guān)參數(shù):");
	scanf("%d%d%d%d%d",&a,&b,&c,&d,&e);
	while(1)
	{
		if(Comm(a,b,c,d,e,buf)==1)
		{
			for(i=0;i<17;i++)
			{
				printf("%c ",buf[i]);
			}
			printf("\n");
		}
		else
		{
			printf("%d \n",Comm(a,b,c,d,e,buf));
			break;
		}
	}
	
}

運行結(jié)果

三、JAVA-JNI ?java程序調(diào)用C++程序

??參考博客
??在寫java程序調(diào)用C程序之前,寫過C#程序調(diào)用用C#封裝好的dll程序。然后,我以為,java程序調(diào)用C程序也可以直接把C封裝好的dll程序拿過來直接用就好。結(jié)果就是一直報錯。那么接下來就是正確的調(diào)用方式。

工具eclipse

3.1

??首先在新建一個類,類的名字隨意。最好加上main()函數(shù)方便我們進(jìn)行模塊調(diào)試。在這個類里面。在這個類里面我們要自己定義將會用C/C++實現(xiàn)的函數(shù)。并且必須用到j(luò)ava提供的 System.loadLibrary()函數(shù)。如下:
`

public class Com {
	
	static {
		System.loadLibrary("CommDLL");			//靜態(tài)語句塊,保證在創(chuàng)建該類的時候,該方法必須且只會調(diào)用一次。參數(shù)就是編寫的動態(tài)庫名稱
	}
	public native int Comm(int nBaud,int parity,int bytesize,int stopbits,int accdatalength,String ComName,char[] rBuf);//將要用C/C++實現(xiàn)的函數(shù)
	public static void main(String[] args) {
	      int term = new Com().Comm(4800, 0, 8, 0, 17,"COM3", Buffer);
			
	}	
}

`
注:native 關(guān)鍵字表示,這個函數(shù)為本地函數(shù)。盡管沒用java語言實現(xiàn),但它有自己的實體。

3.2

??找到剛編寫的java源程序文件所在的位置。然后如下操作:

??注:馬賽克的位置是暫時還不該有的文件

??進(jìn)入控制臺:

??輸入 javac -d ./ Com.java 。即是根據(jù)將java文件經(jīng)過編譯生成二進(jìn)制文件(class文件)

??輸入 javac -h ./ Com.java 生成相關(guān)的頭文件。

??注:如果報錯:'javac不是內(nèi)部或外部命令,也不是可運行的程序或批處理文件。'?請參考相關(guān)博客添加相關(guān)的環(huán)境變量。參考博客。

3.3

??在生成了相關(guān)的庫文件的編寫后。我們要用這個庫文件有兩種辦法。

  • 1:直接將生成的dll文件加入默認(rèn)的環(huán)境變量里面。( 但是不是很推薦這個辦法,因為我們編寫的庫,僅僅只是在自己的程序上用一用。沒有很大的普適性。

  • 2:將生成的dll文件拷貝到自己源文件下面。同時配置一下自己的java程序。
    ?? 右鍵src--->properties--->Native Library--->Workspace

3.4

運行代碼:

public class Com {
	
	static {
		System.loadLibrary("CommDLL");			//靜態(tài)語句塊,保證在創(chuàng)建該類的時候,該方法必須且只會調(diào)用一次。
	}
	public native int Comm(int nBaud,int parity,int bytesize,int stopbits,int accdatalength,String ComName,byte[] rBuf);
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		byte[] Buffer = new byte[18];
		while(true)
		{
			int term = new Com().Comm(4800, 0, 8, 0, 17,"COM3", Buffer);
			if(term==1)
			{
				for(int i=0;i<17;i++)
				{
					System.out.print(Buffer[i]+" ");
					
				}
				System.out.println();
			}
		}
		
	}	
}

運行結(jié)果

四、C/C++封裝動態(tài)運行庫

4.1:關(guān)于工具

??一開始用的工具是VC++6.0,盡管工具有點老,但是它足夠小。動態(tài)庫編好了,在eclipse上面運行的時候,出現(xiàn)了錯誤,大致意思就是:“32位的動態(tài)庫,沒有辦法在64位的設(shè)備上面”。 如果,我還想繼續(xù)使用這個動態(tài)庫,已知的解決辦法就是:下載一個32位的java ? JDK包。但是,相比配置一個可以運行32位的環(huán)境,我更加傾向于編譯生成一個64位的動態(tài)運行庫。然后,我就把代碼粘到了VS上面。一般寫代碼我不太喜歡在VS上面,雖然它的功能很強(qiáng)太,但是我的電腦負(fù)載它真的很費力。

4.2 用JNI編寫本地函具體步驟

?? * 1:建立DLL程序:文件--->新建--->項目--->windows桌面--->動態(tài)鏈接庫

4.2 代碼細(xì)節(jié)

?? * 1:新建一個頭文件,把在第三節(jié)里面生成的頭文件內(nèi)容復(fù)制粘貼過來。




?? * 2:具體cpp文件實現(xiàn)。
當(dāng)我把VC里面的代碼直接粘貼過來的時候,就直接報錯了。const char* 不可以轉(zhuǎn)換為LPCWSTR。我想強(qiáng)制轉(zhuǎn)化成LPCSTTR那肯定不可以的,但是強(qiáng)制轉(zhuǎn)化為wchar *這個是可以的。因為報錯的原因就是函數(shù)createFile()想要的文件名字應(yīng)該是寬字符傳進(jìn)去的。但是當(dāng)時我只解用了將普通字符轉(zhuǎn)成寬字符的函數(shù) MultiByteToWideChar ,不了解兩種字符的可以自行百度一下。用了這個函數(shù)后報錯沒有了。
但是,為了程序的健壯性我決定,把串口的名字暴露出來。然后新的問題出現(xiàn)了,當(dāng)我想為了適應(yīng)之前的程序,把串口的名字當(dāng)中字符數(shù)組傳進(jìn)來的時候。java程序又報錯,所以編譯器太智能了也讓人傷心。Java這邊發(fā)現(xiàn)的我傳入的就是一串字符,馬上要求我把參數(shù)改成字符串類型。那也沒辦法,我沒有能力自己開發(fā)一個IDE,所以就把string 傳了進(jìn)去。但是,我們知道C語言其實沒有stirng這種類型,后來我又加了一點C++的代碼,這樣才勉強(qiáng)有了字符串這種類型。好吧,用函數(shù)把jstring 類型在轉(zhuǎn)成寬字符類型。經(jīng)過這次的修改,代碼可以單獨在VS里面跑起來了。
VS單獨運行代碼:

#include <iostream>
#include<stdlib.h>
#include<windows.h>
using std::string;
int Comm(int nBaud, int parity, int bytesize, int stopbits, int accdatalength,string comName, char rBuf[])
{
	DWORD rSize = 0;
	DWORD dwError;										//清除錯誤
	COMSTAT cs;
	COMMTIMEOUTS timeouts;								//超時數(shù)據(jù)結(jié)構(gòu)
	DCB dcb;											//串口通信配置文件---用LPDCB類型會報錯
	HANDLE hCom;										//串口的句柄(實例)| the instance of com
//////////////////////////////////////////////////////////////////////
//將string轉(zhuǎn)換為LPCWSTR類型
//////////////////////////////////////////////////////////////////////
	int len = comName.length();
	WCHAR buffer[256];
	///////memset原型---extern void *memset(void *buffer, int c, int count) buffer:為指針或是數(shù)組,c:是賦給buffer的值,count:是buffer的長度.//////
	memset(buffer, 0, sizeof(buffer));		//作用是在一段內(nèi)存塊中填充某個給定的值,它是對較大的結(jié)構(gòu)體或數(shù)組進(jìn)行清零操作的一種最快方法
	MultiByteToWideChar(CP_ACP, 0, comName.c_str(), (len+1), buffer, sizeof(buffer) / sizeof(buffer[0]));
	printf("%d\n", buffer[0]);
	hCom = CreateFile(buffer,							//串口的名字
		GENERIC_READ | GENERIC_WRITE,    //串口打開方式
		0,								//共享方式					
		NULL,							//安全屬性
		OPEN_EXISTING,					//指定文件的動作
		0,								//文件屬性---不指定就默認(rèn)為同步IO
		NULL								//指向模板文件的句柄
	);
	if (hCom == INVALID_HANDLE_VALUE)
	{
		return -1;
	}
	///////////////////////////////////////
	//同步IO需要設(shè)置讀數(shù)據(jù)超時
	//////////////////////////////////////
	if (!(GetCommTimeouts(hCom, &timeouts)))		//獲的COMMTIMEOUTS結(jié)構(gòu)失??!
	{
		CloseHandle(hCom);
	}
	timeouts.ReadIntervalTimeout = 1000;			//讀取每個字符之間的超時
	timeouts.ReadTotalTimeoutMultiplier = 500;		//讀取一個字符的超時
	timeouts.ReadTotalTimeoutConstant = 5000;			//固定總超時
	timeouts.WriteTotalTimeoutConstant = 0;			//寫入字符之間超時
	timeouts.WriteTotalTimeoutMultiplier = 0;		//寫入字符總超時
	if (!(SetCommTimeouts(hCom, &timeouts)))			//設(shè)置COMMTIMEOUTS結(jié)構(gòu)失敗
	{
		CloseHandle(hCom);
	}
	////////////////////////////////////////
	//設(shè)置緩沖區(qū)大小
	///////////////////////////////////////
	if (!SetupComm(hCom, 500, 500))				//設(shè)置讀寫緩沖區(qū)失敗
	{
		CloseHandle(hCom);
	}
	//////////////////////////////////////
	//設(shè)置波特率等其它讀文件配置
	/////////////////////////////////////
	if (GetCommState(hCom, &dcb) == 0)			//獲得DCB數(shù)據(jù)失敗
	{
		CloseHandle(hCom);
	}
	//dcb.DCBlength = sizeof(DCB);
	dcb.BaudRate = nBaud;					//波特率為4800
	dcb.Parity = parity;					//校驗方式為無校驗
	dcb.ByteSize = bytesize;						//數(shù)據(jù)位為8位
	dcb.StopBits = stopbits;				//停止位為1位
	if (!SetCommState(hCom, &dcb))			//設(shè)置串口通信配置項失敗
	{
		CloseHandle(hCom);
	}

	//////////////////////////////////////
	//清除緩沖區(qū)
	/////////////////////////////////////
	PurgeComm(hCom, PURGE_RXCLEAR | PURGE_TXCLEAR);
	///////////////////////////////////////
	//清除錯誤
	///////////////////////////////////////
	if (!(ClearCommError(hCom, &dwError, &cs)))
	{
		CloseHandle(hCom);
	}
	////////////////////////////////////////////
	//開始讀取緩沖口的數(shù)據(jù)
	///////////////////////////////////////////

		//讀取串口數(shù)據(jù)
	if (INVALID_HANDLE_VALUE != hCom)
	{
		ReadFile(hCom, rBuf, accdatalength, &rSize, NULL);
		printf("%d \n", rSize);
		if (rSize)
		{
			CloseHandle(hCom);
			return 1;

		}
		else
		{
			CloseHandle(hCom);
			return 0;
		}
	}
	else
	{
		CloseHandle(hCom);
		return 2;
	}
}
void main()
{
	int i;
	char buf[18] = { 0 };
	int a, b, c, d, e;
	char ComName[6];
	printf("請輸入相關(guān)參數(shù):");
	std::cin >> a >> b >> c >> d >> e>>ComName;
	while (1)
	{
		int t = Comm(a, b, c, d, e, ComName, buf);
		if (t == 1)
		{
			for (i = 0; i < 17; i++)
			{
				printf("%c ", buf[i]);
			}
			printf("\n");
		}
		else
		{
			printf("%d\n", t);
			break;
		}
	}

}
  • 3:JNI中基本類型的處理
    ??完成這個作業(yè)之前我只是知道有JNI這個知識點,但是確實沒有系統(tǒng)的學(xué)習(xí)過。但是我就自己學(xué)的一點點東西可以總結(jié)一下。java里面的基礎(chǔ)類型可以放到C/C++里面使用但是像數(shù)組之類的數(shù)據(jù)類型,必須有Java認(rèn)同的類型稍作處理,才可以在C/C++的環(huán)境里面運行。具體請參考:參考博客這片博客好像是sun官網(wǎng)的中翻,值得參考。

  • 4:成功的DLL源代碼:

#include "pch.h"
#include "comm.h"
#include <iostream>
#include <stdlib.h>
#include <windows.h>
using std::string;
/////////////////////////////////////////////////////////////////////////
//
JNIEXPORT jint JNICALL Java_Com_Comm(JNIEnv* env, jobject, jint nBaud, jint parity, jint bytesize, jint stopbits, jint accdatalength,jstring comName, jbyteArray rBuf)
{	DWORD rSize = 0;
	DWORD dwError;										//清除錯誤
	COMSTAT cs;
	COMMTIMEOUTS timeouts;								//超時數(shù)據(jù)結(jié)構(gòu)
	DCB dcb;											//串口通信配置文件---用LPDCB類型會報錯
	HANDLE hCom;										//串口的句柄(實例)| the instance of com
	BYTE rBuffer[255];
//////////////////////////////////////////////////////////////////////
//將jstring轉(zhuǎn)換為LPCWSTR類型
//////////////////////////////////////////////////////////////////////
	WCHAR* buffer = (WCHAR*)env->GetStringChars(comName,NULL);
	hCom = CreateFile(buffer,							//串口的名字
		GENERIC_READ | GENERIC_WRITE,    //串口打開方式
		0,								//共享方式					
		NULL,							//安全屬性
		OPEN_EXISTING,					//指定文件的動作
		0,								//文件屬性---不指定就默認(rèn)為同步IO
		NULL								//指向模板文件的句柄
	);
	if (hCom == INVALID_HANDLE_VALUE)
	{
		return -1;
	}
	///////////////////////////////////////
	//同步IO需要設(shè)置讀數(shù)據(jù)超時
	//////////////////////////////////////
	if (!(GetCommTimeouts(hCom, &timeouts)))		//獲的COMMTIMEOUTS結(jié)構(gòu)失??!
	{
		CloseHandle(hCom);
	}
	timeouts.ReadIntervalTimeout = 1000;			//讀取每個字符之間的超時
	timeouts.ReadTotalTimeoutMultiplier = 500;		//讀取一個字符的超時
	timeouts.ReadTotalTimeoutConstant = 5000;			//固定總超時
	timeouts.WriteTotalTimeoutConstant = 0;			//寫入字符之間超時
	timeouts.WriteTotalTimeoutMultiplier = 0;		//寫入字符總超時
	if (!(SetCommTimeouts(hCom, &timeouts)))			//設(shè)置COMMTIMEOUTS結(jié)構(gòu)失敗
	{
		CloseHandle(hCom);
	}
	////////////////////////////////////////
	//設(shè)置緩沖區(qū)大小
	///////////////////////////////////////
	if (!SetupComm(hCom, 500, 500))				//設(shè)置讀寫緩沖區(qū)失敗
	{
		CloseHandle(hCom);
	}
	//////////////////////////////////////
	//設(shè)置波特率等其它讀文件配置
	/////////////////////////////////////
	if (GetCommState(hCom, &dcb) == 0)			//獲得DCB數(shù)據(jù)失敗
	{
		CloseHandle(hCom);
	}
	//dcb.DCBlength = sizeof(DCB);
	dcb.BaudRate = nBaud;					//波特率為4800
	dcb.Parity = parity;					//校驗方式為無校驗
	dcb.ByteSize = bytesize;						//數(shù)據(jù)位為8位
	dcb.StopBits = stopbits;				//停止位為1位
	if (!SetCommState(hCom, &dcb))			//設(shè)置串口通信配置項失敗
	{
		CloseHandle(hCom);
	}

	//////////////////////////////////////
	//清除緩沖區(qū)
	/////////////////////////////////////
	PurgeComm(hCom, PURGE_RXCLEAR | PURGE_TXCLEAR);
	///////////////////////////////////////
	//清除錯誤
	///////////////////////////////////////
	if (!(ClearCommError(hCom, &dwError, &cs)))
	{
		CloseHandle(hCom);
	}
	////////////////////////////////////////////
	//開始讀取緩沖口的數(shù)據(jù)
	///////////////////////////////////////////

		//讀取串口數(shù)據(jù)
	if (INVALID_HANDLE_VALUE != hCom)
	{
		ReadFile(hCom, &rBuffer, accdatalength, &rSize, NULL);
		if (rSize)
		{
			jbyte* term;								//將RBuffer中的值賦給rBuf
			term = env->GetByteArrayElements(rBuf,FALSE);
			for (int i = 0; i < accdatalength; i++)
			{
				term[i] = rBuffer[i];
			}
			env->ReleaseByteArrayElements(rBuf,term, JNI_COMMIT);
			CloseHandle(hCom);
			return 1;

		}
	}
	else
	{
		CloseHandle(hCom);
		return 1;
	}
	env->ReleaseStringChars(comName,(jchar *)buffer);			//釋放空間
	CloseHandle(hCom);
	return 2;

}

注:代碼寫在自己新建的和頭文件同名的自己建立的源文件(.cpp)里面。

4.3 配置

在生成DLL文件之前,我們還必須做一些重要的配置。

  • 1:把java jdk里面的一些文件拷貝到DLL文件里面去。

??將框起來的三個頭文件復(fù)制到DLL源程序的文件里面。

  • 2:修改一下DLL項目的配置:

右鍵項目 ---> 屬性--->VC++目錄--->包含目錄(把DLL程序所在的文件路徑添加進(jìn)去)

最后,我們在點擊生成。就OK啦。

到此結(jié)束啦,希望可以幫助到你!

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多