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
如果自己根据我的博客配置还不成功的,可能是自己调用的版本问题,注意版本一致, 这个是绝对可以运行成功的,如果实在看不懂,那你花点积分下载我的资源吧,我也救不你。哈哈哈哈~~·
资源地址:点击下载

posted @ 2020-10-24 16:04  jee-cai  阅读(733)  评论(0编辑  收藏  举报