2台のPCを使用しバイナリファイルをRS232Cを使用し1台目のPCは送信専用、2台目のPCは受信専用で、送信側のPCから出したデータを受信側PCでデータの内容を判断し集計するプログラムを作ろうとしています。

送信側のPCでは、"AAB9AAC2AACC01D8AAE2・・・”といった内容のバイナリファイルの内容を1バイトずつ読み込み、それをMsCommを用いてバイナリモードで送信させて、EOFになるまで永遠とそれを繰り返します。

問題は受信側で、たとえば上記のデータの中の"AAB9"ならばカウントを1つ上げる、"AACC01D8"ならばカウントを1つ下げ、それを表示するといったような処理をリアルタイムで行いたいのですが、どうしてもデータの取りこぼしが発生します。

また、データの意味合いとしては、必ず"AA"という1バイトのデータから始まり、それに1バイトから5バイトまでのデータが可変長で付いてきて次の"AA"までが1つの意味となります。

通信パラメータは9600、8ビット、ストップビット1、パリティなしで、その他の制御線は一切使用しないという条件です(要するにRxD、GND線のみの最低限の条件)

受信側のバッファは1024バイトで、MSComm1.RThreshold = 1でOnCommを発生させています。また、送信側のファイルの大きさは1kバイトほどです

正直なところ、このようなことが可能なのかどうかもわからない状況なのですが、現状ではデータを数バイト取りこぼしているだけのようなのでできないことはないのではないか?と考えています。

どなたか、参考文献、ホームページ、プログラム、考え方等を何でもかまいませんん!ぜひ、ご教授願います!!また、現在はVBにて開発中ですが、最悪、言語は問いません。よろしくお願いいたします。

このQ&Aに関連する最新のQ&A

A 回答 (3件)

たしか.1秒に1回100msほど.タイマー関連の処理に取られて.結構速度を落とさないと.取りこぼしが発生するようです。



私の関係した対応では.
バッファを巨大にする
転送速度を4800に落とす
受信ソフトの実行速度をあげるため.受信中は他の仕事をさせない
の3店でした。
    • good
    • 1
この回答へのお礼

お礼が遅れて申し訳ございませんでした。
ここ2,3日たてこんでたもので・・・

具体的な数値を頂き、非常に参考になります。

ありがとうございました。

お礼日時:2001/12/21 22:21

過去質問を検索して下さい。

キーワードは「MSComm」で十分でしょう。
参考までに該当しそうな過去質問を参考URLにつけておきます。

参考URL:http://www.okweb.ne.jp/kotaeru.php3?q=135370
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。

教えていただいたホームページを拝見させていただきました。
早速ポーリングによる方法を試してみます。

お礼日時:2001/12/18 14:53

バイナリデータの送受信ですと、Xon/Xoffを使ったフロー制御ができないので、基本的にハードウェアハンドシェークをするしかありませんが、制御線が結線されていないので、これもだめ。

ということなら、データ受信中には何の制御もしてはだめで、受信に専念してバッファに貯める。貯めたあとで、処理をおこなうしかないと思います。
    • good
    • 0
この回答へのお礼

早速の回答ありがとうございます。

素人考えで非常に申し訳ないのですが、

>データ受信中には何の制御もしてはだめで、受信に専念してバッファに貯める。>貯めたあとで、処理をおこなうしかないと・・・

と、ありますが、たとえばハイパーターミナル等は、どのようにしているのでしょうか?
当然、ハイパーターミナルでは複雑な処理等は行っていないとは思うのですが、現状では、単に受けたデータを表示させるだけでも、データが落ちてしまっています。サンプルソースや、ホームページ等あれば、お教えください。

お礼日時:2001/12/18 12:55

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

Qシリアル通信におけるバイトデータの送受信(VB.NET)

Visual Basic .NETで、WriteLine("テキスト")やReadLineを使えば、テキストデータは送受信できますが、バイトデータはどのようにすれば送受信できるのでしょうか?具体的なコードを知っている方がいたら教えて頂きたいです。

Aベストアンサー

こんにちは
http://msdn2.microsoft.com/ja-jp/library/ms143551(VS.80).aspx

そこまでご存知でしたらあともうひと調べでしたね。

Qシリアル通信プログラミングでのバイナリデータ送信

UNIX系環境(IRIX)でのシリアル通信プログラムを作成していて、
バイナリデータの送信方法がわからず困っています。
write関数を使い、テキストデータの送信は出来ます。
write(fd,"テキスト",byte)のように。

ただ、今回はバイナリデータ送信を考えており、
例えば1byteのデータ00000001(01H)を送りたいと思っています。
このデータを送る場合、write関数で実現出来るのでしょうか?
write(fd,0x01,1)←イメージです。
色々ネットで調べても出てきません。

開発がWindows環境ではないので、API関数が使えない状況で困っています(MsComm等が使えない)。また、fwrite関数は使用してはいけないみたいです。教えてください。宜しくお願いします。

Aベストアンサー

> write(fd,0x01,1)←イメージです。

↑では駄目です。

write(fd,"\x01",1);

または

char data[] = { 0x01 };
write(fd, data, 1);

とする必要があります。

Qエクセル VBA でのCOMポート認識

エクセルのVBAを使用してあるアプリを作成しています。そのアプリはシリアルポートを使用してある機器と接続する事で実現できます。
そこで質問ですが、当該PCが認識しているCOMポートをVBAのSELECT BOXに表示したいのですがどうやれば(どのような関数?)を使用して実装COMポートを認識するのでしょうか?
もちろん、USB<--->シリアルケーブルを使用した場合もCOMポートだと認識しなければなりません。
よろしくお願いいたします。

Aベストアンサー

こんにちは。

Windowsのプログラム(VBA含む)から、COMポートを扱う場合は、WindowsAPI を使用すれば可能
だと思います。

COMポートの実装チェックには、WindowsAPI の「CreateFile」関数でCOMポートのオープンを実行
して、その関数の戻り値がエラーかどうかを見れば判断できると思います。
ただし、COMポートが実装されていてもエラーになるケース(既に使用中、使用不可に設定されて
いるなど)がありますので、その場合はエラーコードを取得してその値で「実装/非実装」を判断しな
いといけないと思います。

以下に、VBA から WindowsAPI (COMポート制御関連を含む)を利用するに当たって、参考になり
そうなサイトを上げてみました。宜しければ覗いてみて下さい。

■参考サイト
注)リンク切れの際は御容赦下さい。

1)VBAでWindowsAPIを使用してシリアル通信を行う方法

◎WindowsAPI講座
http://www.serpress.co.jp/winapi/
・このページよりリンクされている下記項目「シリアル通信(1)~(4)」のページでVBAから通信関連の
 APIを使用する方法が書かれています。
 NO.12 シリアル通信(1) ←必要なWindowAPI定義の説明
 NO.13 シリアル通信(2) ←シリアルポートのオープンとクローズを説明
 NO.14 シリアル通信(3) ←シリアルポートの通信プロトコル、送受信バッファ、タイムアウトの設定
 NO.15 シリアル通信(4) ←シリアルポートの送受信方法を説明
・今回の場合は、
   シリアルポートのオープン → 存在有無チェック → シリアルポートのクローズ
 までを行えば良いようなので、シリアル通信(1)~(2) までを参照すれば良いと思います。

2)CreateFile関数でCOM10以上のCOMポートを使用する際の注意点

◎CreateFile関数(Win32API)でCOM10以上を使う場合の注意点
http://www.aofactory.net/log/eid328.html
・ここで、API関数「CreateFile」で指定するCOMポート名(COM1、COM2など)に「COM10」以上を使用
 する場合の問題点および対策が書かれています。
・指定するCOMポートのデバイス名の頭に "\\.\" を付ければ良いようです。
   VBAでの指定例: "COM10" の場合は、 "\\.\COM10" とする。

3)WindowsAPI利用でCOMポートの存在有無をチェックする方法

◎COMポートが存在するかどうかを調べるには? - OKWaveの過去ログより
http://okwave.jp/qa4033242.html
・ここで、API関数「CreateFile」が失敗した際に、同じくAPI関数「GetLastError」でエラーコードを見て
 COMポートの存在有無を調べる旨が書かれています。
注)ただし、VBAでは「GetLastError」を呼んでもエラーコードが得られない可能性があるので、下記4)
 の方法を採った方が良いようです。

4)VBA から Windows API を利用する方法など

◎Office VBA と Windows API - Microsoft MSDN より
http://msdn.microsoft.com/ja-jp/library/cc326057.aspx
・このページの「エラー情報の取得」の説明で、VBAからWindowsAPIを呼出した際のエラーコードの取得
 方法が書かれています。
・VBAからWindowsAPIのDLLを呼び出した際のエラー情報は、「GetLastError関数」では取得できない
 可能性があるので、VBAの場合は「Errオブジェクト」の「LastDLLErrorプロパティ」でエラーコードを取得
 すれば良いようです。
・今回の場合は、COMポートオープン時のエラーコード取得に、この方法が利用できると思います。

こんにちは。

Windowsのプログラム(VBA含む)から、COMポートを扱う場合は、WindowsAPI を使用すれば可能
だと思います。

COMポートの実装チェックには、WindowsAPI の「CreateFile」関数でCOMポートのオープンを実行
して、その関数の戻り値がエラーかどうかを見れば判断できると思います。
ただし、COMポートが実装されていてもエラーになるケース(既に使用中、使用不可に設定されて
いるなど)がありますので、その場合はエラーコードを取得してその値で「実装/非実装」を判断しな
いといけないと...続きを読む

QC# シリアル通信でデータ受信時の欠損について

Visualstudio 2013 を使用して C# で開発を行っています。

SerialPort Classを使用してデータの送受信をするプログラムを作成しているのですが、
非同期でデータを受信する際にどうしてもうまくデータを取得出来ません。

5Byteのデータは正常に取得できるのですが、
その直後にくる40Byteのデータは、真ん中あたりの10数Byteや最後の10数Byteしか取れません。


serialPort.DataReceived に登録したイベント関数の中身です。

--------------------------------------------------------------------------------------
private void _serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
bytesRead = 0;
// Initialize a buffer to hold the received data
byte[] buffer = new byte[this.serialPort.ReadBufferSize];

try
{
bytesRead = this.serialPort.Read(buffer, 0, buffer.Length);
if (true == serialPort.IsOpen)
{
serialPort.DiscardInBuffer();//受信バッファをクリアする
}

}
catch (Exception ex)
{
DataLog.Exception(ex);
}

//派生クラス用の処理
DeviceClassEventArgs _DeviceClassEventArgs = new DeviceClassEventArgs(buffer, bytesRead);
DeviceClassEvent(this, _DeviceClassEventArgs);
}
--------------------------------------------------------------------------------------

ネットの情報を参考に、
ReceivedBytesThreshold の値を期待するデータ量に逐一変えることで
とりあえず正常に取ることが出来たのですが、これでいいのでしょうか?
期待するデータ量がわからなかった場合は使えないのかなとも思います。

データが欠損してしまう理由、
上記の対処法以外の一般的な対処法など有りましたら教えて下さい。

その他参考になるページ等ありましたら教えていただけると大変助かります。

Visualstudio 2013 を使用して C# で開発を行っています。

SerialPort Classを使用してデータの送受信をするプログラムを作成しているのですが、
非同期でデータを受信する際にどうしてもうまくデータを取得出来ません。

5Byteのデータは正常に取得できるのですが、
その直後にくる40Byteのデータは、真ん中あたりの10数Byteや最後の10数Byteしか取れません。


serialPort.DataReceived に登録したイベント関数の中身です。

-------------------------------------------------------------------------------...続きを読む

Aベストアンサー

DataReceivedイベントが発生したときでも、
シリアルポートへの受信はまだ継続している可能性があるので
不用意にバッファクリアしてはいけない。
非同期の受信処理は、何かと難しいのです。

private void _serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
  bytesRead = 0;
  // Initialize a buffer to hold the received data
  byte[] buffer = new byte[this.serialPort.ReadBufferSize];

  try
  {
    //bytesRead = this.serialPort.Read(buffer, 0, buffer.Length);
    //if (true == serialPort.IsOpen)
    //{
    // serialPort.DiscardInBuffer();//受信バッファをクリアする
    //}

    // 受信バッファにデータがなくなるまで繰り返し読込む
    while (true)
    {
      if (0 == serialPort.BytesToRead)
      {
        break;
      }
      buffer[bytesRead] = (byte)serialPort.ReadByte();
      bytesRead++;
      System.Threading.Thread.Sleep(0);

      // シリアルポートの受信バッファには、
      // ・必要なブロックの途中から受信している。
      // ・次のブロックの先頭部分も受信されている。
      // 可能性があるので、ここで必要なブロックだけRead()できたことを確認する。
      if (必要なブロックが正常に読めたか確認する関数())
      {
        break;
      }
    }
  }
  catch (Exception ex)
  {
    DataLog.Exception(ex);
  }

  //派生クラス用の処理
  DeviceClassEventArgs _DeviceClassEventArgs = new DeviceClassEventArgs(buffer, bytesRead);
  DeviceClassEvent(this, _DeviceClassEventArgs);
}

DataReceivedイベントが発生したときでも、
シリアルポートへの受信はまだ継続している可能性があるので
不用意にバッファクリアしてはいけない。
非同期の受信処理は、何かと難しいのです。

private void _serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
  bytesRead = 0;
  // Initialize a buffer to hold the received data
  byte[] buffer = new byte[this.serialPort.ReadBufferSize];

  try
  {
    //bytesRead = this.serialPort.Read(buffer, 0, buffer.Le...続きを読む

Qバイナリデータとテキストデータの違いについて

宜しくお願いします。

バイナリデータを用語辞典で調べると
「テキスト形式(文字データ)以外のデータ形式全般のこと。
実行可能形式のコンピュータプログラムや、画像や音声、
動画などのデータなどがバイナリデータにあたる。」
(http://e-words.jp/w/E38390E382A4E3838AE383AA.html)
とあります。

これでは、バイナリデータとテキストデータの違いが分かりません。

テキストデータはコードの集まりで、
さらに細かくすると0と1の集まり(?)だから・・・
と考えるとバイナリデータとテキストデータの
違いが分かりません。

Q1.私は何が分かっていないのでしょうか?
Q2.バイナリデータとテキストデータの違いを教えてください。

宜しくお願い致します。

Aベストアンサー

バイナリデータは01の集まりです。
テキストデータは文字としての意味が与えられて居ます。ただテキストデータの01としての表現方法はプラットフォーム(OSやアプリケーション)によって異なります。例えば英文字コードでもメインフレームで使われるEBCDICもあり、unixやPCで使われるASCIIもあります。また日本語など英語以外の文字をあらわすのには、さらに多くの種類があります。また改行を表す文字もいろいろです。
例えば telnet で他のコンピュータにログオンして通信する時の文字コードはASCIIで、改行はCRLFと決まっているので、そうでないコンピュータはtelnetプログラムが自分のコンピュータのコード体系と相互変換します。

ftpでテキストデータを転送する時も同じくASCIIとCRLFと決まっています。ただ日本語文字の時にどのコードを使うかは規格では決まっていないので、ftpクライアントで、相手コンピュータの日本語コード種類を指定して、自分と合わなければ転送時に相互変換します。

Cプログラムでもテキストの改行は'\n'と決まっているので、そうでないWindowsの場合はCプログラムとの間でCRLFと'\n'の相互変換が、ライブラリ中で自動的に行われます。

そういった変換を全く行わないのがバイナリデータです。画像ファイルなどはjpegと形式が決まればどのコンピュータでも同じフォーマットなので変換の必要はありません。逆にテキストとみなして変換するとデータが壊れてしまいます。

バイナリデータは01の集まりです。
テキストデータは文字としての意味が与えられて居ます。ただテキストデータの01としての表現方法はプラットフォーム(OSやアプリケーション)によって異なります。例えば英文字コードでもメインフレームで使われるEBCDICもあり、unixやPCで使われるASCIIもあります。また日本語など英語以外の文字をあらわすのには、さらに多くの種類があります。また改行を表す文字もいろいろです。
例えば telnet で他のコンピュータにログオンして通信する時の文字コードはASCIIで、改行はCRL...続きを読む

QVisual Basic でのコードをASCII変換、16進変換したものを元に戻す方法を教えてください

string(9)のエリア"Aa1アあa "の文字を1文字ずつASCII変換して、16進変換し、string(18)のエリアに格納します
すると"416131B182A08281202020"と変換されます
(一文字ずつ Hex(Asc(Buf))を使用しました)

逆に、"416131B182A08281202020"を"Aa1アあa "に戻したいのですが、
どのような関数を使えばよいのかわかりません。
困っています。教えてください。よろしくお願いいたします。

Aベストアンサー

VB既存の関数ではできないと思うので、自分で関数を作るなりしてください。

ヒントです。
ASC関数により変換された2バイト文字(シフトJIS)の1バイト目は81~9FおよびE0~FC(すべて16進)になります。
16進数から10進数に戻すには、頭に"&H"をつけます。(&H82A0 = 「あ」のシフトJISコード)
文字を数字に変換するのはVal関数、数字(文字コード)から文字に変換するのはChr関数です。

QVBA EasyCommでの送信

文字列を送信する場合は ec.Ascii = "mojiretsu" を送ればよいというのはわかるのですが、例えばキーの'Ctrl'を押すのと同等の命令送信をしたいのですが、この場合どのようにコードを書けばよいか教えていただきたいです。できれば、Altの場合なども教えていただけると助かります。

Aベストアンサー

http://okwave.jp/answer/new?qid=7507694
こちらを参考にすれば
ec.Binary = 17 'Ctrlキーのコード“17”を送信
ec.Binary = 18 'Altキーのコード“18”を送信
かな?

QC言語とシリアル通信の送受信データの概念

C言語とシリアル通信の送受信データの概念

今シリアル通信で基盤上のデータを読み書きするツールを作っています。
基盤はまだ手元にないので、先にプログラムと、基盤の動作を模したプログラムを作るつもりです。
基盤の説明にはデータはバイナリで送るようにと書かれていたので、
文字列で1バイトずつ割り当てようと考えました。
しかし、どうやって1234などの数値を1バイトずつ割り振るのか、
バイナリって何だっけと調べているうちにわけが分からなくなってきました。

たとえば1234という10進数の数値を送りたいとき、
現状ではchar型の文字列"1234"を渡しています。
もしかしてこれは間違っていて、本当は

char s[] = { 1, 2, 3, 4 };
16進数の場合はabcdなら
char s[] = { 0xa, 0xb, 0xc, 0xd };
として渡すのが正しいのでしょうか。
これでprintfを使うと文字化けして何だかバイナリっぽいぞと感じましたが。

また、バイナリ以外ならどんな送り方があるのでしょう?

Aベストアンサー

まあ、それは、データ形式の名前を気にするより、単に BCD でと言うことですね。

こんな感じで変換できますね。
(データを変換するだけなので、最初に送る 0xa1 はつけていません)

あと、BCD だと、(単純なバイナリ送信と違って) 'A' ~ 'F' に相当するコードは出てきません。
なので、0xa1 のように、「BCD としては存在しない」データがコマンドなどに割り当たっているわけです。

#include <stdio.h>

unsigned char toBCD2(int v)
{
return ( (v / 10) * 0x10 + v % 10);
}

void longToBCD(long src, char bcd[], int keta)
{
int i;
for(i = 0; i < keta; i++) // 桁は、BCD の配列の個数(安直ですが)
{
int work = src % 100;
bcd[i] = toBCD2(work);
src /= 100;
}
}

int main()
{
int i;

char result[5];
longToBCD(0x00201e90, result, 5);
for (i = 0; i < 5; i++)
{
printf("%02X ", result[i]);
}

return 0;
}

まあ、それは、データ形式の名前を気にするより、単に BCD でと言うことですね。

こんな感じで変換できますね。
(データを変換するだけなので、最初に送る 0xa1 はつけていません)

あと、BCD だと、(単純なバイナリ送信と違って) 'A' ~ 'F' に相当するコードは出てきません。
なので、0xa1 のように、「BCD としては存在しない」データがコマンドなどに割り当たっているわけです。

#include <stdio.h>

unsigned char toBCD2(int v)
{
return ( (v / 10) * 0x10 + v % 10);
}

void longToBCD(long src,...続きを読む

QVB2010で、シリアル通信の方法を教えてください。

VB2010で、シリアル通信の方法を教えてください。

ツールボックスの「Serial Port」を使っています。
送信までは難なくできたのですが、受信が旨くいきません。
参考にしたサイトは、
http://msdn.microsoft.com/ja-jp/library/cc720852.aspx です。

これを実行すると、受信が出来ないだけでなく、フリーズしてしまいます。

どうやったら、受信できるのでしょうか?

Aベストアンサー

受信データが、
STX(&H02)とETX(&H03)には挟まれた形式のテキスト文字になっている。
エラーチェックのBCCは付加されない。
という仕様ならば
ポートをOpenした直後に
SerialPort1.NewLine = Chr(3)
とすれば良い。
受信したデータの先頭1文字がSTXの場合に正常なデータと判断できます。

Q16進数を10進数に変換する方法...

お初にお目にかかります(^^)
簡潔に質問しますm(_ _)m

バージョン:MS-Visual Basic6.0
質問内容:
16進数を10進数に変換する方法がわかりません。
Hex(Text1.Text) や Oct(Text1.Text) のような方法で
16進数・8進数に変換できるんですが…
10進数に変換する方法がわかりません。

P.S できれば、16進数→10進数、16進数や10進数→2進数
…に、変換する方法も、よろしければ教えてくださいませ
m(_ _)m

Aベストアンサー

16進数→10進数は

Dim StrHex As String
Dim intVal As Integer
StrHex = "1A"
intVal = Val("&H" & StrHex)

で出来ます。


申し訳ありませんが2進数への変換はよく分かりません。


このQ&Aを見た人がよく見るQ&A

人気Q&Aランキング