串口通信编程--多线程异步方式

上位机与1200组态步骤_图解组态王一组态王软件 奥科远电器点击左上角奥科远电器加关注组态王软件组态王软件是一种通用的工业监控软件,它将过程控制设计、现场操作以及工厂资源管理融于一体,将一个企业内部的各种生产系统和应用以及信息交流汇集在一起,实现最优化管理。它基于Microsoft Windows XP/Win7/Win8/Win10/WinServer 系列操作系统,在企业网络的所有层次的各个位置上,用户都可以及时获得系统的实时信息。... 阅读详情

转载请注明出自:blog.youkuaiyun.com/mingojiang

 

目录

一串口通信基础      

1.1串口通信原理与特点     

1.2串口通信的传输方式     

1.3串口通信的同步技术     

1.4串行接口标准     

二 API函数实现串口通信   

2.1打开串口 

2.1.1串口是否有驱动    

2.1.2连接串口    

2.1.3串口逻辑端口号大于10无法打开问题 

2.2串口配置 

2.2.1设置缓冲区大小    

2.2.2设置串口状态  

2.2.3设置需通知的事件      

2.2.4清空缓冲区      

2.3异步接收数据     

三示例代码 

3.1连接串口并设置参数     

3.2发送与接收数据 

3.3关闭串口 

 

 

 

一串口通信基础

        提到串口让人想起并口,它们是计算机中两个比较重要的通信方式.

串口:也叫COM口,把字节的二进制位按位列队进行传输,每个字节占一个固定的时间长,速度慢,但是传输距离远,有9针和25针两种,是阳插座(插座中有针凸起),目前25针较少使用;Modem\鼠标\USB口\老式摄像头等都是用串口.

并口:把字节的二进制位用多条线同时传输,速度快串口8倍左右,传输距离有限,一般计算机内部数据传输用此方式,平常使用的有打印机,扫描仪等;为25针,阴插座(插座有25个针孔).

 

1.1串口通信原理与特点

        串行端口是CPU与串行设备间的编码转换器,当CPU经过串行端口发数据时,字节数据列队成串行位,串行端口接收数据时,串行位转换成字节数据.所以必须安装相应的驱动程序.

        串行通信有成本低的特点,而且可以在现有的电话网络上进行传输,家庭通过电话线上网即是这种方式.只要配置一个相应的通信接口,如:Modem.

1.2串口通信的传输方式

        单工:只能从一头传输到另一头,如只能从A向B传或者B向A传,如看电视,只允许电视台向电视发数据,不允许电视向电视台发数据.在单工传输方式上一般采用两个通信,一个通道传输数据,一个通道传输控制信号.

        半双工:允许互传信息,但是不能同时进行,如对讲机,A说话时,B不能说话,B说话时A不能说话.

        全双工:允许双同时通信,如讲电话.

1.3串口通信的同步技术

        物理连接建立后,需要使用一种机制使对方正确解释发送的数据,发送方安位发出数据后,接收方如何识别这些数据,并如何正确组装成正确的字节.这就需要同步技术.数据同步技术一般解决如下问题:

² 确定发送数据起始时间

² 发送数据的传输速率

² 发送数据所需的时间

² 发送时间间隔

3.1异步传输

        按字节为单位传输,异步传输方式也叫起止方式,在被传输的字节前后加起止位,起止位无信号时处于高电平,接收方检测到低电平信号表示开始接收,收到停止信号表示传输完成.

3.2同步传输

        以数据块为单位传输,在块的前后加一个特殊字节表示起止,传输效率高,线路利用率高,设备负担也大.

1.4串行接口标准

        常用标准有RS-232C,RS-485,RS-422等,其中RS-232C被广泛用于计算机串口通信.RS-232C标准要求一般线路不要超过15米.

 

二 API函数实现串口通信

        API函数串口编程,可采用简单的查询方式或定时方式,也可采用复杂的事件驱动方式,所谓事件驱动方式是当输入缓冲区中有数据时,将自动调用某个方法执行相应的操作.定时方式是在一定的时间间隔内判断缓冲区内有数据被写入,此方法效率不高,查询方式就更落后的一种方式.所以设计的好的串口通信程序一般用事件驱动,有实时,高效,灵活等特点.

一般编制串行通信程序分以下几个部分:

Ø 打开串行端口:打开通信资源,设置通信参数、设置通信事件、创建读、写事件、进入等待串口消息循环。

Ø 读取串行端口信息:当串口发生EV_RXCHAR(接收到字符并放入了输入缓冲区)消息后读取串口、数据传输错误处理、字符串处理如回车符、空格并相应转化成数据,如果模拟量还要进行数据检验等功能。

Ø 写串行端口信息:将要发送的信息写入串口,相应进行错误处理。

Ø 断开串行端口连接:关闭事件,清除通信事件,丢弃通信资源并关闭。

 

2.1打开串口

2.1.1串口是否有驱动

        如何判断PC机中串口是否正常,驱动是否安装,串口名(逻辑端口名)是多少.如果PC机有串口同时驱动正常,那么在注册表的HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP目录下,包含字符"Serial"或"VCom"项下面的值就是,可以有多项,如下图:

项SERIALCOMM下有一个值----COM11,表明有一个可用串口,如果目录下包含字符Serial或VCom的项下没有任何值,表明没有串口或者驱动不正常.以下是获取串口逻辑名的代码:

#define MAX_KEY_LENGTH   255

#define MAX_VALUE_NAME  16383

HKEY hTestKey;

if(ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("HARDWARE\\DEVICEMAP\\SERIALCOMM"), 0, KEY_READ, &hTestKey) ){

        TCHAR   achClass[MAX_PATH] = TEXT(""); // buffer for class name

        DWORD   cchClassName = MAX_PATH; // size of class string

        DWORD   cSubKeys=0;                  // number of subkeys

        DWORD   cbMaxSubKey;             // longest subkey size

        DWORD   cchMaxClass;             // longest class string

        DWORD   cValues;             // number of values for key

        DWORD   cchMaxValue;         // longest value name

        DWORD   cbMaxValueData;      // longest value data

        DWORD   cbSecurityDescriptor; // size of security descriptor

        FILETIME ftLastWriteTime;     // last write time

 

        DWORD i, retCode;

        TCHAR achValue[MAX_VALUE_NAME];

        DWORD cchValue = MAX_VALUE_NAME;

 

        // Get the class name and the value count.

        retCode = RegQueryInfoKey(

                  hKey,                   // key handle

                  achClass,               // buffer for class name

                  &cchClassName,          // size of class string

                  NULL,                   // reserved

                  &cSubKeys,              // number of subkeys

                  &cbMaxSubKey,           // longest subkey size

                  &cchMaxClass,           // longest class string

                  &cValues,               // number of values for this key

                  &cchMaxValue,           // longest value name

                  &cbMaxValueData,        // longest value data

                  &cbSecurityDescriptor,  // security descriptor

                  &ftLastWriteTime);      // last write time

 

        if (cValues > 0) {

                  for (i=0, retCode=ERROR_SUCCESS; i<cValues; i++) {

                           cchValue = MAX_VALUE_NAME; achValue[0] = '\0';

                           if (ERROR_SUCCESS == RegEnumValue(hKey, i, achValue, &cchValue, NULL, NULL, NULL, NULL)) {

                                    CString szName(achValue);

                                    if (-1 != szName.Find(_T("Serial")) || -1 != szName.Find(_T("VCom")) ){

                                              BYTE strDSName[10]; memset(strDSName, 0, 10);

                                              DWORD nValueType = 0, nBuffLen = 10;

                                              if (ERROR_SUCCESS == RegQueryValueEx(hKey, (LPCTSTR)achValue, NULL,

&nValueType, strDSName, &nBuffLen)){

                                                       int nIndex = -1;

                                                       while(++nIndex < 20){

                                                                if (-1 == m_nComArray[nIndex]) {

                                                                          m_nComArray[nIndex] = atoi((char*)(strDSName + 3));

                                                                          break;

                                                                }

                                                       }

                                              }

                                    }

                           }

                  }

        }

        else{

                  AfxMessageBox(_T("机PC机没有COM口....."));

        }

}

RegCloseKey(hTestKey);

 

2.1.2连接串口

串口是系统资源,也当作文件一样操作,所以也用CreateFile函数,如果调用成功返回串口句柄,如果失败返回INVALID_HANDLE_VALUE值.函数参数说明如下:

HANDLE WINAPI CreateFile(

 __in         LPCTSTR lpFileName,//串口名(逻辑端口名),如:”COM1”,”COM2”

 __in            DWORD dwDesiredAccess,//访问模式,对串口有读/写权限

 __in            DWORD dwShareMode,//共享模式,有读/写/删除共享,对串口通信只能独占模式

 __in_opt LPSECURITY_ATTRIBUTES lpSecurityAttributes,//文件安全属性,对串口设置为NULL

 __in            DWORD dwCreationDisposition,//创建方式,串口通信设置为OPEN_EXISTING

 __in            DWORD dwFlagsAndAttributes,//文件属性标记,是否异步方式,在些设置

 __in_opt HANDLE hTemplateFile);//文件句柄,如果不为NULL,新文件从该够本复制或扩展,如果函数执行成功,返回新的串口句柄.

Ø 第一个参数:逻辑串口号,用字符串”COMX”表示,”X”是串口序号,关于电脑中的逻辑串口号,在注册表HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP目录下,包含字符"Serial"或"VCom"项下面的值就是,可以有多个

Ø 第二个参数:是对对串口的访问权限,串口只有读/写(GENERIC_READ/GENERIC_WRITE)权限,可以同时设置成读/写权限,也可以单独只设置读或写权限.

Ø 第三个参数:是共享模式,有读/写/删除共享,对串口通信只能独占模式,即是0.

Ø 第四个参数:文件安全属性,对串口设置成NULL.

Ø 第五个参数:创建方式,有CREATE_ALWAYS/ CREATE_NEW/ OPEN_EXISTING等方式,但是对串口只能是OPEN_EXISTING,只能打开存在的串口,不像文件一样可创建之类

Ø 第六个参数:文件属性与标志,详细信息查看MSDN,如果想把串口设置成异步方式,那么要设置成FILE_FLAG_OVERLAPPED.

Ø 第七个参数:文件句柄,新文件从该句柄复制或扩展,如果函数执行成功,返回新的句柄,对串口通信,设置成NULL

以下为代码示例:

HANDLE hCom = CreateFile("COM1", //打开串口1

             GENERIC_READ|GENERIC_WRITE, //允许读和写操作

             0, //独占方式

             NULL,

             OPEN_EXISTING, //打开存在的串口,必须是OPEN_EXISTING,文件还可以CREATE_NEW,串口不能创建

             FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED, //异步方式打开

             NULL);

if (INVALID_HANDLE_VALUE == m_hCom) {

                           int nError = GetLastError();

             }

如果执行成功返回串口句柄,如果失败通过GetLastError获取错误码.

        

2.1.3串口逻辑端口号大于10无法打开问题

       通过函数CreateFile打开串口,其第一个参数就是串口的逻辑端口名,是用”COMX”表示的,其中X是1~N的整数,当X大于10时,有时会出现无法打开的问题,把逻辑端口名改成"\\\\.\\COM

X"即可解决.

CString szCom;

szCom.Format(_T("\\\\.\\COM%d"), nPort);

COMFile = CreateFile(szCom.GetBuffer(50), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,                                                 NULL,             OPEN_EXISTING, FILE_FLAG_OVERLAPPED,NULL);

2.2串口配置

        对串口进行设置,如缓冲区大小,是否允许二进制,参数配置等.

2.2.1设置缓冲区大小

        设置IO的缓冲区大小根据自己需求,太小容易丢失数据,所以根据自己的需求设置.

BOOL SetupComm(

 HANDLE hFile, //串口句柄,CreateFile的有效返回值

 DWORD dwInQueue, //输入缓冲区字节数

 DWORD dwOutQueue);//输出缓冲区字节数

2.2.2设置串口状态

        设置串口的各种状态,波特率/数据位/停止位/校验位/流控制/二进制等.设置窗口状态是通过函数SetCommState设置的,第一个参数是串口句柄,第二个是DCB指针.DCB结构比较复杂,参数多,所以一般是通过GetCommState来填充一个DCB对象,然后再修改这对象,再把修改好的对像给SetCommState做参数.这是常用的方法.下面是对DCB参数介绍:

typedef struct _DCB { // dcb 

        DWORD DCBlength;           // sizeof(DCB) 

        DWORD BaudRate;            // current baud rate 指定当前的波特率

        DWORD fBinary: 1;          // binary mode, no EOF check 指定是否允许二进制模式,WINDOWS 95中必须为TRUE

        DWORD fParity: 1;          // enable parity checking 指定奇偶校验是否允许

        DWORD fOutxCtsFlow:1;// CTS output flow control 指定CTS是否用于检测发送控制.当为TRUE是CTS为OFF,发送将被挂起

        DWORD fOutxDsrFlow:1;// DSR output flow control 指定DSR是否用于检测发送控制.当为TRUE是DSR为OFF,发送将被挂起

        DWORD fDtrControl:2;       // DTR flow control type DTR_CONTROL_DISABLE值将DTR置为OFF, DTR_CONTROL_ENABLE值将

//DTR置为ON, DTR_CONTROL_HANDSHAKE允许DTR"握手",

        DWORD fDsrSensitivity:1;   // DSR sensitivity 当该值为TRUE时DSR为OFF时接收的字节被忽略

        DWORD fTXContinueOnXoff:1; // XOFF continues Tx 指定当接收缓冲区已满,并且驱动程序已经发送出XoffChar字符时发送

//是否停止.TRUE时,在接收缓冲区接收到缓冲区已满的字节XoffLim且驱动程序已经发送

//出XoffChar字符中止接收字节之后,发送继续进行。FALSE时,在接收缓冲区接收到代表缓冲

//区已空的字节XonChar且驱动程序已经发送出恢复发送的XonChar之后,发送继续进行。

        DWORD fOutX: 1;            // XON/XOFF out flow control TRUE时,接收到XoffChar之后便停止发送.接收到XonChar之后将重新开始

        DWORD fInX: 1;             // XON/XOFF in flow control TRUE时,接收缓冲区接收到代表缓冲区满的XoffLim之后,XoffChar发送出

//去.接收缓冲区接收到代表缓冲区空的XonLim之后,XonChar发送出去

        DWORD fErrorChar: 1;       // enable error replacement 该值为TRUE且fParity为TRUE时,用ErrorChar 成员指定的字符代替奇

//偶校验错误的接收字符

        DWORD fNull: 1;            // enable null stripping TRUE时,接收时去掉空(0值)字节

       DWORD fRtsControl:2;       // RTS flow control RTS_CONTROL_DISABLE时,RTS置为OFF RTS_CONTROL_ENABLE时, RTS置为ON RTS_CONTROL_HANDSHAKE时,当接收缓冲区小于半满时RTS为ON 当接收缓冲区超过四分之三满时RTS为OFF RTS_CONTROL_TOGGLE时,当接收缓冲区仍有剩余字节时RTS为ON ,否则缺省为OFF

       DWORD fAbortOnError:1;     // abort reads/writes on error TRUE时,有错误发生时中止读和写操作

       DWORD fDummy2:17;          // reserved 未使用

      WORD wReserved;            // not currently used 未使用,必须为0

       WORD XonLim;               // transmit XON threshold 指定在XON字符发送这前接收缓冲区中可允许的最小字节数

       WORD XoffLim;              // transmit XOFF threshold 指定在XOFF字符发送这前接收缓冲区中可允许的最小字节数

        BYTE ByteSize;             // number of bits/byte, 4-8 指定端口当前使用的数据位

        BYTE Parity;               // 0-4=no,odd,even,mark,space 指定端口当前使用的奇偶校验方法,可能为:

//EVENPARITY,MARKPARITY,NOPARITY,ODDPARITY

        BYTE StopBits;             // 0,1,2 = 1, 1.5, 2 指定端口当前使用的停止位数,可能为:ONESTOPBIT,ONE5STOPBITS,TWOSTOPBITS

        char XonChar;              // Tx and Rx XON character 指定用于发送和接收字符XON的值

        char XoffChar;             // Tx and Rx XOFF character 指定用于发送和接收字符XOFF值

        char ErrorChar;            // error replacement character 本字符用来代替接收到的奇偶校验发生错误时的值

        char EofChar;              // end of input character 当没有使用二进制模式时,本字符可用来指示数据的结束

        char EvtChar;              // received event character 当接收到此字符时,会产生一个事件

        WORD wReserved1;           // reserved; do not use 未使用

    } DCB; 

以下为示例代码:

             DCB dcb;

             GetCommState(hCom,&dcb);

             dcb.BaudRate = 9600;//波特率

             dcb.fBinary = TRUE;//是否允许传二进制

             dcb.fParity = TRUE;//是否奇偶校验

             dcb.ByteSize = 8;//数据位

             dcb.Parity = ODDPARITY;//奇偶校验方式

             dcb.StopBits = ONESTOPBIT;//停止位

             SetCommState(hCom,&dcb);

2.2.3设置需通知的事件

        设置你关心的事件,当此事件发生时,将得到事件通知,通过SetCommMask函数设置,SetCommMask函数两个参数,第一个为串口句柄,第二个为事件,可通过位或的方式指定多个事件,如下:

BOOL WINAPI SetCommMask(

 __in  HANDLE hFile,

 __in  DWORD dwEvtMask);

示例代码:

SetCommMask(m_hCom, EV_RXCHAR ) ;

EV_RXCHAR事件指当输入缓冲区内有数据时,通过WaitCommEvent函数可获得通知,其他事件同理,其他事件还有EV_BREAK/EV_CTS/EV_RING等,详情参看MSDN.

2.2.4清空缓冲区

        在接收/发送数据前缓冲区中可能有垃圾数据,或者中途想清空缓冲区数据,可以用以下调用以下函数:

BOOL WINAPI PurgeComm(

 __in HANDLE hFile,//串口句柄

 __in DWORD dwFlags//清空方式PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR

);

PURGE_TXABORT | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_RXCLEAR分别表示:立即中断写操作并清空输出缓冲区|清空输出缓冲区|立即中断读操作并清空输入缓冲区|清空输入缓冲区.示例代码如下:

PurgeComm(m_hCom, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR ) ;

2.3异步接收数据

        在2.2.3中通过SetCommMask函数,设置了异步通知事件EV_RXCHAR,所以当输入缓冲区中有数据时,将会有事件触发,那怎么获得事件呢?通过WaitCommEvent函数截取,与WaitForSingleObject原理类似.函数说明如下:

BOOL WINAPI WaitCommEvent(

 __in  HANDLE hFile,

 __out LPDWORD lpEvtMask,

 __in  LPOVERLAPPED lpOverlapped);

第一个参数是串口句柄,第二个参数是Out型指针,接收事件标志的,第三个参数接收事件信息事件状态.以下为示例代码:

HANDLE hEventArr[2];

hEventArr[0] = osRead.hEvent;

hEventArr[1] = *g_OutPutList.GetEvent();

while(1){

             DWORD nResutl = WaitForMultipleObjectsEx(2, hEventArr, FALSE, 200, TRUE/*INFINITE*/);

             if(0 == nResutl){

                           if (g_OutPutList.GetCount() > 1000)

                                         g_OutPutList.RemoveAll();

                           WORD nLen = (WORD)m_nBuffLen + 2;

                           PBYTE pIn = new BYTE[nLen];

                           pIn[0] = HIBYTE(nLen);

                           pIn[1] = LOBYTE(nLen);

                           memcpy(pIn + 2, m_InPutBuff, m_nBuffLen);

                           g_InPutList.AddTail(pIn);

                           m_nBuffLen = 0;

             }

             else if(1 == nResutl){

                           PBYTE pOut = (PBYTE)g_OutPutList.RemoveHead();

                           int nLen = pOut[0] * 0x100 + pOut[1] - 2;

                           WriteCommBlock(pOut + 2, nLen);

                           delete[] pOut;

             }

             DWORD dwEvtMask = 0 ;

             WaitCommEvent( COMFile, &dwEvtMask, &ShareEvent);//等̨¨待äy串ä?口¨²事º?件t

             if ((dwEvtMask & EV_RXCHAR) == EV_RXCHAR) {

                           ReadCommBlock( );

             }

}

 

三示例代码

    关于本文的代码下载链接:http://download.youkuaiyun.com/detail/mingojiang/4425803 VS2010编写的,编译通过,是个串口调试工具. 如图:

 

3.1连接串口并设置参数

DCB dcb ;

BOOL fRetVal ;

COMMTIMEOUTS CommTimeOuts;

CString szCom;

szCom.Format(_T("\\\\.\\COM%d"), nPort);

COMFile = CreateFile(szCom.GetBuffer(50), GENERIC_READ | GENERIC_WRITE,//可¨¦读¨¢、¡é可¨¦写¡ä

                                                                                   FILE_SHARE_READ | FILE_SHARE_WRITE,                                                                                

NULL,

                                                                                   OPEN_EXISTING,

                                                                                   FILE_FLAG_OVERLAPPED,

                                                                                   NULL);

if (INVALID_HANDLE_VALUE == COMFile){

             return ( FALSE ) ;

}

 

SetupComm(COMFile,6000,6000) ;

SetCommMask(/*COMFileTemp*/COMFile, EV_RXCHAR ) ;

CommTimeOuts.ReadIntervalTimeout = 0xFFFFFFFF ;

CommTimeOuts.ReadTotalTimeoutMultiplier = 0 ;

CommTimeOuts.ReadTotalTimeoutConstant = 1000 ;

CommTimeOuts.WriteTotalTimeoutMultiplier = 2*CBR_9600/9600 ;

CommTimeOuts.WriteTotalTimeoutConstant = 0 ;

SetCommTimeouts(/*COMFileTemp*/COMFile, &CommTimeOuts ) ;

 

dcb.DCBlength = sizeof( DCB ) ;

GetCommState(COMFile, &dcb ) ;

dcb.BaudRate =CBR_9600;

dcb.StopBits =ONESTOPBIT;

dcb.Parity = NOPARITY;

dcb.ByteSize=8;

dcb.fBinary=TRUE;

 dcb.fOutxDsrFlow = 0 ;

dcb.fDtrControl = DTR_CONTROL_ENABLE ;

dcb.fOutxCtsFlow = 0 ;

dcb.fRtsControl = RTS_CONTROL_ENABLE ;

dcb.fInX = dcb.fOutX = 1 ;

dcb.XonChar = 0X11 ;

dcb.XoffChar = 0X13 ;

dcb.XonLim = 100 ;

dcb.XoffLim = 100 ;

dcb.fParity = TRUE ;

 

fRetVal = SetCommState(/*COMFileTemp*/COMFile, &dcb ) ;

 

if(!fRetVal) return FALSE;

 

PurgeComm( /*COMFileTemp*/COMFile, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR ) ;

 

EscapeCommFunction( /*COMFileTemp*/COMFile, SETDTR ) ;

 

3.2发送与接收数据

HANDLE hEventArr[2];

hEventArr[0] = osRead.hEvent;

hEventArr[1] = *g_OutPutList.GetEvent();

 

while(1){

             DWORD nResutl = WaitForMultipleObjectsEx(2, hEventArr, FALSE, 200, TRUE/*INFINITE*/);

             if(0 == nResutl){

                           if (g_OutPutList.GetCount() > 1000)

                                         g_OutPutList.RemoveAll();

                           WORD nLen = (WORD)m_nBuffLen + 2;

                           PBYTE pIn = new BYTE[nLen];

                           pIn[0] = HIBYTE(nLen);

                           pIn[1] = LOBYTE(nLen);

                           memcpy(pIn + 2, m_InPutBuff, m_nBuffLen);

                           g_InPutList.AddTail(pIn);

                           m_nBuffLen = 0;

             }

             else if(1 == nResutl){

                           PBYTE pOut = (PBYTE)g_OutPutList.RemoveHead();

                           int nLen = pOut[0] * 0x100 + pOut[1] - 2;

                           WriteCommBlock(pOut + 2, nLen);

                           delete[] pOut;

             }

 

DWORD dwEvtMask = 0 ;

WaitCommEvent( COMFile, &dwEvtMask, &ShareEvent);//等̨¨待äy串ä?口¨²事º?件t

if ((dwEvtMask & EV_RXCHAR) == EV_RXCHAR) {

             ReadCommBlock( );

             }

}

 

3.3关闭串口

//禁止串行端口所有事件

SetCommMask(COMFile, 0) ;

//清除数据终端就绪信号

EscapeCommFunction( COMFile, CLRDTR ) ;

//丢弃通信资源的输出或输入缓冲区字符并终止在通信资源上挂起的读、写操操作

PurgeComm( COMFile, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR ) ;

CloseHandle( COMFile );

COMFile = NULL;

 

转载请注明出自:blog.youkuaiyun.com/mingojiang

 

QT4串口通信编程实战详解 串口通信是一种广泛应用的异步通信方式,通过串行数据流实现设备间的点对点数据传输。其核心原理是将数据按位依次发送,依赖起始位、数据位、校验位和停止位构成完整数据帧,确保接收端正确解析。常见的物理层标准包括RS-232RS-485和USB转串口RS-232适用于短距离(<15m)、点对点通信,电平为±12V,抗干扰能力较弱;RS-485支持多点组网、差分信号传输,最长可达1200米,广泛用于工业现场总线;USB转串口。 阅读详情

相关推荐

深入理解串口通信编程与实践

在Windows操作系统中,串口通信主要是通过Win32 API函数来实现的。这些函数允许开发者对串口进行配置、读写操作以及控制串口的打开与关闭。以下是一些核心的串口函数及其功能简述:CreateFile: 打开或创建一个设备或文件,对于串口来说,可以通过该函数打开串口资源。: 设置串口的通信参数,如波特率、数据位等。: 读取串口的当前通信参数。ReadFile: 从串口读取数据。WriteFile: 向串口写入数据。: 关闭由CreateFile打开的串口句柄。

weixin_42627459的博客 955

BCB多线程编程 ( 转载 )

BCB多线程编程大家可能经常听说“线程”这个词汇:网络蚂蚁采用了多线程下载技术、FoxMail采用了多线程收信技术等等,可能有人就会问:什么是线程呢?一、什么是线程对于初次接触“线程”这个概念的人来说,会对线程这个概念有点模糊,特别是对线程、进程、程序这三个概念的区别和联系不太清楚,所谓程序,其实就是磁盘上的可执行的文件,只有当它被启动后才成为一个进程;而进程指一个当前装载到内存中的程

2822

QT图形界面下Linux串口通信项目实战

QT是一个开源的C++库,广泛应用于创建跨平台的图形用户界面程序,以及开发基于GUI的应用程序。除了界面设计,QT还提供网络、数据库、XML、OpenGL等功能模块。利用QT框架,开发者可以快速构建功能丰富且用户友好的桌面和嵌入式应用程序。QSerialPort模块是Qt框架提供的一个跨平台串口通信类库,用于在不同的操作系统中进行串口通信。它封装了底层的串口操作,使得开发者可以更加便捷地实现串口数据的发送和接收,而不必关心底层的操作细节。

weixin_31315007的博客 718

(RS485 232串口通信数据解析实用干货(1)

文章目录(RS485 232串口通信数据解析实用干货(1)生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UML 图表FLowchart流程图导出与导入导出导入 ** (RS485 232串口通信数据解析实用干货(1) ** /*********************...

qq_39898716的博客 9467

ESP32S3开发板玩转多语言AI对话:小智语音机器人粤语/日语/韩语实测

本文基于正点原子ESP32S3开发板,实测了“小智AI”语音机器人的多语言对话能力。项目巧妙整合云端AI与嵌入式硬件,实现了对粤语、日语、韩语等语言的实时识别与合成,为开发者和爱好者提供了一个低成本、可玩性高的跨语言人机交互开发平台。

h9j8k7l6m5n的博客 537

Excel曲线拟合实战:从基础趋势线到高级回归分析

本文系统介绍了Excel曲线拟合的完整工作流,从基础的散点图与趋势线应用,到利用Solver插件进行自定义高级回归分析。文章详细讲解了线性、多项式、指数、对数等六大常用数学模型的适用场景与选择方法,并强调了通过R²值、残差图评估拟合效果、避免过拟合与外推风险的关键步骤,帮助读者掌握从数据探索到预测评估的实战技能。

weixin_29280219的博客 531

【串口通信】--线程应用(1)

前言:     关于串口通信中的线程问题,本来是早就想总结一下的。但是在这两个星期的学习过程中,发现自己原来的理解还是有很多的不全面的地方。通过两个月的学习,自己对这块的认识还是有了很大的提升,今天我就拿出来给大家一起分享一下。当然对于初次接触线程的人来说,可能会不太容易接受,今天就先说点简单的入门。 背景介绍:     首先说说串口下的多线程,这个其实是有两种情况的。 就是你

韩义--廊坊师范学院信息技术提高班第九期 5317

Android设置鼠标显示的屏幕

【代码】Android设置鼠标显示的屏幕。

薛文旺 670

Visual C++串口通信编程---多线程异步方式

Visual C++串口通信编程---多线程异步方式 1. 串口通信基础 提到串口让人想起并口,它们是计算机中两个比较重要的通信方式。 串口:也叫COM口,把字节的二进制位按位列队进行传输,每个字节占一个固定的时间长,速度慢,但是传输距离远,有9针和25针两种,是阳插座(插座中有针凸起),目前25针较少使用;Modem\鼠标\USB口\老式摄像头等都是用串口。 并口:把字节的二进制位用多条...

《好好先生》专栏 8039

74LS161/48 交通灯控制系统:30-5-20-5 时序逻辑电路 Multisim 仿真验证

本文详细解析了基于74LS161/48芯片的交通灯控制系统设计,通过Multisim仿真验证30-5-20-5时序逻辑电路。从系统架构搭建、状态机实现到波形分析,提供全流程操作指南与典型问题排查方法,助力数字电路课程设计高效完成。

weixin_26742753的博客 377

AXI4协议之AXI4-Lite接口详解及实战

本文首先对AXI4总线协议进行了一个简单的介绍,然后使用vivado提供的模板创建了一个AXI4-Lite Master的接口,并生成了一个具有Master和Slave的代码实例,阅读该示例代码,进行修改后用于自己的项目。

高阶近似的博客 2万+

VS2013 Windows API 串口通信编程--多线程异步方式

转载自:blog.youkuaiyun.com/mingojiang 1.串口通信基础 提到串口让人想起并口,它们是计算机中两个比较重要的通信方式. 串口:也叫COM口,把字节的二进制位按位列队进行传输,每个字节占一个固定的时间长,速度慢,但是传输距离远, 有9针和25针两种,是阳插座(插座中有针凸起),目前25针较少使用;Modem\鼠标\USB口\老式摄像头等都是用串口. 并口:把字节的二进

sjhuangx的专栏 1万+

MTK6769平台Type-C充电全解析:从硬件管脚到PD协议实战(Android15环境)

本文深入解析了MTK6769平台在Android 15环境下Type-C充电的完整链路。从硬件管脚(特别是核心的CC引脚)功能与连接,到USB-PD协议报文抓取与实战分析,并结合MTK平台PD芯片驱动与充电IC驱动的软件框架,提供了从硬件设计到软件调试的系统性解决方案和常见问题排查案例。

ol78901234的博客 309

【备用】串口通信编程--多线程异步方式

转载请注明出自:blog.youkuaiyun.com/mingojiang   目录 一串口通信基础       1.1串口通信原理与特点      1.2串口通信的传输方式      1.3串口通信的同步技术      1.4串行接口标准      二 API函数实现串口通信    2.1打开串口  2.1.1串口是否有驱动     2.1.2连接串口     2.1.3串口逻辑端

转贴工具 1271

芒果YOLO11改进17:即插即用 | 损失函数Repulsion Loss|Repulsion 解决目标遮挡场景下的目标检测,为解决密集人群检测中遮挡设计的损失函数,打造高效

即插即用 | 损失函数Repulsion Loss|Repulsion 解决目标遮挡场景下的目标检测,为解决密集人群检测中遮挡设计的损失函数,打造高效

包括YOLOv5、YOLOv7、YOLOv8等模型改进 482

基于 FPGA Vivado 示波器设计(附源工程)

今天给大侠带来基于 FPGA Vivado 示波器设计,开发板实现使用的是Digilent basys 3,如有想要入手basys3开发板的,可以联系牛总:18511371833。话不多说,上货。 本篇掌握基于添加文件和IP的Vivado工程设计流程,掌握基于Tcl的Vivado工程设计流程,学习示波器的基本组成结构。获取本篇相关源工程代码,可在公众号内回复“示波器设计源工程”。 原理介绍 数字存储示波器能够将模拟信号进行采样、存储以及显示。本系统在DIGILENT ...

7384

VC 多线程异步方式操作串口

#include #include #include using namespace std; DWORD WINAPI CommSend(LPVOID lpParameter);  DWORD WINAPI CommReceive(LPVOID lpParameter);  OVERLAPPED overRead,overWrite;  HANDLE m_hCom; int m

何文斌的专栏 2391

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

Microsoft Windows 平台下 API调用与单片机进行串口通信

Windows 平台下 API调用与单片机进行串口通信 - API串口通信 - 使用Win32的API

Code to create the world 2794

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

使用Boost.Asio编写通信程序

摘要:本文通过形像而活泼的语言简单地介绍了Boost::asio库的使用,作为asio的一个入门介绍是非常合适的,可以给人一种新鲜的感觉,同时也能让体验到asio的主要内容。   Boost.Asio是一个跨平台的网络及底层IO的C++编程库,它使用现代C++手法实现了统一的异步调用模型。 ASIO的同步方式 ASIO库能够使用TCP、UDP、ICMP、串口来发送/接收数

zxh2075的专栏 1083

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

下一篇: 封装与重用演变史
MingoJiang
博客等级 码龄14年 161粉丝 41原创
评论 26
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MingoJiang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值