RS-232Cにおける制御とは?

このQ&Aのポイント
  • RS-232Cにおける制御についての質問です。プラグミング初心者の方がDelphiでRS-232Cの制御を行おうとしており、方法がわからず困っています。
  • RS-232Cでは、通信ポート設定やパケット仕様に応じてコマンド、リプライ、イベント、データの4種類のパケットが使用されます。
  • 具体的なコマンドとして、'Connect'は回線を確立し、'Set Data Output Interval'はデータの出力間隔を設定するものです。
回答を見る
  • ベストアンサー

RS-232Cにおける制御についての質問です。

プラグラミングに対して、全くの初心者のものです。 DelphiでRS-232Cの制御を行おうとしているところですが、どのようにプログミングすればよいのかまったくわかりません。 一応説明書に書かれていることを記します。 (通信ポート設定) Baud Rate 9600,Stop Bit 2,Parity non,Word Length 8,Flow Control XON/XOFF RTS,DTR (通信パケット仕様) ・パケットは全て ヘッダー'#'と、ターミネータ'\r'で区切られる。 ・パケット内の数値データは、全て16進のアスキーコードで表記。 ・機能に応じて以下の4種類のパケットがある。 (1)コマンドパケット (2)リプライパケット (3)イベントパケット (4)データパケット (パケット一覧) (1)Command Packet Format : '#[FID] [P1] [P2] ..[Pn]\r'   項目   型      内容   FID short ファンクションID   Pn long n番目のパラメータ (2)Reply Packet Packet mode 0 Format Normal Reply '#0 [Reply]\r' Data Type: NUM '#0 [Reply] [Data1] [Data] ..[Data n ]\r' Data Type: STR '#0 [Reply] [Strings]\r'   項目   型    内容  Reply short リプライコード            0:正常終了 1:コマンドエラー 2:パラメータ           エラー 3:ビジーエラー 4:通信エラー            10:コマンドに依存したエラー  Data long n番目の数値データ  Strings char* 文字列データ (3)Event Packet Packet mode=1,Format '#1[Event ID][Event Data]\r7' 項目      型     内容 Event ID short イベントの種類 Event Code long イベントの内容 実際のコマンド仕様を記すのでよろしくお願いします。 1.Connect [動作]PCと装置の回線を確立する。 [引数]FID 1 P1 0:イベント出力・・・無効 1: ・・・有効 [戻り値] 0:正常終了 2:パラメーターエラー 3:ビジーエラー 2Set Data Output Interval [動作]データの出力間を設定する。 [引数]FID 7, P1 0:固定,P2 出力間隔 0,10(0xa)~100(0x64)[/10sec],P2=10の時は1秒間隔でデータを出力する,P2=0の時は出力しない。 [戻り値]0:正常終了,2:パラメータエラー 宜しければ、ちょっとした手がかりで構わないので投稿よろしくお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.1

Delphi は未経験なので、VB6およびVB.NETの場合で説明します。 ※以下の説明は、あくまで私の流儀です。 ※通信パケットが不定期に装置からPCに送られる場合を想定してます。 ※データ受信に関して説明します。 ◎RS232C受信用のクラス (1) 先ず、受信バッファにデータが入るまでループして待ちます。 (CPU負荷を減らすためにSleepを入れること) (2) 長時間データがこない場合は、タイムアウトとして仮バッファをクリア。 (3) 受信バッファにデータが在れば、1バイト読込んで仮バッファに追加する。 (フラグを使って“#”~“\r”の間だけ追加するようにすることも可能) (4) 仮バッファに追加したデータが“\r”以外なら(1)に戻る。 (仮バッファに追加する前にチェックして“\r”を含めないようにすることも可能) (5) 仮バッファを本バッファにコピーする。 (6) 仮バッファをクリアする。 (7) パケット受信のイベントを発生させる。 ◎パケット判定用のクラス (1) RS232C受信用クラスがパケット受信イベントを発行するのを待つ。 (2) RS232C受信用クラスの本バッファを取得して、仮パケットに入れる。 (3) 仮パケットの1文字目が“#”以外なら不正データなので仮パケットをクリア。 (4) 仮パケットの2文字目から4文字取り出し、数値に変換する。 (VBの場合なら取り出した文字列の頭に“&H”を付けてVal()関数で数値変換) (5) 数値によりパケットの種類を判定する。 (もし装置へのコマンドによって送られるパケット種類が決まるなら、動作モードを表す変数で対処する) 以上、ここまで。

baitoyou65
質問者

お礼

ありがとうございました。参考にさせていただきます。

関連するQ&A

  • RS232C通信(PC⇔PLC)

    PCとPLCでシリアル通信を行っています。PLCからPCへステータス受信要求し、PCから正常アンサーがあればPLCからPCへ処理開始指令コマンドが出力されるというプロトコルです。実際には、PC側ステータス正常の場合、PLCへの正常アンサーを出力するところまでは行くのですが、その直後にPLCから送信されているはずの処理開始指令コマンドを受信することができません。一連のコマンド送信・受信の間隔が狭すぎるのかと思い、PLC側で処理開始指令コマンド送信前に10msecのウェイトを設けるとPC側で受信することができました。(PLC側の送信が悪いのか、PC側の受信に問題があるのか不明ですが、、、) シリアル通信では、上記のような問題が発生しないように送受信の間隔等なんらかの規約が定められているのでしょうか??ウェイトを設けることなく通信を行いたいのですが、考えられる対処法を教えていただけませんでしょうか。よろしくお願い致します。 なお、通信機器の仕様は以下の通りです。 PLC:三菱シリアルコミニケーションユニット QJ71C24N-R2 PC:WinXpSP2、COMポート、VisualBASIC6.0のCommイベントによりデータ受信(10msecウェイトなしでは、処理開始指令コマンド送信時にCommイベントが発生しませんでした。) ※アスキー文字、PLC・PCともに送信終了コード(CR+LF)でバッファデータ読込み

  • C++配列の型に関するC++規格について教えていただきたいです。

    C++配列の型に関するC++規格について教えていただきたいです。 以前にYahoo知恵袋でも質問しましたが、答えが得られませんでしたので、こちらでも質問させていただきたいと思います。 ※以下、質問になります。(分かり難いかも知れませんが宜しくお願い致します。) 環境は、Visual Studio 2010 (C++) です。 std::fill_n() で次のような警告がでましたので、調べていましたところ、 ...\xutility(2801): warning C4996: 'std::_Fill_n': Function call with parameters that may be unsafe - ... 次のような定義方法を見つけました、 typedef char (&std::tr1::_No)[1]; ↑このような定義方法があることを初めて知りました。 ちなみに、std::fill_n() は次のようになりました。 long data[32]; std::fill_n(data, 32, 0); ←正常 long* p_data = data; std::fill_n(p_data, 32, 0); ←warning long (&a_data)[32] = data; std::fill_n(a_data, 32, 0); ←正常 知りたいのは、配列を関数に渡すときに、 通常は、void func(long* pd); のようにポインタで渡すと思います。 また、void func(long pd[]); や void func(long pd[32]); もポインタの場合と同じになりますが、型保証がありません。 これはC++規格で規定されていることだと思います。 次のようにすると、型保証がされますが、この記法がC++の規格として規定されているかを知りたいです。 1. void func(long (&ad)[32]); // 関数呼び出しは、func(data); 2. void func(long (*pd)[32]); // 関数呼び出しは、func(&data); また、通常のポインタで配列を渡すことを、配列の参照渡し?と言うと思いますが、 この1,2,は何渡し?と言われるのでしょうか? #長い文になって申し訳ありませんが、宜しくお願い致します。

  • VC++6.0でC言語の基本データ型のビット長と範囲をしりたいです

    VC++6.0を使用しています。コマンドラインを使い勉強しているのですが、基本データ型のビット長と使える数の範囲を知りたいです。 たとえば、int型だと32ビットで-32767から32767の範囲の数を扱えるとかを知りたいです。コマンドライン上から調べることはできないのでしょうか? ネットでも書いてあるところがあるならいいのですが、できれば自分の手で調べる方法を見つけたいのです。 ちなみに char, unsigned char, int, unsigned int, short int, unsigned short int, long int unsigned long int, float, double, long doubleなどが知りたいです。 方法を知っている方教えてください。よろしくお願いします。

  • バイナリ出力

    バイナリのテストデータを作成しており、VBAで作成中です。 以下の内容で困っております。 「0~65525の値を2バイトの情報(VCでいうunsigned shortの型)としてバイナリファイルに出力する。」 変数long型で値を取得した場合、4バイトの情報としてバイナリ出力されてしまいます。これを2バイトの情報として出力する方法をご教授願えないでしょうか? よろしくお願いします。

  • integer型、long型、double型

    vb6.0についてお聞きいたします。 こちらの問題は、visual studio 2005のvbでは生じません。 windows xp上で動かしているのですが、どうやら 何もしていないあるパラメータに32000ぐらいの数字よりも大きな 数字をいれるとエラーになってしまいます。 それも、integer型、long型、double型のすべての型で生じます。 そういうものなのでしょうか? HPをいろいろ見ましても、long型で20億ぐらいは 表現できるように書いてあるのですが。

  • Borland C++ Compiler

    学校のC言語の授業で使用するので、Borland C++ Compilerをインストールしました。 今までに作ったプログラムや、教科書に載っていたサンプルプログラムをコンパイルして軽い勉強をしていたのですが、コンパイルの際にエラーが出るようになりました。 コマンドプロンプトでbcc32と打つと、パラメータのリストのようなものが出てくるので、-nなど適当にパラメータをつけて実行したら以下のようなエラーが出るようになりました。 Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland test.c: Turbo Incremental Link 5.00 Copyright (c) 1997, 2000 Borland Error: 外部シンボル '_main' が未解決(C:\BORLAND\BCC55\LIB\C0X32.OBJ が参照) objとtdsファイルは出力されるのですが、exeが出力されません。 どうやったらなおるか、教えてください。

  • C#にてCTI。RS232Cの受信と送信について。

    C#でCTI機能の実現を目指しております。 プログラムは以下サイトからDLして改造しています。 http://tmp.junkbox.info/e14.html しかし、エラーが頻発し原因不明です。 構成、仕様としては、 アロハPC1という機械から電話番号データを受信しPCに受け渡し。 ・データを受け取る(ここは問題なし) データ形式は STX(02H)、着信日時(月日曜時分9桁)、電話番号(20桁)、ETX(03H) として送られてきます。 例) 1214112050457771111 ・正常データの場合はACK(06H)を返信(これをしない場合1秒後に同データが再送される) ・データ整形 ・データ表示 というような形にしたいのです。 上記サイトのプログラムをアロハPC1に合わせて通信できるようにした状態ですと、例のような生データが問題なく表示されます。 これを以下のようにしてみましたが、エラーが出てしまいます。 private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e) { // 受信文字列の取得 string receivedData = ""; string moji = ""; string moji2 = ""; try { receivedData = this.serialPort1.ReadExisting(); receivedData = receivedData.Replace(this.serialPort1.NewLine, "\r\n"); string[] week = { "(日)", "(月)", "(火)", "(水)", "(木)", "(金)", "(土)" }; string stx = receivedData.Substring(0, 1); string etx = receivedData.Substring(30, 1); // ACKを返す。 byte[] ack_data = new byte[1]; ack_data[0] = 06; serialPort1.Write(ack_data,0,1); string data_m = receivedData.Substring(1, 2); string data_d = receivedData.Substring(3, 2); string w = receivedData.Substring(5, 1); int w2 = int.Parse(w); string data_w = week[w2]; string data_h = receivedData.Substring(6, 2); string data_i = receivedData.Substring(8, 2); moji2 = receivedData.Substring(10, 20); // スペースを痴漢 moji2 = moji2.Replace(" ", ""); moji = data_m + "月" + data_d + "日" + data_w + data_h + "時" + data_i + "分 "; if (moji2 == "P") { moji = moji + "着信番号非通知\n"; } else if (moji2 == "O") { moji = moji + "着信番号提供地域外\n"; } else if (moji2 == "C") { moji = moji + "公衆電話\n"; } else { moji = moji + moji2 + "\n"; } } catch (Exception ex) { moji = ex.Message; } // richTextBox側のスレッドに AddRecievedDataメソッドのポインタを渡して、 // 受信文字列を追加させる AddRecievedDataDelegate add = new AddRecievedDataDelegate(AddRecievedData); this.richTextBox1.Invoke(add, moji); } 結果: 1221112260457771111 12月21日(月)12時26分 0457771111 1221112 startIndex に文字列の長さより大きい値を指定することはできません。 パラメータ名: startIndex260457771111 startIndex に文字列の長さより大きい値を指定することはできません。 パラメータ名: startIndex Substringを削除すると「startIndex に文字列の長さより大きい値を指定することはできません。」というようなエラーは出てきません。 receivedData = this.serialPort1.ReadExisting(); を文字列を直接代入した場合はエラーは発生しません。 これをどのようにすれば正常に動くのでしょうか。 また、ACKが正常に送信できてないみたいなのも解れば助かります。 よろしくお願いします。

  • dvd bd-rのファイル名テキスト出力について

    はじめまして dvd-r bd-rのファイル名テキスト出力について教えてください。 OSはWindows 7 H Pです バックアップ用に パソコンのデータをDVD-R BD-Rにバックアップしているんですが 管理のために ディスクの中のファイル名 フォルダ名を テキスト出力する方法を探しています。 いろいろと探したところ コマンドプロンプトで、DIRコマンドを使えばできる事がわかったんですが、 バックアップデータの中には JPG等膨大な量のファイルも含まれているため 出力する際かなり時間がかかってしまいます。 何か拡張子を指定 除外して テキスト出力できる方法はないでしょうか? 簡単に言えば コマンド dir /s での表示・出力の際に jpg やその量の多い拡張子だけ表示させないようにする事はできないか?と言うことです。 回答よろしくお願いします。

  • C言語について質問です

    新版 明解C言語 入門編 この本でC言語を勉強しています。 授業とかではなく自主的にやっています。 入力した文字を出力するプログラムを添字演算子なしで作る問題(演習11-1)を解いてみました。 void put_string(const char *s) { while(*s) putchar(*s++); } int main (void) { char s1[128]; printf("type something: "); scanf("%s", s1); put_string(s1); return(0); } これについて二つの疑問があります。 (1)constと指定されているのにインクリメントされていたら値が変わってエラーが出ないのはなぜか (2)main関数でないほうの関数で*を全て外すと 「パラメータ 's' は const signed char 型として定義されているので signed char * は渡せない(関数 main )」といったエラーが出るのですがなぜか

  • RS-232C通信(その1)

    RS-232Cの通信が上手くいかず困っています。 ユニットはオムロンV600コントローラと三菱シリアルコミュニケーションユニットです。 コントローラ取説を参考にケーブルを製作しましたが自信がありません。 正誤について指摘ください。 <コントローラ取説記載> コントローラ側⇔上位機器 GR 1─シールド   FG SG 9──────SG SD 2──────RD RD 3──────SD RS 4─┐  ┌─RS CS 5─┘  └─CS <製作したケーブル> コントローラ側⇔通信ユニット(A1SJ71QC24N-R2) GR 1─シールド SG 9──────SG 5 SD 2──────RD 2 RD 3──────SD 3 RS 4─┐  ┌─RS 7 CS 5─┘  └─CS 8 ┌─DTR 4 └─DSR 6 接続なしCD 1 宜しくお願いいたします。 背景ですが、現在、設備にV600を設置しておりVBでのプログラムを使い通信しております。 今回、V600を増設する、PCを集約化するなどの理由により、PLCから通信することになったのです。 (過去もPLCから通信しようとしたのですが、出来なくてPCにしてしまいました) そこで困っているのは、A1SJ71で”オーバーラン・フレーミングエラー”が出てしまいます。 データの送り方、受け方が解らないのです。 やりたいのは、 ”アドレス”0010”にアスキーで”070119”を送信したい”です。 コマンドデータは、”WTA10010070119” WT:コマンド A:アスキー 1:ヘッドチャンネル 0100:アドレス 070119:データ 質問1:”CR”はどう付加(表記)すればいいのでしょうか。 プログラムは下記のとおりです。 転送指令 ├─┤├─┬──(MOV K2 D100) A1SJ71のCH2を指定しD100へ │    ├──(MOV K7 D101) データ長7ワード │    ├──($MOV "WTA10010070119" D104) 送信データをD104(CR必要ですがわからない) │    └──(SET M○○) データ転送セット │ 送信指令 ├─┤├────(G.OUTPUT UA D100 D104 M○□)UAは先頭アドレスがXA0から始まる 質問2:間違い教えてください。 以上、宜しくお願いいたします。 ごちゃごちゃして申し訳ありません。 もしかして、”無手順送信用ユーザー登録フレーム”のアドレス”B7H”・”157H”終了コード(CR/LF)の指定をすればいいのですか。 このバッファメモリの変更の仕方がわかりません‥。 バッファメモリの書き替えは、 ”TO”命令で出来そうです。 やってみて、問題がありましたら、(その2)にて質問させていただきます。 また、結果も記載します。

専門家に質問してみよう