delphi 串口通信编程

139
Delphi Delphi 串串串串串串 串串串串串串 串串

Upload: kelli

Post on 15-Jan-2016

199 views

Category:

Documents


0 download

DESCRIPTION

Delphi 串口通信编程. 魏贇. 第一章 基本概念. 通信 串行通信 硬件基础知识 模式及流量 接线和错误预防 错误排除. 1 、通信. 通信:不同的独立系统通过线路互相交换数据 数据通信:终端与计算机之间的通信或计算机与计算机之间的通信 网络:构成整个通信的线路 数据传送 通信的类型 字符传输. 数据传送. 完整的通信系统包括发送端、接收端、转换数据 的接口以及传送数据的实际信道或媒体 DTE ( Data Terminal Equipment ):发送与接收的节点 - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: Delphi 串口通信编程

DelphiDelphi 串口通信编程串口通信编程

魏贇

Page 2: Delphi 串口通信编程

第一章 基本概念第一章 基本概念

1. 通信2. 串行通信3. 硬件基础知识4. 模式及流量5. 接线和错误预防6. 错误排除

Page 3: Delphi 串口通信编程

11 、通信、通信通信:不同的独立系统通过线路互相交换数据数据通信:终端与计算机之间的通信或计算机与

计算机之间的通信网络:构成整个通信的线路数据传送通信的类型字符传输

Page 4: Delphi 串口通信编程

数据传送数据传送完整的通信系统包括发送端、接收端、转换数据的接口以及传送数据的实际信道或媒体

DTE ( Data Terminal Equipment ):发送与接收的节点DSE ( Data Switching Equipment ):中间节点,负责数据转送工作DCE ( Data Communication Equipment ):负责数据与电气信号转

换的设备

DTE 与 DCE 间的数据传输线路通常使用 RS-232

DTE 与 DSE 间的媒体则包括了双绞线、同轴电缆、光纤或无线电等

Page 5: Delphi 串口通信编程

传送的方式传送的方式 并行传送( Parallel ):一次的传输量为 8 个位( 1 字

节) 通过并行端口,如打印机 串行传送( Serial ):一次只传输 1 个位 通过串行端口,如 RS-232

Page 6: Delphi 串口通信编程

通信的种类通信的种类将数据转换成串行通信有两种方式 同步方式:接收设备能自动与发送计算机同步,接收

字符有规则的分割开来,以块为单位,没有起始位和停止位,效率高。

异步方式:以字符为传送单位,传送的字符之间有无规律的间隔,这样可能使接收设备不能正常接收数据,因为每接收完一个字符都不能确切地知道下一个接收的字符从何时开始。(通过加开始位和停止位实现)传输效率低,成本也低。

Page 7: Delphi 串口通信编程

字符传输字符传输位和字节文本编码非文本编码帧

Page 8: Delphi 串口通信编程

位和字节位和字节二进制中的每一位 0 和 1 ,被叫做一个

位每 8 个位构成一个字节一个字节中最右面的位被称为第 0 位,

最左面的位被称为第 7 位。

Page 9: Delphi 串口通信编程

文本编码文本编码文本(字符字母、标点符号等)在计算机

中存储时,每个不同的字符都用不同的数值来表示。这些数值的范围通常在 0-127 或 0-255 范围。

7 位: ASCII 码,每个字节留一个备用位8 位:前 128 个遵循 ASCII 码规则,其余

的 128 个用来做扩展字符、数字符号、图形字符等编码。

Page 10: Delphi 串口通信编程

非文本编码非文本编码

某些可执行指令文件和图形图像文件就是以二进制形式而不是 ASCII 码形式存储的。一个数据可用二进制形式存储,可以占多个字节。在通信领域,常常把这种类型的资料叫做二进制数据。

Page 11: Delphi 串口通信编程

帧帧

帧:在串行异步通信情况下,构成一个字节的那些数据单元被称为数据位,在数据位的前、后要加上起始位、停止位和奇偶校验位。

一个字符所使用的位数根据协议而不同。称这些位数为字符位数据长或字长。通常不是 8 位就是 7 位。

Page 12: Delphi 串口通信编程

22 、串行通信、串行通信RS-232 串行通信RS-485 串行通信USB 接口IEEE-1394

Page 13: Delphi 串口通信编程

RS-232RS-232 串行通信串行通信RS-232 的通信端口是每台计算机上的必要配置,通常含有 COM !和 COM2 两个端口。计算机上的 RS-232 均是公头一般有两种: 9 引脚和 25 引脚

Page 14: Delphi 串口通信编程

RS-485RS-485 串行通信串行通信RS-485 的通信方式可有效地防止噪声信号的干扰。RS-485 的信号将被发送出去时会先分成正负的两条线路,当到达接收端后,再将信号相减还原来原来的信号;如果将原始的信号记为( DT ),而被分成后的信号分别记为( D+ )及( D- ),则原始的信号与离散的信号在由发送端发送出去时: ( DT ) = ( D+ ) - ( D- )

如果此线路受干扰,则两条传输线上的信号会分别成为( D+ ) +Noise 及( D- ) +Noise

( DT ) = [ ( D+ ) +Noise]- [ ( D- ) +Noise]

= ( D+ ) - ( D- )

Page 15: Delphi 串口通信编程

USBUSB (( Universal Serial BusUniversal Serial Bus )接口)接口

集成一般计算机所使用的外围设备的连接方式,而且其所采用的信号传输方式也是串行通信。USB特性:低价位,热连接,单一的连接头方式,连接数

多,线上供电,不占系统资源,错误检测与复原,节省能源,支持四种传输(巨量、实时、中断及控制 4 种传输模式),速度较快( 12M bps/RS-232 最快 115bps )

Page 16: Delphi 串口通信编程

IEEE-1394IEEE-1394

IEEE-1394( 也称 FireWire ,火线 ) 与 USB一样拥有即插即用的功能,也是用于解决计算机与外围设备复杂的连接问题,并且也是使用串行通信的传输方式。

IEEE-1394 的传输速度是 400Mbps ,而且速度还向 1000Mbps迈进

Page 17: Delphi 串口通信编程

USBUSB 与与 IEEE-1394IEEE-1394 的比较的比较

比较项目 USB IEEE-1394 应用 低速设备 高速设备带宽( Mbps ) 1.5,12 100,200,400

电缆长度 5米 4.5米电缆 4 线 6 线即插即用 支持 支持

Page 18: Delphi 串口通信编程

33 、硬件基础知识、硬件基础知识

PC 机的 RS-232 接口名称尚未统一,有多个名称: RS-232 口、串口、通信口、 COM 口、异步口等。

1 2 3 4 5

6 7 8 9

Page 19: Delphi 串口通信编程

常用的常用的 99条条 RS-232RS-232 信号线信号线引脚 信号名称 信号方向 简称 信号功能1 载波检测 DCE-DTE DCD ( Data Carrier Detec

t )数据链路已连接

2 接收数据 DCE-DTE RxD ( Receive ) DTE 接收串行数据3 发送数据 DTE-DCE TxD ( Transmit ) DTE 发送串行数据4 数据终端就绪 DTE-DCE DTR ( Data Terminal Read

y )DTE准备准备就绪

5 信号地 - SG ( Signal Ground )

公共信号地

6 数据设备就绪 DCE-DTE DSR ( Data Set Ready )

DCE准备就绪,可以接收

7 请求发送 DTE-DCE RTS ( Request to Send )

DTE 通知 DCE请求发送

8 清除发送 DCE-DTE CTS ( Clear to Send )

DCE已切换到接收模式

9 振铃指示 DCE-DTE RI ( Ring Indicator )

通知 DTE 有远程呼叫

Page 20: Delphi 串口通信编程

一次应答呼叫过程一次应答呼叫过程

Modem 从接收到振铃信号开始,到数据传输结束Modem 和 DTE恢复到原来的空闲状态为止的过程。

Page 21: Delphi 串口通信编程

数据终端 DTE 的控制软件持续监视振铃指示 RI ,等待该 信号有效响铃后, RI 信号在 ON 和 OFF状态之间交替变化。DTE 的通信控制软件在检测到振铃指示后,开始通过计 算机振铃指示的 ON 和 OFF状态的变化次数来进行计数。 当达到程序设计的次数时,控制软件发出终端就绪信号( DTR )有效,使 Modem 进行摘机状态,开始应答电话 Modem 在等待一小段时间后,自动地发送它的应答载波 信号。同时 Modem 发出数据设备就绪信号( DSR ),通 知 DTE已经完成所有准备工作,正在等待对方的载波信 号

Page 22: Delphi 串口通信编程

在 DTE 发出数据终端就绪信号( DTR )期间, DTE 的控制软件监视数据设备就绪信号( DSR )是否有效,当DSR 为 ON状态后, DTE便知道 Modem已准备建立数据链路,于是 DTE 开始检测载波信号( DCD ),以检查数据链路是否已经建立

当主叫 Modem 的载波信号出现在电话线上时,被叫 Modem 发出载波信号( DCD ),以检查数据链路是否已经建立

在数据链路连接期间,发送数据( TxD )和接收数据( RxD )线上即开始了全又工通信。同时, DTE仍监视载波信号( DCD ),以确定数据链路是否连接

数据传输结束后, DTE 使数据终端就绪信号( DTR )无效, Modem撤消载波检测( DCD ),并且使设备数据就绪信号( DSR )信号无效。数据候链路释放后, Modem 和 DTE返回到初始状态。

Page 23: Delphi 串口通信编程

通信参数通信参数数据的传送速度数据的传送单位

Page 24: Delphi 串口通信编程

数据的传送速度数据的传送速度 波特率:每秒所能产生的最大电压状态改变率(一秒钟可以振荡的次数) bps

通信双方必须要取得一样的通信速度。原始信号经过不一样的波特率取样后,所得的结果完全不一样,如取样速度只有原来一半时,信号被跳着取样,数据因此错误。

Page 25: Delphi 串口通信编程

数据的传送单位数据的传送单位

一般串行通信端口所传送的数据是字符类型,若用来传输文件,则会使用二进制的数据类型。

Page 26: Delphi 串口通信编程

起始位及停止位起始位及停止位异步串行传输时需要当发送端要开始传送数据时,便将传输

线上的电压由低电位提升至高电位,而当传送结束后,再将电压降至低电压。接收端会因起始位的触发(因电压由低电位升至高电位)而开始接收数据;并因停止位的通知(因电压维持在低电位)而确节知道数据的字符已经结束。

Page 27: Delphi 串口通信编程

校验位的检查校验位的检查用来检查所传送数据正确性的一种核对

码,其中又分成奇校验( Odd )及偶校验( Even )

串行通信上的字符数据格式 起始位 + 传送字符 + 校验位 + 停止位

Page 28: Delphi 串口通信编程

44 、模式及流量、模式及流量工作模式硬件握手软件握手

Page 29: Delphi 串口通信编程

工作模式工作模式当计算机在进行数据的传送与接收时,传输线上的数据流动情况可分为 3 种: 单工:传输线上的数据流动只有一个方向 半双工:数据流动是双向,但同一时间只能一个方向

行进 全双工:传输线同时具有两个方向的传输能力

RS-485属于半双工, RS-232属于全双工(引脚在设计时就是接收与传送是分属两个不同的引脚与线路。)

Page 30: Delphi 串口通信编程

串行数据的流动方式串行数据的流动方式当数据要由 A 设备传送至 B 设备前,数据会先被送到 A 设备的数据输出缓冲区,接着再由此缓冲区将数据由 RS-232 线路传送到B 设备;同样地,当数据通过硬件线路传送到 B 设备时,数据首先会送到接收缓冲区,而设备 B 的 CPU再到接收缓冲区将数据读取并进行处理。

Page 31: Delphi 串口通信编程

握手握手握手信号:提供一种控制数据流的方法,即接收设备可

以控制发送设备的数据发送。如果接收设备速度比发送速度快,握手信号可以略去。在异步串行通信中,这称之为握手( handshaking )或流

量控制( flow control )。流量控制:保证传输双方都能正确地传送和接收数据而

不会漏失。握手控制可以具休分为硬件握手和软件握手。

Page 32: Delphi 串口通信编程

硬件握手硬件握手使用专门的握手电路去控制数据的传输。当接收设备准备好之后,就通过专用的握手电路传送一个正电压给发送设备,指示发送设备发送数据。如果接收设备传送一个负电压给发送设备,则指示发送设备停止发送数据。硬件握手用到 DSR 、 CTS 、 DTR 、 RTS4条硬件线路,

其中 DTR 、 RTS 指的是计算机上的 RS-232 端;而 DSR 、 CTS 则是指被控制的设备端。

Page 33: Delphi 串口通信编程

计算机计算机 ->-> 设备设备1. 设备必须将相对于计算机上的 DSR 引脚降为

低电压2. 计算机检测到 DSR 引脚为低电位后,暂停数

据的传输;同时设备继续处理位于缓冲区的数据

3. 等设备的接收缓冲区数据量下降到一定程度后,设备将 DSR 引脚的标准电压升高

4. 计算机一检测到 DSR 引脚为高电压后,随即继续传送数据给设备

Page 34: Delphi 串口通信编程

设备设备 ->-> 计算机计算机1. 计算机将 DTR 引脚降为低电压2. 设备检测到 DTR 引脚为低电压后,暂停数据

的传输;同时计算机也会继续处理位于缓冲区的数据

3. 待计算机的接收缓冲区中数据量下降到一定程度后,计算机将 DTR 引脚的标准电压升高

4. 设备一检测到 DTR 引脚为高电压后,随即继续传送数据给计算机

Page 35: Delphi 串口通信编程

软件握手软件握手以数据线上的数据信号来代替实际的硬件线路最常见的是 XON/XOFF 协议:若接收端欲使发送端暂停数据的传送时,它便向发送端送出 ASCII 第 19 号字符(十六进制是 13 );而欲恢复

传送时,便向发送端送出 ASCII 第 17 号字符(十六进制是 1

1 ),两个字符的交互使用,便可控制发送端的传送操作了。其操作流程与硬件握手类似。

Page 36: Delphi 串口通信编程

55 、接线和错误预防、接线和错误预防接线方法错误预防

Page 37: Delphi 串口通信编程

接线方法接线方法

RS-232 口特点:– 9 引脚或 25 引脚– 公头(区别于打印机接头)

1 2 3 4 5

6 7 8 9

5 4 3 2 1

9 8 7 6

计算机上为公头 连线上为公头

Page 38: Delphi 串口通信编程

当使用 RS-232 与 Modem 进行连接时,直接连接即可

当使用 RS-232 和其他的设备进行连接时,有时就必须做必要的跳线

Page 39: Delphi 串口通信编程

跳线跳线跳线的实际意义就是一个传送的信号必须到达对方的接收引脚,如此才能形成一个完整的通路。跳线:欲将数据从一个地方传送至另一个地方,其实只

要使用第 2 引脚、第 3 引脚与第 5 引脚就可以形成一个最简单的通信线路。实际制作:将 RS-232 线的一端接头拆掉,将里面的第 2 引脚和第 3 引脚对调即可。

跳线的意义:甲方传送的数据必定到乙方的接收信道;而乙方的传送数据则会到达甲方的接收信道,双方的传送与接收形成一个完整的回路。

Page 40: Delphi 串口通信编程

错误预防错误预防检测数据在传送过程中发生的错误 CheckSum: 将所有要传送字符的 ASCII 码做加法运算,

计算其总和后将此数目与一数字(通常是 255 )做除法运算,再取其余数,将此余数组合成传送字符串的一部分而传送出去;同样,接收方也以相同的方式对所传送过来的字符串进行运算操作,以判断数据的正确性,如果不对,则要求发送方重发。

CRC (C yclic Redundancy Check Code 循环冗余校验码)

 将欲传输的数据块视为一堆连续位所构成的一个整数值,并将此数值除一个特定的除数。

Page 41: Delphi 串口通信编程

错误预防原理:将所传送的数值做相加的操作后与一个固定的除数进行除法运算,所得的余数即为校验码。传送与接收的双方只要针对其固定的检查方法分别进行运算,比较后只要双方均一致,即正确;若不一致,数据重传。

Page 42: Delphi 串口通信编程

66 、错误排除、错误排除波特率失配检验错误字长不匹配停止位错帧错

Page 43: Delphi 串口通信编程

波特率失配波特率失配

如果两个设备的波特率设置不同,当接收设备试图接受数据时,程序将报告校验错和帧错。

Page 44: Delphi 串口通信编程

校验错误校验错误

指数据在传输中被破坏,至少可以说明设备在奇偶校验位类型设置不同或者字长不同。

Page 45: Delphi 串口通信编程

字长不匹配字长不匹配发送的是 8 位字长,接收采用 7 位字长发送的是 7 位字长,接收采用 8 位字长

Page 46: Delphi 串口通信编程

停止位错停止位错接收端要求一个停止位,而发送端发送

了两个停止位接收端要求两个停止位,而发送端发送

了一个停止位

Page 47: Delphi 串口通信编程

帧错帧错

一般指位数不匹配。这个类型的错误,通常是在没有接收到要求的停止位时出现。

Page 48: Delphi 串口通信编程

第2章 串行通信程序及组件建立第2章 串行通信程序及组件建立

1 、串行通信的 WindowsAPI简述2 、通信测试3 、自动与事件

Page 49: Delphi 串口通信编程

11 、串行通信的、串行通信的 WindowsWindows APIAPI简述简述

串行通信相关函数串口通信流程

Delphi 的 Windows.pas 单元文件中已经将 Win32

API 均声明进去,因此在 Delphi里面使用 API 时只要在 uses 区段中加入Windows ,使其引用该单元文件即可

Page 50: Delphi 串口通信编程

串行通信相关函数串行通信相关函数 CreateFile:建立文件,在此用打开通信端口 CloseHandle:关闭由 CreateFile建立的文件,在此用于关闭通信端口

GetCommState:取得计算机串口的设置参数 SetCommState: 设置计算机串口的参数 WriteFile: 将数据写入文件,在此用来将数据由串口送出 ReadFile:由文件中读取数据,在此用来取得送到串口的

数据 ClearCommError:清除串行端口的错误,并取得信息

Page 51: Delphi 串口通信编程

串行通信相关函数串行通信相关函数 PurgeComm :清除串口上的缓冲区 EscapeCommFunction :控制串口的硬件状态 SetCommMask :设置事件的掩码,用以触发事件 WaitCommEvent :等待设置事件的发生 GetCommModemStatus :取得串口上的硬件线路状态

Page 52: Delphi 串口通信编程

HANDLE CreateFile(LPCTSTR lpFileName, // 文件名指针DWORD dwDesiredAccess, // 存取(读 /写)模式DWORD dwShareMode,//共享模式

LPSECURITY_ATTRIBUTES lpSecurityAttribute, //security attribute结构指针DWORD dwCreationDistribution, // 打开文件的方式DWORD dwAttrsAndFlags, // 文件属性HANDLE hTemplateFile//带属性复制的文件句柄

);

Page 53: Delphi 串口通信编程

有关参数说明有关参数说明 lpFileName :欲打开的文件名称。以串口通信来说,就是 COM

1 、 COM2 等 dwDesiredAccess :读写模式设备。由于将会对串口进行读写操

作,因此在此给定 GENERIC_READ 和 GENERIC_WRITE 常数 dwShareMode :是否共享串行端口。一般不共享,设为 0

lpSecurityAttribute :传入一个 Security Attribute结构,指明其返回的 Handle 是否可以被子程序所继承。在此设置为 nil ,表示不可继承

dwCreationDistribution :指定如何打开文件。在打开设备时,此参数设定为 OPEN_EXISTING

dwAttrsAndFlags :文件属性及相关标志。此项设置为 0

hTemplateFile :此项设置为 0

Page 54: Delphi 串口通信编程

BOOL CloseHandle(HANDLE hObject);

hObject :要关闭对象的句柄当函数返回 True 时,表示关闭动作完成。

Page 55: Delphi 串口通信编程

Var FHandle: THandle; ComName:array[0..4] of char; // ComName:string;Begin ComName:=‘COM1’;// PCHAR(ComName) FHandle := CreateFile(ComName, GENERIC_READ or GENERIC_

WRITE, 0, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);if FHandle<>INVALID_HANDLE_VALUE then showmessage(‘ 串口打开成功!’ )Else showmessage(‘ 串口打开失败!’ );CloseHandle(FHandle);End;

Page 56: Delphi 串口通信编程

GetCommStateGetCommState

BOOL GetCommState(

HANDLE hFile, // 通信设备的句柄 LPDCB lpDCB // 设备控制块结构的地址 );

Page 57: Delphi 串口通信编程

_DCB = packed record DCBlength: DWORD; //DCB结构的长度 BaudRate: DWORD; //当前波特率 Flags: Longint; // wReserved: Word; //保留,未使用 XonLim: Word; // 传送 XON阈值 XoffLim: Word; // 传送 XOFF阈值 ByteSize: Byte; // 每字节位数( 4-8 ) Parity: Byte; //0-4 : no,odd,even,mark,space StopBits: Byte; //0,1,2:1,1.5,2 XonChar: CHAR; // 设置 Tx 和 Rx 的 XON 字符 XoffChar: CHAR; // 设置 Tx 和 Rx 的 XOFF 字符 ErrorChar: CHAR; // 有错误时的替换字符 EofChar: CHAR; // 表示输入结束的字符 EvtChar: CHAR; // 接收事件字符 wReserved1: Word; //保留,未使用 end; TDCB = _DCB; DCB = _DCB;PDCB = ^TDCB;

Page 58: Delphi 串口通信编程

GetCommStateGetCommState

BOOL SetCommState(

HANDLE hFile, // 通信设备的句柄 LPDCB lpDCB // 设备控制块结构的地址 );

Page 59: Delphi 串口通信编程

VarFDCB: TDCB;

GetCommState(FHandle, FDCB); FDCB.BaudRate := 9600; FDCB.Parity := EVENPARITY; FDCB.Stopbits := ONESTOPBIT; FDCB.Bytesize := 8; SetCommState(FCOMHandle, FDCB);

Page 60: Delphi 串口通信编程

WriteFileWriteFileBOOL WriteFile( HANDLE hFile, // 要写入文件的句柄 LPCVOID lpBuffer,// 写入文件中的数据的指针 DWORD nNumberOfBytesToWrite,// 写入的字节数 LPDWORD lpNumberOfBytesWritten, // 写入总字节

数的指针 LPOVERLAPPED lpOverlapped // overlapped I/O结构

的指针 );// lpOverlapped 通常用来作后台工作时同步检查之用,在

串行通信中若不同时使用串行端口,则可不使用,设为nil

Page 61: Delphi 串口通信编程

var

i:byte;

strlen:DWord;

xx:byte;

dat : array[0..99]of char;

begin

dat[0] := chr($fe); dat[1] := chr($1B); dat[2] := chr($44);

dat[3] := chr($03); dat[4] := chr($02);

xx:=0;

for i:=1 to 4 do xx := xx xor ord(dat[i]);

dat[5] := chr(xx); // 异或校验 strlen:=6; WriteFile(FHandle,dat,strlen,strlen,nil);

end;

Page 62: Delphi 串口通信编程

ReadFileReadFile

BOOL ReadFile(

HANDLE hFile, // 要读取文件的句柄 LPVOID lpBuffer, // 接收数据的缓冲区地址 DWORD NumberOfBytesToRead, //读取的字节数 LPDWORD lpNumberOfBytesRead,//读取总字节数的

地址 LPOVERLAPPED lpOverlapped//OverLapped I/O结构

的地址);

Page 63: Delphi 串口通信编程

Var dat : array[0..99]of char; flag:dword;stepno:integer;begin stepno:=0; repeat Readfile(FHandle,dat,1,flag,nil); if flag>0 then if dat1[0]=chr($fe) then stepno:=1; until (stepno=1)or(flag<=0); Readfile(FHandle,dat,1,flag,nil); length:=ord(dat1[0]); //取长度 readfile(FHandle,dat1,length,flag,nil);end;

Page 64: Delphi 串口通信编程

PurgeCommPurgeComm

BOOL PurgeComm(

HANDLE hFile, // 通信资源的句柄 DWORD dwFlags // 执行动作 );

Page 65: Delphi 串口通信编程

dwFlags:dwFlags: 指定执行的工作指定执行的工作 PURGE_TXABORT: 终止目前所有的传输工作,立即返回,不管是否完完成传输的操作

PURGE_RXABORT: 终止目前所有的读取工作,立即返回,不管是否完成读取操作

PURGE_TXCLEAR:清除传送缓冲区中的所有数据 PURGE_RXCLEAR:清除接收缓冲区中的所有数据

Page 66: Delphi 串口通信编程

EscapeCommFunctionEscapeCommFunction

BOOL EscapeCommFunction(

HANDLE hFile, // 通信设备的句柄 DWORD dwFunc // 指定执行的功能 );

Page 67: Delphi 串口通信编程

dwFuncdwFunc :指定串口必须完成的工作:指定串口必须完成的工作

CLRDTR: 将 DTR 线路降成低电压 CLRRTS: 将 RTS 线路降成低电压 SETDTR: 将 DTR 线路升成高电压 SETRTS: 将 RTS 线路升成高电压 SETXOFF:当接收到 Xoff 字符时激活传输操作 SETXON:当接收到 Xon 字符时激活传输操作 SETBREAK: 设置通信状态为中断(送出 BREAK 信号) CLRBREAK:清除 BREAK 信号,使传输动作继续

Page 68: Delphi 串口通信编程

GetCommModemStatusGetCommModemStatus

取得串口数字输入线路电压状态可用该函数BOOL GetCommModemStatus(

HANDLE hFile, // 通讯设备的句柄 LPDWORD lpModemStat // 控制寄存器中数值的地址

);

Page 69: Delphi 串口通信编程

lpModemStat :指向检测到的状态的参数地址, 32 位长度

MS_CTS_ON : CTS (clear-to-send) 引脚升至高电压MS_DSR_ON : DSR (data-set-ready) 引脚升至高电压MS_RING_ON : RI 引脚升至高电压MS_RLSD_ON : DCD 引脚升至高电压

Page 70: Delphi 串口通信编程

串口通信流程串口通信流程

打开通信端口

打开成功?

通信参数设置

其他函数操作

显示错误信息

关闭串口

结束

开始

继续操作?否

Page 71: Delphi 串口通信编程

22 、通信测试、通信测试通信步骤回路测试

Page 72: Delphi 串口通信编程

通信步骤通信步骤1. 设置通信端口号码2. 使用 CreateFile函数打开通信端口3. 设置通信协议4. 设置传输速度等参数5. 设置其它参数6. 送出字符串或读入字符串,使用 ReadFile 及 WriteFil

e函数7. 使用完毕后以 CloseHandle函数将通信端口关闭

Page 73: Delphi 串口通信编程

回路测试回路测试硬件设置软件实现

Page 74: Delphi 串口通信编程

硬件设置硬件设置两台计算机,各使用其上的一个串口,

一条 RS-232 两边都是母头的线一台计算机,但拥有两个串行通信口,

一条 RS-232 两边都是母头的线一台计算机,一个串行通信口,一条 RS-

232 线,至少其中一边是母头

Page 75: Delphi 串口通信编程

33 、自动与事件、自动与事件自动化的实现轮询方式:不断地发出询问的信号给设备,要求设备返回计算机所要的信息– 使用定时器( Timer组件),设定时间间隔,当时

间间隔一到,便会执行原先放在定时器中的程序代码

– 使用 While…Do 不断地执行程序代码 线程方式:将串行通信的功能封装在一个线程

中,利用线程的不断执行而达到自动化的目的

Page 76: Delphi 串口通信编程

建立多线程建立多线程

工作原理:操作系统将 CPU处理数据的时间切成很多的时间片( Time Slice ),操作系统再将应用程序的代码加载到 CPU 中执行,一旦这一小块的时间执行完毕后,操作系统会将正在执行的程序放一边,然后再取另外一个应用程序进 CPU 中执行,一样只执行这一小块时间片,如此周而复始,所以见到了整个系统中多任务的情况。

Page 77: Delphi 串口通信编程

线程的实现线程的实现应用程序执行后即产生主线程,而主线程可以衍生出其他线程。一个应用程序可以依需要而造出多个线程对象,每一个线程开始执行后即被排入CPU 的执行周期中,这些线程可能被建立后开始执行,直到应用程序结束;也有可能执行完工作后在应用程序结束前就结束掉,实际的情况看具体需求而定。

Page 78: Delphi 串口通信编程

TthreadTthread 类中常用的方法类中常用的方法 Create :建立线程。使用此方法可建立线程,有 1 个参数,若设成 True ,表示建立后不立即执行;若设成False ,则表示一建立后马上执行。

constructor Create(CreateSuspended: Boolean); Free :释放线程,线程程序代码将从内存中被删除 procedure Free; Resume :执行程序代码。若线程暂停时,使用此指令再次激活 procedure Resume;

Suspend :暂停线程。将执行中的线程暂停 procedure Suspend;

Page 79: Delphi 串口通信编程

var SecondProcess: TMyThread; { TMyThread is a custom desc

endant of TThread }begin SecondProcess := TMyThread.Create(True); { create suspen

ded -secondprocess does not run yet } SecondProcess.Priority := tpLower; { set the priority to lowe

r than normal } SecondProcess.Resume; { now run the thread }end;

Page 80: Delphi 串口通信编程

第第 44 章 串行通信中的字符与字节章 串行通信中的字符与字节

1 、字符与字节2 、字节数据的传送与接收

Page 81: Delphi 串口通信编程

11 、字符与字节、字符与字节字符和字节的差别Delphi 中的字符串种类及处理函数中英文字符串长度计算

Page 82: Delphi 串口通信编程

字符和字节的差别字符和字节的差别

Windows支持的字符集有单字符集、双字节字符集及 UniCode 字符集,在西方国家使用 Windows 系统基本使用单字符集,每一个字符都使用一个字节来表示;而亚洲国家由于字符无法单用一个字节表示,因此使用双字节字符集,其中每个字符使用双字节字符集。

Page 83: Delphi 串口通信编程

UniCodeUniCode

UniCode涵盖了世界上所有国家的字符码,每个字符用一个唯一的内码来表示,其特点是所有的字符以两个字节表示,不仅中文使用两个字节,英文也使用两个字节

Page 84: Delphi 串口通信编程

串口通信过程中,如果传送的是一个英文字节组成,只要一个字节就可以将信息传送出去;如果传送的是双字节的字符(如中文),完整的字符传送就必须是两个字节。

Page 85: Delphi 串口通信编程

DelphiDelphi 中的字符串种类及处理函中的字符串种类及处理函数数

Chr(x):返回 X参数的字符, Chr(97)=‘a’ ord(‘a’)=97Ord(x):返回 x参数所列的序数,一般用来解读字符在 ASCII 码中的序数Pos(substr,str):返回 str 中, substr 出现的位置,若找不到则返回 0StrPos(str1,str2):返回 str2 在 str1 出现的第一位置的指针,无则返回 nilCopy(str,index,count):返回 str参数中,索引 index 开始的 count 数目的字

串Delete(str,index,count):删除 str 字串中,由 index 所指定的开始位置的 co

unt 数目的字串Length(str):返回字串 str 的长度SetLength(str,newlen): 设置 str 的长度Value(str,value,code): 将 str 转成数值 value , code 表示发生错误的位置Str(value,str):Trim(str),TrimRight(str),TrimLeft(str): 去空格StringReplace(str,oldpattern,newpattern):替换Insert(s1,s2,index):s1插入 s2 的第 index 位置

Page 86: Delphi 串口通信编程

中英文字符串长度计算中英文字符串长度计算Type Maximum lengt

hMemory required

Used for

ShortString 255 characters 2 to 256 bytes backward compatibility

AnsiString ~2^31 characters 4 bytes to 2GB 8-bit (ANSI) characters

WideString ~2^30 characters 4 bytes to 2GB Unicode characters;

multiuser servers and multi-language applications

Page 87: Delphi 串口通信编程

Var InstrW:WideString; InstrA:ANSIString; Instr:string;Begin Instr:=edit1.text; InstrW:=edit1.text; InstrA:=edit1.text; edit2.text:=inttostr(length(Instr)); edit3.text:=inttostr(length(InstrW)); edit4.text:=inttostr(length(InstrA));End;

Page 88: Delphi 串口通信编程

现 象现 象纯英文字符串使用三种字符串的计算结果相同,显示出一样的字符串长度

纯中文字符串时, String 和 ANSIString 所呈现的结果一样,但WideString 的字符串长度只有它们的一半

中英文混合时, String 及 ANSIString 所呈现的结果还是一样,中文占两个字符和英文占一个字符;但WideString 类型中英文和中文都只占一个字符,

Page 89: Delphi 串口通信编程

结 论结 论 Length函数在不同的类型下所作的计算是不一

样的 Delphi 的确是以 String 作为默认的长字符串类

型 字符串的长度计算可以用 WideString 类型来进

行,在这种情况下,一个中英文字符均被计算为一个字符

实际所占的字节大小需要使用 String 的类型来计算

Page 90: Delphi 串口通信编程

字符编码字符编码

一般的英文字符,可以使用 Ord取得其在ASCII 表中的代表号码;反过来说,如果想以一个号码而得知其所代表的 ASCII 字符是什么,则可以使用 chr函数来实现。

Page 91: Delphi 串口通信编程

Var instr:string;instrW:Widestring; i,len:integer; temp:string;Begin instr:=edit1.text; instrW:=edit1.text; len:=length(instr); temp:=‘’; for i:=1 to len do temp:=temp+inttostr(ord(instr[i])); memo1.text:=temp; len:=length(instrW); temp:=‘’; for i:=1 to len do temp:=temp+inttostr(ord(instrW[i])); memo2.text:=temp;End;

Page 92: Delphi 串口通信编程

22 、字节数据的传送与接收、字节数据的传送与接收字节类型、声明与传送 / 接收动态数组

Page 93: Delphi 串口通信编程

数组名: Array[startIndex..EndIndex] of 类型 ByteSend:Array[0..9] of Byte;

ByteSend[0]:=123;

ByteSend[1]:=46;

Page 94: Delphi 串口通信编程

动态数组动态数组动态数组:声明时不指定数组的大小,而在需要

使用数组之前再指定该数组的大小Delphi 中对于动态数组的声明方式如下:ByteReceive:array of Byte;

….// 其他代码SetLength(ByteReceive,count)

Page 95: Delphi 串口通信编程

var

ByteSend:array of byte;

ByteReceive:array of byte;

count,i:dword;

FHandle: THandle;

begin

FHandle := CreateFile(pchar('COM1'),GENERIC_READ or GENERIC_WRITE, 0, nil, PEN_EXISTING,FILE_ATTRIBUTE_NORMAL, 0);

SetLength(ByteSend,mSend.Lines.Count);

for i:=0 to mSend.Lines.Count -1 do

ByteSend[i]:=StrtoInt(mSend.Lines[i]);

count:=0;

WriteFile(FHandle,bytesend,mSend.Lines.Count,count,nil);

showmessage(inttostr(count));

closehandle(FHandle);

end;

Page 96: Delphi 串口通信编程

第五章 嵌入式汇编语言开发通信程序第五章 嵌入式汇编语言开发通信程序

1. PC 系统及体系结构2. Delphi 中的嵌入式汇编语言3. 嵌入式汇编的通信编程例子

Page 97: Delphi 串口通信编程

11 、、 PCPC 系统及体系结构系统及体系结构寄存器总线结构和主内存访问I/O寻址

Page 98: Delphi 串口通信编程

寄存器寄存器Intel CPU内在 4 个主要的 16 位寄存器,即所谓的AX 、 BX 、 CX 和 DX 。每个寄存器可认为是两个 8

位寄存器,即总共有 8 个 8 位寄存器: AH 、 AL 、BH 、 BL 、 CH 、 CL 、 DH 和 DL 。通常将一个 16 位数的低字节装入 AL ,高字节装入AH 。

Page 99: Delphi 串口通信编程

段地址和编移量段地址和编移量

段地址寄存器可以是 CS (代码段)、 SS(堆栈段)、 DS (数据段)和 ES (附加段)寄存器。偏移量可以保存在 AX 、 BX 、 CX 和 DX寄存器中的任何一个寄存器里,或者保存在专门为作偏移量的一些寄存器里。

Page 100: Delphi 串口通信编程

总线结构总线结构

总线( BUS )是计算机内一组连接设备的电路集合。 PC 机有 3组总线:

数据总线地址总线控制总线

Page 101: Delphi 串口通信编程

主内存访问主内存访问当处理器需要读内存时,它在地址总线上送出地址并在控制总线的读出线上置一个信号。相关的内存器件识别这个地址并将该地址放在数据总线上返回给处理器。发送数据给内存时,一个信号置于控制总线的写入线上,地址放在地址总线上,并将数据入在数据总线上,然后发到内存。

Page 102: Delphi 串口通信编程

I/OI/O 寻址寻址

向 CPU 送出 IN 或 OUT 指令来访问 I/O 地址

OUT 3F8H,AL // 将 AL寄存器中的内容送到 3F8H 端口IN AL,DX // 从 DX寄存器读出数据,并将结果放入 A

L

寄存器中

Page 103: Delphi 串口通信编程

Delphi 中可以使用嵌入式汇编语言,语法如下:asm

statementList

end

statementList 是汇编程序语句,其分隔符可以是分号、换行符或者是 Object Pascal注释

2 、 Delphi 中可以使用嵌入式汇编语言

Page 104: Delphi 串口通信编程

Var PortData:byte;

begin

asm

MOV AL,$20

MOV DX, $20

MOV DX,al

MOV DX, $20

IN AL,DX MOV PortData,AL; // 将 $20 端口的数据读入 Byte变量 PortDat

a

end;

end;

Page 105: Delphi 串口通信编程

(( 11 )汇编语言的基础知识)汇编语言的基础知识

1) 汇编语言的语法2) 寄存器的使用3) 标签4) 汇编指令5) 操作数

Page 106: Delphi 串口通信编程

11 )汇编语言的语法)汇编语言的语法

Label:Prefix Opcode Operand1,Operand2

Label: 标签(可选)Prefix:汇编程序的前缀操作操作码(可选)

Opcode:汇编程序指令操作码或指令Operand:汇编表达式

Page 107: Delphi 串口通信编程

22 )寄存器的使用)寄存器的使用asm语句必须保持 EDI 、 ESI 、 ESP 、

EBP 和 EBX寄存器的内容,但可以自由修改 EAX 、 ECX 和 EDX寄存器的内容

在 asm主语句的入口, BP 指向当前的堆栈, SP 指向堆栈顶端, SS 包含了堆栈的段地址,而 DS 包含了数据段的段地址。

Page 108: Delphi 串口通信编程

33 )标签)标签

标签没有长度限制,但在内嵌汇编器中只有前 32 个字符有效。局部标签必须有 @ 符号开头例:MOV ECX,Delay

@1:

LOOP @1

Page 109: Delphi 串口通信编程

44 )汇编指令)汇编指令Delphi内嵌汇编器支持 3 种汇编指令: DB (定义字节):该指令产生单字节的数据,

每个操作数可以是常量表达式( 8 位),或者是任意长度的字符串。

DW (定义字):该指令产生一序列字,每个操作数可以是常量表达式( 16 位),或者地址表达式。

DD (定义双字):该指令产生一序列字,每个操作数可以是常量表达式( 32 位),或者地址表达式

Page 110: Delphi 串口通信编程

例: asm DB 0FFH { 一个字节 } DB 0,99 { 两个字节 } DB ‘A’ DB ‘Hello world…’,0DH,0AH DB 12,“Delphi” DW 0FFFFH { 一个字 } DW 0,9999 { 两个字 } DW ‘A’ { 与 DB ’A’ 、 0 相同 } DW ‘BA’ { 与 DB ’A’ 、’B’ 相同 } DD 0FFFFFFFFH { 一个双字 } DD 0,99999999 { 两个双字 } DD ‘A’ { 与 DB ’A’ 、 0 、 0 、 0 相同 } DD ‘DCBA’ { 与 DB ’A’ 、’B’ 、’C’ 、’D’ 相同 } end;

Page 111: Delphi 串口通信编程

变量声明变量声明Var ByteVar:Byte; WordVar:Word;

IntVar:Integer;

asm MOV AL,ByteVar MOV BX,WordVar MOV ECX,IntVarend;

Page 112: Delphi 串口通信编程

操作数操作数内嵌汇编器的操作数可以是常量、寄存器、符

号和运算符保留字Var ch:charasm MOV Ch,1 { 将 1装入 CH寄存器 } MOV &Ch,1 { 将 1赋给 CH变量 }End;

Page 113: Delphi 串口通信编程

(( 22 )表达式)表达式

1) Object Pascal 与汇编表达式的不同2) 表达式元素3) 表达式类别4) 表达式类型

Page 114: Delphi 串口通信编程

11 )) Object PascalObject Pascal 与汇编表达式的不同与汇编表达式的不同

Object Pascal 与汇编表达式的最大区别在于所有汇编的表达式必须分解成单独的可以在编译时计算的常量

Page 115: Delphi 串口通信编程

Const

X=10;

Y=20;

Var

Z:Integer;

asm

MOV Z,X+Y

end;

Page 116: Delphi 串口通信编程

Var

X , Y , Z:Integer;

asm

MOV EAX,X

ADD EAX,Y

MOV Z, EAX

end;

Page 117: Delphi 串口通信编程

22 )表达式元素)表达式元素常量寄存器符号

Page 118: Delphi 串口通信编程

常量常量

内嵌汇编器支持两种类型的常量:数值常量 :32 位,一般用十进制,也支持

二进制(数据后加 B ),八进制( O ),十六进制( H 或前加 $ )

字符串常量 : 字符串必须包括在单引号或双引号之间

Page 119: Delphi 串口通信编程

寄存器寄存器寄存器 保留字32 位通用寄存器 EAX EBX ECX EDX

32 位指针或变址寄存器 ESP EBP ESI EDI

16 位通用寄存器 AX BX CX DX

16 位指针或变址寄存器 SP BP SI DI

低 8 位寄存器 AL BL CL DL

16 位段寄存器 CS DS SS ES

高 8 位寄存器 AH BH CH DH

协处理器寄存器堆栈 ST

Page 120: Delphi 串口通信编程

符号符号

Delphi 的内嵌汇编器支持在汇编代码中存取几乎所有的 Object Pascal 标识符,此外还支持特殊符号 @Result ,它对应的是函数内部的结果变量。

Page 121: Delphi 串口通信编程

Function Sum(X,Y:integer):Integer;Begin Result:=X+Y;End;

Function Sum(X,Y:integer):Integer;stdcall;Begin asm

MOV EAX,XADD EAX,Y

MOV @Result,EAX end;End;

Page 122: Delphi 串口通信编程

下述的符号不能在汇编语句中使用:下述的符号不能在汇编语句中使用:

标准过程和函数(例如 WriteLn 和 Chr ) Mem,MemW,MemL,Port 和 PortW 等特殊数组 字符串变量,浮点数和集合常量 没有在当前块声明的标签 在函数外的 @Result 符号

Page 123: Delphi 串口通信编程

33 )表达式类别)表达式类别在内嵌汇编程序中将表达式分为:寄存器、内存引用和立即数Const start=10;Var count:integer;Asm

MOV EAX,start {MOV EAX,xxxx} MOV EAX,count {MOV EAX,[xxxx]} MOV ECX,[start] {MOV ECX,[xxxx]} MOV EDX,OFFSET count {MOV EDX,xxxx}

End;

Page 124: Delphi 串口通信编程

44 )表达式类型)表达式类型每个内嵌汇编表达式都有一个类型,更确切的是都具有长度,因为汇编器仅仅是简单地将表达式类型视作内存位置的长度。

Var QuitFlag:Boolean; // 一个字节 OutBuf:Word; // 一个字

AsmMOV AL, QuitFlag MOV BX, OutBuf MOV DL, OutBuf { 出错 }

End;

Page 125: Delphi 串口通信编程

类型转换:

MOV DL, BYTE PTR OutBuf

MOV DL, BYTE (OutBuf)

MOV DL, OutBuf.Byte

Page 126: Delphi 串口通信编程

33 、嵌入式汇编的通信编程例、嵌入式汇编的通信编程例子子

1) 在 Delphi 中对端口的直接操作2) 行间汇编接收下位机传来的数据的简单例子

3) 直接操作端口的 Delphi 单元

Page 127: Delphi 串口通信编程

11 )在)在 DelphiDelphi 中对端口的直接操作中对端口的直接操作

预定义数组采用直接嵌入式汇编语言

Page 128: Delphi 串口通信编程

预定义数组预定义数组

Delphi保留了 Turbo Pascal 的两个预定义数组 Port 和 PortW 。这两个一维数组的每个元素代表一个数据端口,它们的端口址址同它们的下标是相对应的。例:Port[$20]:=$20; // 将 $20写入 $20 端口PortData:=Port[$20]; // 将 $20 端口的数据读入 byte变量 P

ortData

Page 129: Delphi 串口通信编程

直接嵌入式汇编语言直接嵌入式汇编语言Var PortData:byte;

begin

asm

MOV AL,$20 // 数据 MOV DX, $20 //port 地址 OUT DX,AL // 将 $20写入 $20 端口 MOV DX, $20

IN AL,DX

MOV PortData,AL; // 将 $20 端口的数据读入 byte变量 PortData

end;

end;

Page 130: Delphi 串口通信编程

33 )直接操作端口的)直接操作端口的 DelphiDelphi 单单元元

输出: Out dx,al

Out dx,ax

输入:In al,dx

In ax,dx

Page 131: Delphi 串口通信编程

// PortReadByte 函数//参数: port address

//返回:给 port 的 byte 值function PortReadByte(Addr:Word):Byte;assembler;register;

asm

mov dx,ax

in al,dx

end;

Page 132: Delphi 串口通信编程

// 高速读端口函数: PortReadWord 函数//参数: port address

//返回:给 port 的 word 值//注释:可能有些卡和计算机不能访问全部的 word

function PortReadWord(Addr:Word):Word;assembler;register;

asm

mov dx,ax

in ax,dx

end;

Page 133: Delphi 串口通信编程

// 低速读串口数据//参数: port address//返回:给 port 的 word 值//注释:工作时,要调整 delayfunction PortReadWordLS(Addr:Word):Word;assembler;register;const Delay=150; //依靠 CPU 的速度和卡的速度asm mov dx,ax in al,dx mov ecx,delay @1: loop @1 // 在两次读之间延时 xchg ah,al

inc dx //port+1 in al,dx xchg ah,alend;

Page 134: Delphi 串口通信编程

//PortWriteByte 函数procedure PortWriteByte(Addr:Word;Value:Byte):Word;assembler;regist

er;

asm

xchg ax,dx

out dx,al

end;

Page 135: Delphi 串口通信编程

// 高速写端口过程//注释:工作时,可能有些卡和计算机不能访问全部的 word

procedure PortWriteWord(Addr:Word;Value:Word):Word;assembler;register;

asm

xchg ax,dx

out dx,ax

end;

Page 136: Delphi 串口通信编程

// 低速写端口过程procedure PortWriteWordLS(Addr:Word;Value:Word):Word;assembler;re

gister;const Delay=150 //依靠 CPU 的速度和卡的速度asm xchg ax,dx out dx,al mov ecx,delay @1: loop @1 xchg ah,al

inc dx

out dx,alend;

Page 137: Delphi 串口通信编程

测试:测试:1. 如果使用 9600bps 、偶校验位检查、 8 个位

的数据、两个位的停止位来传输数据,那么传输一个含有 800 字节的字符串需要多长的时间?

2. 说明串口通信的建立步骤。3. 请解释流量控制,并描述流量控制的实现方法。

4. 串口通信程序调试时,接收端没有任何东西,可能的出错原因有哪些?

Page 138: Delphi 串口通信编程

5 、请写一段通过 COM1 发送 90H 数据的程序。

6 、字符串“ 123木头人!”中, Delphi判断的字符总数是多少?字节数又是多少?如果将此字符串由 RS-232 传送出去,则在线路上流动的字节是多少?

Page 139: Delphi 串口通信编程

7 、请以汇编语言实现一段串口通信程序。 参数设置: COM2 ,波特率 1200 ,奇

校 验,停止位 1 位,字长 8 位 操作:收 10 个字符