串口通信是指外设和计算机间,通过数据信号线 、地线、控制线等,按位进行传输数据的一种通讯方式。这种通信方式使用的数据线少,在远距离通信中可以节约通信成本,但其传输速度比并行传输低。
串口是计算机上一种非常通用的设备通信协议。大多数计算机(不包括笔记本电脑)包含两个基于RS-232的串口。串口同时也是仪器仪表设备通用的通信协议;很多GPIB兼容的设备也带有RS-232口。同时,串口通信协议也可以用于获取远程采集设备的数据。
RS-232(ANSI/EIA-232标准)是IBM-PC及其兼容机上的串行连接标准。可用于许多用途,比如连接鼠标、打印机或者Modem,同时也可以接工业仪器仪表。用于驱动和连线的改进,实际应用中RS-232的传输长度或者速度常常超过标准的值。RS-232只限于PC串口和设备间点对点的通信。RS-232串口通信最远距离是50英尺。
RS-232串口,串口按位(bit)发送和接收字节。尽管比按字节(byte)的并行通信慢,但是串口可以在使用一根线发送数据的同时用另一根线接收数据。典型地,串口用于ASCII码字符的传输。通信使用3根线完成:(1)地线,(2)发送,(3)接收。
本文以c#中的SerialPort类为例,分析串口各参数及事件,其他平台串口库的操作类似。
串口事件解释
switch(m_commctrl.GetCommEvent())
{
case 1: // vbMSCommEvSend:
“Sending”
case 2: // vbMSCommEvReceive:
“Receiving”
case 3: // vbMSCommEvCTS:
“Change in CTS Detected”
case 4: // vbMSCommEvDSR:
“Change in DSR Detected”
MSComm控件使用详解
MSComm 控件通过串行端口传输和接收数据,为应用程序提供串行通讯功能。MSComm控件在串口编程时非常方便,程序员不必去花时间去了解较为复杂的API函数,而且在VC、VB、Delphi等语言中均可使用。 Microsoft Communications Control(以下简称MSComm)是Microsoft公司提供的简化Windows下串行通信编程的ActiveX控件,它为应用程序提供了通过串行接口收发数据的简便方法。具体的来说,它提供了两种处理通信问题的方法:一是事件驱动(Event-driven)方法,一是查询法。
1.MSComm控件两种处理通讯的方式
MSComm控件提供下列两种处理通讯的方式:事件驱动方式和查询方式。
1.1 事件驱动方式
事件驱动通讯是处理串行端口交互作用的一种非常有效的方法。在许多情况下,在事件发生时需要得到通知,例如,在串口接收缓冲区中有字符,或者 Carrier Detect (CD) 或 Request To Send (RTS) 线上一个字符到达或一个变化发生时。在这些情况下,可以利用 MSComm 控件的 OnComm 事件捕获并处理这些通讯事件。OnComm 事件还可以检查和处理通讯错误。所有通讯事件和通讯错误的列表,参阅 CommEvent 属性。在编程过程中,就可以在OnComm事件处理函数中加入自己的处理代码。这种方法的优点是程序响应及时,可靠性高。每个MSComm 控件对应着一个串行端口。如果应用程序需要访问多个串行端口,必须使用多个 MSComm 控件。
1.2 查询方式
查询方式实质上还是事件驱动,但在有些情况下,这种方式显得更为便捷。在程序的每个关键功能之后,可以通过检查 CommEvent 属性的值来查询事件和错误。如果应用程序较小,并且是自保持的,这种方法可能是更可取的。例如,如果写一个简单的电话拨号程序,则没有必要对每接收一个字符都产生事件,因为唯一等待接收的字符是调制解调器的“确定”响应。
2.MSComm 控件的常用属性
MSComm 控件有很多重要的属性,但首先必须熟悉几个属性。
CommPort 设置并返回通讯端口号。
Settings 以字符串的形式设置并返回波特率、奇偶校验、数据位、停止位。
PortOpen 设置并返回通讯端口的状态。也可以打开和关闭端口。
Input 从接收缓冲区返回和删除字符。
Output 向传输缓冲区写一个字符串。
下面分别描述:
CommPort属性 设置并返回通讯端口号。
语法 object.CommPort[value ] (value 一整型值,说明端口号。)
说明 在设计时,value 可以设置成从 1 到 16 的任何数
(缺省值为 1)。但是如果用 PortOpen 属性打开一个并不存在的端口时,MSComm 控件会产生错误 68(设备无效)。
注意:必须在打开端口之前设置 CommPort 属性。
RThreshold 属性:在 MSComm 控件设置 CommEvent 属性为 comEvReceive 并产生 OnComm 之前,设置并返回的要接收的字符数。
语法 object.Rthreshold [ = value ](value 整型表达式,说明在产生 OnComm 事件之前要接收的字符数。 )
说明 当接收字符后,若 Rthreshold 属性设置为 0(缺省值)则不产生 OnComm 事件。例如,设置 Rthreshold 为 1,接收缓冲区收到每一个字符都会使 MSComm 控件产生 OnComm 事件。
CTSHolding 属性:确定是否可通过查询 Clear To Send (CTS) 线的状态发送数据。Clear To Send 是调制解调器发送到相联计算机的信号,指示传输可以进行。该属性在设计时无效,在运行时为只读。
语法: object.CTSHolding(Boolean)
Mscomm 控件的 CTSHolding 属性设置值:
True Clear To Send 线为高电平。
False Clear To Send 线为低电平。
说明:如果 Clear To Send 线为低电平 (CTSHolding = False) 并且超时时,MSComm 控件设置 CommEvent 属性为 comEventCTSTO (Clear To Send Timeout) 并产生 OnComm 事件。
Clear To Send 线用于 RTS/CTS (Request To Send/Clear To Send)硬件握手。如果需要确定 Clear To Send 线的状态,CTSHolding 属性给出一种手工查询的方法。
详细信息有关握手协议,请参阅 Handshaking 属性。
SThreshold 属性: MSComm 控件设置 CommEvent 属性为 comEvSend 并产生 OnComm 事件之前,设置并返回传输缓冲区中允许的最小字符数。
语法 object.SThreshold [ = value ]
value 整形表达式,代表在 OnComm 事件产生之前在传输缓冲区中的最小字符数。
说明:若设置 Sthreshold 属性为 0(缺省值),数据传输事件不会产生 OnComm 事件。若设置 Sthreshold 属性为 1,当传输缓冲区完全空时,MSComm 控件产生 OnComm 事件。如果在传输缓冲区中的字符数小于 value,CommEvent 属性设置为 comEvSend,并产生 OnComm 事件。comEvSend 事件仅当字符数与 Sthreshold 交叉时被激活一次。例如,如果 Sthreshold 等于 5,仅当在输出队列中字符数从 5 降到 4 时,comEvSend 才发生。如果在输出队列中从没有比 Sthreshold 多的字符,comEvSend 事件将绝不会发生。
Handshake 常数
常数 值 描述
comNone 0 无握手。
comXonXoff 1 XOn/Xoff 握手。
comRTS 2 Request-to-send/clear-to-send 握手。
comRTSXOnXOff 3 Request-to-send 和 clear-to-send 握手皆可。
OnComm 常数
常数 值 描述
comEvSend 1 发送事件。
comEvReceive 2 接收事件。
comEvCTS 3 clear-to-send 线变化。
comEvDSR 4 data-set ready 线变化。
comEvCD 5 carrier detect 线变化。
comEvRing 6 振铃检测。
comEvEOF 7 文
件结束。
Error 常数
常数 值 描述
comEventBreak 1001 接收到中断信号
comEventCTSTO 1002 Clear-to-send 超时
comEventDSRTO 1003 Data-set ready 超时
comEventOverrun 1006 端口超速
comEventCDTO 1007 Carrier detect 超时
comEventRxOver 1008 接收缓冲区溢出
comEventRxParity 1009 Parity 错误
comEventTxFull 1010 传输缓冲区满
comEventDCB 1011 检索端口 设备控制块 (DCB) 时的意外错误
InputMode 常数
常数 值 描述
comInputModeText 0 (缺省)通过 Input 属性以文本方式取回数据。
comInputModeBinary 1 通过 Input 属性以二进制方式检取回数据。
CDHolding 属性:通过查询 Carrier Detect (CD) 线的状态确定当前是否有传输。Carrier Detect 是从调制解调器发送到相联计算机的一个信号,指示调制解调器正在联机。该属性在设计时无效,在运行时为只读。
语法 object.CDHolding
设置值:CDHolding 属性的设置值为:
设置 描述
True Carrier Detect 线为高电平
False Carrier Detect 线为低电平
说明:注意当 Carrier Detect 线为高电平 (CDHolding = True) 且超时时,MSComm 控件设置CommEvent 属性为 comEventCDTO(Carrier Detect 超时错误),并产生 OnComm 事件。
注意 在主机应用程序中捕获一个丢失的传输是特别重要的,例如一个公告板,因为呼叫者可以随时挂起(放弃传输)。
Carrier Detect 也被称为 Receive Line Signal Detect (RLSD)。
数据类型 Boolean
DSRHolding 属性:确定 Data Set Ready (DSR) 线的状态。Data Set Ready 信号由调制解调器发送到相连计算机,指示作好操作准备。该属性在设计时无效,在运行时为只读。
语法:object.DSRHolding
object 所在处表示对象表达式,其值是“应用于”列表中的对象。
DSRHolding 属性返回以下值:
值 描述
True Data Set Ready 线高
False Data Set Ready 线低
说明:当 Data Set Ready 线为高电平 (DSRHolding = True) 且超时时,MSComm 控件设置 CommEvent 属性为 comEventDSRTO(数据准备超时)并产生 OnComm 事件。
当为 Data Terminal Equipment (DTE) 机器写 Data Set Ready/Data Terminal Ready 握手例程时该属性是十分有用的。
数据类型:Boolean
Settings 属性: 设置并返回波特率、奇偶校验、数据位、停止位参数。
语法: object.Settings[ = value]
说明:当端口打开时,如果 value 非法,则 MSComm 控件产生错误 380(非法属性值)。
Value 由四个设置值组成,有如下的格式:
“BBBB,P,D,S”
BBBB 为波特率,P 为奇偶校验,D 为数据位数,S 为停止位数。value 的缺省值是:
“9600,N,8,1”
InputLen 属性:设置并返回 Input 属性从接收缓冲区读取的字符数。
语法 object.InputLen [ = value]
InputLen 属性语法包括下列部分:
value 整型表达式,说明 Input 属性
从接收缓冲区中读取的字符数。
说明:InputLen 属性的缺省值是 0。设置 InputLen 为 0 时,使用 Input 将使 MSComm 控件读取接收缓冲区中全部的内容。
若接收缓冲区中 InputLen 字符无效,Input 属性返回一个零长度字符串 (“”)。在使用 Input 前,用户可以选择检查 InBufferCount 属性来确定缓冲区中是否已有需要数目的字符。该属性在从输出格式为定长数据的机器读取数据时非常有用。
EOFEnable 属性:确定在输入过程中 MSComm 控件是否寻找文件结尾 (EOF) 字符。如果找到 EOF 字符,将停止输入并激活 OnComm 事件,此时 CommEvent 属性设置为 comEvEOF,
语法:object.EOFEnable [ = value ]
EOFEnable 属性语法包括下列部分:
value 布尔表达式,确定当找到 EOF 字符时,OnComm 事件是否被激活,如“设置值”中所描述。
value 的设置值:
True 当 EOF 字符找到时 OnComm 事件被激活。
False (缺省)当 EOF 字符找到时 OnComm 事件不被激活。
说明:当 EOFEnable 属性设置为 False,OnComm 控件将不在输入流中寻找 EOF 字符。
错误消息(MS Comm 控件)
硬件流控:串口通信中的硬件流控有两种,DTE/DSR方式和RTS/CTS方式,这与DCB结构的初始化有关系,DCB结构中的OutxCtsFlow、 fOutxDsrFlow、fDsrSensitivity、fRtsControl、fDtrControl几个成员的初始值很关键,不同的值代表不同流控,也可以自己设置流控,但建议采用标准流行的流控方式。采用硬件流控时,DTE、DSR、RTS、CTS的逻辑位直接影响到数据的读写及收发数据的缓冲区控制。
软件流控:串口通信中采用特殊字符XON和XOFF作为控制串口数据的收发。与此相关的DCB成员是:fOut、fInX、XoffChar、XonChar、 XoffLim和XonLim。具体含义参见MSDN帮助。
2.硬件流控制
硬件流控制常用的有RTS/CTS流控制和DTR/DSR(数据终端就绪/数据设置就绪)流控制。
硬件流控制必须将相应的电缆线连上,用RTS/CTS(请求发送/清除发送)流控制时,应将通讯两端的RTS、CTS线对应相连,数据终端设备(如计算机)使用RTS来起始调制解调器或其它数据通讯设备的数据流,而数据通讯设备(如调制解调器)则用CTS来起动和暂停来自计算机的数据流。这种硬件握手方式的过程为:我们在编程时根据接收端缓冲区大小设置一个高位标志(可为缓冲区大小的75%)和一个低位标志(可为缓冲区大小的25%),当缓冲区内数据量达到高位时,我们在接收端将CTS线置低电平(送逻辑0),当发送端的程序检测到CTS为低后,就停止发送数据,直到接收端缓冲区的数据量低于低位而将CTS 置高电平。RTS则用来标明接收设备有没有准备好接收数据。
常用的流控制还有还有DTR/DSR(数据终端就绪
/数据设置就绪)。我们在此不再详述。由于流控制的多样性,我个人认为,当软件里用了流控制时,应做详细的说明,如何接线,如何应用。
3.软件流控制
由于电缆线的限制,我们在普通的控制通讯中一般不用硬件流控制,而用软件流控制。一般通过 XON/XOFF来实现软件流控制。常用方法是:当接收端的输入缓冲区内数据量超过设定的高位时,就向数据发送端发出XOFF字符(十进制的19或 Control-S,设备编程说明书应该有详细阐述),发送端收到XOFF字符后就立即停止发送数据;当接收端的输入缓冲区内数据量低于设定的低位时,就向数据发送端发出XON字符(十进制的17或Control-Q),发送端收到XON字符后就立即开始发送数据。一般可以从设备配套源程序中找到发送的是什么字符。
应该注意,若传输的是二进制数据,标志字符也有可能在数据流中出现而引起误操作,这是软件流控制的缺陷,而硬件流控制不会有这个问题
关于流控制的设置问题:
流控制的设置可以用EscapeCommFunction函数来设置,也可以通过DCB结构来设置。
在流控制方式为“无”和“软件控制”的情况下,基本上没有什么问题,但在“硬件控制”下,Win32手册中说明RTS_CONTROL_HANDSHAKE控制方式的含义如下:
Enable RTS handshaking .The driver raises the RTS line when the “type_ahead”(input)buffer is less than one-half full and lowers the RTS line when the buffer is more than three-quarters full.If handshaking is enabled,it is an error for the application to adjust the line by using the EscapeCommFunction function.
也就是说,当缓冲区快满的时候,RTS会自动OFF通知对方暂停发送,当缓冲区重新空出来的时候,RTS也会自动地ON。但我发现当RTS变OFF以后,即使你已经清空了缓冲区,RTS也不会自动地ON,造成对方停在那里不发送。所以,如果要用硬件流控制的话,则还要在接收后最好加上检测缓冲区大小的判断,具体事使用ClearCommError后返回的COMSTAT.cbInQue,当缓冲区已经空出来的时候,要使用invoke EscapeCommFunction(hComm,SETRTS)重新将RTS设置为ON.
串口通信属性
一、属性
1. PortName 串口名 默认值COM1
串口对于操作系统来说是一个文件,如果设置PortName为本机不存在的串口名(即文件名),如“COM7”或“COMK”,Open()打开串口将失败,提示“端口COM7不存在”。
2. BaudRate 获取或设置串行波特率bit/s 默认值9600
比特率=波特率X单个调制状态对应的二进制位数。
RS232是要用在近距离传输上最大距离为30M
RS485用在长距离传输最大距离1200M
3. DataBits 获取或设置每个字节的标准数据位长度 默认值8
当计算机发送一个信息包,实际的数据不会是8位的,标准的值是5、7和8位。如何设置取决于你想传送的信息。比如,标准的ASCII码是0~127(7位)。扩展的ASCII码是0~255(8位)。如果数据使用简单的文本(标准 ASCII码),那么每个数据包使用7位数据。每个包是指一个字节,包括开始/停止位,数据位和奇偶校验位。由于实际数据位取决于通信协议的选取,术语“包”指任何通信的情况。
4. StopBits 获取或设置每个字节的标准停止位数 默认值One
用于表示单个包的最后一位。典型的值为1,1.5和2位。由于数据是在传输线上定时的,并且每一个设备有其自己的时钟,很可能在通信中两台设备间出现了小小的不同步。因此停止位不仅仅是表示传输的结束,并且提供计算机校正时钟同步的机会。适用于停止位的位数越多,不同时钟同步的容忍程度越大,但是数据传输率同时也越慢。
5. Parity 获取或设置奇偶校验检查协议 默认值None
在串口通信中一种简单的检错方式。有四种检错方式:偶、奇、高和低。当然没有校验位也是可以的。对于偶和奇校验的情况,串口会设置校验位(数据位后面的一位),用一个值确保传输的数据有偶个或者奇个逻辑高位。例如,如果数据是011,那么对于偶校验,校验位为0,保证逻辑高的位数是偶数个。如果是奇校验,
校验位位1,这样就有3个逻辑高位。高位和低位不真正的检查数据,简单置位逻辑高或者逻辑低校验。这样使得接收设备能够知道一个位的状态,有机会判断是否有噪声干扰了通信或者是否传输和接收数据是否不同步。
6. ParityReplace 获取或设置一个字节,该字节在发生奇偶校验错误时替换数据流中的无效字节 默认值63(?)
7. ReadBufferSize 获取或设置 SerialPort 输入缓冲区的大小 默认值4096
ReadBufferSize 属性忽略任何小于 4096 的值??由于 ReadBufferSize 属性只表示 Windows 创建的缓冲区,而 BytesToRead 属性除了表示 Windows 创建的缓冲区外还表示 SerialPort 缓冲区,所以 BytesToRead 属性可以返回一个比 ReadBufferSize 属性大的值。
8. ReadTimeout 获取或设置读取操作未完成时发生超时之前的毫秒数 默认值-1
确切的说ReadTimeout设置了Read(outBuf, offset, count)超时等待的时间,即如果接收缓冲区一直没有数据,则Read()等待ReadTimeout毫秒后甩TimeoutException异常。但是在ReadTimeout期间,只要有一个数据,则Read()立马返回,而不是等待count个字节数据。ReadTimeout不是为了Read()阻塞等待count个字节,那它有什么意义?
9. ReceivedBytesThreshold 获取或设置 DataReceived 事件发生前内部输入缓冲区中的字节数 默认值1
如果缓冲区一次性有4个字节数据,那么DataReceived事件是触发1次还是4次?
10. WriteBufferSize 获取或设置串行端口输出缓冲区的大小 默认值2048
ReadBufferSize 属性忽略任何小于 4096 的值。
由于 ReadBufferSize 属性仅表示 Windows 创建的缓冲区,所以它可以返回比 BytesToRead属性小的值,这表示 SerialPort 和 Windows 创建的缓冲区。
11. WreiteTimeout 获取或设置写入操作未完成时发生超时之前的毫秒数 默认值-1
写入超时值在 Win32 通信 API 中最初被设置为 500 毫秒。此属性允许您设置此值。此值可以设置为 0 以立即从写入操作返回,或设置为任意正值,也可以设置为默认的 InfiniteTimeout。此属性不影响 BaseStream 的 BeginWrite 方法。
12. BytesToRead 获取接收缓冲区中数据的字节数
由于 ReadBufferSize 属性只表示 Windows 创建的缓冲区,而 BytesToRead 属性除了表示 Windows 创建的缓冲区外还表示 SerialPort 缓冲区,所以 BytesToRead 属性可以返回一个比 ReadBufferSize 属性大的值。
13. BytesToWrite 获取发送缓冲区中数据的字节数
14. NewLine 获取或设置用于解释 ReadLine( )和WriteLine( )方法调用结束的值 默认值“\n”
15. DiscardNull 获取或设置一个值,指示 Null 字节在端口和接收缓冲区之间传输时是否被忽略 默认值false
正常情况下,特别是对于二进制传输而言,此值应该设置为 false。将此属性设置为 true 会使 UTF32 和 UTF16 编码字节产生意外结果。
16. Handshake 获取或设置串行端口数据传输的握手协议 默认值None
使用握手时,将指示连接到 SerialPort 对象的设备在缓冲区中至少有 (ReadBufferSize-1024) 个字节时停止发送数据。当缓冲区中的字节数小于等于 1024 时,将指示设备重新开始发送数据。如果设备在大于 1024 个字节的块中发送数据,可能会导致缓冲区溢出。
如果将 Handshake 属性设置为 RequestToSendXOnXOff 并将 CtsHolding 设置为 false,则不会发送 XOff 字符。如果后来将 CtsHolding 设置为 true,则必须发送更多的数据后才会发送 XOff 字符。
17. Encodeing 获取或设置传输前后文本转换的字节编码 默认为 ASCIIEncoding
ASCIIEncoding 不提供错误检测。出于安全原因,建议您使用 UTF8Encoding、UnicodeEncoding 或 UTF32Encoding 并启用错误检测。
ASCIIEncoding 仅支持 U+0000 和 U+007F之间的 Unicode 字符值。因此,UTF8Encoding、UnicodeEncoding 和 UTF32Encoding 可以更好地适应全球化的应用程序。
18. DtrEnable 获取或设置一个值,该值在串行通信过程中启用数据终端就绪 (DTR) 信号 默认值 false
在 XON/XOFF 软件握手、请求发送/可以发送 (RTS/CTS) 硬件握手和调制解调器通信的过程中通常启用数据终端就绪 (DTR)。
19. RtsEnable 获取或设置一个值,该值指示在串行通信中是否启用请求发送 (RTS) 信号 默认值false
请求发送 (RTS) 信号通常用在请求发送/可以发送 (RTS/CTS) 硬件握手中。
20. CDHolding 获取端口的载波检测行的状态
此属性可用于监视端口的载波检测行的状态。无载波通常表明接收方已挂断且载波已被丢弃。
21. CtsHolding 获取“可以发送”行的状态
在请求发送/可以发送 (RTS/CTS) 硬件握手中使用可以发送 (CTS) 行。发送数据之前端口会查询 CTS 行。
22. DsrHolding 获取数据设置就绪 (DSR) 信号的状态
在数据设置就绪/数据终端就绪 (DSR/DTR) 握手中使用此属性。通常由调制解调器将数据设置就绪 (DSR) 信号发送到端口,以表明它已经为数据传输或数据接收做好准备。
23. BufferSize 值1024
24. maxDataBits 值8
25. minDataBits 值5
26. SERIAL_NAME 值\\Device\\Serial
二、方法
1. Open() 打开一个新的串行端口连接
2. Close() 关闭端口连接,将 IsOpen 属性设置为 false,并释放内部 Stream 对象
3. Read(Byte[], int, int) 输入缓冲区读取一些字节并将那些字节写入字节数组中指定的偏移量处
4. ReadByte() 从 SerialPort 输入缓冲区中同步读取一个字节
5. ReadChar() 从 SerialPort 输入缓冲区中同步读取一个字符
6. ReadExisting() 在编码的基础上,读取 SerialPort 对象的流和输入缓冲区中所有立即可用的字节
6. ReadLine() 一直读取到输入缓冲区中的 NewLine 值
7. ReadTo() 一直读取到输入缓冲区中的指定 value 的字符串
8. Write(string) 将指定的字符串写入串行端口
9. Write(Byte[], int, int) 使用缓冲区的数据将指定数量的字符写入串行端口
10. WriteLine() 将指定字符串和NewLine值写入输出缓冲区
11. DiscardInBuffer() 丢弃接收缓冲区的数据
12. DiscardOutBuffer() 丢弃发送缓冲区的数据
12. static GetPortNanes() 获取当前计算机的串口名称数组
三、事件
1. DataReceive事件 数据接收事件的方法
不保证对接收到的每个字节引发 DataReceived 事件。 使用 BytesToRead 属性确定缓冲区中剩余的要读取的数据量。从 SerialPort 对象接收数据时,将在辅助线程上引发 DataReceived 事件。
2. PinChanged事件 串行管脚更改事件的方法
在 SerialPort 对象进入 BreakState 时引发,但在端口退出 BreakState 时不引发。将在辅助线程上引发 PinChanged 事件。
3. ErrorReceived事件 错误事件的方法
如果在流的尾字节上出现奇偶校验错误,将向输入缓冲区添加一个值为 126 的额外字节。将在辅助线程上引发 PinChanged 事件。
评论
查看更多