vs串口读写dll封装C++#(免费源码分享)
一、首先。老规矩。配置好自己的vs环境和建立一个dll工程。
我的环境:
- vs2013
- 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
如果自己根据我的博客配置还不成功的,可能是自己调用的版本问题,注意版本一致, 这个是绝对可以运行成功的,如果实在看不懂,那你花点积分下载我的资源吧,我也救不你。哈哈哈哈~~·
资源地址:点击下载
一键三连呀!