前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >windows下的串口编程,串口操作类封装

windows下的串口编程,串口操作类封装

作者头像
杨永贞
发布于 2022-06-09 09:58:03
发布于 2022-06-09 09:58:03
2.6K00
代码可运行
举报
运行总次数:0
代码可运行

以往都是在嵌入式设备中经常操作串口,或者使用QT的串口类。在Win32中处理串口也是有办法的,操作文件的打开和读写进行串口的操作。使用ReadFile、WriteFile函数。

基本步骤

使用Win32文件方式操作:打开串口(创建文件)->配置参数->发送(写文件)-->接收(读文件)

打开串口

打开串口的第一步是初始化或设置串口配置,目的是创建串口代理,整篇文章我们都将用文件句柄作为串口代理。

  • 创建端口句柄
  • 获取配置(DCB)
  • 修改配置
  • 保存配置
  • 设置通讯超时

创建端口句柄 串口句柄是可以被用来存取的串口对象句柄,创建串口句柄的函数是CreateFile,如下代码所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
handlePort_ = CreateFile(portName, // 端口设备: 默认 "COM1" 
GENERIC_READ | GENERIC_WRITE, // 设备打开模式: 允许读写 
0, // 不共享 
NULL, // 默认安全设置 
OPEN_EXISTING, // 打开方式:打开已经存在的端口 
0, // 默认 NULL
); // 默认

这其中需要注意的是:portName是个LPCSTR类型,需要注意字符编码。直接用c++的m_portName.c_str()即可。若是UNICODE的字符串,则需要转换下wchar to char。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
std::wstring ansi2Wchar(LPCSTR pszSrc, int nLen)
{
  int nSize = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pszSrc, nLen, 0, 0);
  if (nSize <= 0)
    return NULL;

  WCHAR* pwszDst = new WCHAR[nSize + 1];
  if (NULL == pwszDst)
    return NULL;

  MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pszSrc, nLen, pwszDst, nSize);
  pwszDst[nSize] = 0;

  if (pwszDst[0] == 0xFEFF)  // skip 0xFEFF
    for (int i = 0; i < nSize; i++)
      pwszDst[i] = pwszDst[i + 1];

  std::wstring wcharString(pwszDst);
  delete[] pwszDst;
  pwszDst = nullptr;

  return wcharString;
}

以下为打开串口的封装:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
bool WindowsSerialPort::openCom()
{
  bool open = false;

#ifdef _WIN32

  DCB dcb;
  SecureZeroMemory(&dcb, sizeof(DCB));

  auto comName = ansi2Wchar(m_portName.c_str(), m_portName.size());
#ifdef UNICODE
  wchar_t* buffer = new wchar_t[m_portName.size()];
  MultiByteToWideChar(CP_ACP, 0, m_portName.c_str(), m_portName.size(), buffer, m_portName.size() * sizeof(wchar_t));
  buffer[m_portName.size()] = 0;
  m_port = ::CreateFile(buffer, GENERIC_WRITE | GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING, NULL);
  delete[] buffer;
  buffer = NULL;
#else
  m_port = ::CreateFile(m_portName.c_str(), GENERIC_WRITE | GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
                        NULL);
#endif

  if (m_port == INVALID_HANDLE_VALUE)
  {
    open = false;
    LOGGING_ERROR("%s is invalid", m_portName.c_str());
    m_port = INVALID_HANDLE_VALUE;

    return open;
  }

  if (!GetCommState(m_port, &dcb))
  {
    open = false;
    LOGGING_ERROR("%s cannot get status", m_portName.c_str());
    m_port = INVALID_HANDLE_VALUE;

    return open;
  }

  dcb.BaudRate = m_baud;
  dcb.ByteSize = 8;
  dcb.fParity = NOPARITY;
  dcb.Parity = NOPARITY;
  dcb.StopBits = 0;
  dcb.fInX = 0;
  dcb.fOutX = 0;
  dcb.fOutxCtsFlow = 0;
  dcb.fRtsControl = 0;
  auto err = SetCommState(m_port, &dcb);
  if (!err)
  {
    open = false;

    LOGGING_ERROR("%s cannot set comm status", m_portName.c_str());
    m_port = INVALID_HANDLE_VALUE;

    return open;
  }

  COMMTIMEOUTS timeout;
  memset(&timeout, 0, sizeof(timeout));
  GetCommTimeouts(m_port, &timeout);
  // TODO: 可能需要根据实际情况调整该参数
  timeout.ReadTotalTimeoutConstant = 50;
  timeout.ReadIntervalTimeout = 10;
  SetCommTimeouts(m_port, &timeout);

  open = true;

#endif

  return open;
}

COMMTIMEOUTS 含义

COMMTIMEOUTS主要用于串口超时参数设置。

COMMTIMEOUTS结构如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
typedef struct _COMMTIMEOUTS { 
DWORD ReadIntervalTimeout;  //间隔超时
DWORD ReadTotalTimeoutMultiplier; 
DWORD ReadTotalTimeoutConstant; 
DWORD WriteTotalTimeoutMultiplier; 
DWORD WriteTotalTimeoutConstant; 
} COMMTIMEOUTS,*LPCOMMTIMEOUTS;

间隔超时 =  ReadIntervalTimeout 总超时   =   ReadTotalTimeoutMultiplier   * 字节数   +   ReadTotalTimeoutConstant

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// COMMTIMEOUTS对象 COMMTIMEOUTS comTimeOut; 
// 接收时,两字符间最大的时延 
comTimeOut.ReadIntervalTimeout = 3; 
// 读取每字节的超时 
comTimeOut.ReadTotalTimeoutMultiplier = 3; 
// 读串口数据的固定超时 // 总超时 = ReadTotalTimeoutMultiplier * 字节数 ReadTotalTimeoutConstant 
comTimeOut.ReadTotalTimeoutConstant = 2; 
// 写每字节的超时 
comTimeOut.WriteTotalTimeoutMultiplier = 3; 
// 写串口数据的固定超时 
comTimeOut.WriteTotalTimeoutConstant = 2; 
// 将超时参数写入设备控制 
SetCommTimeouts(handlePort_,&comTimeOut);

ReadIntervalTimeout 指定通讯线上两个字符到达的最大时延,以毫秒为单位。在ReadFile操作期间,时间周期从第一个字符接收到算起。如果收到的两个字符之间的间隔超过该值,ReadFile操作完毕并返回所有缓冲数据。如果ReadIntervalTimeout为0,则该值不起作用。 如果值为MAXDWORD, 并且ReadTotalTimeoutConstant和ReadTotalTimeoutMultiplier两个值都为0, 则指定读操作携带已经收到的字符立即返回,即使没有收到任何字符。 ReadTotalTimeoutMultiplier 指定以毫秒为单位的累积值。用于计算读操作时的超时总数。对于每次读操作,该值与所要读的字节数相乘。 ReadTotalTimeoutConstant 指定以毫秒为单位的常数。用于计算读操作时的超时总数。对于每次读操作,ReadTotalTimeoutMultiplier与所要读的字节数相乘后与该值相加。 如果ReadTotalTimeoutMultiplier和ReadTotalTimeoutConstant都为0,则在读操作时忽略总超时数。 WriteTotalTimeoutMultiplier 指定以毫秒为单位的累积值。用于计算写操作时的超时总数。对于每次写操作,该值与所要写的字节数相乘。 WriteTotalTimeoutConstant 指定以毫秒为单位的常数。用于计算写操作时的超时总数。对于每次写操作, WriteTotalTimeoutMultiplier与所要写的字节数相乘后与该值相加。 如果 WriteTotalTimeoutMultiplier 和 WriteTotalTimeoutConstant都为0,则在写操作时忽略总超时数。 提示:用户设置通讯超时后,如没有出错,串口已经被打开。

串口数据读取过程

串口读取事件分为两个阶段: 第一个阶段:串口执行到ReadFile()函数时,串口还没有开始传输数据,所以串口缓冲区的第一个字节是没有装数据的,这时候总超时起作用,如果在总超时时间内没有进行串口数据的传输,ReadFile()函数就返回,当然 没有读取到任何数据。而且,间隔超时并没有起作用。

第二阶段:假设总超时为20秒,程序运行到ReadFile(),总超时开始从0 计时,如果在计时到达10秒时,串口开始了数据的传输。那么从接收的第一个字节开始,间隔超时就开始计时,假如间隔超时为1ms,那么在读取完第一个字节后,串口开始等待1ms,如果1ms之内接收到了第二个字节,就读取第二个字节,间隔超时重置为0并计时,等待第三个字节的到来。如果第三个字节到来的时间超过了1ms,那么ReadFile()函数立即返回,这时候总超时计时是没到20秒的。

如果在20秒总计时时间结束之前,所有的数据都遵守数据间隔为1ms的约定并陆陆续续的到达串口缓冲区,那么就成功进行了一次串口传输和读取;如果20秒总计时时间到,串口还陆陆续续的有数据到达,即使遵守字节间隔为1ms的约定,ReadFile()函数也会立即返回,这时候总超时就起作用了。

总结,总超时在两种情况下起作用: 第一:串口没进行数据传输,等待总超时时间那么长ReadFile()才返回。非正常数据传输 第二:数据太长,总超时设置太短,数据还没读取完就返回了。读取的数据是不全的。

间隔超时触发是有条件的: 第一:在总超时时间内。 第二:串口进行了数据的传输。 成功的进行一次串口数据的传输和读取,只有总超时和间隔超时相互参与配合才能完成。

发送数据

串口数据发送多作为写文件处理的,程序员可以应用文件操作函数发送数据到串口。采用WriteFile函数发送数据到串口。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
BOOL
WINAPI
WriteFile(
    _In_ HANDLE hFile,
    _In_reads_bytes_opt_(nNumberOfBytesToWrite) LPCVOID lpBuffer,
    _In_ DWORD nNumberOfBytesToWrite,
    _Out_opt_ LPDWORD lpNumberOfBytesWritten,
    _Inout_opt_ LPOVERLAPPED lpOverlapped
    );
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
if (WriteFile(handlePort_, // 文件句柄 
outputData, // 数据缓冲区指针 
sizeBuffer, // 字节数 
&length,
NULL) == 0) // 接收成功发送数据长度的指针 
{ 
	AfxMessageBox("writing of serial communication has problem."); return FALSE;
}
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
inline std::string stringToHex(const std::string& data)
{
    const std::string hex = "0123456789ABCDEF";
    std::stringstream ss;

    for (std::string::size_type i = 0; i < data.size(); ++i)
        ss << "0x" << hex[(unsigned char)data[i] >> 4] << hex[(unsigned char)data[i] & 0xf] << " ";
    return ss.str();
}

  ......
  LOGGING_DEBUG("send:%s", stringToHex(send).data());
  std::cout << "->send:" << stringToHex(send) << std::endl;

  std::this_thread::sleep_for(std::chrono::milliseconds(5));
  PurgeComm(m_port, PURGE_RXCLEAR | PURGE_TXCLEAR);
  DWORD dwWrite = 0;
  DWORD dwRet = WriteFile(m_port, send.c_str(), send.size(), &dwWrite, NULL);
  PurgeComm(m_port, PURGE_RXCLEAR | PURGE_TXCLEAR);
  if (!dwRet)
  {
    errorCode = base_module_error::make_error_code(base_module_error::BaseModuleErrorCode::serial_port_write_error);
    return;
  }

接收数据

串口数据接收多作为读文件处理。程序员可以应用文件操作函数从串口接收数据。用ReadFile函数接收串口的数据。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
if (ReadFile(handlePort_, // 句柄 
inputData, // 数据缓冲区指针 
sizeBuffer, // 字节数 
&length, // 指向已经读入的字节数 
NULL) == 0) // 重叠I/O结构体 
{ 
	AfxMessageBox("Reading of serial communication has problem."); return FALSE; 
}
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  char _buf;
  DWORD dwRead;
  //clock_t begin,end;
  auto begin = std::chrono::system_clock::now();
  BOOL bReadOK = ReadFile(m_port, &_buf, 1, &dwRead, NULL);
  auto spend = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now() - begin).count();
  if(spend != 0){
      //计算花费时间
      LOGGING_DEBUG("spend:%d ms",spend);
  }
  if (bReadOK && (dwRead > 0))
    return static_cast<uint8_t>(_buf);
  else
  {
      if(GetLastError()!=0){
          LOGGING_ERROR("ReadFile error,GetLastError:%u", GetLastError());
          std::cout << "ReadFile error,GetLastError:" << GetLastError() << std::endl;
      }
      errorCode = base_module_error::make_error_code(base_module_error::BaseModuleErrorCode::serial_port_read_error);
      return 0;
  }


std::string WindowsSerialPort::getFrameData(const std::string& sd)
{
  char sendDataArray[50];
  memset(sendDataArray, 0xFC, sizeof(sendDataArray));
  char* pSendDataArray = sendDataArray;
  memcpy((pSendDataArray + 3), sd.c_str(), sd.size());

  uint8_t crcHi, crcLo;
  auto* pDat = reinterpret_cast<uint8_t*>(const_cast<char*>(sd.data()));
  CRCCal(pDat, sd.size(), &crcHi, &crcLo);

  sendDataArray[sd.size() + 3] = (char)(crcLo & 0x00FFU);
  sendDataArray[sd.size() + 4] = (char)(crcHi & 0x00FFU);

  std::string _send(pSendDataArray, sd.size() + 3 + 2);
  pSendDataArray = nullptr;
  pDat = nullptr;

  return _send;
}

void WindowsSerialPort::CRCCal(uint8_t* pnt, uint8_t len, uint8_t* CrcHi, uint8_t* CrcLo)
{
  uint8_t i;
  uint16_t crc = 0;

  while (len-- != 0)
  {
    for (i = 0x80; i != 0; i /= 2)
    {
      if ((crc & 0x8000U) != 0)
      {
        crc *= 2;
        crc ^= 0x1021U;
      }
      else
      {
        crc *= 2;
      }

      if ((*pnt & i) != 0)
        crc ^= 0x1021U;
    }

    pnt++;
  }

  *CrcHi = crc >> 8U;
  *CrcLo = crc & 0xFFU;
}

关闭串口

可以调用CloseHandle API函数关闭串口。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
if(CloseHandle(handlePort_) == 0) // 调用该函数关闭串口 
{ 
	AfxMessageBox("Port Closeing isn''t successed."); return FALSE;
}

关于内存泄漏

虚拟内存是您的程序处理的内容。它由所有由malloc,new等人返回的地址组成。每个进程都有自己的虚拟地址空间。虚拟地址的使用在理论上受到程序地址大小的限制:32位程序具有4GB的地址空间; 64位程序有更多。实际上,一个进程可以分配的虚拟内存量少于这些限制。

物理内存是芯片焊接到您的主板,或安装在您的内存插槽。在任何给定时间使用的物理内存量都限制在计算机中的物理内存量。

虚拟内存子系统将您的程序使用的虚拟地址映射到CPU发送到RAM芯片的物理地址。 在任何特定时刻,大部分分配的虚拟地址都是未映射的;因此物理内存使用低于虚拟内存使用。 如果访问已分配但未映射的虚拟地址,操作系统会无形地分配物理内存并将其映射。 如果不访问虚拟地址,操作系统可能会取消映射物理内存。 应用程序一般使用malloc,calloc,realloc,new等函数从堆中分配到一块内存,使用完后,程序未调用对应的free或delete释放该内存块,从而导致内存泄漏。

所以内存泄漏会导致进程的虚拟内存使用不断增加,而由于申请后未被访问使用,所以并不会映射到物理内存占用电脑内存资源(这样系统可以防止某个恶心进程占着茅坑不拉屎…)。 当是如果程序运行的事件够长,每次泄漏不断累积,长期下去虚拟内存空间也会被全部用完,此时系统会使用系统的硬盘存储充当虚拟内存的扩展,如使用C盘空间(操作据编译器不同而不同),所以这样漏下去还是会导致电脑系统卡顿甚至蓝屏。

引用

COMMTIMEOUTS主要用于串口超时参数设置_liuzhuomju的博客-CSDN博客

串口通讯超时的设置与含义(COMMTIMEOUTS) | 超时

ReadFile function (fileapi.h) - Win32 apps | Microsoft Docs

使用Win32创建串口通讯程序-ztemt-ChinaUnix博客

关于内存的两个概念

虚拟内存以及进程的虚拟内存分布(第六章)_ivy_0709的博客-CSDN博客_虚拟内存分布

内存泄漏、虚拟内存、物理内存的联系

串口之ReadFile、WriteFile函数详解_一苇渡江694的博客-CSDN博客_readfile

串口之ReadFile、WriteFile函数详解_一苇渡江694的博客-CSDN博客_readfile

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-06-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Windows下串口编程与单片机串口设备通信(win32-API)
串行通信接口,通常简称为“串口”,是一种数据传输方式,其中信息以连续的比特流形式发送,每个比特在不同的时间点被传输。这与并行通信形成对比,在并行通信中,多个比特同时通过多个线路传输。串口通信因其简单的硬件需求和广泛的应用场景而受到青睐,尤其是在远程通信、设备控制、数据采集等领域。
DS小龙哥
2025/05/27
1480
Windows下串口编程与单片机串口设备通信(win32-API)
VC++ 串口开、关、读、写操作及注意事项
最近帮朋友做一款工具,设计到对操作系统串口的操作,虽然这个东西已经是历史产物了,但是还有很多设备再用,索性从网络上找了一些代码最终完成这个小功能。下面资料将介绍串口在打开、关闭、读和写的时候一些注意事项以及参数的配置(代码中有详细注释。)
我与梦想有个约会
2020/01/04
1.7K0
VFP多线程读取串口
因为我要发送的指令很多,所以当时用方案二同步去读取,结果很卡。方法一倒没有试过,但COM口只支持16个。
加菲猫的VFP
2023/08/21
4130
VFP多线程读取串口
虚拟串口模拟器和串口调试助手使用教程「建议收藏」
虚拟串口(虚拟 COM 端口),应该很多人都知道,也就是一种模拟物理串行接口的 软件 。 它完全复制了硬件 COM 接口的功能,并且将被操作系统和串行应用程序识别为真实端口。
全栈程序员站长
2022/07/01
8.2K0
虚拟串口模拟器和串口调试助手使用教程「建议收藏」
异步方式串口收发数据
在现代软件开发中,串口通信仍然是一个重要的领域,尤其是在嵌入式系统、工业控制和物联网设备中。Windows操作系统提供了一套完整的API来支持串口通信,包括同步和异步两种模式。本文将重点介绍如何在Windows平台上使用异步方式进行串口数据的收发。
Michel_Rolle
2024/10/11
2.9K0
Windows串口编程的IOCTL和函数
在Windows系统中,串口编程是一项常见的任务,尤其是在需要与硬件设备进行通信的应用程序中。串口编程涉及到一系列的IOCTL(Input-Output Control)操作和函数调用,这些操作和函数提供了对串口进行配置、读写数据以及错误处理的能力。本文将详细介绍Windows串口编程中的IOCTL和相关函数,以及如何使用它们来实现串口通信。
Michel_Rolle
2024/10/11
2.9K0
VC++ 串口开、关、读、写操作及注意事项
最近帮朋友做一款工具,设计到对操作系统串口的操作,虽然这个东西已经是历史产物了,但是还有很多设备再用,索性从网络上找了一些代码最终完成这个小功能。下面资料将介绍串口在打开、关闭、读和写的时候一些注意事项以及参数的配置(代码中有详细注释。)
我与梦想有个约会
2019/01/02
2.4K0
Java调用C/C++ 动态库dll操作串口实例
大家好,今天分享的是使用C/C++编写一个读取串口数据的代码,然后将其编译成Windows下的动态链接库(.dll文件),然后写一个简单的java demo来调用C/C++接口。
飞哥
2021/08/06
1.5K0
c++windows内核编程笔记day12 硬盘逻辑分区管理、文件管理、内存管理[通俗易懂]
GetSystemDirectory();//获取系统路径 GetWindowsDirectory();//获取windows路径 GetCurrentDirectory();//获取当前工作文件夹 SetCurrentDirectory();//改动当前工作文件夹 CreateFile/ReadFile/WriteFile/GetFileSize/SetFilePointer //返回文件大小的低32位 DWORD GetFileSize( HANDLE hFile,// handle to file LPDWORD lpFileSizeHigh //输出參数:返回文件大小的高32位 ); //创建文件并写入文本代码演示样例 HANDLE hf=CreateFile(“file.txt”,GENERIC_WRITE,FILE_SHARE_READ,NULL, OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL); char txt[]=”hello file to write”; DWORD len=0;//返回实际写入的长度 WriteFile(hf,txt,strlen(txt),&len,NULL); CloseHandle(hf); //读代替码演示样例 HANDLE hf=CreateFile(“file.txt”,GENERIC_READ,FILE_SHARE_READ, NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL); CHAR txt[1000]={0}; DWORD len=0;//实际读到的长度 ReadFile(hf,txt,sizeof(txt),&len,NULL); printf(“读取到的字符串:%s\n”,txt); CloseHandle(hf);
全栈程序员站长
2022/07/07
5390
【编程基础】Windows下如何玩转串口编程
在windows下,各种外设都被看成文件,这个跟Linux下看成设备节点类似,所以串口当然是被看成是一个文件。既然被看成文件,所以打开和读写都跟文件类似。 打开串口跟打开文件一样,Win32下就是C
程序员互动联盟
2018/03/14
3K0
【编程基础】Windows下如何玩转串口编程
RS232串口的Windows编程纪要
再次是一篇入门文,各路神仙退散。 直接进入主题,又不是历史课,关于RS232那些前世今生的故事就不摆了。 硬件链接 首先以9针小口为例(大口应当只能去博物馆看了吧)看一下管脚排布,其实RS232本身没进博物馆都已经够让我惊讶了。 (图片来自互联网) 通常使用的接线图: (图片来自互联网) 硬件接口部分的重点: 绝大多数情况下,我们只需要接2号、3号、5号,RXD/TXD/SG三根线就能正常工作。(顺便多说一句,古老的大串口是2、3、7号) 直连模式一般用于延长线或者大小口的转换线。
俺踏月色而来
2018/06/15
1.7K0
Win32文件系统编程
单个文件容量.  意思就是一个文件可以是多大的. NTFS 是可以4G以上的大文件. FAT32则不可以.
IBinary
2022/05/10
7270
Win32文件系统编程
Win10 串口通信 —— 同步异步
之前接到的一个小项目,好像不能算。win10下的串口通信,不需要界面,排除了Qt,MFC只剩C++ 底层了,调用WindowsApi来实现。翻了翻网上资料大致写出来了。
何其不顾四月天
2023/03/10
1.3K0
短信收发类无错版JustinIO.cs
本文由来源 21aspnet,由 system_mush 整理编辑,其版权均为 21aspnet 所有,文章内容系作者个人观点,不代表 Java架构师必看 对观点赞同或支持。如需转载,请注明文章来源。
Java架构师必看
2020/10/16
7850
一种高效的串口自定义16进制通信协议的嵌入式应用开发解决方案
摘要:本文在探讨传统数据收发不足之后,介绍如何使用带FIFO的串口来减少接收中断次数,通过一种自定义通讯协议格式,给出帧打包方法;之后介绍一种特殊的串口数据发送方法,可在避免使用串口发送中断的情况下,提高系统的响应速度。
杨源鑫
2022/03/24
2.2K0
一种高效的串口自定义16进制通信协议的嵌入式应用开发解决方案
Windows 编程(多进程)
进程从来不执行任何东西,它只是纯种的容器,若要使进行完成某项操作,它必 须拥有一个在它的环境中运行的纯种,此线程负责执行包含在进程的地址空 间的中的代码.也就是,真正完成代码执行的是线程,而进程只是纯种的容器, 或者说是线程的执行环境.
全栈程序员站长
2022/07/13
1.2K0
Java串口通信技术探究3:RXTX库线程 优化系统性能的SerialPortEventListener类
在之前的文章中,我们讨论了使用单例模式的SerialPortEventListener类。然而,这种模式在某些情况下并不理想,因为它会导致重复创建监听器,从而无法正确获取串口返回的数据。那么,如何实现SerialPortEventListener的复用呢?
Yeats_Liao
2023/12/25
4470
.NET Core 跨平台 串口通讯 ,Windows/Linux 串口通讯,flyfire.CustomSerialPort 的使用
串口通讯用于设备之间,传递数据,物联网设备中广泛使用串口方式连接通讯,物联网通讯协议 :Modbus 协议 ASCII、RTU、TCP模式是应用层的协议,与通讯方式无关。
痴者工良
2021/04/26
1.7K0
进程间通信之CreatePipe
BOOL WINAPI CreatePipe( _Out_ PHANDLE hReadPipe, _Out_ PHANDLE hWritePipe, _In_opt_ LPSECURITY_ATTRIBUTES lpPipeAttributes, _In_ DWORD nSize );
全栈程序员站长
2022/09/17
1K0
CreatePipe、CreateProcess函数
管 道(Pipe)实际是用于进程间通信的一段共享内存,创建管道的进程称为管道服务器,连接到一个管道的进程为管道客户机。一个进程在向管道写入数据后,另 一进程就可以从管道的另一端将其读取出来。匿名管道(Anonymous Pipes)是在父进程和子进程间单向传输数据的一种未命名的管道,只能在本地计算机中使用,而不可用于网络间的通信。
全栈程序员站长
2022/09/17
1.4K0
相关推荐
Windows下串口编程与单片机串口设备通信(win32-API)
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验