使用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, 
                        0, 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, 0, ThreadWrite, NULL, 0, NULL);
	HRead = CreateThread(NULL, 0, ThreadRead, NULL, 0, NULL);

	while (1);

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

收發測試圖

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

圖片資源加載失敗


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM