• 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]!
    ", 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
    ");
    		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
    ", 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
    ");
    		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
    ");
    		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 = '';
    }
    
    
    //继电器串口控制发送函数
    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
    如果自己根据我的博客配置还不成功的,可能是自己调用的版本问题,注意版本一致, 这个是绝对可以运行成功的,如果实在看不懂,那你花点积分下载我的资源吧,我也救不你。哈哈哈哈~~·
    资源地址:点击下载

    一键三连呀!
  • 相关阅读:
    每日英语:Apple's Latest iPhone Puts Focus Back on Fingerprint Security
    每日英语:Stressed at Work? Reflect on the Positive
    每日英语:Hold On: Reasons For Never Giving Up Your Dream
    每日英语:China's New Anti-Graft Website: A Tale of Tigers, Flies and Bath Tubs
    每日英语:China Overtakes U.S. in Number of Diabetes Cases
    每日英语:New Reason To Get The Kids To Bed On Time
    每日英语:Why Are Items Pricier in China?
    每日英语:Burning Question / Does Reading In Dim Light Hurt Your Eyes?
    每日英语:Genetic Manipulation Extends Life of Mice 20%
    架构设计之Spring-Session分布式集群会话管理
  • 原文地址:https://www.cnblogs.com/jee-cai/p/14095322.html
Copyright © 2020-2023  润新知