Using Windows API to implement a simple serial assistant

Use the window API to develop a serial assistant with string sending and receiving functions

Development environment

  • Visual Studio 2015

Serial device related 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
);

step

  1. Create a device handle
  2. Create a device file
  3. Configure serial port parameters
  4. Create read and write threads
  5. Read and write device files
  6. Close the device file after exiting the thread

Implementation code


#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;
}

Send and receive test chart

  • Remarks (on the left is the serial port software developed by myself, on the right is the XCOM V2.0 serial host computer software developed by the punctual atom team)

Image resource loading failed

Guess you like

Origin www.cnblogs.com/veis/p/12757813.html