龙盟编程博客 | 无障碍搜索 | 云盘搜索神器
快速搜索
主页 > 软件开发 > C/C++开发 >

Delphi控制并行端口位操作[组图]

时间:2009-12-22 15:42来源:未知 作者:admin 点击:
分享到:
并行端口简称并口,它有3个端口:数据端口、状态端口、控制端口,常用的并口为LPT1,它的3个端口的地址分别为:378H、379H和37AH。 一、并口读写 在汇编语言中,可以用 in、out 指令操

  并行端口简称并口,它有3个端口:数据端口、状态端口、控制端口,常用的并口为LPT1,它的3个端口的地址分别为:378H、379H和37AH。
  
  一、并口读写
  
  在汇编语言中,可以用 in、out 指令操作并口,而在Delphi中并没有相对应的函数、方法可对并口进行读写,幸运的是Delphi可以嵌入汇编程序,通过直接嵌入汇编指令 in、out 可方便地对并口进行读写。我们还可以通过调用 Windows API 函数或第三方提供的DLL、VXD来访问并口,但通过使用嵌入汇编的方法对并口进行读写更方便、快捷。
  
  使用下面的 ReadPort 函数和 WritePort 过程可以读写并口,参数 Port 为要操作的端口地址。
  
   function ReadPort(Port:Word):BYTE;
  
  var
  
  B:BYTE;
  
  begin
  
  ASM
  
  MOV DX, Port;
  
  IN AL, DX;
  
  MOV B, AL;
  
  END;
  
  Result:=B;
  
  end;
  
  procedure WritePort(Port:WORD;ConByte:BYTE);
  
  begin
  
  ASM
  
  MOV DX, Port;
  
  MOV AL, ConByte;
  
  OUT DX, AL;
  
  END;
  
  end; 二、位操作
  
  要按位来控制并口,可以先读取并口的数据,再进行位操作,最后再重新写入并口,就可以实现对并口的位的控制。
  
   <!-- frame contents -->
<!-- /frame contents -->   逻辑运算符and对两个要操作的数执行按位的逻辑与运算:即中有1“与”1的结果为1,其它的0“与”1、1“与”0、0“与”0的结果都为0。
  
  逻辑运算符or对两个要操作的数执行按位的逻辑或运算:即只要相“或”的两位有一位是1,结果就为1;否则“或”的结果为0。
  
  
  使用and运算符可以对指定的位置0,例如:十六进制84H的二进制为:10000100,它的第三位为1,若要将第三位置为0,且其它位不变,可以使用:$84 and $FB = $80,80H的二进制值为10000000。
  
  使用or运算符可以对指定的位置1,例如:十六进制84H的第二位为0,若要将第二位置为1,且其它位不变,可以使用:$84 or $02 = $86,86H的二进制值为10000110。
  
  例子:
  
  1、将数据端口378H的D2位的电位设置为低,即置0:
  
   B:=ReadPort($378);
  
  B:=B and $FB;
  
  WritePort($378,B);
  2、将数据端口378H的D2位的电位设置为高,即置1:
  
   B:=ReadPort($378);
  
  B:=B or $04;
  
  WritePort($378,B);
  3、判定数据端口378H的D2位的电位高低:
  
   B:=ReadPort($378);
  
  if ((B and $04)=$04) then
  
  //电位为高时的代码
  
  else
  
  //电位为低时的代码
  
  或:
  
  B:=ReadPort($378);
  
  if ((B or $FB)=$FF) then
  
  //电位为高时的代码
  
  else
  
  //电位为低时的代码
  三、具体实现
  
  下面的例子是控制并口的数据端口378H的各个位的电位高低。数据端口的8个位:D0~D7分别对应并行接口的2~9脚,关于并行接口其它的引脚的说明就查看相关资料,这里就不多说了。
  
  首先运行 Delphi,新建一个工程,按一下F12在Form1的单元文件Unit1中加入读写端口的代码:
  
   function ReadPort(Port:WORD):BYTE;
  
  procedure WritePort(Port:WORD;ConByte:BYTE);
  
  function ReadPort(Port:WORD):BYTE;
  
  var
  
  B:BYTE;
  
  begin
  
  ASM
  
  MOV DX, Port;
  
  IN AL, DX;
  
  MOV B, AL;
  
  END;
  
  Result:=B;
  
  end;
  
  procedure WritePort(Port:WORD;ConByte:BYTE);
  
  begin
  
  ASM
  
  MOV DX, Port;
  
  MOV AL, ConByte;
  
  OUT DX, AL;
  
  END;
  
  
  end;
  
  添加8个 CheckBox 组件,修改它们的 Caption(标题)属性分别为 D0 到 D7 ,将它们按右到左进行排列好。
  
  双击 CheckBox1,在CheckBox1组件的OnClick(单击)事件中加入以下的程序代码:
  
   procedure TForm1.CheckBox1Click(Sender: TObject);
  
  var
  
  b:BYTE;
  
  begin
  
  b:=0;
  
  if CheckBox1.Checked then
  
  b:=b or $01;
  
  if CheckBox2.Checked then
  
  b:=b or $02;
  
  if CheckBox3.Checked then
  
  b:=b or $04;
  
  if CheckBox4.Checked then
  
  b:=b or $08;
  
  if CheckBox5.Checked then
  
  b:=b or $10;
  
  if CheckBox6.Checked then
  
  b:=b or $20;
  
  if CheckBox7.Checked then
  
  b:=b or $40;
  
  if CheckBox8.Checked then
  
  b:=b or $80;
  
  WritePort($378,b); //写数据端口
  
  end;
  
  输入完成后,把CheckBox2到CheckBox8这7个CheckBox组件的OnClick事件设置为CheckBox1的OnClick事件:CheckBox1Click。
  
  此时编译运行程序,已经可以通过点击这8个CheckBox来控制LPT1的数据端口的各个位的电位高低了。
  
  下面再加入监控并口的数据端口状态的功能。
  
  在Form1中加入一个Timer组件:Timer1,修改它的Enabled属性为False,Interval属性为1。
  
  在Timer1的OnTimer事件中加入:
  
   procedure TForm1.Timer1Timer(Sender: TObject);
  
  var
  
  B:BYTE;
  
  begin
  
  B:=ReadPort($378); //读数据端口
  
  CheckBox1.Checked:=((B or $FE)=$FF);
  
  CheckBox2.Checked:=((B or $FD)=$FF);
  
  CheckBox3.Checked:=((B or $FB)=$FF);
  
  CheckBox4.Checked:=((B or $F7)=$FF);
  
  CheckBox5.Checked:=((B or $EF)=$FF);
  
  CheckBox6.Checked:=((B or $DF)=$FF);
  
  CheckBox7.Checked:=((B or $BF)=$FF);
  
  CheckBox8.Checked:=((B or $7F)=$FF);
  
  end;
  
  再加入一个CheckBox组件,修改的Caption属性为“监控并口”,并在它的OnClick事件中加入:
  
   procedure TForm1.CheckBox9Click(Sender: TObject);
  
  begin
  
  Timer1.Enabled:=CheckBox9.Checked;
  
  end;
  
  编译运行程序,点击“监控并口”,就可以监控并口LPT1数据端口378H的状态,并可以实时地修改它的状态。
  
  为了方便查看、验证数据端口378H的状态,我做了一个小小的并口测试电路,该电路使用了一个打印接口、8个LED(发光二极管)和8个1K的电阻,连接线路如图所示:
  
  
  按照电路图制作完成后,安装到电脑的并口上,运行编写好的程序就可以方便地查看数据端口378H的各个位的电位高低了。
  
  最后,我们再来做一个走马灯实验。
  
  先声明一个全局变量 tb:在“Form1:TForm1”的下面加上“tb:BYTE”:
  
   var
  
  Form1: TForm1;
  
  tb:BYTE;
  再在Form1中加入一个Timer和一个CheckBox,修改Timer2的Enabled属性为False,修改Interval属性为300,双击Timer2,在它的OnTimer事件中加入:
  
   procedure TForm1.Timer2Timer(Sender: TObject);
  
  var
  
  B:BYTE;
  
  begin
  
  if tb=0 then
  
  tb:=1
  
  else
  
  tb:=tb * 2;
  
  WritePort($378,tb);
  
  B:=ReadPort($378);
  
  CheckBox1.Checked:=((B or $FE)=$FF);
  
  CheckBox2.Checked:=((B or $FD)=$FF);
  
  CheckBox3.Checked:=((B or $FB)=$FF);
  
  CheckBox4.Checked:=((B or $F7)=$FF);
  
  CheckBox5.Checked:=((B or $EF)=$FF);
  
  CheckBox6.Checked:=((B or $DF)=$FF);
  
  CheckBox7.Checked:=((B or $BF)=$FF);
  
  CheckBox8.Checked:=((B or $7F)=$FF);
  
  end;
  修改CheckBox10的Caption属性为“走马灯演示”,再双击CheckBox10,在它OnClick事件中加入:
  
   procedure TForm1.CheckBox10Click(Sender: TObject);
  
  begin
  
  Timer2.Enabled:=CheckBox10.Checked;
  
  
  end;
  
  编译运行程序。
  
  
  点击“走马灯演示”,有没有看到“走马灯”的效果?通过修改Timer2的Interval可以调节速度,更多、更Cool的效果就看你的创意了。
  
  注重:以上嵌入汇编访问并口的方法只能在Win9X下使用,若要在WinNT/2K下访问并口应该使用 Windows API 函数或专门读写并口的DLL、VXD。
  
  以上程序在Win98+Delphi6.0下测试通过
  
精彩图集

赞助商链接