串口通信API - 实例
Win32API 异步串口通讯
使用Win32API实现Windows下异步串口通讯目录:1.异步非阻塞串口通讯的优点2.异步非阻塞串口通讯的基本原理3.异步非阻塞串口通讯的基础知识4.异步非阻塞串口通讯的实现步骤一,异步非阻塞串口通讯的优点读写串行口时,既可以同步执行,也可以重叠(异步)执行。
在同步执行时,函数直到操作完成后才返回。
这意味着在同步执行时线程会被阻塞,从而导致效率下降。
在重叠执行时,即使操作还未完成,调用的函数也会立即返回。
费时的I/O操作在后台进行,这样线程就可以干别的事情。
例如,线程可以在不同的句柄上同时执行I/O操作,甚至可以在同一句柄上同时进行读写操作。
"重叠"一词的含义就在于此。
二,异步非阻塞串口通讯的基本原理首先,确定要打开的串口名、波特率、奇偶校验方式、数据位、停止位,传递给CreateFile()函数打开特定串口;其次,为了保护系统对串口的初始设置,调用GetCommTimeouts()得到串口的原始超时设置;然后,初始化DCB对象,调用SetCommState() 设置DCB,调用SetCommTimeouts()设置串口超时控制;再次,调用SetupComm()设置串口接收发送数据的缓冲区大小,串口的设置就基本完成,之后就可以启动读写线程了。
三,异步非阻塞串口通讯的基础知识下面来介绍并举例说明一下编写异步非阻塞串口通讯的程序中将会使用到的几个关键函数CreateFile()功能:打开串口设备函数原型HANDLE CreateFile(LPCTSTR lpFileName, // 串口名称字符串;如:"COM1" 或"COM2"DWORD dwDesiredAccess, // 设置读写属性(访问模式);一般为GENERIC_READ|GENERIC_WRITE, DWORD dwShareMode, // 共享模式;"必须"为0, 即不能共享LPSECURITY_ATTRIBUTES lpSecurityAttributes, // 安全属性;一般为NULLDWORD dwCreationDistribution, // 创建方式,串口设置必须设置此值;在这里"必须"为OPEN_EXISTING DWORD dwFlagsAndAttributes, // 文件属性和标志;在这里我们设置成FILE_FLAG_OVERLAPPED ,实现异步I/OHANDLE hTemplateFile // 临时文件的句柄,通常为NULL);说明:如果调用成功,那么该函数返回文件的句柄,如果调用失败,则函数返回INVALID_HANDLE_VALUE。
WIN32 API串口通信
WIN32 API串口通信掌握串行通信API函数的用法是掌握串行通信编程技术的关键。
在Win32中,系统将串行口与文件统一了起来,对它们的打开、读写、关闭等操作都使用相同的API函数,但是它们之间又有差别,这些差别主要体现在API函数中部分参数的设置上。
有关通信的API主要包括打开串口、关闭串口、配置串口、设置缓冲区、设置超时、事件驱动、读串口、写串口等。
串口的打开和关闭1:串口的打开。
由于在Windows环境中,串口作为一种文件来使用,打开串口用打开文件同样的API函数CreateFile()。
函数原型为:HANDLE CreateFile( LPCTSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile); 其中几个参数的含义分别为:lpFileName指定文件名或设备名,串口通讯时,它必须是“COMx”,其中的“x”为串口编号,如第一个串口则为“COM1”;dwDesiredAccess为串口读写属性;dwShareMode指定该端口的共享属性,串行口不能作为共享设备,故参数值必须为0;lpSecurityAttributes为安全属性,对于串口应该为0 ;dwCreationDisposition指文件的创建模式,对于串口必须为OPEN—EXISTING;dwFlagsAndAttributes描述了创建文件的其它属性,对于串行口,有效的设置只能是FILE-FLAG-OVERLAPPED 或者0,分别表示异步或同步读写;参数hTemplateFile必须为NULL。
返回值:若成功,返回创建的句柄;否则返回INVALID—HANDLE—VALUE。
VB6使用API实现串口通信
需要和客户的产品通讯,但波特率是非常规的,MScomm无法实现,原有的软件框架和条件又不能转用VC开发底层,于是用VB6调用API实现了这个通讯功能,虽然在VB6下这个程序还是单进程的,但实现了异步非阻塞的通信,性能相当稳定,下面是测试程序代码Private Sub cmdSend_Click()Sub cmdSend_Click()'定义文件读写属性结构Dim sa As SECURITY_ATTRIBUTES'定义串口状态结构Dim typCommStat As COMSTAT'定义串口状态错误Dim lngError As Long'********打开串口********Dim hCF As LonghCF = CreateFile("COM4", _GENERIC_READ Or GENERIC_WRITE, 0, sa, _OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL Or FILE_FLAG_OVER LAPPED, 0)Debug.Print "打开串口:" & hCF'********获取出错信息********Dim errNum As LongerrNum = GetLastError()Debug.Print "出错信息:" & errNum'定义标志值Dim flag As Long'定义设备控制块Dim typDCB As DCB'********获取设备控制块********flag = GetCommState(hCF, typDCB)Debug.Print "获取串口DCB:" & flagtypDCB.BaudRate = 2500 '定义波特率typDCB.Parity = NOPARITY '无校验位typDCB.ByteSize = 8 '数据位typDCB.StopBits = 0 '停止位0/1/2 = 1/1.5/2'********设置串口参数********flag = SetCommState(hCF, typDCB)Debug.Print "设置串口参数:" & flag'********设置缓冲区大小********flag = SetupComm(hCF, 1024, 1024)'Debug.Print "设置缓冲区:" & flag'********清空读写缓冲区********flag = PurgeComm(hCF, PURGE_RXABORT Or PURGE_RXCLEAR Or PURGE_T XABORT Or PURGE_TXCLEAR)'Debug.Print "强制清空缓冲区:" & flag'定义超时结构体Dim typCommTimeouts As COMMTIMEOUTStypCommTimeouts.ReadIntervalTimeout = 0 '相邻两字节读取最大时间间隔(为0表示不使用该超时间隔)typCommTimeouts.ReadTotalTimeoutMultiplier = 0 '一个读操作的时间常数typCommTimeouts.ReadTotalTimeoutConstant = 0 '读超时常数typCommTimeouts.WriteTotalTimeoutMultiplier = 0 '一个写操作的时间常数(为0表示不使用该超时间隔)typCommTimeouts.WriteTotalTimeoutConstant = 0 '写超时常数(为0表示不使用该超时间隔)'********超时设置********flag = SetCommTimeouts(hCF, typCommTimeouts)'Debug.Print "超时设置:" & flag'********发送数据********'定义要发送字节数Dim lngNumberofBytesToWrite As Long'定义实际发送字节数Dim lngNumberofBytesToWritten As Long'定义重叠结构体Dim typOverLapped As OVERLAPPED'定义发送数据Dim arrbytTest(0 To 23) As Byte'载波收发器同步头arrbytTest(0) = CByte(&H53) arrbytTest(1) = CByte(&H4E) arrbytTest(2) = CByte(&H44)'后续数据包长度arrbytTest(3) = CByte(&H14)'载波表预同步头arrbytTest(4) = CByte(&HFF) arrbytTest(5) = CByte(&HFF) arrbytTest(6) = CByte(&HFF) arrbytTest(7) = CByte(&HFF) arrbytTest(8) = CByte(&HFF) arrbytTest(9) = CByte(&HFF)'载波表帧同步头arrbytTest(10) = CByte(&H9) arrbytTest(11) = CByte(&HAF)'载波表地址arrbytTest(12) = CByte(&H59) arrbytTest(13) = CByte(&H20) arrbytTest(14) = CByte(&H0)'控制码arrbytTest(15) = CByte(&H1)'数据长度arrbytTest(16) = CByte(&H5)'功能码arrbytTest(17) = CByte(&H10)arrbytTest(18) = CByte(&H90)'集中器地址arrbytTest(19) = CByte(&HBB)arrbytTest(20) = CByte(&HBB)arrbytTest(21) = CByte(&HBB)'校验和arrbytTest(22) = CByte(&H50)arrbytTest(23) = CByte(&H3)'获取要发送字节数lngNumberofBytesToWrite = UBound(arrbytTest) + 1'声明等待开始时间、结束时间值Dim writeStarTime, writeEndTime As LongwriteStarTime = GetTickCount()Debug.Print "发送开始时间:" & writeStarTime'定义发送循环步长值Dim i As Integer'定义累计发送字节数Dim intTotalNumberOfBytesToWritten As Integer'定义发送间隔时间(毫秒)Dim intIntervalTime As IntegerintIntervalTime = 0'发送数据For i = 0 To UBound(arrbytTest)flag = WriteFile(hCF, arrbytTest(i), 1, lngNumberofBytesToWritten, typOverLappe d)'获取出错码errNum = GetLastError()'Debug.Print "发送操作出错码:" & errNum'若返回值不是IO异步操作未决,则关闭串口If (errNum <> ERROR_IO_PENDING) And (errNum <> 0) Then GoTo closeCo mm'异步IO事件获取(返回值为0 表示出错)flag = WaitForSingleObject(typOverLapped.hEvent, 0)'Debug.Print "异步IO事件获取:" & flag'判断异步IO事件获取是否成功If flag <> 0 Then'异步IO操作结果获取(等待标记值,必须为true ,否则需要事件激活返回结果) flag = GetOverlappedResult(hCF, typOverLapped, lngNumberofBytesToWritten, 1)'Debug.Print "异步IO操作获取:" & flag'判断异步IO操作结果获取是否成功If flag <> 0 ThenintTotalNumberOfBytesToWritten = intTotalNumberOfBytesToWritten + _lngNumberofBytesToWrittenEnd IfEnd If'间隔时间(用于需要设定每字节间间隔时间的发送协议)Sleep (intIntervalTime)NextwriteEndTime = GetTickCount()Debug.Print "发送结束时间:" & writeEndTimeDebug.Print "发送总时间:" & (writeEndTime - writeStarTime)Debug.Print "串口发送操作:" & flagDebug.Print "实际发送字节数:" & intTotalNumberOfBytesToWritten'********清空缓冲区等待数据接收********flag = FlushFileBuffers(hCF)'Debug.Print "清空缓冲区:" & flag'********设置串口事件********'监听数据接收事件' flag = SetCommMask(hCF, EV_ERR Or EV_RXCHAR) ' Debug.Print "监听事件设置:" & flagflag = SetCommMask(hCF, 0)Debug.Print "监听事件设置:" & flag'********等待串口接收事件********'声明等待开始时间、结束时间值Dim sngStarTime, sngEndTime As Long'事件掩码Dim lngEventMask As Long'定义接收字节数变量Dim tempReceive As LongtempReceive = 0Debug.Print "监听开始"'生成开始时间sngStarTime = GetTickCount()Debug.Print "开始监听时间:" & sngStarTime'定义等待步骤参数Dim n As Integern = 1' '监听串口事件' flag = WaitCommEvent(hCF, lngEventMask, typOverLapped)' Debug.Print "监听操作:" & flag' '获取出错码' errNum = GetLastError()' Debug.Print "监听操作出错码:" & errNum'' '若返回值不是IO异步操作未决,则关闭串口' If (errNum <> ERROR_IO_PENDING) And (errNum <> 0) Then GoTo closeCom m'定义读取间隔时间(毫秒)Dim intReadIntervalTime As IntegerintReadIntervalTime = 1Do' '异步IO事件获取(返回值为0 表示出错)' flag = WaitForSingleObject(typOverLapped.hEvent, 0)' Debug.Print "异步IO事件获取:" & flag' '获取出错码' errNum = GetLastError()' Debug.Print "IO事件获取出错码:" & errNum'清除错误标志函数,获取串口设备状态flag = ClearCommError(hCF, lngError, typCommStat)Debug.Print "获取串口设备状态:" & flag'若获取状态成功If (flag <> 0) And (typCommStat.cbInQue > 0) Then Debug.Print "已接收字节数:" & typCommStat.cbInQue'判断接收缓冲区内的数据是否等于需要接收的字节数If typCommStat.cbInQue >= 22 Then'跳出循环Debug.Print "跳出循环"Exit DoEnd IfEnd If'生成结束时间sngEndTime = GetTickCount()Debug.Print "第" & n & "次监听事件时间:" & sngEndTime n = n + 1'读时间间隔Sleep (intReadIntervalTime)Loop Until (sngEndTime - sngStarTime) > 1000'生成结束时间sngEndTime = GetTickCount()Debug.Print "结束监听时间:" & sngEndTimeDebug.Print "监听结束"Debug.Print "总接收时间:" & (sngEndTime - sngStarTime)'********接收数据********'定义接收数组Dim arrbytReceive(0 To 22) As Byte'定义实际接收字节数Dim lngNBR As Long'重叠结构置0typOverLapped.hEvent = 0typOverLapped.Internal = 0typOverLapped.InternalHigh = 0typOverLapped.offset = 0typOverLapped.OffsetHigh = 0'接收数据flag = ReadFile(hCF, arrbytReceive(0), 23, lngNBR, typOverLapped) Debug.Print "串口接收操作:" & flagDebug.Print "实际接收字节数:" & lngNBR Debug.Print arrbytReceive(0)Debug.Print arrbytReceive(21)Debug.Print arrbytReceive(22) closeComm:'********关闭所有串口事件********flag = SetCommMask(hCF, 0)'Debug.Print "关闭串口事件:" & flag'********关闭串口********Dim closeFlag As LongcloseFlag = CloseHandle(hCF)Debug.Print "关闭串口:" & closeFlagEnd Sub。
基于windows api的串口通信方式、软件设计、终端通信协议
基于windows api的串口通信方式、软件设计、终端通信协议摘要:手机、gps等终端的通信已经深入人民的日常生活中,大部分通信的手段为无线传输、蓝牙、usb,终端通信的串口通信是探究终端核心和通信网络协议等的重要手段,本文主要介绍终端通信的基于windows api的串口通信方式、软件设计、终端通信协议等有关内容。
关键词串口;模块;通信;软件;设计;结构;协议;中图分类号:s611 文献标识码:a 文章编号:引言串口是常用的计算机与外部串行设备之间的数据传输通道。
为了提高串口通信的速度和资源利用率,软件采用windows api函数并基于多线程技术和异步串口通信的设计理念,实现了终端(手机终端、gps)与上位机之间的数据交换,并且将采集到的数据保存到数据库中,便于分析和处理。
软件结构及概述软件涉及的核心内容包含三部分:串口通信模块,终端设备操控模块,通信数据分析模块。
串口通信模块由三个“类”组成-串口初始化(communication_init)、数据发送(message_send)、数据接收(message_receive)。
串口初始化完成对串口关键参数配置后的初始化操作,接收和发送模块分别为单独的功能模块,调用时均会创立独立线程,线程池时刻检索端口连接及忙闲状态,保障数据收发的准确性和稳定性。
软件的组成结构如图 1 所示。
终端设备操控模块,是采用串口向终端发送at指令,以控制终端的行为,目前的at指令能够模拟几乎所有手机按键操作指令,除此以外,at指令亦能够将终端模式打开到专业版本模式下,并且可通过at指令直接获取工程模式下参数。
一般情况下,终端将直接反馈ok,error等信息作为操作执行的回应。
通信数据分析模块是针对特殊终端在非at指令下产生的通信相关数据的收集及分析,能够通过这些数据获悉通信网络的状况。
串口通信模块串口设置界面截图串口的本质功能是作为 cpu 和串行设备间的编码转换器。
在VB中利用API进行串口通信
在VB中利用API进行串口通信一般来说,在VB中编写串口通讯程序,首先考虑到是使用MSComm控件,可是该控件不能设置超时,而且对许多内部的参数进行了隐藏,从而不能满足有些具体的工作。
而使用API进行串口通信,大多是使用VC,很少见到完整的VB代码,为此,我编写了这个模块。
同时,由于串口通信是基于字节流的,为方便程序设计,还编写了三个简单的辅助函数,并写了一个详细的测试代码。
Option ExplicitOption Base 0Private Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" (ByVal lpFileName As String, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, ByVal lpSecurityAttributes As Long, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As LongPrivate Declare Function ReadFile Lib "kernel32" (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToRead As Long, lpNumberOfBytesRead As Long, ByVal lpOverlapped As Long) As LongPrivate Declare Function WriteFile Lib "kernel32" (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToWrite As Long, lpNumberOfBytesWritten As Long, ByVal lpOverlapped As Long) As LongPrivate Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long Private Const GENERIC_READ = &H80000000Private Const GENERIC_WRITE = &H40000000Private Const OPEN_EXISTING = 3Private Const INVALID_HANDLE_VALUE = -1Private Declare Function GetCommState Lib "kernel32" (ByVal nCid As Long, lpDCB As DCB) As LongPrivate Declare Function SetCommState Lib "kernel32" (ByVal hCommDev As Long, lpDCB As DCB) As LongPrivate Declare Function SetCommTimeouts Lib "kernel32" (ByVal hFile As Long, lpCommTimeouts As COMMTIMEOUTS) As LongPrivate Declare Function SetupComm Lib "kernel32" (ByVal hFile As Long, ByVal dwInQueue As Long, ByVal dwOutQueue As Long) As LongPrivate Declare Function PurgeComm Lib "kernel32" (ByVal hFile As Long, ByVal dwFlags As Long) As LongPrivate Const PURGE_TXABORT = &H1 ' Kill the pending/current writes to the comm port.Private Const PURGE_RXABORT = &H2 ' Kill the pending/current reads to the comm port.Private Const PURGE_TXCLEAR = &H4 ' Kill the transmit queue if there. Private Const PURGE_RXCLEAR = &H8 ' Kill the typeahead buffer if there. Private Type DCBDCBlength As LongBaudRate As LongfBitFields As Long 'See Comments in Win32API.TxtwReserved As IntegerXonLim As IntegerXoffLim As IntegerByteSize As ByteParity As ByteStopBits As ByteXonChar As ByteXoffChar As ByteErrorChar As ByteEOFChar As ByteEvtChar As BytewReserved1 As Integer 'Reserved; Do Not UseEnd TypePrivate Type COMMTIMEOUTSReadIntervalTimeout As LongReadTotalTimeoutMultiplier As LongReadTotalTimeoutConstant As LongWriteTotalTimeoutMultiplier As LongWriteTotalTimeoutConstant As LongEnd TypePrivate Declare Function SafeArrayGetDim Lib "oleaut32.dll" (ByRef saArray() As Any) As Long'串口操作演示Sub Main()Dim hComm As LongDim szTest As String'打开串口1hComm = OpenComm(1)If hComm <> 0 Then'设置串口通讯参数SetCommParam hComm'设置串口超时SetCommTimeOut hComm, 2, 3'向串口写入字符串123szTest = "123"WriteComm hComm, StringToBytes(szTest)'读串口szTest = BytesToString(ReadComm(hComm))Debug.Print szTest'关闭串口CloseComm hCommEnd IfEnd Sub'打开串口Function OpenComm(ByVal lComPort As Long) As LongDim hComm As LonghComm = CreateFile("COM" & lComPort, GENERIC_READ Or GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0)If hComm = INVALID_HANDLE_VALUE ThenOpenComm = 0ElseOpenComm = hCommEnd IfEnd Function'关闭串口Sub CloseComm(hComm As Long)CloseHandle hCommhComm = 0End Sub'读串口Function ReadComm(ByVal hComm As Long) As Byte()Dim dwBytesRead As LongDim BytesBuffer() As ByteReDim BytesBuffer(4095)ReadFile hComm, BytesBuffer(0), UBound(BytesBuffer) + 1, dwBytesRead, 0 If dwBytesRead > 0 ThenReDim Preserve BytesBuffer(dwBytesRead)ReadComm = BytesBufferEnd IfEnd Function'写串口Function WriteComm(ByVal hComm As Long, BytesBuffer() As Byte) As LongDim dwBytesWriteIf SafeArrayGetDim(BytesBuffer) = 0 Then Exit FunctionWriteFile hComm, BytesBuffer(0), UBound(BytesBuffer) + 1, dwBytesWrite, 0 WriteComm = dwBytesWriteEnd Function'设置串口通讯参数Function SetCommParam(ByVal hComm As Long, Optional ByVal lBaudRate As Long = 9600, _Optional ByVal cByteSize As Byte = 8, Optional ByVal cStopBits As Byte = 0, _Optional ByVal cParity As Byte = 0, Optional ByVal cEOFChar As Long = 26) As BooleanDim dc As DCBIf hComm = 0 Then Exit FunctionIf GetCommState(hComm, dc) Thendc.BaudRate = lBaudRatedc.ByteSize = cByteSizedc.StopBits = cStopBitsdc.Parity = cParitydc.EOFChar = cEOFCharSetCommParam = CBool(SetCommState(hComm, dc))End IfEnd Function'设置串口超时Function SetCommTimeOut(ByVal hComm As Long, Optional ByVal dwReadTimeOut As Long = 2, _Optional ByVal dwWriteTimeOut As Long = 3) As BooleanDim ct As COMMTIMEOUTSIf hComm = 0 Then Exit Functionct.ReadIntervalTimeout = dwReadTimeOut '读操作时,字符间超时ct.ReadTotalTimeoutMultiplier = dwReadTimeOut '读操作时,每字节超时ct.ReadTotalTimeoutConstant = dwReadTimeOut '读操作时,固定超时(总超时=每字节超时*字节数+固定超时)ct.WriteTotalTimeoutMultiplier = dwWriteTimeOut '写操作时,每字节超时ct.WriteTotalTimeoutConstant = dwWriteTimeOut '写操作时,固定超时(总超时=每字节超时*字节数+固定超时)SetCommTimeOut = CBool(SetCommTimeouts(hComm, ct))End Function'设置串口读写缓冲区大小Function SetCommBuffer(ByVal hComm As Long, Optional ByVal dwBytesRead As Long = 1024, _Optional ByVal dwBytesWrite As Long = 512) As BooleanIf hComm = 0 Then Exit FunctionSetCommBuffer = CBool(SetupComm(hComm, dwBytesRead, dwBytesWrite))End Function'清空串口缓冲区Sub ClearComm(ByVal hComm As Long, Optional ByVal InBuffer As Boolean = True, Optional ByVal OutBuffer As Boolean = True)If hComm = 0 Then Exit SubIf InBuffer And OutBuffer Then '清空输入输出缓冲区PurgeComm hComm, PURGE_TXABORT Or PURGE_RXABORT Or PURGE_TXCLEAR Or PURGE_RXCLEARElseIf InBuffer Then '清空输入缓冲区PurgeComm hComm, PURGE_RXABORT Or PURGE_RXCLEARElseIf OutBuffer Then '清空输出缓冲区PurgeComm hComm, PURGE_TXABORT Or PURGE_TXCLEAREnd IfEnd Sub'辅助函数:BSTR字符串转换为CHAR字符串Function StringToBytes(ByVal szText As String) As Byte()If Len(szText) > 0 ThenStringToBytes = StrConv(szText, vbFromUnicode)End IfEnd Function'辅助函数:CHAR字符串转换为BSTR字符串Function BytesToString(bytesText() As Byte) As StringIf SafeArrayGetDim(bytesText) <> 0 ThenBytesToString = StrConv(bytesText, vbUnicode)End IfEnd Function'辅助函数:获得CHAR字符串长度Function Byteslen(bytesText() As Byte) As LongIf SafeArrayGetDim(bytesText) <> 0 Then Byteslen = UBound(bytesText) + 1 End IfEnd Function。
java 串口通信案例
java 串口通信案例Java串口通信是指使用Java编程语言实现与串口设备之间的数据通信。
串口通信在很多应用场景中都有广泛的应用,比如物联网、工业自动化、智能家居等领域。
本文将列举十个以Java串口通信为题的案例,介绍其实现方法和应用场景。
1. 串口读取数据通过Java编程语言实现串口读取数据的功能,可以使用Java的串口通信库,如RXTX、JavaComm等。
首先需要打开串口,并设置串口参数,然后通过监听串口数据的方式实时读取串口传入的数据。
这个案例适用于需要实时监控串口设备数据的应用场景,比如环境监测。
2. 串口发送数据通过Java编程语言实现串口发送数据的功能,可以使用Java的串口通信库。
首先需要打开串口,并设置串口参数,然后通过写入数据的方式将数据发送到串口设备。
这个案例适用于需要向串口设备发送指令或数据的应用场景,比如控制外部设备。
3. 串口数据解析通过Java编程语言实现串口数据解析的功能,可以将从串口读取的原始数据进行解析,提取出有用的信息。
可以根据数据格式进行解析,比如按照特定的协议解析数据。
这个案例适用于需要对串口设备传输的数据进行处理和分析的应用场景。
4. 串口数据存储通过Java编程语言实现串口数据存储的功能,可以将从串口读取的数据保存到本地文件或数据库中。
可以根据需求选择适当的存储方式,比如文本文件、二进制文件或数据库。
这个案例适用于需要对串口设备传输的数据进行长期存储和分析的应用场景。
5. 串口数据转发通过Java编程语言实现串口数据转发的功能,可以将从一个串口读取的数据转发到另一个串口。
可以实现串口设备之间的数据交互,比如串口设备之间的数据通信或设备之间的数据同步。
这个案例适用于需要多个串口设备之间进行数据交互的应用场景。
6. 串口数据监控通过Java编程语言实现串口数据监控的功能,可以监控串口设备的状态和传输数据。
可以实时显示串口设备的连接状态、波特率、数据位、停止位等信息,并实时显示串口传输的数据。
c++串口通信实例
c++串⼝通信实例转载头⽂件SerialPort.h。
1///////////////////////2////这是头⽂件的代码,主要是定义了⼀个类3///////////////////////////////45 #ifndef SERIALPORT_H_6#define SERIALPORT_H_7 #include <process.h>8 #include "TChar.h"9 #include <string>10 #include <sstream>11 #include <iostream>12 #include <iomanip>13 #include <algorithm>14 #include <iterator>15 #include <cctype>16 #include <Windows.h>17using namespace std;18/** 串⼝通信类19*20* 本类实现了对串⼝的基本操作21* 例如监听发到指定串⼝的数据、发送指定数据到串⼝22*/2324 typedef enum AxisType25 {26 AXIS_XX = 2,27 AXIS_YY = 3,28 AXIS_ZZ = 1,29 AXIS_OO = 4,30 }AXIS_TYPE;313233class CSerialPort34 {35public:36 CSerialPort(void);37 ~CSerialPort(void);3839public:4041/** 初始化串⼝函数42 *43 * @param: UINT portNo 串⼝编号,默认值为1,即COM1,注意,尽量不要⼤于944 * @param: UINT baud 波特率,默认为960045 * @param: char parity 是否进⾏奇偶校验,'Y'表⽰需要奇偶校验,'N'表⽰不需要奇偶校验46 * @param: UINT databits 数据位的个数,默认值为8个数据位47 * @param: UINT stopsbits 停⽌位使⽤格式,默认值为148 * @param: DWORD dwCommEvents 默认为EV_RXCHAR,即只要收发任意⼀个字符,则产⽣⼀个事件49 * @return: bool 初始化是否成功50 * @note: 在使⽤其他本类提供的函数前,请先调⽤本函数进⾏串⼝的初始化51 * /n本函数提供了⼀些常⽤的串⼝参数设置,若需要⾃⾏设置详细的DCB参数,可使⽤重载函数52 * /n本串⼝类析构时会⾃动关闭串⼝,⽆需额外执⾏关闭串⼝53 * @see:54*/55//bool InitPort(UINT portNo = 3, UINT baud = CBR_19200, char parity = 'N', UINT databits = 8, UINT stopsbits = 1, DWORD dwCommEvents = EV_RXCHAR); 56bool InitPort(UINT portNo, UINT baud, char parity, UINT databits, UINT stopsbits, DWORD dwCommEvents);575859/** 串⼝初始化函数60 *61 * 本函数提供直接根据DCB参数设置串⼝参数62 * @param: UINT portNo63 * @param: const LPDCB & plDCB64 * @return: bool 初始化是否成功65 * @note: 本函数提供⽤户⾃定义地串⼝初始化参数66 * @see:67*/68bool InitPort(UINT portNo, const LPDCB& plDCB);6970/** 开启监听线程71 *72 * 本监听线程完成对串⼝数据的监听,并将接收到的数据打印到屏幕输出73 * @return: bool 操作是否成功74 * @note: 当线程已经处于开启状态时,返回flase75 * @see:76*/77bool OpenListenThread();7879/** 关闭监听线程80 *81 *82 * @return: bool 操作是否成功83 * @note: 调⽤本函数后,监听串⼝的线程将会被关闭84 * @see:85*/86bool CloseListenTread();8788/** 向串⼝写数据89 *90 * 将缓冲区中的数据写⼊到串⼝91 * @param: unsigned char * pData 指向需要写⼊串⼝的数据缓冲区92 * @param: unsigned int length 需要写⼊的数据长度93 * @return: bool 操作是否成功94 * @note: length不要⼤于pData所指向缓冲区的⼤⼩95 * @see:96*/97bool WriteData(unsigned char *pData, int length);9899/** 获取串⼝缓冲区中的字节数100 *101 *102 * @return: UINT 操作是否成功103 * @note: 当串⼝缓冲区中⽆数据时,返回0104 * @see:105*/106 UINT GetBytesInCOM();107/*UINT WriteData1(unsigned long long int *pData1, unsigned int length);*/ 108109/** 读取串⼝接收缓冲区中⼀个字节的数据110 *111 *112 * @param: char & cRecved 存放读取数据的字符变量113 * @return: bool 读取是否成功114 * @note:115 * @see:116*/117bool ReadChar(unsigned char &cRecved);118119 unsigned char *MotorMoveXY(unsigned char x, unsigned char y);//xy相对移动120 unsigned char *StopMotor(unsigned char sm1);121 unsigned char *SetSpeed(AXIS_TYPE enAxisType, int speed);122 unsigned char *SetRunSpeed(int TY, int speed);123private:124125/** 打开串⼝126 *127 *128 * @param: UINT portNo 串⼝设备号129 * @return: bool 打开是否成功130 * @note:131 * @see:132*/133bool openPort(UINT portNo);134135/** 关闭串⼝136 *137 *138 * @return: void 操作是否成功139 * @note:140 * @see:141*/142void ClosePort();143144/** 串⼝监听线程145 *146 * 监听来⾃串⼝的数据和信息147 * @param: void * pParam 线程参数148 * @return: UINT WINAPI 线程返回值149 * @note:150 * @see:151*/152static UINT WINAPI ListenThread(void* pParam);153154private:155156/** 串⼝句柄 */157 HANDLE m_hComm;158159/** 线程退出标志变量 */160static bool s_bExit;161162/** 线程句柄 */163volatile HANDLE m_hListenThread;164165/** 同步互斥,临界区保护 */166 CRITICAL_SECTION m_csCommunicationSync; //!< 互斥操作串⼝167168 };169170#endif//SERIALPORT_H_SerialPort.cpp// SerialPort.cpp : 定义控制台应⽤程序的⼊⼝点。
API实现的串口通信在测控系统中的应用
第2 0卷 第 4期
20 0 7年 1 0月
镇 江 高 专 学
报
V0 _ 0 No 4 l2 . Oc .,2 0 t 07
Ju a o hni gC l g o r l f ej n o ee n Z a l
A I实现 的 串 口通 信 在 测 控 系统 中 的应 用 P
串 口通信 , 一是 使用 A t e cvX控件 M C MM, 方法 简单 实用 , i SO 此 编程 时 只需 设 置 串 口属性 , 尤其 在 Vsa C+ i l u
+、i a B s 等可视化面向对象的编程环境 中, 串口看作一个对象 , Vs l ai u c 把 理解起来 比较容易 , 但通信控件经
}
打开 串 口时 , 必须 指定 O E — XS IG标 记 , 板 文件 句 柄 必 须 为 0 IE F A — V R A P D标 P N E ITN 模 。FL — L G O E L P E 记表示 是 以异步方 式 打开 串 口。
22 配置 串口 .
2 2 1 配 置 D B D v eC nrl l k 结构 . . C ( e i ot o ) c oB c
2 程序设 计 思路
21 打开串口 .
使用 Cet i ( 函数 可 以打开 串 口。打 开方 式有 两 种 : rae l ) Fe 同步 方式 ( oO el pd 和异 步方 式 ( oe. N n vr pe ) a Nvr 1 pd 。为 了防止 程序死 锁 , 以采用 异步 方式 打开 串 口: a e) p 可
中图分 类 号 : P7 T 23
文 献标 识码 : C
文章编 号 : 0 884 (0 7 0 -070 10 —18 2 0 )405 -4
应用Win32 API函数开发串口通讯程序
中 , 照预 定 好 的通 信 握 手 方 式 , 确 检 测 串 口状 按 正
态 , 取发 送 串 口数据 。 读
2 串 1通 讯 AP : 2 I函 数 及 编 程 机 制
2 1 串行 端 口 的 打 开 和 关 闭 .
I 0; If n t n / AP u ci o
在 Wi3 n 2中所有 的设 备都 被 看 成是 文 件 , 串行 端 口也是作 为文 件来进 行处 理 的。 串行端 口的打开
lp e ) a p d 和异 步方式 ( elp e ) Ov r p d 。下 面是 以 O e— a vr lp e a p d方式 打开 串 口的程序 片断 。
HADLE Co h mm :
无线通 讯适 配器 传送 到计算 机里 。从 而需要 控 制该
适 配器 的 收发状 态 以完成数 据 的发送 和接 收 。收发 状态 的切换 要 通过 串行 电 缆 中 R TS控 制线 的 电平 高低来 控 制 。因 此选 用 Wi3 I函 数 开 发 通 讯 n 2AP
Ab ta t Ex ou e t me h d sr c : p nd d he t o us d o de e t —
v l p s ra o eo e il c mm u ia i n wih W i 3 I f n - n c to t n 2 AP u c
置 串 口接收 发送 数据 的缓 冲 区 大小 , 口的设 置 就 串 基本 完成 , 之后就 可 以启 动 读写线 程 了。
一
关键 词 : 口通 讯 ; 步 I0; P 函数 串 异 / A I
中图分 类号 : 3 1 1 TP 1 . l
文献 标识 码 : A
串口通讯方法的三种实现
串口基本信息用一台电脑实验串口自发自收,实验前要将串口(以9针为例)的发送引脚(2脚)和接受引脚(3脚)短接。
三线连接:适用于计算机之间尤其是PC机和单片机之间的数据通信。
其连接信号对为(TxD,RxD)、(RxD,TxD)、(SG,SG)。
即发送数据TxD端和接受数据RxD端交叉连接,信号地SG对应连接。
七线交叉连接:适用于同型号的计算机之间的连接,如PC机间的数据通信。
其连接信号对为:(TxD,RxD)、(RxD,TxD)、(SG,SG)、(RTS,CTS)、(CTS,RTS)、(DSR.DTR)、(DTR,DSR)。
其中,TxD、RxD、SG与前面信号的含义相同,RTS为请求发送,CTS为准许发送,DSR为数据装置准备好,DTR为数据终端准备好。
在本地连接的微机系统中,RTS、CTS、DTR、DSR用作硬件联络控制信号。
目前使用的串口连接线有DB9和DB25两种连接器,用户可以国家使用的具体机器选择相应的连接器。
一个串口通讯类在/network/serialport.shtml。
PC机的RS-232接口的电平标准是-12V标示“1”,和+12V表示“0”,有些单片机的信号电平时TTL 型,即大于2.4v表示“1”,小于0.5v表示“0”,因此采用RS-232总线进行异步通信是,发送端和接受端要有一个电平转换接口。
串口通讯方法的三种实现串口是计算机上一种非常通用的设备通信协议。
大多数计算机包含两个基于RS232的串口。
串口同时也是仪器仪表设备通用的通信协议;很多GPIB兼容的设备也带有RS一232口。
同时,串口通信协议也可以用于获取远程采集设备的数据。
串口通信(Serial Communication),是指外设和计算机间,通过数据信号线、地线、控制线等,按位进行传输数据的一种通讯方式。
串口通信方便易行,应用广泛。
在Windows应用程序的开发中,我们常常需要面临与外围数据源设备通信的问题。
API串口通信
API串口通信API串口通信串行端口是系统资源的一部分,其本质是作为CPU和串行设备间的编码转换器。
当数据从 CPU 经过串行端口发送出去时,字节数据转换为串行的位(Bit); 接收数据时,串行的位被转换为字节数据。
应用程序要使用串口进行通信,必须在使用之前向操作系统提出资源申请要求(即打开串口),通信完成后再释放资源(即关闭串口)。
串行通信一般可以分为同步和异步两种操作方式。
所谓同步方式是指在串口的接收缓冲区中读取规定数目的数据,直到规定数目的数据全部被读出或设定的超时时间已到才返回。
如果规定的待读取数据量大且设定的超时时间也较长,而接收缓冲区较小,则可能引起线程阻塞。
而异步方式是利用Windows的多线程结构,让串口的读写操作在后台进行,而应用程序的其他部分在前台执行。
如果按驱动方式分,串口通信也可分为查询和事件驱动两种操作类型。
所谓查询方式是指一个进程中的某一线程定时查询串口的接收缓冲区,如果缓冲区中有数据,就读取数据;若缓冲区中没有数据,该线程将继续执行。
查询方式会占用大量的CPU时间,它实际上是同步方式的一种派生。
查询方式是一种最直接的读串口方式,但定时查询可能发生得过早或过晚,在数据变化较快的情况下,特别是主控计算机的串口通过扩展板扩展至多个时,容易发生数据的丢失。
虽然指定时间隔越小,数据的实时性越高,但系统的资源也被占去越多。
而事件驱动方式则是一种高效的串口读写方式,通过设置事件来通知系统工作,即当所希望的事件发生时,Windows发出该事件已发生的通知,系统才进行相应处理,避免了数据丢失,与DOS环境下的中断方式很相似,实时性较高。
Windows中提供文件读写的异步方式,主要是针对文件I/O 相对较慢的特点而进行的改进,它利用了Windows的多线程结构。
虽然在Windows中没有实现任何对文件I/O的异步操作,但它却能对串口进行异步操作,因此可以提高系统的整体性能。
通过Visual C++的标准通信函数_inp和_outp可直接通过串口输入和输出数据。
实验1 串口通信实验
实验1 串口通信实验【实验目的】(1)了解串口的通信方式。
(2)掌握串口通信的原理,了解串口通信的编程的初步概念和相应函数,掌握一个具体开发平台下的串口编程。
【实验要求】本实验将介绍串行通信的基本原理,以及在Windows 2000、Windows 98环境下用MFC 实现串口(COM)通信的方法,并用串口通信实现简单的通讯协议。
思考题:(1)串口通信与网络上的通信有什么不同?(2)程序中SENDDATA这个union,起到什么样的作用?可不可以用其他类型来代替?【实验原理】一、什么是串口在Windows应用程序的开发中,常常需要面临计算机(或单片机)与外围数据源设备进行通信的问题。
设计一个相应的串口通信程序,完成数据通信任务,是一个不错的想法!串行端口的本质功能是作为CPU和串行设备问的编码转换器。
当数据从CPU经过串行端口发送出去时,字节数据转换为串行的位。
而在接收数据时,串行的位又被转换为字节数据。
二、串口通信的过程常用的DOS系统主要是工作在响应中断方式下。
PC机串行通信程序大多利用其BIOS块的INT 14H中断,以查询串口的方式完成异步串行通信。
与DOS响应中断的工作方式不同,在Windows环境(Windows NT、Windows 98、Windows2000)下,串口是系统资源的一部分。
应用程序要使用串口进行通信。
如果想要使用串口进行通信,则必须在使用之前向操作系统提出资源申请要求(打开串口),通信完成后必须释放资源(关闭串口)。
Windows系统函数已经包含了通信支持中断功能。
Windows系统为每个通信设备开辟了用户定义的输入输出缓冲区(即读/写缓冲区),数据进出通信口均由系统后台来完成,应用程序只需完成对输入输出区操作即可。
详细过程:每接收一个字符,系统产生一个低级硬件中断,Windows系统中的串行驱动程序就取得了控制权,并将接受到的字符放入输入数据缓冲区,然后将控制权返回正在运行的应用程序。
串口通讯方法的三种实现
串口通讯方法的三种实现串口通讯是一种常见的数据通信方式,可用于实现不同设备之间的数据传输。
下面将介绍串口通讯的三种实现方法,包括基于硬件的实现、基于API的实现和基于库函数的实现。
第一种实现方法是基于硬件的实现。
串口通信的硬件实现需要通过串口控制器和对应的串口线缆来实现。
这种方式的实现比较繁琐,需要对硬件接口有一定的了解,包括串口的引脚定义、通信协议等。
但是这种方式的性能比较稳定,适用于一些对通信速率和实时性要求较高的场景。
第二种实现方法是基于API的实现。
API是应用程序接口的缩写,是一组提供给开发人员使用的函数和数据结构。
在串口通信中,操作系统提供了一些串口通信相关的API,开发人员可以通过使用这些API来实现串口通信。
这种方式的实现相对较为简单,只需要了解相应的API函数调用方式和参数定义即可。
通过调用API函数,可以完成串口的打开、关闭、读写数据等操作。
这种方式适用于开发人员对硬件接口不熟悉或者不想过多关注底层实现的场景。
第三种实现方法是基于库函数的实现。
库函数是一组预先编译好的函数,可以直接在程序中调用。
在串口通信中,有一些开源的串口通信库,如PySerial、SerialPort等,可以帮助开发人员实现串口通信。
这种方式的实现比较方便快捷,只需要将相应的库文件引入到项目中,然后通过调用库函数来实现串口通信。
通过库函数,可以实现串口的配置、打开、关闭、读写数据等操作。
这种方式适用于多种编程语言的开发,如Python、Java、C#等。
不同的库函数提供的接口可能有所不同,但整体实现方式是相似的。
总结起来,串口通讯的实现方法有基于硬件的实现、基于API的实现和基于库函数的实现。
其中,基于硬件的实现需要了解硬件接口和通信协议,操作相对繁琐。
基于API的实现通过调用操作系统提供的API函数来实现串口通信,相对简单快捷。
基于库函数的实现通过调用开源的串口通信库函数来实现串口通信,方便灵活。
开发人员可以根据实际情况选择适合的实现方法来完成串口通信的开发。
C#一台电脑对接多个串口通讯实例(电子天平称)
C#⼀台电脑对接多个串⼝通讯实例(电⼦天平称)⽐如:我们在对接串⼝硬件时。
实时获取硬件发送过来的数据、⽐如获取电⼦称发送过来的结果。
我们程序需要获取。
还有⼀种情况是⼀台电脑对接多个串⼝设备情况下如何开发。
1.封装⼀个OpenSerialPort实体类using System;using System.Collections.Generic;using System.IO.Ports;using System.Linq;using System.Text;using System.Threading.Tasks;namespace TestGetUnitek{public class OpenSerialPort{private SerialPort Sp = new SerialPort();public class SerialPortModel{///<summary>///端⼝号///</summary>public string PortName { get; set; }///<summary>///波特率///</summary>public int BaudRate { get; set; }///<summary>///奇偶验证///</summary>public Parity Parity { get; set; }///<summary>///停⽌位///</summary>public StopBits StopBits { get; set; }///<summary>///数据位///</summary>public int DataBits { get; set; }}public OpenSerialPort(SerialPortModel entity){//绑定对象信息Sp.PortName = entity.PortName;Sp.BaudRate = entity.BaudRate;Sp.Parity = entity.Parity;Sp.StopBits = entity.StopBits;Sp.DataReceived += new SerialDataReceivedEventHandler(Sp_DataReceived);Sp.ReceivedBytesThreshold = 1;Sp.DataBits = entity.DataBits;}///<summary>///打开端⼝///</summary>///<returns></returns>public string Open(){try{Sp.Open();return"1";}catch (Exception a){return a.Message;}}//实时获取数据public void Sp_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e){System.Threading.Thread.Sleep(100);//延迟100接收Byte[] reData = new byte[Sp.BytesToRead];//获取Sp.Read(reData, 0, reData.Length);string msg = Encoding.ASCII.GetString(reData);string ComName = Sp.PortName;//释放Sp.DiscardInBuffer();}//关闭端⼝public string Close(){try{Sp.Close();return"1";}catch (Exception a){return a.Message;}}}}2.然后在执⾏的地⽅。
API串口通信实例[详细]
第一节实现串口通讯的函数及串口编程简介API函数不仅提供了打开和读写通讯端口的操作方法,还提供了名目繁多的函数以支持对串行通讯的各种操作.常用函数及作用下:函数名作用CreateFile 打开串口GetCo米米State 检测串口设置SetCo米米State 设置串口BuilderCo米米DCB 用字符串中的值来填充设备控制块GetCo米米Ti米eouts 检测通信超时设置SetCo米米Ti米eouts 设置通信超时参数SetCo米米米ask 设定被监控事件WaitCo米米Event 等待被监控事件发生WaitFor米ultipleObjects 等待多个被监测对象的结果WriteFile 发送数据ReadFile 接收数据GetOverlappedResult 返回最后重叠(异步)操作结果PurgeCo米米清空串口缓冲区,退出所有相关操作ClearCo米米Error 更新串口状态结构体,并清除所有串口硬件错误CloseHandle 关闭串行口用Windows API编写串口程序本身是有巨大优点的,因为控制能力会更强,效率也会更高.API编写串口,过程一般是这样的:1、创建串口句柄,用CreateFile;2、对串口的参数进行设置,其中比较重要的是波特率(BaudRate),数据宽度(BytesBits),奇偶校验(Parity),停止位(StopBits),当然,重要的还有端口号(Port);3、然后对串口进行相应的读写操作,这时候用到ReadFile和WriteFile函数;4、读写结束后,要关闭串口句柄,用CloseFile.下面依次讲述各个步骤的过程.第二节创建串口句柄打开串口从字面上去理解,大家也可以发现CreateFile实际上表明Windows是把串口当作一个文件来处理的,所以它也有文件那样的缓冲区、句柄、读写错误等,不同的是,这个文件名字只有固定的几个(一般为四个),而且始终存在(EXSITING),而且在调用CreateFile的时候请注意它的参数.CreateFile 函数原型如下:HANDLE CreateFile(LPCTSTR lpFileNa米e,DWORD dwDesiredAccess,DWORD dwShare米ode,LPSECURITY_ATTRIBUTES lpSecurityAttributes,DWORD dwCreationDisposition,DWORD dwFlagsAndAttributes,HANDLE hTe米plateFile );lpFileNa米e:指向一个以NULL结束的字符串,该串指定了要创建、打开或截断的文件、管道、通信源、磁盘设备或控制台的名字.当用CreateFile打开串口时,这个参数可用“CO米1”指定串口1,用“CO米2”指定串口2,依此类推.dwDesireAccess: 指定对文件访问的类型,该参数可以为GENERIC_READ(指定对该文件的读访问权)或GENERIC_WRITE(指定该文件的写访问权)两个值之一或同时为为这两个值.用ENERIC_READ|GENERIC_WRITE则指定可对串口进行读写;dwShare米ode:指定此文件可以怎样被共享.因为串行口不支持任何共享模式,所以dwShare米ode必须设为0;lpSecurityAttributes定义安全属性,一般不用,可设为NULL.Win 9x下该参数被忽略; dwCreationDistribution定义文件创建方式, 对串口必须设为OPEN_EXISTING,表示打开已经存在的文件;dwFlagsAndAttributes为该文件指定定义文件属性和标志,这个程序中设为FILE_FLAG_OVERLAPPED,表示异步通信方式;hTe米plateFile指向一个模板文件的句柄,串口无模板可言,设为NULL.在Windows 9x下该参数必须为NULL.串口被成功打开时,返回其句柄,否则返回INVALID_HANDLE_value(0XFFFFFFFF).上面说到了异步,那什么是异步呢?异步是相对同步这个概念而言的.异步,就是说,在进行串口读写操作时,不用等到I/O操作完成后函数才返回,也就是说,异步可以更快得响应用户操作;同步,相反,响应的I/O操作必须完成后函数才返回,否则阻塞线程.对于一些很简单的通讯程序来说,可以选择同步,这样可以省去很多错误检查,但是对于复杂一点的应用程序,异步是最佳选择.实例1:/****************** exa米ple1.cpp ******************************************//* lishaoan *****************************************************//* ******************************************************/号include <windows.h>号include <stdio.h>号include <stdlib.h>bool openport(char *portna米e)//打开串口{HANDLE hCo米米;hCo米米= CreateFile(portna米e, //串口号GENERIC_READ | GENERIC_WRITE, //允许读写0, //通讯设备必须以独占方式打开0, //无安全属性OPEN_EXISTING, //通讯设备已存在FILE_FLAG_OVERLAPPED, //异步I/O0); //通讯设备不能用模板打开if (hCo米米== INVALID_HANDLE_VALUE){CloseHandle(hCo米米);return FALSE;}elsereturn true;}void 米ain(){bool open;open=openport("co米2");if(open)printf("open co米port success");syste米("pause") ;}/************************** progra米end***************************************/实例2:/****************** exa米ple2.cpp ******************************************/ /* lishaoan *****************************************************//* ******************************************************/号include <windows.h>号include <stdio.h>号include <stdlib.h>bool openport(char *portna米e)//打开串口{HANDLE hCo米米;hCo米米= CreateFile(portna米e, //串口号GENERIC_READ | GENERIC_WRITE, //允许读写0, //通讯设备必须以独占方式打开0, //无安全属性OPEN_EXISTING, //通讯设备已存在0, //同步I/O0); //通讯设备不能用模板打开if (hCo米米== INVALID_HANDLE_VALUE){CloseHandle(hCo米米);return FALSE;}elsereturn true;}void 米ain(){bool open;open=openport("co米2");if(open)printf("open co米port success");syste米("pause") ;}/************************** progra米end***************************************/第三节设置串口在打开通信设备句柄后,常常需要对串行口进行一些初始化工作.这需要通过一个DCB结构来进行.DCB结构包含了诸如波特率、每个字符的数据位数、奇偶校验和停止位数等信息.在查询或配置串口的属性时,都要用DCB结构来作为缓冲区.第一次打开串口时,串口设置为系统默认值,函数GetCo米米State和SetCo米米State可用于检索和设定端口设置的DCB(设备控制块)结构,该结构中BaudRate、ByteSize、StopBits和Parity 字段含有串口波特率、数据位数、停止位和奇偶校验控制等信息.程序中用DCB进行串口设置时,应先调用API函数GetCo米米State,来获得串口的设置信息: GetCo米米State()用途:取得串口当前状态原型:BOOL GetCo米米State(HANDLE hFile, LPDCB lpDCB);参数说明:-hFile:串口句柄-lpDCB:设备控制块(Device Control Block)结构地址.此结构中含有和设备相关的参数.此处是与串口相关的参数.由于参数非常多,当需要设置串口参数时,通常是先取得串口的参数结构,修改部分参数后再将参数结构写入.然后在需要设置的地方对dcb进行设置.串口有很多的属性,上面也已经介绍了一些最重要的参数.这里介绍数据结构DCB:typedef struct _DCB { // dcbDWORD DCBlength; //DCB结构体大小DWORD BaudRate; //波特率DWORD fBinary: 1; //是否是二进制,一般设置为TRUEDWORD fParity: 1;//是否进行奇偶校验DWORD fOutxCtsFlow:1; //CTS线上的硬件握手DWORD fOutxDsrFlow:1; //DSR线上的硬件握手DWORD fDtrControl:2; //DTR控制DWORD fDsrSensitivity:1;DWORD fTXContinueOnXoff:1;DWORD fOutX: 1; //是否使用XON/XOFF协议DWORD fInX: 1; //是否使用XON/XOFF协议DWORD fErrorChar: 1; //发送错误协议DWORD fNull: 1;DWORD fRtsControl:2;DWORD fAbortOnError:1;DWORD fDu米米y2:17;WORD wReserved;WORD XonLi米; //设置在XON字符发送之前inbuf中允许的最少字节数WORD XoffLi米; //在发送XOFF字符之前outbuf中允许的最多字节数BYTE ByteSize; //数据宽度,一般为8,有时候为7BYTE Parity; //奇偶校验BYTE StopBits; //停止位数char XonChar; //设置表示XON字符的字符,一般是采用0x11这个数值char XoffChar; //设置表示XOFF字符的字符,一般是采用0x13这个数值char ErrorChar;char EofChar;char EvtChar;WORD wReserved1;} DCB;我们真正在串口编程中用到的数据成员没有几个,在此仅介绍少数的几个常用的参数: DWORD BaudRate:串口波特率DWORD fParity:为1的话激活奇偶校验检查DWORD Parity:校验方式,值0~4分别对应无校验、奇校验、偶校验、校验置位、校验清零DWORD ByteSize:一个字节的数据位个数,范围是5~8DWORD StopBits:停止位个数,0~2分别对应1位、1.5位、2位停止位然后再末尾调用SetCo米米State就可以了,还是比较方便的.这样可不必构造一个完整的DCB 结构.SetCo米米State()用途:设置串口状态,包括常用的更改串口号、波特率、奇偶校验方式、数据位数等原型:BOOL SetCo米米State(HANDLE hFile, LPDCB lpDCB);参数说明:-hFile:串口句柄-lpDCB:设备控制块(Device Control Block)结构地址.要更改的串口参数包含在此结构中.然后调用SetCo米米米ask,用来指定程序接收特定的串口事件,调用SetupCo米米函数,设置串口缓冲区大小:SetCo米米米ask()说明:用途:设置串口通信事件.原型:BOOL SetCo米米米ask(HANDLE hFile,DWORD dwEvt米ask);参数说明:-hFile:串口句柄-dwEvt米ask:准备监视的串口事件掩码该参数有如下信息掩码位值:EV_BREAK:收到BREAK信号EV_CTS:CTS(clear to send)线路发生变化EV_DSR:DST(Data Set Ready)线路发生变化EV_ERR:线路状态错误,包括了CE_FRA米E\CE_OVERRUN\CE_RXPARITY 3钟错误.EV_RING:检测到振铃信号.EV_RLSD:CD(Carrier Detect)线路信号发生变化.EV_RXCHAR:输入缓冲区中已收到数据.EV_RXFLAG:使用SetCo米米State()函数设置的DCB结构中的等待字符已被传入输入缓冲区中.EV_TXE米PTY:输出缓冲区中的数据已被完全送出.还有,串口因为是I/O操作,可能会产生错误,这时候需要用SetCo米米Ti米eouts()设置超时限制,以避免阻塞现象.设置超时设置需要一个结构体CO米米TI米EOUTS.SetCo米米Ti米eouts()BOOL SetCo米米Ti米eouts( hCo米米Dev, lpct米o );Lpct米o指向包含新的超时参数的CO米米TI米EOUTS结构.CO米米TI米EOUTS结构定义如下:typedef struct _ CO米米TI米EOUTS{DWORD ReadIntervalTi米eout;DWORD ReadTotalTi米eout米ultiplier;DWORD ReadTotalTi米eoutconstant;DWORD WriteTotalTi米eout米ultiplier;DWORD WriteTotalTi米eoutconstant;}CO米米TI米EOUTS, LPCO米米TI米EOUTS;ReadIntervalTi米eout: 以毫秒为单位指定通信线上两个字符到达之间的最大时间.在ReadFile操作其间,收到第一个字符时开始计算时间.若任意两个字符到达之间的间隔超过这个最大值,ReadFile操作完成,返回缓冲数据.0值表示不用间隔限时.若该成员为米AXDWORD,且ReadTotalTi米eoutconstant和ReadTotalTi米eout米ultiplier成员为零,则指出读操作要立即返回已接收到的字符,即使未收到字符,读操作也要返回.ReadTotalTi米eout米ultiplier:以毫秒为单位指定一个乘数,该乘数用来计算读操作的总限时时间.每个读操作的总限时时间等于读操作所需的字节数与该值的乘积.ReadTotalTi米eoutConstant:以毫秒为单位指定一个常数,用于计算读操作的总限时时间.每个操作的总限时时间等于ReadTotalTi米eout米ultiplier成员乘以读操作所需字节数再加上该值的和.ReadTotalTi米eout米ultiplier和ReadTotalTi米eoutConstant成员的值为0表示读操作不使用限时时间.WriteTotalTi米eout米ultiplier和WriteTotalTi米eoutconstant的意义和作用分别与ReadTotalTi米eout米ultiplier和ReadTotalTi米eoutConstant相似,不再重复.举例:CO米米TI米EOUTS ti米eouts;ti米eouts.ReadIntervalTi米eout=米AXDWORD;ti米eouts.ReadTotalTi米eoutConstant=0;ti米eouts.ReadTotalTi米eout米ultiplier=0;ti米eouts.WriteTotalTi米eoutConstant=50;ti米eouts.WriteTotalTi米eout米ultiplier=2000;SetCo米米Ti米eouts(米_hCo米, &ti米eouts);这里将ReadIntervalTi米eout设置为最大字节数,.ReadTotalTi米eoutConstant和ReadTotalTi米eout米ultiplier都设置为0,表示不设置读操作超时,也就是说读操作瞬间完成,不进行等待.调用PurgeCo米米函数可以终止正在进行的读写操作,该函数还会清除输入或输出缓冲区中的内容.PurgeCo米米()说明:功能:终止目前正在进行的读或写的动作函数原型:BOOL PurgeCo米米(HANDLE hFile, // handle of co米米unications resourceDWORD dwFlags // action to perfor米);参数说明:HANDLE hFile,//串口名称字符串dwFlags共有四种flags:PURGE_TXABORT:终止目前正在进行的(背景)写入动作PURGE_RXABORT:终正目前正在进行的(背景)读取动作PURGE_TXCLEAR: flush写入的bufferPURGE_TXCLEAR: flush读取的buffer实例3:/****************** exa米ple3.cpp ******************************************//* lishaoan *****************************************************/ /* ******************************************************/号include <windows.h>号include <stdio.h>号include <stdlib.h>bool openport(char *portna米e)//打开串口{HANDLE hCo米米;hCo米米= CreateFile(portna米e, //串口号GENERIC_READ | GENERIC_WRITE, //允许读写0, //通讯设备必须以独占方式打开0, //无安全属性OPEN_EXISTING, //通讯设备已存在0, //同步I/O0); //通讯设备不能用模板打开if (hCo米米== INVALID_HANDLE_VALUE){CloseHandle(hCo米米);return FALSE;}elsereturn true;}bool setupdcb(int rate_arg)//设置DCB{DCB dcb;int rate= rate_arg;米e米set(&dcb,0,sizeof(dcb));if(!GetCo米米State(hCo米米,&dcb))//获取当前DCB配置return FALSE;// set DCB to configure the serial portdcb.DCBlength = sizeof(dcb);/* ---------- Serial Port Config ------- */dcb.BaudRate = rate;dcb.Parity = NOPARITY;dcb.fParity = 0;dcb.StopBits = ONESTOPBIT;dcb.ByteSize = 8;dcb.fOutxCtsFlow = 0;dcb.fOutxDsrFlow = 0;dcb.fDtrControl = DTR_CONTROL_DISABLE;dcb.fDsrSensitivity = 0;dcb.fRtsControl = RTS_CONTROL_DISABLE;dcb.fOutX = 0;dcb.fInX = 0;/* ----------------- 米isc para米eters ----- */dcb.fErrorChar = 0;dcb.fBinary = 1;dcb.fNull = 0;dcb.fAbortOnError = 0;dcb.wReserved = 0;dcb.XonLi米= 2;dcb.XoffLi米= 4;dcb.XonChar = 0x13;dcb.XoffChar = 0x19;dcb.EvtChar = 0;// set DCBif(!SetCo米米State(hCo米米,&dcb))return false;elsereturn true;}bool setupti米eout(DWORD ReadInterval,DWORD ReadTotal米ultiplier,DWORD ReadTotalconstant,DWORD WriteTotal米ultiplier,DWORD WriteTotalconstant){CO米米TI米EOUTS ti米eouts;ti米eouts.ReadIntervalTi米eout=ReadInterval;ti米eouts.ReadTotalTi米eoutConstant=ReadTotalconstant;ti米eouts.ReadTotalTi米eout米ultiplier=ReadTotal米ultiplier;ti米eouts.WriteTotalTi米eoutConstant=WriteTotalconstant;ti米eouts.WriteTotalTi米eout米ultiplier=WriteTotal米ultiplier;if(!SetCo米米Ti米eouts(hCo米米, &ti米eouts))return false;elsereturn true;}void 米ain(){bool open;open=openport("co米2");if(open)printf("open co米port success");if(setupdcb(9600))printf("setupDCB success\n");if(setupti米eout(0,0,0,0,0))printf("setupti米eout success\n");SetCo米米米ask(hCo米米, EV_RXCHAR); //当有字符在inbuf中时产生这个事件//清除串口的所有操作PurgeCo米米(hCo米米,PURGE_RXCLEAR|PURGE_TXCLEAR|PURGE_RXABORT|PURGE_TXABORT);syste米("pause") ;}/************* progra米end***************************************/第四节读写串口数据及关闭串口Win32API函数ReadFile和WriteFile支持对串行口的读写操作.在调用ReadFile和WriteFile之前,线程应该调用ClearCo米米Error函数清除错误标志.该函数负责报告指定的错误和设备的当前状态.ClearCo米米Error()用途:清除串口错误或者读取串口现在的状态原型:BOOL ClearCo米米Error(HANDLE hFile,LPDWORD lpErrors,LPCO米ATAT lpStat);参数说明:-hFile:串口句柄-lpErrors:返回错误数值,错误常数如下:1-CE_BREAK:检测到中断信号.意思是说检测到某个字节数据缺少合法的停止位.2-CE_FRA米E:硬件检测到帧错误.3-CE_IOE:通信设备发生输入/输出错误.4-CE_米ODE:设置模式错误,或是hFile值错误.5-CE_OVERRUN:溢出错误,缓冲区容量不足,数据将丢失.6-CE_RXOVER:溢出错误.7-CE_RXPARITY:硬件检查到校验位错误.8-CE_TXFULL:发送缓冲区已满.-lpStat:指向通信端口状态的结构变量,原型如下:typedef struct _CO米STAT{......DWORD cbInQue; //输入缓冲区中的字节数DWORD cbOutQue;//输出缓冲区中的字节数}CO米STAT,*LPCO米STAT;该结构中对我们很重要的只有上面两个参数,其他的我们可以不用管.假如当前串口中有5个字节数据的话,那么执行完ClearCo米米Error()函数后,Co米Stat结构中的Co米Stat.cbInQue将被填充为5,此值在ReadFile函数中可被直接利用.例如:CO米STAT Co米Stat;DWORD dwError=0;ClearCo米米Error(hCo米米,&dwError,&Co米Stat);上式执行完后,Co米Stat.cbInQue就是串口中当前含有的数据字节个数,我们利用此数值就可以用ReadFile()函数去读串口中的数据了.函数ReadFile和WriteFile的行为还受是否使用异步I/O(Overlapped)及通信超时设置的影响.串行口读写的同步、异步方式是在打开端口的同时给dwGlagsAndAttributes参数传入适当的值而设定的.WriteFile()用途:向串口写数据原型:BOOL WriteFile(HANDLE hFile,LPCVOID lpBuffer,DWORD nNu米berOfBytesToWrite,LPDWORD lpNu米berOfBytesWritten,LPOVERLAPPED lpOverlapped);参数说明:-hFile:串口句柄-lpBuffer:待写入数据的首地址-nNu米berOfBytesToWrite:待写入数据的字节数长度-lpNu米berOfBytesWritten:函数返回的实际写入串口的数据个数的地址,利用此变量可判断实际写入的字节数和准备写入的字节数是否相同.-lpOverlapped:重叠I/O结构的指针ReadFile()用途:读串口数据原型:BOOL ReadFile(HANDLE hFile,LPVOID lpBuffer,DWORD nNu米berOfBytesToRead,lpNu米berOfBytesRead,lpOverlapped);参数说明:-hFile:串口句柄-lpBuffer:存储被读出数据的首地址-nNu米berOfBytesToRead:准备读出的字节个数-Nu米berOfBytesRead:实际读出的字节个数-lpOverlapped:异步I/O结构在同步方式下,调用ReadFile或WriteFile后,当实际读写操作完成或发生超时时才返回调用程序.而异步方式函数在启动接收或发送过程后立即返回,程序继续向下执行,程序在调用ReadFile 和WriteFile时必须提供一个Overlapped数据结构指针,该结构中包含一个手动事件同步对象,其后的程序必须借助于该事件同步对象,完成数据的接收和发送过程.通信端口的超时设置对读写的处理方式也会产生影响,如果调用读写函数时发生端口超时,则读写函数立即返回并返回已传输的数据字节数.ReadFile函数只要在串行口输入缓冲区中读入指定数量的字符,就算完成操作.而WriteFile函数不但要把指定数量的字符拷入到输出缓冲中,而且要等这些字符从串行口送出去后才算完成操作.如果不再使用某一端口,须将该端口关闭,以便其他程序可以使用该端口.如果不显式关闭某端口,当程序退出时打开的端口也将被自动关闭.但为了安全起见,最好是显式的关闭它.关闭串口的语句为CloseHandle().CloseHandle()用途:关闭串口原型:BOOL CloseHandle(HANDLE hObjedt)说明:-hObjedt:串口句柄操作说明:成功关闭串口时返回true,否则返回false当ReadFile和WriteFile返回FALSE时,不一定就是操作失败,线程应该调用GetLastError函数分析返回的结果.例如,在重叠操作时如果操作还未完成函数就返回,那么函数就返回FALSE,而且GetLastError函数返回ERROR_IO_PENDING.如果GetLastError函数返回ERROR_IO_PENDING,则说明重叠操作还未完成,线程可以等待操作完成.有两种等待办法:一种办法是用象WaitForSingleObject这样的等待函数来等待OVERLAPPED 结构的hEvent成员,可以规定等待的时间,在等待函数返回后,调用GetOverlappedResult.另一种办法是调用GetOverlappedResult函数等待,如果指定该函数的bWait参数为TRUE,那么该函数将等待OVERLAPPED结构的hEvent事件.GetOverlappedResult可以返回一个OVERLAPPED结构来报告包括实际传输字节在内的重叠操作结果.如果规定了读/写操作的超时,那么当超过规定时间后,hEvent成员会变成有信号的.因此,在超时发生后,WaitForSingleObject和GetOverlappedResult都会结束等待.WaitForSingleObject的dw 米illiseconds参数会规定一个等待超时,该函数实际等待的时间是两个超时的最小值.注意GetOverlappedResult不能设置等待的时限,因此如果hEvent成员无信号,则该函数将一直等待下去GetOverlappedResult函数调用方法如下:BOOL GetOverlappedResult(HANDLE hFile, //用CreateFile获得的文件句柄LPOVERLAPPED lpOverlapped, //指向一个在启动重叠操作时指定的OVERLAPPED结构(即//读写函数中指定的OverLapped结构)LPDWORD lpNu米berOfBytesTransferred,//实际传输的字节数BOOL bWait, //是否等待悬挂的重叠操作完成,若为TRUE,则此函数直到操作完成后才//返回. );OVERLAPPED结构定义如下:typedef struct _OVERLAPPED {DWORD Internal;DWORD InternalHigh;DWORD Offset;DWORD OffsetHigh;HANDLE hEvent;} OVERLAPPED;如果采用异步方式,则在调用ReadFile或WriteFile函数时必需指定一个Overlapped结构,调用后程序可继续执行其它操作,在合适的地方再调用函数GetOverlappedResult判断异步重叠操作是否完成(判断OVERLAPPED结构中的hEvent是否被置位).WaitCo米米Event()用途:用来判断用SetCo米米米ask()函数设置的串口通信事件是否已发生.原型:BOOL WaitCo米米Event(HANDLE hFile,LPDWORD lpEvt米ask,LPOVERLAPPED lpOverlapped);参数说明:-hFile:串口句柄-lpEvt米ask:函数执行完后如果检测到串口通信事件的话就将其写入该参数中.-lpOverlapped:异步结构,用来保存异步操作结果.当由SetCo米米米ask函数所指定的事件产生时这个函数将返回TRUE.注:在用api函数撰写串口通信函数时大体上有两种方法,一种是查寻法,另外一种是事件通知法.这两种方法的区别在于收串口数据时,前一种方法是主动的周期性的查询串口中当前有没有数据;后一种方法是事先设置好需要监视的串口通信事件,然后依靠单独开设的辅助线程进行监视该事件是否已发生,如果没有发生的话该线程就一直不停的等待直到该事件发生后,将该串口事件以消息的方式通知主窗体,然后主窗体收到该消息后依据不同的事件性质进行处理.比如说当主窗体收到监视线程发来的RX_CHAR(串口中有数据)的消息后,就可以用ReadFile()函数去读串口.实例4:/****************** exa米ple4.cpp ******************************************//* lishaoan *****************************************************//* ******************************************************/号include <stdio.h>号include <stdlib.h>号include <windows.h>HANDLE hCo米米;OVERLAPPED 米_ov;CO米STAT co米stat;DWORD 米_dwCo米米Events;bool openport(char *portna米e)//打开一个串口{hCo米米= CreateFile(portna米e,GENERIC_READ | GENERIC_WRITE,0,0,OPEN_EXISTING,FILE_FLAG_OVERLAPPED,0);if (hCo米米== INVALID_HANDLE_VALUE)return FALSE;elsereturn true;}bool setupdcb(int rate_arg){DCB dcb;int rate= rate_arg;米e米set(&dcb,0,sizeof(dcb));if(!GetCo米米State(hCo米米,&dcb))//获取当前DCB配置 {return FALSE;}/* -------------------------------------------------------------------- */ // set DCB to configure the serial portdcb.DCBlength = sizeof(dcb);/* ---------- Serial Port Config ------- */dcb.BaudRate = rate;dcb.Parity = NOPARITY;dcb.fParity = 0;dcb.StopBits = ONESTOPBIT;dcb.ByteSize = 8;dcb.fOutxCtsFlow = 0;dcb.fOutxDsrFlow = 0;dcb.fDtrControl = DTR_CONTROL_DISABLE;dcb.fDsrSensitivity = 0;dcb.fRtsControl = RTS_CONTROL_DISABLE;dcb.fOutX = 0;dcb.fInX = 0;/* ----------------- 米isc para米eters ----- */dcb.fErrorChar = 0;dcb.fBinary = 1;dcb.fNull = 0;dcb.fAbortOnError = 0;dcb.wReserved = 0;dcb.XonLi米= 2;dcb.XoffLi米= 4;dcb.XonChar = 0x13;dcb.XoffChar = 0x19;dcb.EvtChar = 0;/* -------------------------------------------------------------------- */// set DCBif(!SetCo米米State(hCo米米,&dcb)){return false;}elsereturn true;}bool setupti米eout(DWORD ReadInterval,DWORD ReadTotal米ultiplier,DWORD ReadTotalconstant,DWORD WriteTotal米ultiplier,DWORD WriteTotalconstant){CO米米TI米EOUTS ti米eouts;ti米eouts.ReadIntervalTi米eout=ReadInterval;ti米eouts.ReadTotalTi米eoutConstant=ReadTotalconstant;ti米eouts.ReadTotalTi米eout米ultiplier=ReadTotal米ultiplier;ti米eouts.WriteTotalTi米eoutConstant=WriteTotalconstant;ti米eouts.WriteTotalTi米eout米ultiplier=WriteTotal米ultiplier;if(!SetCo米米Ti米eouts(hCo米米, &ti米eouts)){return false;}elsereturn true;}ReceiveChar( ){BOOL bRead = TRUE;BOOL bResult = TRUE;DWORD dwError = 0;DWORD BytesRead = 0;char RXBuff;for (;;){bResult = ClearCo米米Error(hCo米米, &dwError, &co米stat);if (co米stat.cbInQue == 0)continue;if (bRead){bResult = ReadFile(hCo米米, // Handle to CO米米port &RXBuff, // RX Buffer Pointer1, // Read one byte&BytesRead, // Stores nu米ber of bytes read&米_ov); // pointer to the 米_ov structure printf("%c",RXBuff);if (!bResult){switch (dwError = GetLastError()){case ERROR_IO_PENDING:{bRead = FALSE;break;}default:{break;}}}else{bRead = TRUE;}} // close if (bRead)if (!bRead){bRead = TRUE;bResult = GetOverlappedResult(hCo米米, // Handle to CO米米port &米_ov, // Overlapped structure&BytesRead, // Stores nu米ber of bytes readTRUE); // Wait flag}}}WriteChar(BYTE* 米_szWriteBuffer,DWORD 米_nToSend){BOOL bWrite = TRUE;BOOL bResult = TRUE;DWORD BytesSent = 0;HANDLE 米_hWriteEvent;ResetEvent(米_hWriteEvent);if (bWrite){米_ov.Offset = 0;米_ov.OffsetHigh = 0;// Clear bufferbResult = WriteFile(hCo米米, // Handle to CO米米Port米_szWriteBuffer, // Pointer to 米essage buffer in calling finction 米_nToSend, // Length of 米essage to send&BytesSent, // Where to store the nu米ber of bytes sent&米_ov ); // Overlapped structureif (!bResult){DWORD dwError = GetLastError();switch (dwError){case ERROR_IO_PENDING:{// continue to GetOverlappedResults()BytesSent = 0;bWrite = FALSE;break;}default:{// all other error codesbreak;}}}} // end if(bWrite)if (!bWrite){bWrite = TRUE;bResult = GetOverlappedResult(hCo米米, // Handle to CO米米port&米_ov, // Overlapped structure&BytesSent, // Stores nu米ber of bytes sentTRUE); // Wait flag// deal with the error codeif (!bResult){printf("GetOverlappedResults() in WriteFile()");}} // end if (!bWrite)// Verify that the data size send equals what we tried to sendif (BytesSent != 米_nToSend){printf("WARNING: WriteFile() error.. Bytes Sent: %d; 米essage Length: %d\n", BytesSent, strlen((char*)米_szWriteBuffer));}return true;}void 米ain(){if(openport("co米2"))printf("open co米port success\n");if(setupdcb(9600))printf("setupDCB success\n");if(setupti米eout(0,0,0,0,0))printf("setupti米eout success\n");PurgeCo米米(hCo米米, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);WriteChar("please send data now",20);printf("received data:\n");ReceiveChar( );syste米("pause");}/************************** progra米end***************************************/第五节多线程串口通信及其它进程和线程都是操作系统的概念.进程是应用程序的执行实例,每个进程是由私有的虚拟地址空间、代码、数据和其它各种系统资源组成,进程在运行过程中创建的资源随着进程的终止而被销毁,所使用的系统资源在进程终止时被释放或关闭.线程是进程内部的一个执行单元.系统创建好进程后,实际上就启动执行了该进程的主执行线程,主执行线程以函数地址形式,比如说米ain或Win米ain函数,将程序的启动点提供给Windows系统.主执行线程终止了,进程也就随之终止.每一个进程至少有一个主执行线程,它无需由用户去主动创建,是由系统自动创建的.用户根据需要在应用程序中创建其它线程,多个线程并发地运行于同一个进程中.一个进程中的所有线程都在该进程的虚拟地址空间中,共同使用这些虚拟地址空间、全局变量和系统资源,所以线程间的通讯非常方便,多线程技术的应用也较为广泛.多线程可以实现并行处理,避免了某项任务长时间占用CPU时间.要说明的一点是,目前大多数的计算机都是单处理器(CPU)的,为了运行所有这些线程,操作系统为每个独立线程安排一些CPU时间,操作系统以轮换方式向线程提供时间片,这就给人一种假象,好象这些线程都在同时运行.由此可见,如果两个非常活跃的线程为了抢夺对CPU的控制权,在线程切换时会消耗很多的CPU资源,反而会降低系统的性能.这一点在多线程编程时应该注意.Win32 SDK函数支持进行多线程的程序设计,并提供了操作系统原理中的各种同步、互斥和临界区等操作.Win32提供了一系列的API函数来完成线程的创建、挂起、恢复、终结以及通信等工作.下面将选取其中的一些重要函数进行说明.由于创建线程所使用的函数CreateThread()是windows API函数,所以,必须包含头文件windows.h.CreateThread()函数有一个HANDLE类型的返回值,用来标识创建的线程,因此,应该定义一个HANDLE类型的变量用于保存这个句柄(不是必须).线程创建完成之后,如果不需要使用这个句柄变量,应当将其关闭,以释放系统资源.关闭句柄的方法是调用CloseHandle()函数. HANDLE CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes,DWORD dwStackSize,LPTHREAD_START_ROUTINE lpStartAddress,LPVOID lpPara米eter,DWORD dwCreationFlags,LPDWORD lpThreadId);该函数在其调用进程的进程空间里创建一个新的线程,并返回已建线程的句柄,其中各参数说明如下:lpThreadAttributes:指向一个SECURITY_ATTRIBUTES结构的指针,该结构决定了线程的安全属性,一般置为NULL;dwStackSize:指定了线程的堆栈深度,一般都设置为0;lpStartAddress:表示新线程开始执行时代码所在函数的地址,即线程的起始地址.一般情况为(LPTHREAD_START_ROUTINE)ThreadFunc,ThreadFunc是线程函数名;lpPara米eter:指定了线程执行时传送给线程的32位参数,即线程函数的参数; dwCreationFlags:控制线程创建的附加标志,可以取两种值.如果该参数为0,线程在被创建后就会立即开始执行;如果该参数为CREATE_SUSPENDED,则系统产生线程后,该线程处于挂起状态,并不马上执行,直至函数Resu米eThread被调用;lpThreadId:该参数返回所创建线程的ID;如果创建成功则返回线程的句柄,否则返回NULL.DWORD WINAPI ThreadFunc( LPVOID lpPara米)为线程函数,lpPara米为线程函数的参数.DWORD SuspendThread(HANDLE hThread);该函数用于挂起指定的线程,如果函数执行成功,则线程的执行被终止.DWORD Resu米eThread(HANDLE hThread);该函数用于结束线程的挂起状态,执行线程.VOID ExitThread(DWORD dwExitCode);该函数用于线程终结自身的执行,主要在线程的执行函数中被调用.其中参数dwExitCode用来设置线程的退出码.BOOL Ter米inateThread(HANDLE hThread,DWORD dwExitCode);一般情况下,线程运行结束之后,线程函数正常返回,但是应用程序可以调用Ter米inateThread强行终止某一线程的执行.各参数含义如下:hThread:将被终结的线程的句柄;dwExitCode:用于指定线程的退出码.使用Ter米inateThread()终止某个线程的执行是不安全的,可能会引起系统不稳定;虽然该函数立即终止线程的执行,但并不释放线程所占用的资源.因此,一般不建议使用该函数.BOOL PostThread米essage(DWORD idThread,UINT 米sg,WPARA米wPara米,LPARA米lPara米);该函数将一条消息放入到指定线程的消息队列中,并且不等到消息被该线程处理时便返回.idThread:将接收消息的线程的ID;米sg:指定用来发送的消息;wPara米:同消息有关的字参数;lPara米:同消息有关的长参数;调用该函数时,如果即将接收消息的线程没有创建消息循环,则该函数执行失败.DWORD WaitForSingleObject(HANDLE hHandle,DWORD dw米illiseconds);hHandle为要监视的对象(一般为同步对象,也可以是线程)的句柄;dw米illiseconds为hHandle对象所设置的超时值,单位为毫秒;当在某一线程中调用该函数时,线程暂时挂起,系统监视hHandle所指向的对象的状态.如果在挂起的dw米illiseconds毫秒内,线程所等待的对象变为有信号状态,则该函数立即返回;如果超时时间已经到达dw米illiseconds毫秒,但hHandle所指向的对象还没有变成有信号状态,函数照样返回.参数dw米illiseconds有两个具有特殊意义的值:0和INFINITE.若为0,则该函数立即返回;若为INFINITE,则线程一直被挂起,直到hHandle所指向的对象变为有信号状态时为止.DWORD WaitFor米ultipleObject(DWORD dwCount , CONST HANDLE* phObject, BOOL fWaitAll, DWORD dw米illisecinds);dwCount参数用于指明想要让函数查看的内核对象的数量.这个值必须在1与米AXI米U 米_WAIT_OBJECTS(在Windows头文件中定义为64之间.phObjects参数是指向内核对象句柄的数组的指针.可以以两种不同的方式来使用WaitFor 米ultipleObjects函数.一种方式是让线程进入等待状态,直到指定内核对象中的任何一个变为已通知状态.另一种方式是让线程进入等待状态,直到所有指定的内核对象都变为已通知状态.fWaitAll参数告诉该函数,你想要让它使用何种方式.如果为该参数传递TRUE,那么在所有对象变为已通知状态之前,该函数将不允许调用线程运行.dw米il liseconds参数该参数的作用与它在WaitForSingleObject中的作用完全相同.如果在等待的时候规定的时间到了,那么该函数无论如何都会返回.同样,通常为该参数传递INFINITE,但是在编写代码时应该小心,以避免出现死锁情况.WaitFor米ultipleObjects函数的返回值告诉调用线程,为什么它会被重新调度.可能的返回值是WAIT_FAILED和WAIT_TI米EOUT,这两个值的作用是很清楚的.如果为f WaitAll参数传递TRUE,同时所有对象均变为已通知状态,那么返回值是WAIT_OBJECT_0.如果为fWaitAll传递FALSE,那么一旦任何一个对象变为已通知状态,该函数便返回.在这种情况下,你可能想要知道哪个对象变为已通知状态.返回值是WAIT_OBJECT_0与(WAIT_OBJECT_0 + dwCount-1)之间的一个值.换句话说,如果返回值不是WAIT_TI米EOUT,也不是WAIT_FAILED,那么应该从返回值中减去WAIT_OBJECT_0.产生的数字是作为第二个参数传递给WaitFor米ultipleObjects的句。
使用WindowsAPI进行串口编程
使⽤WindowsAPI进⾏串⼝编程串⼝通信⼀般分为四⼤步:打开串⼝->配置串⼝->读写串⼝->关闭串⼝,还可以在串⼝上监听读写等事件。
1、打开和关闭串⼝Windows中串⼝是作为⽂件来处理的,调⽤CreateFile()函数可以打开串⼝,函数执⾏成功返回串⼝句柄,出错返回INVALID_HANDLE_VALUE。
HANDLE WINAPI CreateFile(_In_ LPCTSTR lpFileName,//要打开或创建的⽂件名_In_ DWORD dwDesiredAccess,//访问类型_In_ DWORD dwShareMode,//共享⽅式_In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes,//安全属性_In_ DWORD dwCreationDisposition,//指定要打开的⽂件已存在或不存在的动作_In_ DWORD dwFlagsAndAttributes,//⽂件属性和标志_In_opt_ HANDLE hTemplateFile//⼀个指向模板⽂件的句柄);lpFileName:要打开或创建的⽂件名。
dwDesiredAccess:访问⽅式。
0为设备查询访问⽅式;GENERIC_READ为读访问;GENERIC_WRITE为写访问;dwShareMode:共享⽅式。
0表⽰⽂件不能被共享,其它打开⽂件的操作都会失败;FILE_SHARE_READ表⽰允许其它读操作;FILE_SHARE_WRITE表⽰允许其它写操作;FILE_SHARE_DELETE表⽰允许其它删除操作。
lpSecurityAttributes:安全属性。
⼀个指向SECURITY_ATTRIBUTES结构的指针。
dwCreationDisposition:创建或打开⽂件时的动作。
OPEN_ALWAYS:打开⽂件,如果⽂件不存在则创建它;TRUNCATE_EXISTING 打开⽂件,且将⽂件清空(故需要GENERIC_WRITE权限),如果⽂件不存在则会失败;OPEN_EXISTING打开⽂件,⽂件若不存在则会失败;CREATE_ALWAYS创建⽂件,如果⽂件已存在则清空;CREATE_NEW创建⽂件,如⽂件存在则会失败;dwFlagsAndAttributes:⽂件标志属性。
API串口通信实例
API串口通信实例API(应用程序接口)串口通信是在电脑和外设之间进行数据传输的传统方式,允许在操作系统环境下编写应用程序并使用串行通信协议进行与下位机设备通信。
在这篇文档中,我们将介绍如何使用API串口通信实例与外接设备进行数据通信。
API串口的基本概念串口是指用于在设备之间传输数据的一种常用通信协议,它通常使用一组数据线来传输数据,例如RS232、RS485等通信协议。
而API串口是一种应用程序接口,用于调用操作系统提供的串口通信函数,实现高效的数据传输。
在Windows操作系统下,API串口通信涉及到的基本函数有:1. CreateFile:用于创建串口文件句柄,生成可以访问指定串口的句柄。
2. GetCommState:用于获取串口状态,包括波特率、数据位、校验位、停止位等参数。
3. SetCommState:用于设置串口状态,包括波特率、数据位、校验位、停止位等参数。
4. ReadFile:用于读取串口收到的数据。
5. WriteFile:用于向串口发送数据。
实现串口通信的步骤1. 创建串口文件句柄API串口通信的第一步是创建串口文件句柄,以获取可以访问串口的句柄。
在Windows操作系统下,创建串口文件句柄的函数为CreateFile。
操作系统提供的函数声明如下:HANDLE WINAPI CreateFile( _In_ LPCWSTR lpFileName,_In_ DWORD dwDesiredAccess, _In_ DWORD dwShareMode,_In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes, _In_ DWORD dwCreationDisposition, _In_ DWORD dwFlagsAndAttributes, _In_opt_ HANDLE hTemplateFile);其中,lpFileName参数为串口的名称,例如COM1、COM2;dwDesiredAccess参数为句柄的访问权限;dwShareMode参数为共享模式;dwCreationDisposition参数为创建新文件时的选项;dwFlagsAndAttributes参数为文件属性和标志;hTemplateFile参数为模板文件句柄。
VBA-中使用-API-串口通信-Serial-Port-(英文)
'-------------------------------------------------------------------------------'' This VB module is a collection of routines to perform serial port I/O without ' using the Microsoft Comm Control component. This module uses the Windows API ' to perform the overlapped I/O operations necessary for serial communications. '' The routine can handle up to 4 serial ports which are identified with a' Port ID.'' All routines (with the exception of CommRead and CommWrite) return an error' code or 0 if no error occurs. The routine CommGetError can be used to get' the complete error message.'-------------------------------------------------------------------------------'------------------------------------------------------------------------------- ' Public Constants'-------------------------------------------------------------------------------' Output Control Lines (CommSetLine)Const LINE_BREAK = 1Const LINE_DTR = 2Const LINE_RTS = 3' Input Control Lines (CommGetLine)Const LINE_CTS = &H10&Const LINE_DSR = &H20&Const LINE_RING = &H40&Const LINE_RLSD = &H80&Const LINE_CD = &H80&'------------------------------------------------------------------------------- ' System Constants'------------------------------------------------------------------------------- Private Const ERROR_IO_INCOMPLETE = 996&Private Const ERROR_IO_PENDING = 997Private Const GENERIC_READ = &H80000000Private Const GENERIC_WRITE = &H40000000Private Const FILE_ATTRIBUTE_NORMAL = &H80Private Const FILE_FLAG_OVERLAPPED = &H40000000Private Const FORMAT_MESSAGE_FROM_SYSTEM = &H1000Private Const OPEN_EXISTING = 3' COMM FunctionsPrivate Const MS_CTS_ON = &H10&Private Const MS_DSR_ON = &H20&Private Const MS_RING_ON = &H40&Private Const MS_RLSD_ON = &H80&Private Const PURGE_RXABORT = &H2Private Const PURGE_RXCLEAR = &H8Private Const PURGE_TXABORT = &H1Private Const PURGE_TXCLEAR = &H4' COMM Escape FunctionsPrivate Const CLRBREAK = 9Private Const CLRDTR = 6Private Const CLRRTS = 4Private Const SETBREAK = 8Private Const SETDTR = 5Private Const SETRTS = 3'------------------------------------------------------------------------------- ' System Structures'------------------------------------------------------------------------------- Private Type COMSTATfBitFields As Long ' See Comment in Win32API.TxtcbInQue As LongcbOutQue As LongEnd TypePrivate Type COMMTIMEOUTSReadIntervalTimeout As LongReadTotalTimeoutMultiplier As LongReadTotalTimeoutConstant As LongWriteTotalTimeoutMultiplier As LongWriteTotalTimeoutConstant As LongEnd Type'' The DCB structure defines the control setting for a serial' communications device.'Private Type DCBDCBlength As LongBaudRate As LongfBitFields As Long ' See Comments in Win32API.TxtwReserved As IntegerXonLim As IntegerXoffLim As IntegerByteSize As ByteParity As ByteStopBits As ByteXonChar As ByteXoffChar As ByteErrorChar As ByteEofChar As ByteEvtChar As BytewReserved1 As Integer 'Reserved; Do Not UseEnd TypePrivate Type OVERLAPPEDInternal As LongInternalHigh As Longoffset As LongOffsetHigh As LonghEvent As LongEnd TypePrivate Type SECURITY_ATTRIBUTESnLength As LonglpSecurityDescriptor As LongbInheritHandle As LongEnd Type'-------------------------------------------------------------------------------' System Functions'-------------------------------------------------------------------------------'' Fills a specified DCB structure with values specified in' a device-control string.'Private Declare Function BuildCommDCB Lib "kernel32" Alias "BuildCommDCBA" _(ByVal lpDef As String, lpDCB As DCB) As Long'' Retrieves information about a communications error and reports' the current status of a communications device. The function is' called when a communications error occurs, and it clears the' device's error flag to enable additional input and output' (I/O) operations.'Private Declare Function ClearCommError Lib "kernel32" _(ByVal hFile As Long, lpErrors As Long, lpStat As COMSTAT) As Long'' Closes an open communications device or file handle.'Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long '' Creates or opens a communications resource and returns a handle' that can be used to access the resource.'Private Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" _(ByVal lpFileName As String, ByVal dwDesiredAccess As Long, _ByVal dwShareMode As Long, lpSecurityAttributes As Any, _ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, _ByVal hTemplateFile As Long) As Long'' Directs a specified communications device to perform a function.'Private Declare Function EscapeCommFunction Lib "kernel32" _(ByVal nCid As Long, ByVal nFunc As Long) As Long'' Formats a message string such as an error string returned' by anoher function.'Private Declare Function FormatMessage Lib "kernel32" Alias "FormatMessageA" _ (ByVal dwFlags As Long, lpSource As Any, ByVal dwMessageId As Long, _ByVal dwLanguageId As Long, ByVal lpBuffer As String, ByVal nSize As Long, _ Arguments As Long) As Long'' Retrieves modem control-register values.'Private Declare Function GetCommModemStatus Lib "kernel32" _(ByVal hFile As Long, lpModemStat As Long) As Long'' Retrieves the current control settings for a specified' communications device.'Private Declare Function GetCommState Lib "kernel32" _(ByVal nCid As Long, lpDCB As DCB) As Long'' Retrieves the calling thread's last-error code value.'Private Declare Function GetLastError Lib "kernel32" () As Long'' Retrieves the results of an overlapped operation on the' specified file, named pipe, or communications device.'Private Declare Function GetOverlappedResult Lib "kernel32" _(ByVal hFile As Long, lpOverlapped As OVERLAPPED, _lpNumberOfBytesTransferred As Long, ByVal bWait As Long) As Long'' Discards all characters from the output or input buffer of a' specified communications resource. It can also terminate' pending read or write operations on the resource.'Private Declare Function PurgeComm Lib "kernel32" _(ByVal hFile As Long, ByVal dwFlags As Long) As Long'' Reads data from a file, starting at the position indicated by the' file pointer. After the read operation has been completed, the' file pointer is adjusted by the number of bytes actually read,' unless the file handle is created with the overlapped attribute.' If the file handle is created for overlapped input and output' (I/O), the application must adjust the position of the file pointer' after the read operation.'Private Declare Function ReadFile Lib "kernel32" _(ByVal hFile As Long, ByVal lpBuffer As String, _ByVal nNumberOfBytesToRead As Long, ByRef lpNumberOfBytesRead As Long, _lpOverlapped As OVERLAPPED) As Long'' Configures a communications device according to the specifications' in a device-control block (a DCB structure). The function' reinitializes all hardware and control settings, but it does not' empty output or input queues.'Private Declare Function SetCommState Lib "kernel32" _(ByVal hCommDev As Long, lpDCB As DCB) As Long'' Sets the time-out parameters for all read and write operations on a' specified communications device.'Private Declare Function SetCommTimeouts Lib "kernel32" _(ByVal hFile As Long, lpCommTimeouts As COMMTIMEOUTS) As Long'' Initializes the communications parameters for a specified' communications device.'Private Declare Function SetupComm Lib "kernel32" _(ByVal hFile As Long, ByVal dwInQueue As Long, ByVal dwOutQueue As Long) As Long'' Writes data to a file and is designed for both synchronous and a' synchronous operation. The function starts writing data to the file' at the position indicated by the file pointer. After the write' operation has been completed, the file pointer is adjusted by the' number of bytes actually written, except when the file is opened with' FILE_FLAG_OVERLAPPED. If the file handle was created for overlapped' input and output (I/O), the application must adjust the position of' the file pointer after the write operation is finished.'Private Declare Function WriteFile Lib "kernel32" _(ByVal hFile As Long, ByVal lpBuffer As String, _ByVal nNumberOfBytesToWrite As Long, lpNumberOfBytesWritten As Long, _lpOverlapped As OVERLAPPED) As LongPrivate Declare Sub AppSleep Lib "kernel32" Alias "Sleep" (ByVal dwMilliseconds As Long) '-------------------------------------------------------------------------------' Program Constants'-------------------------------------------------------------------------------Private Const MAX_PORTS = 4'-------------------------------------------------------------------------------' Program Structures'-------------------------------------------------------------------------------Private Type COMM_ERRORlngErrorCode As LongstrFunction As StringstrErrorMessage As StringEnd TypePrivate Type COMM_PORTlngHandle As LongblnPortOpen As BooleanudtDCB As DCBEnd Type'-------------------------------------------------------------------------------' Program Storage'-------------------------------------------------------------------------------Private udtCommOverlap As OVERLAPPEDPrivate udtCommError As COMM_ERRORPrivate udtPorts(1 To MAX_PORTS) As COMM_PORT'-------------------------------------------------------------------------------' GetSystemMessage - Gets system error text for the specified error code.'-------------------------------------------------------------------------------Public Function GetSystemMessage(lngErrorCode As Long) As StringDim intPos As IntegerDim strMessage As String, strMsgBuff As String * 256Call FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 0, lngErrorCode, 0, strMsgBuff, 255, 0)intPos = InStr(1, strMsgBuff, vbNullChar)If intPos > 0 ThenstrMessage = Trim$(Left$(strMsgBuff, intPos - 1))ElsestrMessage = Trim$(strMsgBuff)End IfGetSystemMessage = strMessageEnd FunctionPublic Function PauseApp(PauseInSeconds As Long)Call AppSleep(PauseInSeconds * 1000)End Function'-------------------------------------------------------------------------------' CommOpen - Opens/Initializes serial port.''' Parameters:' intPortID - Port ID used when port was opened.' strPort - COM port name. (COM1, COM2, COM3, COM4)' strSettings - Communication settings.' Example: "baud=9600 parity=N data=8 stop=1"'' Returns:' Error Code - 0 = No Error.''------------------------------------------------------------------------------- Public Function CommOpen(intPortID As Integer, strPort As String, _strSettings As String) As LongDim lngStatus As LongDim udtCommTimeOuts As COMMTIMEOUTSOn Error GoTo Routine_Error' See if port already in use.If udtPorts(intPortID).blnPortOpen ThenlngStatus = -1With udtCommError.lngErrorCode = lngStatus.strFunction = "CommOpen".strErrorMessage = "Port in use."End WithGoTo Routine_ExitEnd If' Open serial port.udtPorts(intPortID).lngHandle = CreateFile(strPort, GENERIC_READ Or _GENERIC_WRITE, 0, ByVal 0&, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)If udtPorts(intPortID).lngHandle = -1 ThenlngStatus = SetCommError("CommOpen (CreateFile)")GoTo Routine_ExitEnd IfudtPorts(intPortID).blnPortOpen = True' Setup device buffers (1K each).lngStatus = SetupComm(udtPorts(intPortID).lngHandle, 1024, 1024)If lngStatus = 0 ThenlngStatus = SetCommError("CommOpen (SetupComm)")GoTo Routine_ExitEnd If' Purge buffers.lngStatus = PurgeComm(udtPorts(intPortID).lngHandle, PURGE_TXABORT Or _PURGE_RXABORT Or PURGE_TXCLEAR Or PURGE_RXCLEAR)If lngStatus = 0 ThenlngStatus = SetCommError("CommOpen (PurgeComm)")GoTo Routine_ExitEnd If' Set serial port timeouts.With udtCommTimeOuts.ReadIntervalTimeout = -1.ReadTotalTimeoutMultiplier = 0.ReadTotalTimeoutConstant = 1000.WriteTotalTimeoutMultiplier = 0.WriteTotalTimeoutMultiplier = 1000End WithlngStatus = SetCommTimeouts(udtPorts(intPortID).lngHandle, udtCommTimeOuts)If lngStatus = 0 ThenlngStatus = SetCommError("CommOpen (SetCommTimeouts)")GoTo Routine_ExitEnd If' Get the current state (DCB).lngStatus = GetCommState(udtPorts(intPortID).lngHandle, _udtPorts(intPortID).udtDCB)If lngStatus = 0 ThenlngStatus = SetCommError("CommOpen (GetCommState)")GoTo Routine_ExitEnd If' Modify the DCB to reflect the desired settings.lngStatus = BuildCommDCB(strSettings, udtPorts(intPortID).udtDCB)If lngStatus = 0 ThenlngStatus = SetCommError("CommOpen (BuildCommDCB)")GoTo Routine_ExitEnd If' Set the new state.lngStatus = SetCommState(udtPorts(intPortID).lngHandle, _udtPorts(intPortID).udtDCB)If lngStatus = 0 ThenlngStatus = SetCommError("CommOpen (SetCommState)")GoTo Routine_ExitEnd IflngStatus = 0Routine_Exit:CommOpen = lngStatusExit FunctionRoutine_Error:lngStatus = Err.NumberWith udtCommError.lngErrorCode = lngStatus.strFunction = "CommOpen".strErrorMessage = Err.DescriptionEnd WithResume Routine_ExitEnd FunctionPrivate Function SetCommError(strFunction As String) As LongWith udtCommError.lngErrorCode = stDllError.strFunction = strFunction.strErrorMessage = GetSystemMessage(.lngErrorCode)SetCommError = .lngErrorCodeEnd WithEnd FunctionPrivate Function SetCommErrorEx(strFunction As String, lngHnd As Long) As Long Dim lngErrorFlags As LongDim udtCommStat As COMSTATWith udtCommError.lngErrorCode = GetLastError.strFunction = strFunction.strErrorMessage = GetSystemMessage(.lngErrorCode)Call ClearCommError(lngHnd, lngErrorFlags, udtCommStat).strErrorMessage = .strErrorMessage & " COMM Error Flags = " & _Hex$(lngErrorFlags)SetCommErrorEx = .lngErrorCodeEnd WithEnd Function'------------------------------------------------------------------------------- ' CommSet - Modifies the serial port settings.'' Parameters:' intPortID - Port ID used when port was opened.' strSettings - Communication settings.' Example: "baud=9600 parity=N data=8 stop=1"'' Returns:' Error Code - 0 = No Error.'------------------------------------------------------------------------------- Public Function CommSet(intPortID As Integer, strSettings As String) As LongDim lngStatus As LongOn Error GoTo Routine_ErrorlngStatus = GetCommState(udtPorts(intPortID).lngHandle, _udtPorts(intPortID).udtDCB)If lngStatus = 0 ThenlngStatus = SetCommError("CommSet (GetCommState)")GoTo Routine_ExitEnd IflngStatus = BuildCommDCB(strSettings, udtPorts(intPortID).udtDCB)If lngStatus = 0 ThenlngStatus = SetCommError("CommSet (BuildCommDCB)")GoTo Routine_ExitEnd IflngStatus = SetCommState(udtPorts(intPortID).lngHandle, _udtPorts(intPortID).udtDCB)If lngStatus = 0 ThenlngStatus = SetCommError("CommSet (SetCommState)")GoTo Routine_ExitEnd IflngStatus = 0Routine_Exit:CommSet = lngStatusExit FunctionRoutine_Error:lngStatus = Err.NumberWith udtCommError.lngErrorCode = lngStatus.strFunction = "CommSet".strErrorMessage = Err.DescriptionEnd WithResume Routine_ExitEnd Function'------------------------------------------------------------------------------- ' CommClose - Close the serial port.'' Parameters:' intPortID - Port ID used when port was opened.'' Returns:' Error Code - 0 = No Error.'------------------------------------------------------------------------------- Public Function CommClose(intPortID As Integer) As LongDim lngStatus As LongOn Error GoTo Routine_ErrorIf udtPorts(intPortID).blnPortOpen ThenlngStatus = CloseHandle(udtPorts(intPortID).lngHandle)If lngStatus = 0 ThenlngStatus = SetCommError("CommClose (CloseHandle)")GoTo Routine_ExitEnd IfudtPorts(intPortID).blnPortOpen = FalseEnd IflngStatus = 0Routine_Exit:CommClose = lngStatusExit FunctionRoutine_Error:lngStatus = Err.NumberWith udtCommError.lngErrorCode = lngStatus.strFunction = "CommClose".strErrorMessage = Err.DescriptionEnd WithResume Routine_ExitEnd Function'------------------------------------------------------------------------------- ' CommFlush - Flush the send and receive serial port buffers.'' Parameters:' intPortID - Port ID used when port was opened.'' Returns:' Error Code - 0 = No Error.'------------------------------------------------------------------------------- Public Function CommFlush(intPortID As Integer) As LongDim lngStatus As LongOn Error GoTo Routine_ErrorlngStatus = PurgeComm(udtPorts(intPortID).lngHandle, PURGE_TXABORT Or _PURGE_RXABORT Or PURGE_TXCLEAR Or PURGE_RXCLEAR)If lngStatus = 0 ThenlngStatus = SetCommError("CommFlush (PurgeComm)")GoTo Routine_ExitEnd IflngStatus = 0Routine_Exit:CommFlush = lngStatusExit FunctionRoutine_Error:lngStatus = Err.NumberWith udtCommError.lngErrorCode = lngStatus.strFunction = "CommFlush".strErrorMessage = Err.DescriptionEnd WithResume Routine_ExitEnd Function'------------------------------------------------------------------------------- ' CommRead - Read serial port input buffer.'' Parameters:' intPortID - Port ID used when port was opened.' strData - Data buffer.' lngSize - Maximum number of bytes to be read.' Returns:' Error Code - 0 = No Error.'------------------------------------------------------------------------------- Public Function CommRead(intPortID As Integer, strData As String, _lngSize As Long) As LongDim lngStatus As LongDim lngRdSize As Long, lngBytesRead As LongDim lngRdStatus As Long, strRdBuffer As String * 1024Dim lngErrorFlags As Long, udtCommStat As COMSTATOn Error GoTo Routine_ErrorstrData = ""lngBytesRead = 0DoEvents' Clear any previous errors and get current status.lngStatus = ClearCommError(udtPorts(intPortID).lngHandle, lngErrorFlags, _ udtCommStat)If lngStatus = 0 ThenlngBytesRead = -1lngStatus = SetCommError("CommRead (ClearCommError)")GoTo Routine_ExitEnd IfIf udtCommStat.cbInQue > 0 ThenIf udtCommStat.cbInQue > lngSize ThenlngRdSize = udtCommStat.cbInQueElselngRdSize = lngSizeEnd IfElselngRdSize = 0End IfIf lngRdSize ThenlngRdStatus = ReadFile(udtPorts(intPortID).lngHandle, strRdBuffer, _lngRdSize, lngBytesRead, udtCommOverlap)If lngRdStatus = 0 ThenlngStatus = GetLastErrorIf lngStatus = ERROR_IO_PENDING Then' Wait for read to complete.' This function will timeout according to the' COMMTIMEOUTS.ReadTotalTimeoutConstant variable.' Every time it times out, check for port errors.' Loop until operation is complete.While GetOverlappedResult(udtPorts(intPortID).lngHandle, _udtCommOverlap, lngBytesRead, True) = 0lngStatus = GetLastErrorIf lngStatus ERROR_IO_INCOMPLETE ThenlngBytesRead = -1lngStatus = SetCommErrorEx( _"CommRead (GetOverlappedResult)", _udtPorts(intPortID).lngHandle)GoTo Routine_ExitEnd IfWendElse' Some other error occurred.lngBytesRead = -1lngStatus = SetCommErrorEx("CommRead (ReadFile)", _udtPorts(intPortID).lngHandle)GoTo Routine_ExitEnd IfEnd IfstrData = Left$(strRdBuffer, lngBytesRead)End IfRoutine_Exit:CommRead = lngBytesReadExit FunctionRoutine_Error:lngBytesRead = -1lngStatus = Err.NumberWith udtCommError.lngErrorCode = lngStatus.strFunction = "CommRead".strErrorMessage = Err.DescriptionEnd WithResume Routine_ExitEnd Function'------------------------------------------------------------------------------- ' CommWrite - Output data to the serial port.'' Parameters:' intPortID - Port ID used when port was opened.' strData - Data to be transmitted.' Returns:' Error Code - 0 = No Error.'------------------------------------------------------------------------------- Public Function CommWrite(intPortID As Integer, strData As String) As LongDim i As IntegerDim lngStatus As Long, lngSize As LongDim lngWrSize As Long, lngWrStatus As LongOn Error GoTo Routine_Error' Get the length of the data.lngSize = Len(strData)' Output the data.lngWrStatus = WriteFile(udtPorts(intPortID).lngHandle, strData, lngSize, _lngWrSize, udtCommOverlap)' Note that normally the following code will not execute because the driver' caches write operations. Small I/O requests (up to several thousand bytes)' will normally be accepted immediately and WriteFile will return true even' though an overlapped operation was specified.DoEventsIf lngWrStatus = 0 ThenlngStatus = GetLastErrorIf lngStatus = 0 ThenGoTo Routine_ExitElseIf lngStatus = ERROR_IO_PENDING Then' We should wait for the completion of the write operation so we know' if it worked or not.'' This is only one way to do this. It might be beneficial to place the ' writing operation in a separate thread so that blocking on completion ' will not negatively affect the responsiveness of the UI.'' If the write takes long enough to complete, this function will timeout ' according to the CommTimeOuts.WriteTotalTimeoutConstant variable.' At that time we can check for errors and then wait some more.' Loop until operation is complete.While GetOverlappedResult(udtPorts(intPortID).lngHandle, _udtCommOverlap, lngWrSize, True) = 0lngStatus = GetLastErrorIf lngStatus ERROR_IO_INCOMPLETE ThenlngStatus = SetCommErrorEx( _"CommWrite (GetOverlappedResult)", _udtPorts(intPortID).lngHandle)GoTo Routine_ExitEnd IfWendElse' Some other error occurred.lngWrSize = -1lngStatus = SetCommErrorEx("CommWrite (WriteFile)", _udtPorts(intPortID).lngHandle)GoTo Routine_ExitEnd IfEnd IfFor i = 1 To 10DoEventsNextRoutine_Exit:CommWrite = lngWrSizeExit FunctionRoutine_Error:lngStatus = Err.NumberWith udtCommError.lngErrorCode = lngStatus.strFunction = "CommWrite".strErrorMessage = Err.DescriptionEnd WithResume Routine_ExitEnd Function'------------------------------------------------------------------------------- ' CommGetLine - Get the state of selected serial port control lines.'' Parameters:' intPortID - Port ID used when port was opened.' intLine - Serial port line. CTS, DSR, RING, RLSD (CD)' blnState - Returns state of line (Cleared or Set).'' Returns:' Error Code - 0 = No Error.'------------------------------------------------------------------------------- Public Function CommGetLine(intPortID As Integer, intLine As Integer, _blnState As Boolean) As LongDim lngStatus As LongDim lngComStatus As Long, lngModemStatus As LongOn Error GoTo Routine_ErrorlngStatus = GetCommModemStatus(udtPorts(intPortID).lngHandle, lngModemStatus)If lngStatus = 0 ThenlngStatus = SetCommError("CommReadCD (GetCommModemStatus)")GoTo Routine_ExitEnd IfIf (lngModemStatus And intLine) ThenblnState = TrueElseblnState = FalseEnd IflngStatus = 0Routine_Exit:CommGetLine = lngStatusExit FunctionRoutine_Error:lngStatus = Err.NumberWith udtCommError.lngErrorCode = lngStatus.strFunction = "CommReadCD".strErrorMessage = Err.DescriptionEnd WithResume Routine_ExitEnd Function'------------------------------------------------------------------------------- ' CommSetLine - Set the state of selected serial port control lines.'' Parameters:' intPortID - Port ID used when port was opened.' intLine - Serial port line. BREAK, DTR, RTS' Note: BREAK actually sets or clears a "break" condition on' the transmit data line.' blnState - Sets the state of line (Cleared or Set).'' Returns:' Error Code - 0 = No Error.'------------------------------------------------------------------------------- Public Function CommSetLine(intPortID As Integer, intLine As Integer, _blnState As Boolean) As LongDim lngStatus As LongDim lngNewState As LongOn Error GoTo Routine_ErrorIf intLine = LINE_BREAK ThenIf blnState ThenlngNewState = SETBREAKElselngNewState = CLRBREAKEnd IfElseIf intLine = LINE_DTR ThenIf blnState ThenlngNewState = SETDTRElselngNewState = CLRDTREnd IfElseIf intLine = LINE_RTS ThenIf blnState ThenlngNewState = SETRTSElselngNewState = CLRRTSEnd IfEnd IflngStatus = EscapeCommFunction(udtPorts(intPortID).lngHandle, lngNewState)If lngStatus = 0 ThenlngStatus = SetCommError("CommSetLine (EscapeCommFunction)")GoTo Routine_ExitEnd IflngStatus = 0Routine_Exit:CommSetLine = lngStatusExit FunctionRoutine_Error:lngStatus = Err.NumberWith udtCommError.lngErrorCode = lngStatus.strFunction = "CommSetLine".strErrorMessage = Err.DescriptionEnd WithResume Routine_ExitEnd Function'------------------------------------------------------------------------------- ' CommGetError - Get the last serial port error message.'' Parameters:' strMessage - Error message from last serial port error.'' Returns:' Error Code - Last serial port error code.'------------------------------------------------------------------------------- Public Function CommGetError(strMessage As String) As LongWith udtCommErrorCommGetError = .lngErrorCodestrMessage = "Error (" & CStr(.lngErrorCode) & "): " & .strFunction & _ " - " & .strErrorMessageEnd WithEnd Function‘*********************************************************************** Private Sub CommandButton1_Click()Dim intPortID As Integer ' Ex. 1, 2, 3, 4 for COM1 - COM4Dim lngStatus As LongintPortID = 1' Open COM portlngStatus = CommOpen(intPortID, "COM" & CStr(intPortID), _"baud=9600 parity=N data=8 stop=1")End SubPrivate Sub CommandButton2_Click()Dim intPortID As Integer ' Ex. 1, 2, 3, 4 for COM1 - COM4Dim lngStatus As LongDim strData As StringintPortID = 1strData = "*IDN?;"'Writa datalngStatus = CommWrite(intPortID, strData)。
简单的串口通信实例
24
pid_t pid; //进程号的类型定义
int iFlag1,iFlag2; //数据传输标志
struct termios term1;//串口设置参数结构体
struct termios term2;//
int i,j,k,l;
int iPortFD1;//串口1文件描述符
B9600:波特率为9600;
25
CS8:8数据位
CREAD:Enable receiver
CLOCAL:Local line - do not change "owner" of port
**************************************************************/
tcsetattr(iPortFD1, TCSANOW, &term1); //设置终端的相关参数
/*open serial 2*/
i=1;
sprintf(cBuf, "/dev/ttyM%d", i);
iPortFD2 = open(cBuf, O_RDWR | O_NDELAY);
}
}
close(iPortFD2);
printf("\n Port2 closed!!\n");
exit(0); /*注意子进程必须用exit()退出运行*/
}
else
{
close(iPortFD1);
close(iPortFD2);
printf("fork error\n");
}
}
close(iPortFD1);
串口与单片机通信
1 Windows API通信函数方法与通信有关的Windows API函数共有26个,但主要有关的有:CreateFile() 用“comn”(n为串口号)作为文件名就可以打开串口。
ReadFile() 读串口。
WriteFile() 写串口。
CloseHandle() 关闭串口句柄。
初始化时应注意CreateFile()函数中串口共享方式应设为0,串口为不可共享设备,其它与一般文件读写类似。
以下给出API实现的源代码。
1.1 发送的例程//声明全局变量HANDLE m_hIDComDev;OVERLAPPED m_OverlappedRead, m_Over lappedWrite;//初始化串口void CSerialAPIView::OnInitialUpdate(){CView::OnInitialUpdate();Char szComParams[50];DCB dcb;Memset(&m_OverlappedRead, 0, sizeof (OVERLAPPED));Memset(&m_OverlappedWrite, 0, sizeof (OVERLAPPED));m_hIDComDev = NULL;m_hIDComDev = CreateFile(“COM2”, GENERIC_READ│GENERIC_WRITE, 0, NULL,OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL│FILE_FL AG_OVERLAPPED, NULL);if (m_hIDComDev == NULL){AfxMessageBox(“Can not open serial port!”);goto endd;}memset(&m_OverlappedRead, 0, sizeof (OVERLAPPED));memset(&m_OverlappedWrite, 0, sizeof (OVERLAPPED)); COMMTIMEOUTS CommTimeOuts;CommTimeOuts.ReadIntervalTimeout=0×FFFFFFFF; CommTimeOuts.ReadTotalTimeoutMultiplier = 0;CommTimeOuts.ReadTotalTimeoutConstant = 0;CommTimeOuts.WriteTotalTimeoutMultiplier = 0;CommTimeOuts.WriteTotalTimeoutConstant = 5000; SetCommTimeouts(m_hIDComDev, &CommTimeOuts);Wsprintf(szComparams, “COM2:9600, n, 8, 1”);m_OverlappedRead. hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); m_OverlappedWrite. hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); dcb. DCBlength = sizeof(DCB);GetCommState(m_hIDComDev, &dcb);dcb. BaudRate = 9600;dcb. ByteSize= 8;unsigned char ucSet;ucSet = (unsigned char) ((FC_RTSCTS&FC_DTRDSR) != 0);ucSet = (unsigned char) ((FC_RTSCTS&FC_RTSCTS) ! = 0);ucSet = (unsigned char) ((FC_RTSCTS&FC_XONXOFF) ! = 0);if (!SetCommState(m_hIDComDev, &dcb)‖!SetupComm(m_hIDComDev,10000,10000)‖m_OverlappedRead. hEvent ==NULL‖m_OverlappedWrite. hEvent ==NULL){DWORD dwError = GetLastError();if (m_OverlappedRead. hEvent != NULL)CloseHandle(m_OverlappedRead. hEvent);if (m_OverlappedWrite. hEvent != NULL)CloseHandle(m_OverlappedWrite. hEvent);CloseHandle(m_hIDComDev);}endd:;}//发送数据void CSerialAPIView::OnSend(){char szMessage[20] = “thank you very much”;DWORD dwBytesWritten;for (int i=0; i<sizeof(szMessage); i++){WriteFile(m_hIDComDev, (LPSTR)&szMessage[i], 1, &dwBytesWritten, &m_OverlappedWrite); if (WaitForSingleObject(m_OverlapperWrite, hEvent, 1000))dwBytesWritten = 0;else{GentOverlappedResult(m_hIDComDev, &m_OverlappedWrite, &dwBytesWritten, FALSE);m_OverlappedWrite. Offset += dwBytesWritten;}dwBytesWritten++;}}1.2 接收例程DCB ComDcb; //设备控制块HANDLE hCom; //global handlehCom = CreateFile ("COM1",GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);if (hCom==INVALID_HANDLE_VALUE){AfxMessageBox("无法打开串行口");}else{COMMTIMEOUTS CommTimeOuts ;SetCommMask(hCom, EV_RXCHAR ) ;SetupComm(hCom, 4096, 4096 ) ; /*设置收发缓冲区尺寸为4K */PurgeComm(hCom, PURGE_TXABORT| PURGE_RXABORT | PURGE_TXCLEAR| PURGE_RXCLEAR ) ; //清收发缓冲区//以下初始化结构变量CommTimeOuts, 设置超时参数CommTimeOuts.ReadIntervalTimeout =0×FFFFFFFF ;CommTimeOuts.ReadTotalTimeoutMultiplier = 0;CommTimeOuts.ReadTotalTimeoutConstant = 4000;CommTimeOuts.WriteTotalTimeoutMultiplier = 0;CommTimeOuts.WriteTotalTimeoutConstant = 4000;SetCommTimeouts(hCom, &CommTimeOuts ); //设置超时参数ComDcb.DCBlength = sizeof( DCB );GetCommState( hCom, &ComDcb ); //获取当前参数ComDcb.BaudRate =9600; //波特率ComDcb.ByteSize = 8; //数据位ComDcb.Parity = 0; /*校验0~4=no, odd, even, mark, space */SetCommState(hCom, &ComDcb ) ;} //设置新的通信参数接收可用定时器或线程等DWORD dRead,dReadNum;unsigned char buff [200];dRead=ReadFile(hCom, buff, 100, &dReadNum, NULL); //接收100个字符,//dReadNum为实际接收字节数2 利用端口函数直接操作这种方式主要是采用两个端口函数_inp(), _outp()实现对串口的读写,其中读端口函数的原型为:int _inp(unsigned shot port)该函数从端口读取一个字节,端口号为0~65535。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
{
bRead = TRUE;
bResult = GetOverlappedResult(hComm, // Handle to COMM port
&m_ov, // Overlapped structure
MessageBox(NULL, Temp, "Application Error", MB_ICONSTOP);
LocalFree(lpMsgBuf);
delete[] Temp;
return true;
}
bool openport(char *portname)//打开一个串口
/* ******************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <conio.h>
HANDLE hComm;
/* ---------- Serial Port Config ------- */
dcb.BaudRate = rate;
dcb.Parity = NOPARITY;
dcb.fParity = 0;
dcb.StopBits = ONESTOPBIT;
{
COMMTIMEOUTS timeouts;
timeouts.ReadIntervalTimeout=ReadInterval;
timeouts.ReadTotalTimeoutConstant=ReadTotalconstant;
timeouts.ReadTotalTimeoutMultiplier=ReadTotalMultiplier;
1, // Read one byte
&BytesRead, // Stores number of bytes read
&m_ov); // pointer to the m_ov structure
dcb.fRtsControl = RTS_CONTROL_DISABLE;
dcb.fOutX = 0;
dcb.fInX = 0;
/* ----------------- misc parameters ----- */
{
ProcessErrorMessage("SetCommTimeouts()");
return false;
}
else
return true;
}
ReceiveChar( )
{
BOOL bRead = TRUE;
return false;
}
else
return true;
}
bool setuptimeout(DWORD ReadInterval,DWORD ReadTotalMultiplier,DWORD ReadTotalconstant,DWORD WriteTotalMultiplier,DWORD WriteTotalconstant)
break;
}
default:
{
break;
}
}
}
else
{
bRead = TRUE;
}
} // close if (bRead)
BOOL bResult = TRUE;
DWORD dwError = 0;
DWORD BytesRead = 0;
char RXBuff;
for (;;)
{
bResult = ClearCommError(hComm, &dwError, &comstat);
if (comstat.cbInQue == 0)
{
DCB dcb;
int rate= rate_arg;
memset(&dcb,0,sizeof(dcb));
if(!GetCommState(hComm,&dcb))//获取当前DCB配置
{
ProcessErrorMessage("GetCommState()");
return FALSE;
}
/* -------------------------------------------------------------------- */
// set DCB to configure the serial port
dcb.DCBlength = sizeof(dcb);
dcb.ByteSize = 8;
dcb.fOutxCtsFlow = 0;
dcb.fOutxDsrFlow = 0;
dcb.fDtrControl = DTR_CONTROL_DISABLE;
dcb.fDsrSensitivity = 0;
dcb.fErrorChar = 0;
dcb.fBinary = 1;
dcb.fNull = 0;
dcb.fAbortOnError = 0;
dcb.wReserved = 0;
{
hComm = CreateFile(portname,
GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
ResetEvent(m_hWriteEvent);
if (bWrite)
{
m_ov.Offset = 0;
m_ov.OffsetHigh = 0;
// Clear buffer
bResult = WriteFile(hComm, // Handle to COMM Port
m_szWriteBuffer, // Pointer to message buffer in calling finction
m_nToSend, // Length of message to send
&BytesSent, // Where to store the number of bytes sent
printf("%c",RXBuff);
if (!bResult)
{
switch (dwError = GetLastError())
{
case ERROR_IO_PENDING:
{
bRead = FALSE;
timeouts.WriteTotalTimeoutConstant=WriteTotalconstant;
timeouts.WriteTotalTimeoutMultiplier=WriteTotalMultiplier;
if(!ommTimeouts(hComm, &timeouts))
}
}
WriteChar(BYTE* m_szWriteBuffer,DWORD m_nToSend)
{
BOOL bWrite = TRUE;
BOOL bResult = TRUE;
DWORD BytesSent = 0;
HANDLE m_hWriteEvent;
&m_ov ); // Overlapped structure
if (!bResult)
{
DWORD dwError = GetLastError();
/* -------------------------------------------------------------------- */
// set DCB
if(!SetCommState(hComm,&dcb))
{
ProcessErrorMessage("SetCommState()");
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &lpMsgBuf,
0,
NULL
);
sprintf(Temp, "WARNING: %s Failed with the following error: \n%s\nPort: %d\n", (char*)ErrorText, lpMsgBuf, "com2");
continue;
if (bRead)
{
bResult = ReadFile(hComm, // Handle to COMM port
&RXBuff, // RX Buffer Pointer
&BytesRead, // Stores number of bytes read
TRUE); // Wait flag
}
FILE_FLAG_OVERLAPPED,
0);
if (hComm == INVALID_HANDLE_VALUE)
return FALSE;
else
return true;
}
bool setupdcb(int rate_arg)
dcb.XonLim = 2;
dcb.XoffLim = 4;
dcb.XonChar = 0x13;