Discussion:
Windows95,98とWindowsXPとRS232C関係でコーディングに違いはあるのでしょうか
(too old to reply)
unknown
2008-05-19 08:56:02 UTC
Permalink
上田と言います。

VC6でWindowsAPIのみでのプログラムを作成しています。
RS232C関連の部分をDLLではなく直接OBJファイルとしてリンクしました。
Windows95、98では問題なくRS232C部分は動作しています。確認済み。

 ところが、XPで同じソフトを起動してみたところ、RS232C関連は全く無視
されています。COM1にリバースケーブルで別のパソコンで受信待機にしても
まったく受信できません。プログラムは相手方が受信できない状態では
通信できないコメントを返すようにしていますが、まったく無視されています。
RS232C以外では全く正常に動作します。
なにかコーディングで間違えていると思います。
 なお、XPはLANを使用中です。単なるCOM違いなのでしょうか。
RS232C関係の機器は接続しておらず、パソコンも買ってから改造もして
いません。困っています。よろしくお願い致します。
UETA, Shin-ichi
2008-05-19 13:08:10 UTC
Permalink
こんにちは、植田です。
Post by unknown
 ところが、XPで同じソフトを起動してみたところ、RS232C関連は全く無視
されています。COM1にリバースケーブルで別のパソコンで受信待機にしても
まったく受信できません。プログラムは相手方が受信できない状態では
通信できないコメントを返すようにしていますが、まったく無視されています。
どちらが何を無視しているのか文脈からは判断しかねますが、最低限チェック
すべきところとしては ――

・そもそもCreateFile、ReadFile、WriteFileなどの呼び出しは成功しているのか?
・ハンドシェークが原因で送信が保留されている可能性はないのか?
・非同期I/O&マルチスレッドで組んでいる場合、イベントのハンドリングに問題は
 ないのか? スレッドが眠ったままになっていないか? デッドロックしていないか?
 etc.

Win9x系とWinNT系では、同じWin32 APIであっても、実装レベルで挙動が異なる
ことが往々にしてあります。使っているAPIの説明をもう一度よく読んで確認してみ
た方がいいかもしれません。

# それは時として英語版のリファレンスを読むことを意味します(苦笑)

できればラインモニタを手元に置いておきたいですね。高価なものではなくても、
とりあえず送受信の様子さえ「見える化」できれば手掛かりになります。

# うちの「キャロちゃん」、最近出番がないなぁ。
# 私もこの手のプログラミングは散々やってきたものの、ここのところご無沙汰
# なので、具体的な違いは何だったか、にわかには思い出せない...。
Post by unknown
RS232C関係の機器は接続しておらず、パソコンも買ってから改造もして
いません。
BIOSレベルでシリアルポートを殺していたりして?
--
植田システム設計事務所
Ueta System Design Studio
http://www.usdesign.jp/
植田真一
mailto:***@usdesign.jp
unknown
2008-05-20 06:15:01 UTC
Permalink
上田です。

植田さん、いつもありがとうございます。
さてご指摘にありました諸点について確かめて見ました。
まず、BIOSについてですが、COM1は3F8/IRQ4,COM2は2F8/IRQ3となっており
この設定は通常で、Windows95,98共COM1、COM2は同じ設定です。
マザーボードの説明書にもCOM1のみが実装として記載されています。
物理的にCOM1にリバースケーブルを接続しています。
さて、CreateFileが成功しているかですが、プログラムを一部改定して
その有無を表示させたところではオープンしているようです。
また送信可の状態です。
オープン条件は9600bps,DTR/DSR制御,8bit選択。

 ラインモニターの件ですが、RS232Cミニテスターが(昔使っていたのが)
ありましたので、それを間に挟みこみました。ただ、残念ながらコネクタのサイズの
関係で確認したいパソコン側からは逆位置になります。まあ、表示文字位置はほぼ
対象になりますから、確認はできます。
これを用いて確認しました。次はその結果です。
送信側(パソコン)から見ると手前から

TD、 RTS、 DSR、 CD(点灯しません)
  RD、 CTS、 DTR、  
となります。
正常な送信ですと、
RTSとDTRがオン(赤)で他は(緑)
でスタンバイOKです。
データを送信するとTDが瞬間で断続的に(赤)が点灯します。

さて、この状態で確認したいパソコンで問題プログラムを起動させると
CTSとDSRが追加してオン(赤)の状態になります。
つまり準備OKの訳です。
この状態で無理やりデータ送信をしても、テスタ上のどのランプも
瞬間で断続的に(赤)が点灯はしません。もちろん受信側では
データは受け取ってはいないのです。
 ただ、何故だか分からないのですが、RS232C接続のプリンタをつないで
初めての場合だけ、プリンタがびくと動くのです。この現象は正常な状態で
プリンタを使えても再現されます。ここがヒントかも知れないと考えては
いるのですが、現在お手上げの状態です。
どうしたものでしょうか。

/***********************
堺市南区原山台
上田 恭平
E_Mail ***@sannet.ne.jp
*************************/
UETA, Shin-ichi
2008-05-20 08:32:29 UTC
Permalink
どうも、植田です。
Post by unknown
 ただ、何故だか分からないのですが、RS232C接続のプリンタをつないで
初めての場合だけ、プリンタがびくと動くのです。この現象は正常な状態で
プリンタを使えても再現されます。ここがヒントかも知れないと考えては
いるのですが、現在お手上げの状態です。
シリアルポート接続のPnPデバイスの検出に絡むものだろうか...?
何かのタイミングで制御線がバタバタしているのを以前見た記憶が
あります。

さて、それはともかく、作成したプログラムをいきなり走らせても障害
の原因を特定するのは難しいですから、まずは低レベルなところから
確実に動いているかどうかをチェックしてみては?

たとえば、次のコードは単にデータを垂れ流すだけのコード(コンソール
アプリケーション)です。

#include "windows.h"

int main(int argc, char* argv[])
{
HANDLE hComm = CreateFile("\\\\.\\COM1",
GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
DCB dcb = {sizeof(DCB)};
BuildCommDCB("9600,n,8,1", &dcb);
SetCommState(hComm, &dcb);

// 送信データが短すぎて確認できないときは、もっと大きな配列を
// 確保するか、適当にループさせて時間を稼いでください。
char text[] = "0123456789";
DWORD written = 0;
WriteFile(hComm, text, strlen(text), &written, NULL);

CloseHandle(hComm);
return 0;
}

非同期I/Oはおろかハンドシェイクさえも使っていません。
当方の環境(ThinkPad+WinXPSP2)で送信を確認しています。
これが動くのであれば、あとは設定の問題か、イベントやスレッドの
管理の問題ではないかと思います。

# 身も蓋もない言い方をすると、今まではかろうじて動いていた
# だけで、実は潜在的なバグが潜んでいた、ということでしょう。

貴殿がどのようなコードの書き方をしているのかによりますが、
送信処理で確実に送信していること、受信処理で確実に受信して
いること、など、低レベルな処理からボトムアップで固めていかな
いと、上の方であれこれやっても埒が明かないですよ。
--
植田システム設計事務所
Ueta System Design Studio
http://www.usdesign.jp/
植田真一
mailto:***@usdesign.jp
unknown
2008-05-25 05:50:00 UTC
Permalink
上田です。
ご指摘の通りに新たにテスト用の別関数(下記記載)をつくり
本来のプログラムの先頭に挿入してRS232Cプリンタで印刷できるか
どうかをテストしました。
結果は、98、XP共正常に印刷することが確認されました。
この後は本来のプログラムでRS232Cに関係する関数全てを
チェックすることになりますが、どこにポイントを置けば
良いか提案いただければありがたいです。
なお、RS232Cの通信だけでなく、当初はキー入力を受付ていたのですが
現在はファンクションキー以外は受け付けないように変わってきています。
テストに用いた関数と変数は次の通り

HANDLE hComm1; // 本来ではstaticを指定 
DCB dcb;
COMMTIMEOUTS timeouts;

int test_com1open(void);
int test_setcom1(HANDLE);
int test_timeoutset(HANDLE);

/* DTR/DSR制御 */
/* 回線オープン */
int rsopen2(void)
{
int sw,sw1,sw2,sw3;

sw = 0; sw1 = 0; sw2 = 0; sw3 = 0;
sw1 = test_com1open();
sw2 = test_setcom1(hComm1);
sw3 = test_timeoutset(hComm1);
PurgeComm( hComm1,PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);
if(sw1 != 0){ sw++; }
if(sw2 != 0){ sw++; }
if(sw3 != 0){ sw++; }
return(sw);
}

int test_com1open(void)
{
int sw;

sw = 1;
hComm1 = CreateFile(
"COM1",
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if(hComm1 == INVALID_HANDLE_VALUE){
sw = 0;
}
return(sw);
}

// sw =0は失敗
int test_com1write(HANDLE hd,char *data)
{
BOOL sw;
DWORD datalen;

sw = WriteFile(hd,data,strlen(data),&datalen,NULL);
if(sw == 0){ return(0); }
else{ return(1); }
}

int test_setcom1(HANDLE hd)
{
BOOL sw1,sw2;
int sw;

sw = 0;
sw1 = GetCommState(hd,&dcb);
dcb.BaudRate = 9600;
dcb.ByteSize = 8;
dcb.Parity = NOPARITY;
dcb.fParity = FALSE;
dcb.StopBits = ONESTOPBIT;
dcb.fOutxCtsFlow = FALSE;
dcb.fOutxDsrFlow = TRUE;
dcb.fDtrControl = DTR_CONTROL_HANDSHAKE; // DTR
sw2 = SetCommState( hd,&dcb);
if(sw1 != 0){ sw++; }
if(sw2 != 0){ sw++; }
return(sw);
}

int test_timeoutset(HANDLE hd)
{
BOOL sw1,sw2;
int sw;

sw = 0;
sw1 = GetCommTimeouts(hd,&timeouts);
timeouts.ReadIntervalTimeout = MAXDWORD;
timeouts.ReadTotalTimeoutMultiplier = 0;
timeouts.ReadTotalTimeoutConstant = 1000;
timeouts.WriteTotalTimeoutMultiplier = 0;
timeouts.WriteTotalTimeoutConstant = 60000;
sw2 = SetCommTimeouts(hd,&timeouts);
if(sw1 != 0){ sw++; }
if(sw2 != 0){ sw++; }
return(sw);
}

// 頭に挿入した関数
int test_com1(void)
{
int i,sw,sw1,sw2,sw3,sw4,sw5;
char data[257];

cls_str(data,257);
sprintf(data,"%s","1234567890 1234567890 ABCDEFG HIJKLMN OPQRSTUWDXYZ
abcdeghijklmnopqrstuvwxyz 1234567890 1234567890");
sw = 0; sw1 = 0; sw2 = 0; sw3 = 0; sw4 = 0; sw5 = 0;
sw1 = test_com1open();
sw2 = test_setcom1(hComm1);
sw3 = test_timeoutset(hComm1);

PurgeComm( hComm1,PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);
for(i = 0; i<10; i++){
sw4 = test_com1write(hComm1,data);
}
sw5 = CloseHandle(hComm1);
if(sw1 != 0){ sw++; }
if(sw2 != 0){ sw++; }
if(sw3 != 0){ sw++; }
if(sw4 != 0){ sw++; }
if(sw5 != 0){ sw++; }
return(sw);
}

/***********************
堺市南区原山台
上田 恭平
E_Mail ***@sannet.ne.jp
************************/
unknown
2008-05-28 03:14:00 UTC
Permalink
上田です。

この1週間程ずっとWindows98,95ではRS232Cでの通信はできるが
XPになると全く無視されるという問題に悪戦苦闘して来ました。
なんとか、XPで動作するようになりましたので報告致します。
方法として
RS232C関係の部分を点検しながら書き直しました。
元はCOM1~COM4までに対応している便利なルーチンでしたが、
ややこしいのでCOM1に限定し、ハンドルをstatic からグローバルに
し、hComm1としました。後、COM1に限定した内容に全て書き換えました。
その内容でビルドして98、95で問題なく動作がすることを確かめました。
同じプログラムをXPで確認させたのですが、やはり動作できません。
この原因は私の点検ミスで、98,95ではある読み込むべきファイルは
存在していたのですが、XPではそのファイルだけ欠落していたためでした。
これは開発途中で追加したファイルで、当然98,95では存在しますが
XPでは追加していなかったからです。
今回はこのふたつがからみあった原因でした。
 ただ、最初にふれたXPと98,95との違いによる動作不良については
static と グローバルとの違いだけでそうなるとは言い切れません。
別の個所が原因かもしれません。元のプログラムは間違いと言えば
NULL とすべきところを0と書かれて居た位です。そのように書き直し
ても動作不良は同じでしたし、他は悪いところはありませんでした。
その意味では原因不明ですが。

/************************
堺市南区原山台
上田 恭平
E_Mail ***@sannet.ne.jp
*************************/
unknown
2008-05-20 06:52:01 UTC
Permalink
上田です。

重要なことが分かりました。
試しに以前DOS版として作っていたプログラムを
WindowsXPのDOS窓から起動したところ、画面は崩れましたが
印刷データは正常に送信されました。
RS232C関連の関数はほとんど同じですので
DOSではOKで、WindowsXPでは送信できないとことが大きなヒントだと
思います。

/**********************
堺市南区原山台
上田 恭平
E_Mail ***@sannet.ne.jp
***********************/
Yuuichi Naruoka
2008-05-20 10:12:25 UTC
Permalink
 成岡@DTI静岡です。

 VCではなくVBでですが、似たような現象が起こったことがあります。

 私の場合は「XPと昔のOSとの仕様の違い」が原因でした。

 過去のOSではプログラムが自分自身のwindowをアクティブにできたのですが、
XPではプログラム自身では“できません”。
タスクバー上の自分自身を示す部分が点滅するだけでした。
後はユーザーが意図的にアクティブにしてやる必要がありました。
さてここで、
「プログラムが非アクティブ状態の時はシリアル受信イベントを受け付けない」
と言うトラブルが発生しました。
またなぜか「プログラムが勝手に非アクティブになってしまう」
現象も経験しました。
これで困ったのは非アクティブ時はmsg_boxすら出てこない、と言うことです。
ちなみに非アクティブになる原因は結局解明できなかったのですが
なんとか運用で回避してもらうことにしました(^^;。
# 結構作業者がマウスで指示する項目が多いプログラムだったので、
# 指示時に自動的にアクティブになる。

 95,98ではOKだがXPでは、と言うことなので
もしかしたら関係があるかもしれません。
--
成岡@DTI(***@jade.dti.ne.jp)
unknown
2008-05-28 03:22:00 UTC
Permalink
上田です。

今回の原因の2番目は読むべきファイルが存在しなかったことで、キー入力を受け取れなかったことがありました。丸岡さんでは非ウインドウとのことでしたが、ウインドウはアクティブでしたが、キー入力不可となりました。
 私の経験では、PCプリンタが準備不足の時印刷命令を送ると非アクティブと
なります。

/***********************
堺市南区原山台
上田 恭平
E_Mail ***@sannet.ne.jp
************************/

Continue reading on narkive:
Loading...