AKI-RS232C ラインモニターキット用モニタソフト 2018/02/23
2018/03/04 Delphi ソースコードを追加
2018/03/03 キット+USB 変換モジュールの画像を追加
秋月電子通商のラインモニタキット (¥3,600)(http://akizukidenshi.com/catalog/g/gK-00045/)用のツールです。
■ FT232RL USB/RS232C 変換モジュール(¥1,400.)(http://akizukidenshi.com/catalog/g/gK-01798/)を合体。パソコンへの接続を USB に変更。
赤色の配線は、+5V の電源供給です。

■ 専用のモニタソフト (Winodws98/95用 )が付属されていますが、自分用に作ってみました。
付属のモニタソフトと同様に、モニタ表示はリアルタイムではありません。
「モニタ開始」→「モニタ終了」または1024バイト受信→モニタ結果表示 になります。
Windows 8.1 (64bit) にて、動作を確認しています。

■ソースコード
※シリアル通信には、CPortLib コンポーネントを使っています。
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, CPort, Vcl.StdCtrls, Vcl.Grids, CPortCtl,
IniFiles;
type
TForm1 = class(TForm)
Edit1: TEdit;
Button1: TButton;
ComPort1: TComPort;
Button2: TButton;
Label1: TLabel;
Button3: TButton;
StringGrid1: TStringGrid;
Button4: TButton;
ComboBox1: TComboBox;
Label2: TLabel;
CheckBox1: TCheckBox;
CheckBox2: TCheckBox;
Label3: TLabel;
ComComboBox1: TComComboBox;
Label4: TLabel;
ComboBox2: TComboBox;
Label5: TLabel;
procedure Button1Click(Sender: TObject);
procedure ComPort1RxChar(Sender: TObject; Count: Integer);
procedure Button2Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure Button4Click(Sender: TObject);
procedure StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer;
Rect: TRect; State: TGridDrawState);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure CheckBox1Click(Sender: TObject);
procedure CheckBox2Click(Sender: TObject);
private
{ Private 宣言 }
public
{ Public 宣言 }
end;
TRxData = record
RxTime : Cardinal;
RxChar : AnsiChar;
end;
var
Form1: TForm1;
RxDataAry : array of TRxData;
RxDataCount : integer;
GTicks : Cardinal;
GCmdMode : integer;
GStr : string;
SeigyoCode : array of string = [
'NUL', 'SOH', 'STX', 'ETX', 'EOT', 'ENQ', 'ACK', 'BEL', 'BS', 'HT',
'LF', 'VT', 'FF', 'CR', 'SO', 'SI', 'DLE', 'DC1', 'DC2', 'DC3',
'DC4', 'NAK', 'SYN', 'ETB', 'CAN', 'EM', 'SUB', 'ESC', 'FS', 'GS',
'RS', 'US'];
const
DEL = $7E;
implementation
{$R *.dfm}
function Ratemesure: string;
var
DataCount : integer;
Baud : array [0..99] of integer;
m, n : integer;
BaudRate : integer;
bps : string;
begin
result := '';
if GStr.Length > 100 then begin
DataCount := GStr.Length;
m :=0;
for n := 0 to DataCount div 2 - 1 do begin
Baud[m] := Ord(GStr[n * 2 + 2]);
Baud[m] := Baud[m] * 256;
Baud[m] := Baud[m] + Ord(GStr[n * 2 + 1]) + 15;
Baud[m] := Trunc(Baud[m] * 108.459); // nsec 108.459=1/9.22MHz
Inc(m);
if m = 100 then Break;
end;
BaudRate := 5000000; // nsec
for n := 0 to 50 -1 do begin
if Baud[n] <> 0 then begin
if Baud[n] < BaudRate then BaudRate := Baud[n];
end;
end;
if (3333332 * 0.85 < BaudRate) and (BaudRate < 3333332 * 1.15) then bps := '300bps'
else if (1666666 * 0.85 < BaudRate) and (BaudRate < 1666666 * 1.15) then bps := '600bps'
else if ( 833333 * 0.85 < BaudRate) and (BaudRate < 833333 * 1.15) then bps := '1200bps'
else if ( 416666 * 0.85 < BaudRate) and (BaudRate < 416666 * 1.15) then bps := '2400bps'
else if ( 208332 * 0.85 < BaudRate) and (BaudRate < 208332 * 1.15) then bps := '4800bps'
else if ( 104166 * 0.85 < BaudRate) and (BaudRate < 104166 * 1.15) then bps := '9600bps'
else if ( 69444 * 0.85 < BaudRate) and (BaudRate < 69444 * 1.15) then bps := '14400bps'
else if ( 52083 * 0.85 < BaudRate) and (BaudRate < 52083 * 1.15) then bps := '19200bps'
else if ( 34722 * 0.85 < BaudRate) and (BaudRate < 34722 * 1.15) then bps := '28800ps'
else if ( 26041 * 0.85 < BaudRate) and (BaudRate < 26041 * 1.15) then bps := '38400bps'
else if ( 17361 * 0.85 < BaudRate) and (BaudRate < 17361 * 1.15) then bps := '57600bps'
else if ( 8680 * 0.85 < BaudRate) and (BaudRate < 8680 * 1.15) then bps := '115200bps'
else if ( 4340 * 0.85 < BaudRate) and (BaudRate < 4340 * 1.15) then bps := '230400bps'
else if ( 2170 * 0.85 < BaudRate) and (BaudRate < 2170 * 1.15) then bps := '460800bps'
else if ( 1085 * 0.85 < BaudRate) and (BaudRate < 1085 * 1.15) then bps := '921600bps';
result := bps;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
str : string;
i, j :integer;
begin
with ComPort1 do begin
BaudRate:= br115200;
DataBits := dbEight;
StopBits := sbOneStopBit;
Open;
if Connected then begin
if ComboBox1.ItemIndex >= 0 then begin
Button1.Enabled := False;
Button2.Enabled := True;
Button3.Enabled := False;
WriteStr(ComboBox1.ItemIndex.Tostring); // 9600bps
Sleep(100);
WriteStr('V');
Sleep(100);
ReadStr(str, 1024);
Edit1.Text := str;
if CheckBox1.Checked then
WriteStr('d')
else
WriteStr('D');
Sleep(100);
case ComboBox2.ItemIndex of
0 : WriteStr('G'); // 双方向
1 : WriteStr('A');
2 : WriteStr('B');
end;
with StringGrid1 do begin
for i := 1 to ColCount -1 do begin
for j := 0 to RowCount - 1 do begin
Cells[i, j] := '';
end;
end;
end;
RxDataCount := 0;
GTicks := GetTickCount;
end;
end;
end;
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
if ComPort1.Connected then begin
Button1.Enabled := True;
Button2.Enabled := False;
Button3.Enabled := True;
ComPort1.WriteStr('E');
if GCmdMode = 0 then
Button3Click(self);
end;
end;
procedure TForm1.Button3Click(Sender: TObject);
var
i : integer;
n, m : integer;
c : AnsiChar;
j : integer;
k : integer;
begin
j := 1;
for i := 0 to RxDataCount div 2 -1 do begin
if RxDataAry[i*2].RxTime - GTicks >= 200 then begin
StringGrid1.Cells[j, 1] := IntToStr(RxDataAry[i*2].RxTime - GTicks);
GTicks := RxDataAry[i*2].RxTime;
StringGrid1.ColCount := StringGrid1.ColCount + 1;
Inc(j);
end;
n := Ord(RxDataAry[i * 2].RxChar);
m := Ord(RxDataAry[i * 2 + 1].RxChar);
if (n shr 4 = $A) and (m shr 4 = $B) then begin
c := AnsiChar(n shl 4 + m and $0F);
k := Ord(c);
with StringGrid1 do begin
Cells[j, 2] := IntToHex(Ord(c), 2);
if k < $20 then
Cells[j, 3] := SeigyoCode[Ord(c)]
else if k = DEL then
Cells[j, 3] := 'DEL'
else if k < DEL then
Cells[j, 3] := string(c)
else
Cells[j, 3] := '.';
Cells[j, 0] := IntToStr(i+1);
end;
Inc(j);
end
else if (n shr 4 = $8) and (m shr 4 = $9) then begin
c := AnsiChar(n shl 4 + m and $0F);
k := Ord(c);
with StringGrid1 do begin
Cells[j, 4] := IntToHex(Ord(c), 2);
if k < $20 then
Cells[j, 5] := SeigyoCode[Ord(c)]
else if k = DEL then
Cells[j, 5] := 'DEL'
else if k < DEL then
Cells[j, 5] := string(c)
else
Cells[j, 5] := '.';
Cells[j, 0] := IntToStr(i+1);
end;
Inc(j);
end;
end;
end;
procedure TForm1.Button4Click(Sender: TObject);
var
str : string;
begin
with ComPort1 do begin
if Button4.Caption <> '計測中止' then begin
if Button1.Enabled then begin
BaudRate := br115200;
DataBits := dbEight;
StopBits := sbOneStopBit;
Open;
if Connected then begin
Button1.Enabled := False;
Label1.Caption := 'ボーレート計測中...';
Button4.Caption := '計測中止';
WriteStr('V');
Sleep(100);
ReadStr(str, 1024);
Edit1.Text := str;
RxDataCount := 0;
GStr := '';
WriteStr('M'); //
GCmdMode := 101;
end;
end;
end
else begin
if Connected then begin
WriteStr('E');
GCmdMode := 0;
Label1.Caption := 'ボーレート計測中止';
Button4.Caption := 'ボーレート計測';
Button1.Enabled := True;
end;
end;
end;
end;
procedure TForm1.CheckBox1Click(Sender: TObject);
begin
CheckBox2.Checked := not CheckBox1.Checked;
end;
procedure TForm1.CheckBox2Click(Sender: TObject);
begin
CheckBox1.Checked := not CheckBox2.Checked;
end;
procedure TForm1.ComPort1RxChar(Sender: TObject; Count: Integer);
var
str : string;
i : integer;
Ticks : Cardinal;
begin
ComPort1.ReadStr(str, Count);
if GCmdMode = 101 then begin
GStr := GStr + str;
Label1.Caption := IntToStr(RxDataCount);
RxDataCount := RxDataCount + str.Length;
if RxDataCount > 100 then begin
Label1.Caption := IntToStr(RxDataCount);
ComPort1.WriteStr('E');
GCmdMode := 0;
ShowMessage(Ratemesure);
Label1.Caption := Ratemesure;
Button4.Caption := 'ボーレート計測';
Button1.Enabled := True;
end;
end
else begin
Ticks := GetTickCount;
if RxDataCount < 1024 then begin
Label1.Caption := IntToStr(RxDataCount);
for i := 1 to str.Length do begin
RxDataAry[RxDataCount].RxTime := Ticks;
RxDataAry[RxDataCount].RxChar := AnsiChar(str[i]);
Inc(RxDataCount);
if RxDataCount >= 1024 then begin
Label1.Caption := IntToStr(RxDataCount);
Button3.Enabled := True;
Button2Click(self);
Break;
end;
end;
end;
end;
end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
var
ini : TIniFile;
begin
Comport1.StoreSettings(TStoreType.stIniFile, ChangeFileExt(ParamStr(0), '.ini'));
ini := TIniFile.Create(ChangeFileExt(ParamStr(0), '.ini'));
try
with StringGrid1 do begin
ini.WriteInteger('StringGrid', 'ColWidth', DefaultColWidth);
ini.WriteInteger('StringGrid', 'RowHeight', DefaultRowHeight);
end;
ini.WriteBool('CheckBox', '8Bit', CheckBox1.Checked);
ini.WriteBool('CheckBox', '8+1Bit', CheckBox2.Checked);
ini.WriteInteger('ComboBox', 'MoniBaudRate', ComboBox1.ItemIndex);
ini.WriteInteger('ComboBox', 'MoniHoukou', ComboBox2.ItemIndex);
finally
ini.Free;
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
var
ini : TIniFile;
begin
Setlength(RxDataAry, 1024);
RxDataCount := 0;
Edit1.Text := '';
Label1.Caption := '';
Comport1.LoadSettings(TStoreType.stIniFile, ChangeFileExt(ParamStr(0), '.ini'));
ComComboBox1.Text := ComPort1.Port;
ini := TIniFile.Create(ChangeFileExt(ParamStr(0), '.ini'));
try
with StringGrid1 do begin
DefaultColWidth := ini.ReadInteger('StringGrid', 'ColWidth', DefaultColWidth);
DefaultRowHeight := ini.ReadInteger('StringGrid', 'RowHeight', DefaultRowHeight);
end;
CheckBox1.Checked := ini.ReadBool('CheckBox', '8Bit',True);
CheckBox2.Checked := ini.ReadBool('CheckBox', '8+1Bit',False);
ComboBox1.ItemIndex := ini.ReadInteger('ComboBox', 'MoniBaudRate', 4);
ComboBox2.ItemIndex := ini.ReadInteger('ComboBox', 'MoniHoukou', 0);
finally
ini.Free;
end;
end;
procedure TForm1.StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer;
Rect: TRect; State: TGridDrawState);
var
ARect,BRect : TRect;
s : string;
n : integer;
begin
ARect := Rect;
BRect := Rect;
ARect.Top := Rect.Top + 1;
ARect.Bottom := Rect.Bottom - 1;
ARect.Left := Rect.Left;
ARect.Right := Rect.Right - 1;
BRect.Top := Rect.Top + 5;
BRect.Bottom := Rect.Bottom - 1;
BRect.Left := Rect.Left+1;
BRect.Right := Rect.Right - 1;
with StringGrid1 do begin
if (ARow = 0) or (ACol = 0) then begin
if ((ARow = 2) or (ARow = 3)) and (ACol = 0) then begin
Canvas.Brush.Color := clLime;//$00D6D6D6;
Canvas.Pen.Color := clWhite;//Green;//Black;
Canvas.RoundRect(ARect.Left,ARect.Top,ARect.Right,ARect.Bottom,8,8);
Canvas.Font.Height := 16;
Canvas.Font.Color := clBlack;
end
else if ((ARow = 4) or (ARow = 5)) and (ACol = 0) then begin
Canvas.Brush.Color := clSkyBlue;//Aqua;//$00D6D6D6;
Canvas.Pen.Color := clWhite;//Blue;//Black;
Canvas.RoundRect(ARect.Left,ARect.Top,ARect.Right,AREct.Bottom,8,8);
Canvas.Font.Height := 16;
Canvas.Font.Color := clBlack;
end
else if (ARow = 1) and (ACol = 0) then begin
Canvas.Brush.Color := clBtnFace;
Canvas.Pen.Color := clWhite;//Blue;//Black;
Canvas.RoundRect(ARect.Left,ARect.Top,ARect.Right,AREct.Bottom,8,8);
Canvas.Font.Height := 16;
Canvas.Font.Color := clBlack;
end
else begin
Canvas.Brush.Color := clBtnFace;//$00D6D6D6;
Canvas.FillRect(Rect);
Canvas.Font.Height := 13;
Canvas.Font.Color := clGray;
end;
DrawText(Canvas.Handle, PChar(Cells[ACol,ARow]),
Length(Cells[ACol,ARow]),
BRect, DT_CENTER); // DT_CENTERがセンタリング指定
end
else begin
if (ARow = 1) and (ACol > 0) then begin
s := Cells[ACol, ARow];
if s <> '' then begin
Canvas.Brush.Color := clSilver;
Canvas.FillRect(ARect);
Canvas.Font.Height := 13;
Canvas.Font.Color := clBlack;
Canvas.TextOut(ARect.Left+1,ARect.Top+3, Cells[ACol,ARow]);
end;
end
else if (ARow = 3) and (ACol > 0) then begin
s := Cells[ACol, 2];
if s <> '' then begin
n := StrToInt('$'+ s);
if (n < $20) or (n = DEL) then begin
Canvas.Brush.Color := clRed;
Canvas.FillRect(ARect);
Canvas.Font.Color := clWhite;
end
else if (n > DEL) then begin
Canvas.Brush.Color := clYellow;
Canvas.FillRect(ARect);
end
else begin
Canvas.Brush.Color := $0000FF80;//clGreen;//clMoneyGreen;//Lime;
Canvas.FillRect(ARect);
end;
DrawText(Canvas.Handle, PChar(Cells[ACol,ARow]),
Length(Cells[ACol,ARow]),
BRect, DT_CENTER); // DT_CENTERがセンタリング指定
end;
end
else if (ARow = 5) and (ACol > 0) then begin
s := Cells[ACol, 4];
if s <> '' then begin
n := StrToInt('$'+ s);
if (n < $20) or (n = DEL) then begin
Canvas.Brush.Color := clRed;
Canvas.FillRect(ARect);
Canvas.Font.Color := clWhite;
end
else if (n > DEL) then begin
Canvas.Brush.Color := clYellow;
Canvas.FillRect(ARect);
end
else begin
Canvas.Brush.Color := clSkyBlue;//Aqua;
Canvas.FillRect(ARect);
end;
DrawText(Canvas.Handle, PChar(Cells[ACol,ARow]),
Length(Cells[ACol,ARow]),
BRect, DT_CENTER); // DT_CENTERがセンタリング指定
end;
end;
end;
end;
end;
end.
■開発環境
Delphi 10.1 Professional / Windows 8.1 (64bit)
■ダウンロード
ダウンロード(EXE本体のみ)
※アイコンは、作成していません。Delphi デフォルトのままです。