serial.pp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. program Terminal_test;
  2. {******************************************************************************
  3. * Really really budget attempt at Serial IO with Linux and FPC.
  4. * My first FPC program. Re-built and refined on 12/6/99
  5. * Written under X windows with nedit 5.0.2 (Not a bad editor)
  6. * This SHOULD work without including the CRT Unit, However it has problems
  7. * With reading from the keyboard unless the CRT unit is included ?!?
  8. *
  9. * Designed to talk to an RS485 Buss, using RTS as the Tx/Rx Select Pin
  10. * No Copyrights or warrantys.
  11. * Let me know if it's of some use to you.
  12. * Brad Campbell ([email protected])
  13. ******************************************************************************}
  14. uses Linux, Crt;
  15. Const DTR : Cardinal = TIOCM_DTR;
  16. Const RTS : Cardinal = TIOCM_RTS;
  17. Var FD : Longint;
  18. InChr : String[1];
  19. InStr : String[80];
  20. Quit : Boolean;
  21. InLen, Loop : Integer;
  22. tios : Termios;
  23. fds : FDSet;
  24. Procedure DumpFlags;
  25. begin
  26. IOCtl(FD,TIOCMGET,@tios);
  27. Writeln('Input Flags : $',hexstr(tios.c_iflag,8));
  28. Writeln('Output Flags : $',hexstr(tios.c_oflag,8));
  29. Writeln('Local Flags : $',hexstr(tios.c_lflag,8));
  30. Writeln('Control Flags : $',hexstr(tios.c_cflag,8));
  31. End;
  32. Procedure RS485RX;
  33. Begin
  34. IOCtl(FD,TIOCMBIS,@RTS);
  35. End;
  36. Procedure RS485TX;
  37. Begin
  38. IOCtl(FD,TIOCMBIC,@RTS);
  39. End;
  40. Procedure DtrOn;
  41. Begin
  42. IOCtl(FD,TIOCMBIS,@DTR);
  43. End;
  44. Procedure DtrOff;
  45. Begin
  46. IOCtl(FD,TIOCMBIC,@DTR);
  47. End;
  48. Procedure SendToRemote(OutString : String);
  49. Begin
  50. Rs485TX; {Switch Buss to Transmit}
  51. if fdWrite(FD,OutString[1],Length(OutString)) <> Length(OutString) then
  52. Writeln('Write Error');
  53. {Write(OutString);} {Uncomment for Local Echo}
  54. TCDrain(FD); {Block Program until all data sent out port has left UART}
  55. RS485RX; {Switch Buss back to Recieve}
  56. End;
  57. { Not limited to baud selection I have here, it's just all I use }
  58. Procedure SetBaudrate;
  59. Var NewBaud : LongInt;
  60. Begin
  61. Writeln;
  62. Writeln('New Baud Rate (300,1200,2400,4800, 9600,19200,38400) ? ');
  63. Readln(NewBaud);
  64. Case NewBaud of
  65. 300 : NewBaud := B300;
  66. 1200 : NewBaud := B1200;
  67. 2400 : NewBaud := B2400;
  68. 4800 : NewBaud := B4800;
  69. 9600 : NewBaud := B9600;
  70. 19200 : NewBaud := B19200;
  71. 38400 : NewBaud := B38400;
  72. Else
  73. Begin
  74. Writeln('Invalid Baud Rate. Baud not Changed');
  75. Writeln;
  76. NewBaud := 0;
  77. End;
  78. End;
  79. { Sets Baud Rate Here }
  80. If NewBaud <> 0 then
  81. Begin
  82. IOCtl(FD,TCGETS,@tios); {Get IOCTL TermIOS Settings}
  83. CFSetOSpeed(tios,NewBaud); {Set Relevant Bits}
  84. IOCtl(FD,TCSETS,@tios); {Put them back with IOCTL}
  85. Writeln('New Baudrate ',HexStr(NewBaud,2),' Set');
  86. {This line just prints what the constant equates to for
  87. Information Only}
  88. End;
  89. End;
  90. Begin
  91. Quit := False;
  92. Writeln('Brad''s Dumb Terminal Test prog v0.2');
  93. Writeln('Ctrl-C to exit program');
  94. Writeln('Ctrl-D to set Baud Rate');
  95. Writeln('Uses /dev/ttyS0 (Com 1)');
  96. Writeln;
  97. FD:=fdOpen('/dev/ttyS0',Open_RdWr or Open_NonBlock or Open_Excl);
  98. {Open Port Read/Write, Not Blocking and Exclusive}
  99. if FD > 0 then Begin
  100. Writeln('Port Open');
  101. FLock(FD,LOCK_EX);
  102. {Attempt to Lock the port, I'm not sure this is strictly nessecary}
  103. Writeln('Port Locked');
  104. {Set Comms Parms, 9600 Baud, 8 Data Bits, Reciever Enabled,
  105. Modem Control Lines Ignored}
  106. {Read man 3 termios for More options}
  107. IOCtl(FD,TCGETS,@tios);
  108. tios.c_cflag := B9600 Or CS8 Or CREAD Or CLOCAL;
  109. tios.c_lflag := 0;
  110. tios.c_oflag := 0;
  111. tios.c_iflag := 0;
  112. IOCtl(FD,TCSETS,@tios);
  113. DumpFlags; {This is for information only and dumps the contents of
  114. the Termios registers}
  115. Repeat
  116. FD_Zero (FDS); {Clear File Descriptors Array}
  117. FD_Set (0,FDS); {Input from Keyboard}
  118. FD_SET (FD,FDS); {Input from Serial Port}
  119. Select(FD+1,@FDS,nil,nil,nil); {Will Wait for input from above}
  120. If FD_ISSET(0,FDS) then {Has there been a key pressed ?}
  121. If fdRead(0,InChr[1],80) <> 0 then
  122. Begin
  123. if InChr[1] = Chr(3) then Quit := True;
  124. if InChr[1] = Chr(4) then SetBaudRate;
  125. SendToRemote(InChr[1]);
  126. End;
  127. If FD_ISSET(FD,FDS) then {Have we data waiting in UART ? }
  128. Begin
  129. InLen := fdRead(FD,InStr[1],80);
  130. If InLen > 0 then
  131. For Loop := 1 to Inlen do
  132. Write(InStr[Loop]);
  133. End;
  134. Until Quit = True; {Were Outa Here}
  135. FLock(FD,LOCK_UN); {Unlock Port}
  136. fdClose(FD); {Close Port}
  137. End
  138. Else Writeln('Open Port Error'); {We failed to Open/Lock the UART}
  139. End.