简单的小工具是VS2015 + Qt5.6.1实现的,界面部分是Qt实现,串口是封装的WinAPI,把串口收发模块封装成了个Serialport.dll 供Qt界面调用。

由于VS2015需要Universal CRT运行环境,因此把Qt编译成了静态的版本。

一、串口收发是封装的Win32,单独封装成了一个Serialport.dll.

包括串口通信类:

class CSerialport
{
public:
CSerialport();
~CSerialport();
BOOL openComm(const string & name);
BOOL closeComm();
BOOL setCommState(const DCB & dcb)const;
BOOL getCommState(DCB & dcb)const;
BOOL setCommTimeouts(const COMMTIMEOUTS & commtimeOuts)const;
BOOL purgeComm(DWORD flags = PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT)const;
BOOL setupComm(DWORD dwInQueue, DWORD dwOutQueue)const;
int readFile(vector<char> & buffer, DWORD nNumberOfBytesToRead,DWORD & lpNumberOfBytesRead, LPOVERLAPPED pLoverlapped = NULL);
int writeFile(vector<char> & buffer, DWORD nNumberOfBytesToRead, DWORD & lpNumberOfBytesRead, LPOVERLAPPED pLoverlapped = NULL);
string getPortName()const;
HANDLE getHandle()const;
//
private:
HANDLE m_hspCom;
string m_commName;
};

此类负责基本的串口通信。

线程类:

 class CBaseThread
{
public:
CBaseThread(void);
virtual ~CBaseThread(void);
public:
virtual void start(); //创建线程
virtual void end(); //结束线程
virtual void resume(); //重启线程
virtual void suspend(); //暂停线程
//
virtual int getThreadID() const; //获得线程ID
virtual BOOL isRun() const; //判断线程是否运行
virtual void runTask() = ; //子类实现此函数完成业务逻辑
//
static unsigned _stdcall threadFunc(void* pParam); //线程函数,调RunTask逻辑 protected:
HANDLE m_hEndEvent; //设置退出线程处理
HANDLE m_hExitEvent; //线程RunTask结束时设置,确保线程正常退出
HANDLE m_hThreadHandle;
unsigned int m_uThreadID;
//
};

线程基类,封装了_beginthreadex()。

串口线程调度线程:

typedef int (*pGET_DATA_CAAL_BACK)(list<char> &);

class CSerialportThread :
public CBaseThread
{
public:
CSerialportThread(void);
virtual ~CSerialportThread(void);
void setCommConfig(const char* com, int baudRate, char byteSize, char parity, char stopBits);
static CSerialportThread * getInstance();
int writeFile(const char * writeBuffer,int size);
void initCallBack(void *);
protected:
virtual void runTask();
void initComm();
protected:
CSerialport m_serialport;
//
string m_com;
int m_baudRate;
char m_byteSize;
char m_parity;
char m_stopBits;
bool m_bInit;
pGET_DATA_CAAL_BACK m_addDataCallBack;
};

继承CBaseThread实现runTask()线程函数,由CSerialport 类成员变量进行串口的通信的管理,并提供一个回调接口,将接收到的数据回调给接收数据维护的类。

串口数据接收维护类:

class CCommDataHolder
{
public:
CCommDataHolder();
~CCommDataHolder();
//
static std::shared_ptr<CCommDataHolder> getInstance();
static int getDataCallBackS(list<char> & buffer); int getCommData(char * buffer,int len);
protected:
int getDataCallBack(list<char> & buffer);
//
private:
static std::shared_ptr<CCommDataHolder> s_pInstance;
static std::mutex s_mt;
//
list<char> m_listData;
std::mutex m_mt;
};

数据维护类,上层应用来这里取数据即可。

Serialport.dll导出接口:

 #pragma once

 #define SERIALPORT_DLL_EXPORT __declspec(dllexport)

 #ifdef __cplusplus
extern "C"
{
#endif // SERIALPORT_DLL_EXPORT int commReadData(char* buffer,int size);
SERIALPORT_DLL_EXPORT int commWriteData(const char* buffer, int size);
SERIALPORT_DLL_EXPORT void setCommConfig(const char* com,int baudRate,char byteSize,char parity,char stopBits);
SERIALPORT_DLL_EXPORT void start();
SERIALPORT_DLL_EXPORT void end(); #ifdef __cplusplus
}
#endif //

二、Qt界面实现

界面实现主要是设置串口的通信的参数,然后设置串口通信的收发区域,这里使用textEdit控件,然后设置了一下数据的展现方式,分ASCII和HEX(16进制发送),

16进制发送的形式应该为: 61 25 AA 7A 5B的这种形式,然后选择Hex选项,发送。

串口列表:自动枚举系统的所有已存在串口enumPort(QStringList & strList)

 void SerialPortTools::enumPort(QStringList & strList)
{
HKEY hKey;
LPCTSTR lpSubKey = _T("HARDWARE\\DEVICEMAP\\SERIALCOMM\\"); if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, lpSubKey, , KEY_READ, &hKey) != ERROR_SUCCESS)
{
return;
}
WCHAR szValueName[] = { };
WCHAR szPortName[] = { };
LONG status;
DWORD dwIndex = ;
DWORD dwSizeValueName = ;
DWORD dwSizeofPortName = ;
DWORD Type;
dwSizeValueName = ;
dwSizeofPortName = ;
do
{
status = RegEnumValue(hKey, dwIndex++, szValueName, &dwSizeValueName, NULL, &Type, (PUCHAR)szPortName, &dwSizeofPortName);
if ((status == ERROR_SUCCESS))
{
QString tmp = CCodecUtils::str2qstr(CEcoder::wstringToString(szPortName));
strList << tmp;
}
dwSizeValueName = ;
dwSizeofPortName = ;
} while ((status != ERROR_NO_MORE_ITEMS));
RegCloseKey(hKey);
}

设置好串口参数,串口号,波特率,数据位,校验位,停止位等参数后setCommConfig(com.c_str(), baudRate, byteSize, parity, stopBit);

,打开串口start();开启调度串口通信线程。

打开串口需要引用Serialport.dll的接口函数

 void SerialPortTools::openPort()
{
QString strCom = ui.comboBox->currentText();
QString strBaudRate = ui.comboBox_2->currentText();
QString strByteSize = ui.comboBox_3->currentText();
//
string com = CCodecUtils::qstr2str(strCom);
int baudRate = strBaudRate.toInt();
int byteSize = strByteSize.toInt();
int parity = ui.comboBox_4->currentIndex();
int stopBit = ui.comboBox_5->currentIndex();
setCommConfig(com.c_str(), baudRate, byteSize, parity, stopBit);
//
start();
m_timer.start();
MessageBoxInfo(tr("提示"), tr(" 串口打开成功 "));
ui.openaction->setEnabled(false);
ui.closeaction->setEnabled(true);
}

数据接收的实现是设置了一个定时器,不断去调用commReadData(char* buffer,int size) 去读取dll数据缓存区的数据,读到之后更新到数据接收区的界面。

发送则很简单,获取数据发送区的内容,点击发送,直接调用commWriteData(const char *buffer,int size)发送串口数据。

定时器:

     m_timer.setInterval();
connect(&m_timer, SIGNAL(timeout()), this, SLOT(reciveData()));

数据收:

 void SerialPortTools::reciveData()
{
char szRead[] = { };
memset(&szRead, , );
int nRet = commReadData(szRead, );
m_strRec = CCodecUtils::qstr2str(ui.textEdit->toPlainText());
if (nRet != )
{
string str = szRead;
m_strRec += str;
if (ui.radioButton->isChecked())
{
ui.textEdit->setText(CCodecUtils::str2qstr(m_strRec));
}
else if (ui.radioButton_2->isChecked())
{
char sz[];
memset(&sz, , );
ui.textEdit->setText(CCodecUtils::str2qstr(CCodecUtils::byte2HexCpp(m_strRec)));
}
}
}

数据发:

 void SerialPortTools::sendData()
{
QString str = ui.textEdit_2->toPlainText();
string strSend = CCodecUtils::qstr2str(str);
if (!strSend.empty())
{
//
if (ui.radioButton_3->isChecked())
{
commWriteData(strSend.c_str(), strSend.length() + );
}
else if (ui.radioButton_4->isChecked())
{
string strtmp = CCodecUtils::hexStr2Str(CCodecUtils::eraseSpace(strSend));
commWriteData(strtmp.c_str(),strtmp.length()+);
//
}
}
}

串口关闭end();

 void SerialPortTools::closePort()
{
end();
ui.openaction->setEnabled(true);
ui.closeaction->setEnabled(false);
}

软件运行:

用虚拟串口工具打开COM1和COM2两个串口对,打开两次SerialPortTools.exe ,分别打开COM1和COM2,进行简单的数据通信测试。

源码地址:https://github.com/karllen/SerialPortTools

VS2015 +Qt5 串口工具的更多相关文章

  1. 【转】 Ubuntu下配置USB转串口及串口工具配置--不错

    原文网址:http://blog.csdn.net/dreambegin/article/details/6985028 注意:默认情况下ubuntu已经安装了USB转串口驱动(pl2303).我的是 ...

  2. 好久没来了,重出江湖,共享个python34+pyqt+pyserial串口工具源码

    真的是好久没来了,写博客对我来说还真是难坚持下来,热度一过就忘了,就算什么时候想起来也懒得去敲一个字,这次真不知道能坚持多久,随心吧,想写写,不想写也不勉强自己. 最近由于工作调试需要自己写了一个带图 ...

  3. VS2015集成新潮工具4

    VS2015集成新潮工具(四)   本课程来源与微软connect视频教程,Modern Web Tooling in Visual Studio 2015 本课程主要讲下当下流行的前端工具 bowe ...

  4. Minicom串口工具安装及配置

    Minicom串口工具安装及配置 1. 简述 嵌入式开发多采用串口线连接电脑进行开发及调试. 2 安装及配置串口工具(以Minicom为例) Tiny4412开发板提供的有RS232电平的DB9公头接 ...

  5. tftp服务、串口工具minicom

    linux下安装tftp服务 参考这位仁兄的经验 确实百度上很多关于配置tftp服务的方法,但是这篇文章的介绍真的是很精简,对于一个刚接触纯linux环境的小白来说是很舒服的一件事. 首先是安装tft ...

  6. Windows下PythonQt编译(vs2015+Qt5.11.2+PythonQt 3.2)探索

    时间:2018年10月20日 笔者最近在做Qt方面的开发工作,需用到脚本程序对程序内部进行扩展,就很自然的想到了PythonQt,下面介绍PythonQt在Windows下的的安装编译心得,水平有限, ...

  7. 通过串口工具下发指令的Python脚本

    前言 最近一段时间在测试物联网相关的App自动化,涉及通过串口工具给硬件设备下发指令. 使用的串口工具:SecureCRT 解决办法 通过引用Python的第三方库:serial,通过编写Python ...

  8. vs2015 qt5.8新添加文件时出现“无法找到源文件ui.xxx.h”

    转载请注明出处:http://www.cnblogs.com/dachen408/p/7147135.html vs2015 qt5.8新添加文件时出现“无法找到源文件ui.xxx.h” 暂时解决版本 ...

  9. 物联网架构成长之路(37)-基于C#开发串口工具

    0. 前言 作为物联网平台开发,最基础的工具链还是要有的.前几篇博客,介绍了用C#开发一个MQTT的客户端,用于模拟设备连接平台,并发送数据到平台.但是对于一些硬件来说,可能会用到串口uart来发送数 ...

随机推荐

  1. 高斯消元法(Gauss Elimination)【超详解&模板】

    高斯消元法,是线性代数中的一个算法,可用来求解线性方程组,并可以求出矩阵的秩,以及求出可逆方阵的逆矩阵.高斯消元法的原理是:若用初等行变换将增广矩阵 化为 ,则AX = B与CX = D是同解方程组. ...

  2. 学习SpringMVC中优秀的代码编写风格

    在org.springframework.web.servlet.FrameworkServlet 中有下面这段代码 private class ContextRefreshListener impl ...

  3. Spring MVC和Struts2的比较

    Spring MVC PK Struts2 我们用struts2时采用的传统的配置文件的方式,并没有使用传说中的0配置.spring3 mvc可以认为已经100%零配置了(除了配置spring mvc ...

  4. Java操作PDF之iText超入门

    iText是著名的开放项目,是用于生成PDF文档的一个java类库.通过iText不仅可以生成PDF或rtf的文档,而且可以将XML.Html文件转化为PDF文件. http://itextpdf.c ...

  5. java虚拟机学习-慢慢琢磨JVM(2)

    1 JVM简介 JVM是我们Javaer的最基本功底了,刚开始学Java的时候,一般都是从“Hello World”开始的,然后会写个复杂点class,然后再找一些开源框架,比如Spring,Hibe ...

  6. Java 多线程详解(五)------线程的声明周期

    Java 多线程详解(一)------概念的引入:http://www.cnblogs.com/ysocean/p/6882988.html Java 多线程详解(二)------如何创建进程和线程: ...

  7. js循环给li绑定事件实现 点击li弹出其索引值 和内容

    代码如下: html代码 <ul> <li>房产</li> <li>家居</li> <li>二手房</li> < ...

  8. [机器学习实践] 针对Breast-Cancer数据集

    本篇博客中,我们将对一个UCI数据库中的数据集:Breast-Cancer数据集,应用已有的机器学习方法来实现一个分类器. 本文代码链接 数据集概况 数据集的地址为:link 在该页面中,可以进入Da ...

  9. hdu3622

    hdu3622 题意 每回合给定两个坐标点,可以选择一个放置炸弹,自己决定炸弹的半径,问 n 个回合后,使炸弹半径最小值最大. 分析 存在对立关系:每回合只能选择一个地方放置炸弹.i 表示 第一个位置 ...

  10. 每天一个JS 小demo之“随机”抽奖。主要知识点:Math函数,数组方法,递归

    <!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"& ...