vs串口讀寫dll封裝C++#(免費源碼分享)


一、首先。老規矩。配置好自己的vs環境和建立一個dll工程。

我的環境:

  1. vs2013
  2. win10

二、開始寫代碼

廢話不多說。因為自己之前搞這個的時候,很多都要積分才可以下載,我這里就把我的整個工程分享出來供大家使用。經過測試工程讀寫完全正常。我在之前有發了一篇博客記錄了讀寫的截圖。
https://blog.csdn.net/weixin_43673603/article/details/107681314
代碼的輸出輸入為十六進制轉換,你們可以根據自己的需要去重新寫一個接收到的數據格式轉換函數,就可以輸出自己想要的格式。

首先自己新建兩個文件,一個com.c。一個com.h。名字可以自己其吧,只不過后面自己要改下頭文件引用。

com.c內容(這個串口的配置文件)

#include "stdafx.h"
#include <stdio.h>
#include "Com.h"

//
// Construction/Destruction
//
CCom::CCom()
{
	hPort = INVALID_HANDLE_VALUE;

	memset(LineBuf, 0, sizeof(LineBuf));
	dataLen = 0;
}

CCom::~CCom()
{
	close();
}

/** 奇偶校驗 0-4 = no,odd,even,mark,space 每字節一位停止位 0,1,2 = 1, 1.5, 2 OpenPort( _T("com1:"), 4800, 8, 0, 1 ); */
BOOL CCom::open(LPTSTR lpszPortName,
	DWORD baudRate,
	BYTE byteSize,
	BYTE parity,
	BYTE stopBits)
{
	if (hPort != INVALID_HANDLE_VALUE)
	{
		//::MessageBox(NULL, "hPort != INVALID_HANDLE_VALUE", "錯誤", MB_OK);
		return FALSE;
	}

	//打開串口
	hPort = CreateFile(lpszPortName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);

	//如果打開端口出錯, 返回FALSE
	if (hPort == INVALID_HANDLE_VALUE)
	{
		//不能打開端口
		DWORD errNum = GetLastError();
		char buf[256];
		sprintf(buf, "Unable to open port[%s] errCode[%d]!\n", lpszPortName, errNum);
		//::MessageBox(NULL, buf, "Err code", MB_OK);
		return FALSE;
	}

	//指定端口監測的事件集
	SetCommMask(hPort, EV_ERR | EV_RXCHAR | EV_BREAK | EV_CTS | EV_DSR | EV_ERR | EV_RING | EV_RLSD | EV_RXCHAR | EV_RXFLAG | EV_TXEMPTY);

	//分配設備緩沖區
	SetupComm(hPort, 512, 32);

	//初始化緩沖區中的信息
	PurgeComm(hPort, PURGE_TXCLEAR | PURGE_RXCLEAR);

	//配置串行端口
	if (!InitDCB(baudRate, byteSize, parity, stopBits))
	{
		//::MessageBox(NULL, "配置串行端口", "錯誤", MB_OK);
		return FALSE;
	}

	//設置端口超時值 
	if (!InitCommTimeouts())
	{
		//::MessageBox(NULL, "設置端口超時值", "錯誤", MB_OK);
		return FALSE;
	}

	//設置端口上指定信號的狀態
	// SETDTR: 發送DTR (data-terminal-ready)信號
	// SETRTS: 發送RTS (request-to-send)信號
	EscapeCommFunction(hPort, SETDTR);
	EscapeCommFunction(hPort, SETRTS);

	//clear( hPort );
	PurgeComm(hPort, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);

	return TRUE;
}

DWORD CCom::write(TCHAR *buf, DWORD dwCharToWrite)
{
	if (hPort == INVALID_HANDLE_VALUE)
		return 0;

	BOOL  fWriteState;
	DWORD dwBytesWritten;

	//寫入數據
	fWriteState = WriteFile(hPort,
		buf,
		dwCharToWrite * sizeof(TCHAR),
		&dwBytesWritten,
		NULL);

	if (!fWriteState)
	{
		//不能寫數據
		printf("Can't Write String to Com\n");
		dwBytesWritten = 0;
	}

	return dwBytesWritten;
}


BOOL CCom::InitDCB(DWORD baudRate,
	BYTE byteSize,
	BYTE parity,
	BYTE stopBits)
{
	DCB   PortDCB;
	DWORD dwError;

	PortDCB.DCBlength = sizeof (DCB);

	//得到端口的默認設置信息
	GetCommState(hPort, &PortDCB);

	//改變DCB結構設置
	PortDCB.BaudRate = baudRate;		//波特率 
	PortDCB.ByteSize = byteSize;	//每字節的位數 number of bits/byte, 4-8 
	PortDCB.Parity = parity;		//奇偶校驗 0-4=no,odd,even,mark,space 

	PortDCB.StopBits = (stopBits == 2) ? 2 : 0;	//每字節一位停止位 0,1,2 = 1, 1.5, 2 

	//根據DCB結構配置端口 

	if (!SetCommState(hPort, &PortDCB))
	{
		this->close();

		//不能配置串行端口
		dwError = GetLastError();

		char buf[256];
		sprintf(buf, "Unable to configure the serial port err:%d\n", dwError);
		//::MessageBox(NULL, buf, "Err code", MB_OK);

		return FALSE;
	}
	return TRUE;
}

BOOL CCom::InitCommTimeouts()
{
	COMMTIMEOUTS CommTimeouts;
	DWORD dwError;

	//得到超時參數
	GetCommTimeouts(hPort, &CommTimeouts);
	//改變COMMTIMEOUTS結構設置

	CommTimeouts.ReadIntervalTimeout = MAXDWORD;
	CommTimeouts.ReadTotalTimeoutMultiplier = 0;
	CommTimeouts.ReadTotalTimeoutConstant = 0;
	CommTimeouts.WriteTotalTimeoutMultiplier = 10;
	CommTimeouts.WriteTotalTimeoutConstant = 1000;

	//設置端口超時值 
	if (!SetCommTimeouts(hPort, &CommTimeouts))
	{
		this->close();

		//不能設置超時值
		printf("Unable to set the time-out parameters\n");
		dwError = GetLastError();
		return FALSE;
	}

	return TRUE;
}

BOOL CCom::close()
{
	if (hPort != INVALID_HANDLE_VALUE)
	{
		//關閉串口
		CloseHandle(hPort);
		hPort = INVALID_HANDLE_VALUE;

		return TRUE;
	}
	else
	{
		return TRUE;
	}
}

DWORD CCom::read(char * buf, DWORD size)
{
	if (hPort == INVALID_HANDLE_VALUE)
		return 0;

	//從串口讀取數據
	if (!ReadFile(hPort, buf, size, &size, NULL))
	{
		//不能從串口讀取數據
		printf("Error in read from serial port\n");
		size = 0;
	}

	return size;
}

int CCom::readSyn(char *buf, DWORD wCount, DWORD wWaitTickCount)
{
	//讀滿 wCound 個字符
	DWORD nReadCount = 0;

	DWORD wTimeBegin = ::GetTickCount();

	while (nReadCount < wCount)
	{
		int count = read(buf + nReadCount, wCount - nReadCount);
		if (count < 0)
			return -1;

		if (count == 0)
		{
			if (wWaitTickCount > 0 && ::GetTickCount() - wTimeBegin > wWaitTickCount)
				return 0;

			//Sleep(1);
		}
		else
			nReadCount += count;
	}

	return 1;
}

接下來是com.h文件(串口配置頭文件)

#include <windows.h>

class CCom
{
public:
	BOOL open(LPTSTR lpszPortName,
		DWORD baudRate,
		BYTE byteSize,
		BYTE parity,
		BYTE stopBits); //打開串口
	BOOL close(); //關閉串口

	int readSyn(char * buf, DWORD wCount, DWORD wWaitTickCount = 0);
	DWORD read(char * buf, DWORD size);

	DWORD write(TCHAR *buf, DWORD dwBytesToWrite); //寫數據

	CCom();
	virtual ~CCom();

private:
	HANDLE hPort;

	char LineBuf[256];
	DWORD dataLen;

	BOOL InitDCB(DWORD baudRate,
		BYTE byteSize,
		BYTE parity,
		BYTE stopBits); //配置串口
	BOOL InitCommTimeouts(); //設置超時參數
};

工程原本的.c文件。我的工程叫UartComdll。所以這里叫UartComdll.c

// UartComdll.cpp : 定義 DLL 應用程序的導出函數。
//

#include "stdafx.h"
#include "Com.h"
#include <stdio.h>
#include <stdlib.h>
#include "UartCom.h"
#include <string.h>
#include <iostream>
using namespace std;
char* uartbuff;
void delay(unsigned int xms)  // xms代表需要延時的毫秒數
{
	unsigned int x, y;
	for (x = xms; x>0; x--)
	for (y = 110000; y>0; y--);
}
unsigned char Hex_buf[6];                                 //繼電器串口接收緩存
unsigned char MotorHex_buf[100];                          //步進電機
unsigned char i = 0x01;
CCom gCom;
BOOL gbInit = false;
int gCurCom = 0;
TPackaMsg boradMes;


#define MSG_HEAD1 0xFF
#define MSG_HEAD2 0xFE

void UartClose(void)
{
	if (gbInit)
	{
		gCom.close();
		gbInit = false;
	}
}


int UartInit(int nCom)
{
	if (!gbInit || nCom != gCurCom)
	{
		char sNum[8] = { 0 };
		char sComName[16] = "com";
		strcat(sComName, _itoa(nCom, sNum, 10));

		UartClose();

		gbInit = gCom.open(sComName, 115200, 8, 0, 1);
		if (gbInit)
		{
			gCurCom = nCom;
			return 1;
		}
		return -1;
	}

	if (!gbInit)
		return -1;	//打開端口失敗
	return 1;
}




void substring(char *s, char ch1, char ch2, char *substr)
{
	while (*s && *s++ != ch1);
	while (*s && *s != ch2) *substr++ = *s++;
	*substr = '\0';
}


//繼電器串口控制發送函數
int ControlRelaytoUart( unsigned char buf){
	unsigned char index;
	unsigned char checkvalue;
	Hex_buf[0] = 0xff;
	Hex_buf[1] = 0xfe;   //裝載串口一幀數據頭部
	Hex_buf[2] = 0x01;    //板子編號
	Hex_buf[3] = buf;     //繼電器
	Hex_buf[4] = 0xde;  //
	checkvalue = 0;
	for (index = 0; index < 5; index++){ checkvalue ^= Hex_buf[index]; }
	Hex_buf[5] = checkvalue;   //裝載尾部
	gCom.write((TCHAR*)Hex_buf,sizeof(Hex_buf));
	return 1;
}

int ControlRelay(int id, unsigned char controldata){                 //接口調用發數據給串口
	if (id == 1){//id是板子編號
		ControlRelaytoUart(controldata);//進入串口發送數據函數
	}
	return 1;
}
void testrelay(unsigned char num){
	for (i; i < 17; i++){
		ControlRelay(1, num);
		num = num + 0x01;
		delay(10000);
	}
}



接下來就是在工程原本的頭文件編寫了,引出來我們的封裝函數可以被第三方調用。
UartComdll.h

#ifndef _RS232DLL_H_
#define _RS232DLL_H_

#define Uart_API __declspec(dllexport) 

#define player 4

extern "C"   //輸出dll中的接口,為程序所用,也為自己的測試程序所用
{

	Uart_API void UartClose(void);
	Uart_API int UartInit(int nCom);
	Uart_API int ControlRelay(int id, unsigned char controldata);
	Uart_API void testrelay(unsigned char num);
}

#endif

自此,全部完成。我們只需要點擊

就可以得到我們的dll和lib。在你的工程debug目錄下的文件夾中就可以找到,有些是x64的,就要去x64中財可以找到。

至於怎么引用,可以看我下一篇博客。
https://blog.csdn.net/weixin_43673603/article/details/107855147
如果自己根據我的博客配置還不成功的,可能是自己調用的版本問題,注意版本一致, 這個是絕對可以運行成功的,如果實在看不懂,那你花點積分下載我的資源吧,我也救不你。哈哈哈哈~~·
資源地址:點擊下載


免責聲明!

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



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