一个简单得异步串口类

学习笔记之----在Qt下的串口读写       Tags:  linux Qt 串口        这几天一直纠结于Qt下的串口读写,我把疑问和解决过程陆续记录下来,怕以后忘记了嘿嘿。 欢迎大家一起学习分享经验,但是禁止抄袭呀!       因为Qt没有提供给我们现成的串口类,在Qt下想实现串口读写操作,有两种办法:       1.自定义串口类       通常我们都是使用写好的第三方串口类,当然了有linux下与window下两个版本,我是做Linux下开发的,所以这里就先提供Linux下的串口类资源,网上相关的资源很多很多,baidu 阅读详情

/*
一个简单异步串口类(WIN32),这个是我自己一直使用得串口类

这个异步类只实现了一些简单功能。在使用时候需要注意下面几点:
1。串口得相关参数需要在open之前设置好,打开之后,就不能设置了
2。读取串口数据采取查询方式
3。向串口发送数据函数得执行需要一定得时间,知道成功它才返回。
4。默认是没有硬件握手得,如果要握手,需要调用函数setflowctrl
5。串口波特率直接传递数值就可以,比如9600。
如果有问题,请与我联系。Email:stevecrise@163.com
优快云上帐号:stevecrisewu(月亮骑士)

说明:
1。发送数据用write函数,直到成功才返回(如果没有其他错误的话)
2。读取数据用read函数,能够立刻返回,需要你定时去调用。当然,你也可以用消息通知的办法,你可以创建一个线程来给你的应用程序发送消息。
3。获取线控状态函数用getlstatus函数,如下示就可以返回DSR,CTS,RI和CD的线的状态。
      value=getlstatus();
     DSR=value&S_DSR;
     CTS=value&S_CTS;
     RI=value&S_RI;
     CD=value&S_CD;
*/
#include <windows.h>

/* MODEM CONTROL setting */
#define C_DTR  0x01
#define C_RTS  0x02

/* MODEM LINE STATUS */
#define S_CTS  0x01
#define S_DSR  0x02
#define S_RI  0x04
#define S_CD  0x08

#define SIO_OK  0
#define SIO_ERROR -1 

class CAsynComm 
{
public:
 //构造函数
 CAsynComm();
 //析构函数
 virtual ~CAsynComm();
protected:
 //串口号
 volatile int nPort; 
 //串口句柄
 volatile HANDLE ComHandle;
 //DCB结构
 DCB MyDcb;  
 //输入输出缓冲区大小
 int InbufSize, OutbufSize;
 //超时参数
 COMMTIMEOUTS coTimeOut;
 //OVERLAPPED结构
 OVERLAPPED ro,wo;
 //初始化函数
 void Init();
 //判断串口是否打开函数
 bool IsOpen(); 
public:
 //从串口读取一个字符,返回SIO_ERROR表示失败,否则为0-255之间的一个数
 int getch();
 //向串口写一个字符,返回SIO_ERROR表示失败,SIO_OK表示成功写入
 int putch(char ch);
 //从串口读取len个字符并放到缓冲区buf中,返回SIO_ERROR表示失败,否则返回实际读取的字符数
 int read(char *buf, int len);
 //向串口写入len个字符,返回SIO_ERROR表示失败,否则返回实际写入串口的字符数
 int write(char *buf, int len);    
 //关闭串口
 int close();
 //打开串口,port为串口号,默认打开9600,n,8,1,无硬件握手
 virtual int open(int port);
 //设置串口通信参数
 int setsetting(int BaudRate, int ByteSize = 8, int Parity = NOPARITY, int StopBits = ONESTOPBIT);
 //设置硬件握手
 int setflowctrl();
 //读取控制线状态
 int getlstatus();
 //设置DTR状态
 int setdtr(bool enable);
 //设置RTS状态
 int setrts(bool enable);
 //设置超时时间
 int settimeout(unsigned long ulTimeOut);
 //设置输入输出缓冲区大小函数
 int setiosize(int isize,int osize);
};

cpp文件如下:

#include "AsynComm.h"
//初始化串口
CAsynComm::CAsynComm()
{
 Init(); 
}

//关闭串口并释放资源
CAsynComm::~CAsynComm()
{
 close();
 if(ro.hEvent != INVALID_HANDLE_VALUE)
  CloseHandle(ro.hEvent);

 if(wo.hEvent != INVALID_HANDLE_VALUE)
  CloseHandle(wo.hEvent); 
}

//初始化函数
void CAsynComm::Init()
{
 memset(&MyDcb, 0, sizeof(MyDcb));
 MyDcb.DCBlength = sizeof(MyDcb);
 
 MyDcb.BaudRate = 9600;  //通信速率
 MyDcb.ByteSize = 8;  //比特位 
 MyDcb.Parity   = NOPARITY; //奇偶校验位
 MyDcb.StopBits = ONESTOPBIT; //停止位
 
 ComHandle = INVALID_HANDLE_VALUE; //初始化为无效句柄
 
 InbufSize = 8192;  //默认输入缓冲为8k
 OutbufSize = 8192;  //默认输出缓冲为8k
 memset(&coTimeOut, 0, sizeof(coTimeOut)); //定义超时,默认为5秒
 coTimeOut.ReadIntervalTimeout = 0xFFFFFFFF;
 coTimeOut.ReadTotalTimeoutMultiplier = 0;
 coTimeOut.ReadTotalTimeoutConstant = 0;
 coTimeOut.WriteTotalTimeoutMultiplier = 0;
 coTimeOut.WriteTotalTimeoutConstant = 5000;
 
 memset(&ro, 0, sizeof(ro));  //读入时候得重叠结构
 memset(&wo, 0, sizeof(wo));  //写入时候得重叠结构
 ro.hEvent = CreateEvent(NULL, true, false, NULL); 
 wo.hEvent = CreateEvent(NULL, true, false, NULL);  
}

//返回TRUE表示串口处于open状态
bool CAsynComm::IsOpen()
{
 return (ComHandle!=INVALID_HANDLE_VALUE); 
}

//关闭串口
int CAsynComm::close()
{
 if(IsOpen()) CloseHandle(ComHandle);   
 ComHandle = INVALID_HANDLE_VALUE;
 return SIO_OK; 
}

//异步读函数
//buf为用户提供得暂存缓冲区,len为缓冲区大小
//函数返回SIO_ERROR表示读取失败,原因可能是串口没有打开等
//函数返回非负数表示成功读取得字节数
int CAsynComm::read(char *buf, int len)
{
 if(!IsOpen()) return SIO_ERROR; //串口没有打开
 memset(buf,0,len);

 COMSTAT  stat;
 DWORD error;

 if(ClearCommError(ComHandle, &error, &stat) && error > 0)  //清除错误
 {
  PurgeComm(ComHandle, PURGE_RXABORT | PURGE_RXCLEAR);
  return SIO_ERROR;
 }
 if(!stat.cbInQue) return SIO_ERROR;  //如果缓冲区没有数据,直接返回

 unsigned long count = 0;
 len = min((int)(len - 1), (int)stat.cbInQue);  //取缓存中得实际数据和len得最小值

 if(!ReadFile(ComHandle, buf, len, &count, &ro))  //如果调用失败,则看错误类型,count包含了读取得实际字节
 {
  if(GetLastError() == ERROR_IO_PENDING)   
  {
   if(!GetOverlappedResult(ComHandle, &ro, &count, false))
   {
    if(GetLastError() != ERROR_IO_INCOMPLETE) count = 0;
   }
  }
  else
   count = 0;
 }   
 
 if(count>0) 
 {
  buf[count] = '/0'; 
  return count; 
 }
 return SIO_ERROR;
}

//从缓冲区中读取一个字节函数
int CAsynComm::getch()
{
 if(!IsOpen()) return SIO_ERROR; //串口没有打开
 COMSTAT  stat;
 DWORD error;
 char buf[2];

 if(ClearCommError(ComHandle, &error, &stat) && error > 0)  //清除错误
 {
  PurgeComm(ComHandle, PURGE_RXABORT | PURGE_RXCLEAR);
  return SIO_ERROR;
 }
 if(!stat.cbInQue) return SIO_ERROR;  //如果缓冲区没有数据,直接返回
 unsigned long count = 0; 

 if(!ReadFile(ComHandle, buf, 1, &count, &ro))  //如果调用失败,则看错误类型,count包含了读取得实际字节
 {
  if(GetLastError() == ERROR_IO_PENDING)
  {
   if(!GetOverlappedResult(ComHandle, &ro, &count, false))
   {
    if(GetLastError() != ERROR_IO_INCOMPLETE) count = 0;
   }
  }
  else
   count = 0;
 }   
 
 if(count>0) 
 {  
  return ((int)(buf[0])); 
 }
 
 return SIO_ERROR;
}

//异步写函数
//buf为需要写入得数据缓冲区,len为其长度
//返回SIO_ERROR表示写入失败,否则返回实际写入得字节数
//在这里,我们采取了超时机制,知道数据成功写入才返回,超时时间可以用函数settimeout设置
int CAsynComm::write(char *buf, int len)
{
 if(!IsOpen()) return SIO_ERROR;  //串口没有打开

 if(buf==NULL) return SIO_ERROR;
 DWORD    error;
 
 if(ClearCommError(ComHandle, &error, NULL) && error > 0) //清除错误
 {
  PurgeComm(ComHandle, PURGE_TXABORT | PURGE_TXCLEAR); 
 }
 
 unsigned long count = 0;
 unsigned long value=0;
 if(!WriteFile(ComHandle, buf, len, &count, &wo))  //如果调用失败,则看错误类型
 {
  value=GetLastError();
  if(value != ERROR_IO_PENDING) count = 0;  //如果非ERROR_IP_PENDING,则返回错误
  else
  {
   if(!GetOverlappedResult(ComHandle, &wo, &count, TRUE))
   {
    if(GetLastError() != ERROR_IO_INCOMPLETE) count = 0;
   }
  }
 }
 if(count>0) return count;
 return SIO_ERROR;
}

//向缓冲区写一个字节函数
int CAsynComm::putch(char ch)
{
 if(!IsOpen()) return SIO_ERROR; //串口没有打开
 
 DWORD    error;
 char buf[2];
 
 if(ClearCommError(ComHandle, &error, NULL) && error > 0)  //清除错误
 {
  PurgeComm(ComHandle, PURGE_TXABORT | PURGE_TXCLEAR); 
 }
 
 buf[0]=ch;
 buf[1]=0;
 
 unsigned long count = 0;
 
 if(!WriteFile(ComHandle, buf, 1, &count, &wo))  //如果调用失败,则看错误类型
 {
  if(GetLastError() != ERROR_IO_PENDING) count = 0;
  else
  {
   if(!GetOverlappedResult(ComHandle, &wo, &count, TRUE))
   {
    if(GetLastError() != ERROR_IO_INCOMPLETE) count = 0;
   }
  }
 }
 if(count>0) return SIO_OK;
 return SIO_ERROR;
}

//串口打开函数,只需要指定端口号就可以
//对于串口得基本参数,系统默认采取9600,n,8,1和无硬件握手
//如果希望调整参数,请打开串口之前调用setsetting,settimeout,setflowctrl,setiosize等函数
int CAsynComm::open(int port)
{
 if(port>1024 || port<1) return SIO_ERROR;  //非法端口号
 
 if(IsOpen()) close();    //如果已经打开,则关闭
 nPort = port;
 char str[10];
 
 if(ro.hEvent==INVALID_HANDLE_VALUE || wo.hEvent==INVALID_HANDLE_VALUE) return SIO_ERROR; 
 strcpy(str, "COM");
 ltoa(port, str + 3, 10);
 ComHandle = CreateFile(    //打开串口
   str,
   GENERIC_READ | GENERIC_WRITE,
   0,
   NULL,
   OPEN_EXISTING,
   FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,  //重叠标志
   NULL
   );
 if(!IsOpen()) return SIO_ERROR;  //打开失败,直接返回
  
 SetupComm(ComHandle, InbufSize, OutbufSize); //设置缓冲区大小
 SetCommState(ComHandle, &MyDcb);  //设置通信参数 
 SetCommTimeouts(ComHandle, &coTimeOut);  //设置超时
 PurgeComm(ComHandle, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR ); //清除错误
 
 return SIO_OK; 
}

//设置通信参数
//不允许在串口打开之后还可设置
//BaudRate为通信速率,如9600,19200,38400等,传递时候可直接传递数值
int CAsynComm::setsetting(int BaudRate, int ByteSize, int Parity, int StopBits)
{
 if(IsOpen()) return SIO_ERROR;
 
 MyDcb.BaudRate = BaudRate;
 MyDcb.ByteSize = ByteSize;
 MyDcb.Parity   = Parity;
 MyDcb.StopBits = StopBits;
 
 return SIO_OK;
}

//设置超时时间
//不允许在串口打开之后还可设置
int CAsynComm::settimeout(unsigned long ulTimeOut)
{
 if(IsOpen()) return SIO_ERROR; 
 coTimeOut.WriteTotalTimeoutConstant = ulTimeOut;
 return SIO_OK;
}

//设置硬件握手,流量控制
//不允许在串口打开之后还可设置
int CAsynComm::setflowctrl()
{
 if(IsOpen()) return SIO_ERROR; 
 MyDcb.fOutxCtsFlow=TRUE;
 MyDcb.fRtsControl=TRUE;
 return SIO_OK;
}

//获取线路状态
int CAsynComm::getlstatus()
{
 DWORD  dwEvtmask; 
 int ret=0;
 if(!IsOpen()) return SIO_ERROR; 

 if(GetCommModemStatus(ComHandle,&dwEvtmask)==0)
 {
  return SIO_ERROR;
 }
 ret=dwEvtmask; 
 return ret;
}

//设置DTR线状态
int CAsynComm::setdtr(bool enable)
{
 if(!IsOpen()) return SIO_ERROR;
 
 DWORD data=CLRDTR; 
 if(enable)data=SETDTR;
 if(EscapeCommFunction(ComHandle,data))return SIO_OK;
 return SIO_ERROR;
}

//设置RTS线状态
int CAsynComm::setrts(bool enable)
{
 if(!IsOpen()) return SIO_ERROR;
 
 DWORD data=CLRRTS; 
 if(enable)data=SETRTS;
 if(EscapeCommFunction(ComHandle,data))return SIO_OK;
 return SIO_ERROR;
}

//设置缓冲区参数函数
//不允许在串口打开之后还可设置
int CAsynComm::setiosize(int isize,int osize)
{
 if(IsOpen()) return SIO_ERROR;
 if(isize<=0) return SIO_ERROR;
 if(osize<=0) return SIO_ERROR;
 InbufSize = isize;
 OutbufSize = osize;
 return SIO_OK;
}

SpringBoot-15-多表查询之多对多查询可选中间表 多对多查询,一个用户可以有多个角色,一个角色可以有多个用户。需要使用中间表,但不是必要的,如果宽表中已经包含了这种对应关系的话,就没必要使用中间表了。 阅读详情

相关推荐

Angular 相关的知识点和项目汇总

Angular 知识点和项目汇总

weixin_45428910的博客 578

C++串口同步和异步的读取与串口设备编程

本文主要讲述如何对串口进行高效率的读写,当串口中数据到达时立即读取进行处理,以及如何将该方法运用到串口设备编程中。为了使得程序更加清晰文中的代码去除了异常处理的情况。文中加粗的文字相应的比较重要,需要多注意。当然文中会有错误,欢迎评论指正。文章中代码下载地址 http://pan.baidu.com/s/1pLsP9wB1、COM口WindowsAPI函数CreateFile("COM1", .....

Wlk1229 2万+

VTK四视图联动避坑指南:解决vtkImagePlaneWidget窗宽窗位同步与切片序号更新的那些坑

本文详细解析了VTK四视图联动开发中的关键技术点与常见问题,包括切片位置同步、窗宽窗位同步的实现原理及回调机制设计。针对开发中遇到的回调事件不触发、渲染性能低下等问题,提供了实用的解决方案和优化技巧,帮助开发者高效构建医学影像和科学可视化应用。

weixin_42638178的博客 392

C# 串口通讯 异步读写

串口通讯中异步读写代码。

malaopang的博客 753

使用STM32微控制器实现光电传感器的接口和数据处理

本文将介绍如何使用STM32微控制器实现光电传感器的接口和数据处理的方案,包括硬件设计、引脚配置、数据采集、滤波和阈值判断等关键步骤,并给出相应的代码示例。本文将介绍如何使用STM32微控制器实现光电传感器的接口和数据处理的方案,包括硬件设计、引脚配置、数据采集、滤波和阈值判断等关键步骤,并给出相应的代码示例。在光电传感器的接口和数据处理的实现过程中,要关注系统的性能。在使用STM32微控制器实现光电传感器的接口和数据处理之前,需要设计一个合适的硬件平台。

weixin_66608063的博客 3203

从ORCAP-1589警告看Cadence ORCAD的DRC设置:如何避免‘网络别名’引发的潜在短路风险

本文深入解析Cadence ORCAD中ORCAP-1589警告的深层含义,探讨网络别名可能引发的短路风险及DRC设置优化方案。通过分析网络别名的设计意图、DRC规则配置及最佳实践,帮助工程师有效规避设计风险,提升电路设计的可靠性和规范性。

weixin_34194829的博客 297

串口异步读写

#pragma once#include #include typedef UINT lpCallBack (LPVOID lpParam);class BaseComm{public: BaseComm(void); virtual ~BaseComm(void); // 打开串口  // 输入: pPort - 串口名称或设备路径,可用"COM1" //       nBau

xiaodan007的专栏 8164

SAP MTO模式实战:从库存管理到成本核算的深度解析

本文深入解析SAP MTO(Make-to-Order)模式在制造业中的应用,从库存管理到成本核算的全流程实战技巧。通过对比MTS模式,详细阐述MTO的核心逻辑、库存管理配置、成本核算路径及与PP模块的集成要点,帮助企业实现按单生产的高效管理,优化库存水平和资金占用。

weixin_29204205的博客 709

Qt实战---多线程的串口接收类QSerialPort

Qt | QSerialPort、QTcpSocket等QIODevice设备的跨线程调用报错解决办法以及多线程的使用

qq_39262215的博客 1万+

基于 FastAPI + LangGraph + LLM 大语言模型的通用 Agent 多智能体系统架构设计与开发实战、产业应用

FastAPI是一个现代、快速(高性能)的Python Web框架,专门用于构建API。它由Sebastián Ramírez(@tiangolo)创建,基于Starlette(用于Web部分)和Pydantic(用于数据部分)构建。性能优先:FastAPI是当前最快的Python Web框架之一,性能与NodeJS和Go相当。这得益于其基于Starlette的异步架构,能够充分利用Python 3.6+的async/await特性。开发效率。

AI天才研究院 231

万字详解YOLOv8网络结构Backbone/neck/head以及Conv、Bottleneck、C2f、SPPF、Detect等模块

YOLOv8是由Ultralytics开发的最先进的目标检测模型,推升了速度、准确性和用户友好性的界限。YOLO这一缩写代表“你只看一次”(You Only Look Once),通过在一次网络传递中同时预测所有边界框,提升了算法的效率和实时处理能力。相比之下,其他一些目标检测技术需要经过多个阶段或过程来完成检测。YOLOv8在流行的YOLOv5架构上进行了扩展,在多个方面提供了改进。

专注于图像领域,主要研究内容包括计算机视觉和深度学习,特别是在图像分类、目标检测和图像生成等方面有深入的研究和实践经验。 14万+

WinCE串口编程API函数

1.打开串口 HANDLE CreateFile(      LPCTSTR lpFileName,      DWORD dwDesiredAccess,      DWORD dwShareMode,      LPSECURITY_ATTRIBUTES lpSecurityAttributes,      DWORD dwCreationDisposition,  

tanzhongqiao的专栏 1091

【AUTOSAR SystemServices】AUTOSAR CP中Watchdog Manager模块技术解析

本文深入解析了AUTOSAR中的Watchdog Manager模块实现。该模块通过多层次监督机制(Alive/Deadline/Logical Supervision)确保系统安全运行,具备动态模式切换和分级故障处理能力。 关键实现包括: 数据结构设计:包含监督实体状态结构体(实时状态维护)、监督配置结构体(支持模式切换)和全局状态信息(系统级监控) 核心流程优化:初始化采用事务性设计,检查点处理通过条件编译优化,主监控循环采用流水线式并行处理 监督机制实现:Alive监督采用滑动窗口算法,Deadlin

1039

【MyBatis】多对多条件下插入中间表(使用insert标签的属性)

文章目录需求解决方案测试编写Dao层Service层Test类 需求 我的数据库中有两张表,一张是Blog表,一张是Type表,分别代表了博客和博客类别,它们之间是多对多关系,它们由一张中间表blog_type维护。 (简单起见,blog表只有两个数据,id和title。type表只有id和name) 那么需求就是: 现在我想插入一条Blog数据,因为blog和type是多对多关系,想插入其中一个数据,就得维护他们之间那个中间表blog_type的关系(插入中间表字段)。 解决方案 那么我能想到的解决方案

大吉的博客 2237

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

【MySQL用法】MyBatis 多对多 中间表插入数据,添加记录后获取主键ID

1、需求内容 有一个很常见的需求,即添加记录后获取添加后的主键ID,特别是在一次前端调用中需要插入多个表的场景。除了添加单条记录时获取主键值,有时候可能需要获取批量添加记录时各记录的主键值,MyBatis从3.3.1版本开始支持批量添加记录并返回各记录主键字段值。 比如我在做这个员工管理系统的时候,由于user和role是多对多关系,且user主键是自增的,所有我们没办法提前知晓这个user_...

No8g攻城狮的博客 4143

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

Java-08 深入浅出 Mybatis 数据库多对多关系设计:中间表、映射与性能优化

本文是数据库多对多关系设计的实战指南,涵盖从中间表创建到MyBatis高级映射的完整链路。内容包括学生与课程、用户与角色、商品与标签等典型多对多场景分析,MyBatis resultMap中collection标签的配置方法(ofType、property映射),中间表索引优化策略,避免N+1查询的JOIN方式,Redis缓存应用,以及分表分库方案。适用于Java后端开发者在设计权限系统、内容管理系统或电商商品标签等业务场景时参考。

谢谢你的喜欢 我们一起无限进步 3788

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

hibernate之多对多映射操作中间表

hibernate之多对多映射操作中间表

cst_code的博客 8004

15.Hibernate 多对多关联映射

本节课,咱们一起继续聊聊多对多关联映射。多对多关联映射的实现;双向多对多关联映射的实现。

这是一个web全栈开发的博客,取其精华去其糟粕,争取让大家一看就懂,一学就会,一用就成~ 1797

jpa多对多+中间表的查询,删除,添加

jpa多对多+中间表的查询,删除,添加 实体类数据库如下: 表单类 资产类 中间表:为双主键模式,head_id为表单

weixin_45631100的博客 4085

hibernate 多对多只删除中间表数据

首先配置表的多对多映射 具体方法参见《深入浅出hibernate》  下面列出删除中间表数据的方法  role跟Program 是多对多关系  Java代码   Role role = get(roleId);            for(Long programId : programIds){               Program p = get(Pro

haylee的专栏 6707

多对多中间表的不使用联合主键,自己持有Id

问题是这样的 在ORACLE数据库中存在一个多对多的的关系,即LinkManage(链接表),Organ(机构表),中间建有一个中间表LinkOrgan(链接-机构表),中间表不仅持有多方的ID为外键,并且有自己的Id属性(不是联合主键),还有自己的Status(状态)属性,CreatTime(创建时间),UpdateTime(更新时间)之类的属性。        单纯的在多对多方建立关系,在保

hexi_sijin的专栏 4096

SpringData Manytomany 中间表添加额外字段

SpringData Manytomany 中间表添加额外字段Course跟user是两张多对多关联表添加中间表实体类,表名跟多对多插入的中间表一致说明参数说明 Course跟user是两张多对多关联表 //省略部分不相关代码以及getter跟setter /** * 课程列表 */ @ApiModelProperty(hidden = true) //放弃延时加载,改为立即加载 @ManyToMany(cascade = CascadeType.PERSIST) @JoinTable(name =

a1787882124的博客 3010

Qt-creaderasync-cwriteasync-异步串口接发

不知道为啥这么说,感觉就是吧Qserial类实例化传入另一个类中,这个类有一个定时器timer? creaderasync.cc #include "serialportreader.h" #include <QCoreApplication> QT_USE_NAMESPACE SerialPortReader::SerialPortReader(QSerialPort *serialPort, QObject *parent) : QObject(parent) , m_

南北粉面馆 307

QT多线程串口开发总结

QT多线程串口开发总结 1、优势 使用多线程技术可以充分发挥CPU的性能,我们在主线程上面绘制UI和一些简单的工作(信号之间的传递等等)、在子线程中完成庞大数据的处理。 2、串口类构建 在串口类中封装串口的一系列接口函数。串口的初始化函数、接收缓冲区数据...

zj490044512的博客 1346

Qt QSerialPort串口通信

QSerialPort串口通信的使用

搬砖 7114

MFC基于API写的串口通信

程序流程:打开串口——>发送数据——>接收数据——>关闭串口 第一步打开串口按钮 void CSerialAssistantDlg::OnBnClickedButtonOpenSerial() { // TODO: 在此添加控件通知处理程序代码 CString CButtonOpenText;// 定义字符串,用于存储获取的编辑框文本 GetDlgItemText(IDC_BUTTON_OPEN_SERIAL, CButtonOpenText); //获取给发...

qq_43675859的博客 2993
上一篇: QQ2004的Rich句柄查找方法以及尾巴病毒的实现
stevecrisewu
博客等级 码龄25年 1粉丝 4原创
评论 6
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值