1. 程式人生 > WINDOWS開發 >使用Windows API實現一個簡單的串列埠助手

使用Windows API實現一個簡單的串列埠助手

目錄

使用window API開發一個具有字串收發功能的串列埠助手

開發環境

  • Visual Studio 2015

串列埠裝置相關的API


// 函式原型 
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
);

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

BOOL WINAPI GetCommState(
  _In_     HANDLE hFile,_Inout_  LPDCB lpDCB
);

BOOL ReadFile(
  HANDLE hFile,LPVOID lpBuffer,DWORD nNumberOfBytesToRead,LPDWORD lpNumberOfBytesRead,LPOVERLAPPED lpOverlapped
);

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

BOOL PurgeComm(
  HANDLE hFile,DWORD dwFlags
);

BOOL CloseHandle(
  HANDLE hObject
);

步驟

  1. 建立一個裝置控制代碼
  2. 建立一個裝置檔案
  3. 配置串列埠引數
  4. 建立讀寫執行緒
  5. 對裝置檔案進行讀寫
  6. 退出執行緒後關閉裝置檔案

實現程式碼


#define _CRT_SECURE_NO_WARNINGS
#include <windows.h>
#include <stdio.h>

HANDLE hCom; // 控制代碼,用於初始化串列埠

DWORD WINAPI ThreadWrite(LPVOID lpParameter)
{
	char outputData[100] = { 0x00 }; // 輸出資料快取

	if (hCom == INVALID_HANDLE_VALUE)
	{
		puts("開啟串列埠失敗");
		return 0;
	}

	DWORD strLength = 0;
	while (1)
	{
		for (int i = 0; i < 100; i++)
		{
			outputData[i] = 0;
		}
		fgets(outputData,100,stdin); // 從控制檯輸入字串
		strLength = strlen(outputData);
		printf("傳送了%d個位元組\r\n",strLength); // 列印字串長度
		WriteFile(hCom,outputData,strLength,&strLength,NULL); // 串列埠傳送字串
		fflush(stdout);
		PurgeComm(hCom,PURGE_TXCLEAR | PURGE_RXCLEAR); // 清空緩衝區
		Sleep(100);
	}
	return 0;
}

DWORD WINAPI ThreadRead(LPVOID lpParameter)
{
        // INVALID_HANDLE_VALUE表示出錯,會設定GetLastError
	if (hCom == INVALID_HANDLE_VALUE)   
	{
	        puts("開啟串列埠失敗");
		return 0;
	}
	char getputData[100] = { 0x00 }; // 輸入資料快取
	// 利用錯誤資訊來獲取進入串列埠緩衝區資料的位元組數
	DWORD dwErrors; // 錯誤資訊
	COMSTAT Rcs; // COMSTAT結構通訊裝置的當前資訊
	int Len = 0;
	DWORD length = 100; //用來接收讀取的位元組數
	while (1)
	{
		for (int i = 0; i < 100; i++)
		{
			getputData[i] = 0;
		}

		ClearCommError(hCom,&dwErrors,&Rcs); // 獲取讀緩衝區資料長度
		Len = Rcs.cbInQue;
		ReadFile(hCom,getputData,Len,&length,NULL);  // 獲取字串
		PurgeComm(hCom,PURGE_TXCLEAR | PURGE_RXCLEAR);  // 清空緩衝區
		if (Len > 0)
		{
			printf("接收的資料為:%s\r\n",getputData);
			fflush(stdout);
		}
		Sleep(100);
	}
	return 0;
}

int main()
{
	// 初始化串列埠
	TCHAR *com_name = (TCHAR *)malloc(10 * sizeof(TCHAR));
	do
	{
		printf("請輸入需要開啟的串列埠號(示例:COM2):");
		scanf("%s",com_name);
		getchar();
		hCom = CreateFile(com_name,GENERIC_READ | GENERIC_WRITE,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
		if (hCom == INVALID_HANDLE_VALUE)
			printf("串列埠號不存在,請重新輸入!\n");
		else
			break;
	} while (1);
	free(com_name);

	// 獲取和設定串列埠引數
	DCB myDCB;
	myDCB.BaudRate = 115200;       // 波特率
	myDCB.Parity = NOPARITY;     // 校驗位
	myDCB.ByteSize = 8;          // 資料位
	myDCB.StopBits = ONESTOPBIT; // 停止位
	SetCommState(hCom,&myDCB);  // 設定串列埠引數
	printf("baud rate is %d\n",(int)myDCB.BaudRate);

	// 執行緒建立
	HANDLE HRead,HWrite;
	HWrite = CreateThread(NULL,ThreadWrite,NULL);
	HRead = CreateThread(NULL,ThreadRead,NULL);

	while (1);

	CloseHandle(HRead);
	CloseHandle(HWrite);
        CloseHandle(hCom);
	return 0;
}

收發測試圖

  • 備註(左邊為自己開發的串列埠軟體,右邊為正點原子團隊開發的XCOM V2.0串列埠上位機軟體)

技術分享圖片