シリアル通信をするには?

解決


沢庵  2005-02-22 03:12:37  No: 56495

はじめまして沢庵です
過去ログでerror LNK2019 の解決法が載っているのを拝見させてもらいましたが,それでも解決することが出来ませんでした。
ソースは以下のようになっています。

#include <Windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <erslib.h>

int main(int argc, char*argv[])
{
  return 0;
}

int hComm()
{
  HANDLE    hComm;
  BYTE    bSendBuffer[256];
  DWORD    dwSendSize;
  DCB    dcb;
  COMMTIMEOUTS  Timeout;
  BOOL    Ret;
  int            n;

//ポートの初期化
hComm = CreateFile("com",
  GENERIC_READ | GENERIC_WRITE        FILE_SHARE_READ | FILE_SHARE_WRITE,
  NULL,
  OPEN_EXISTING,
  FILE_ATTRIBUTE_NORMAL,
  NULL);

if(hComm == INVALID_HANDLE_VALUE)
{
//エラー処理
//必要なら GetLastError() をチェックする。
  printf("Port could not open.\n");
  exit(0);
}

ソースは長文になるため問題点だけ載せました。
erslib.h は http://www.vector.co.jp/soft/win95/prog/se224900.html で
貰いました。
VC++.NETはまだはじめてから日も浅い為専門的なことは理解が不足しておりますが
宜しくお願いします。


REE  2005-02-22 03:50:42  No: 56496

>ソースは長文になるため問題点だけ載せました。

で、どこに問題点が書いてあるのですか?


沢庵  2005-02-22 04:12:52  No: 56497

失礼しました。肝心の問題点が未記入でした。
初めから言い直すと,VC++.NETでシリアル通信のプログラムを作るのが目的だったのですが,ビルドエラー "error LNK2019" と "fatal error LNK2019" が検出されその解決法が解らず悩んでいました。
ここの過去ログで似てるものがあったのですがいまいち自分の知識だけでは理解できないため助言を貰いたいのです。


みい  2005-02-22 04:40:18  No: 56498

"LNK2019"の後にエラーの変数名が出るはずですが、どの変数でエラーが起きてますか?
> int hComm()
> {
>     HANDLE        hComm;
関数名と変数名を同じにするのは止めた方が良いと思います。


沢庵  2005-02-22 22:53:03  No: 56499

返信遅れてすみません。返事有難う御座います。
>"LNK2019"の後にエラーの変数名が出るはずですが
に対しましては
"未解決の外部シンボル _WinMain@16 が関数_WinMainCRTStartup で参照されました。"
という文で、main関数の定義で起こったものだと思われます。


みい  2005-02-23 01:03:41  No: 56500

コンソールアプリケーション?
もしWindowsアプリケーションなら
http://madia.world.coocan.jp/cgi-bin/Vcbbs/wwwlng.cgi?print+200212/02120032.txt


沢庵  2005-02-23 09:45:33  No: 56501

助言有難うございます。おかげでコンパイル成功しました。
ですが新たにデバッグで上手くいかなかったため期待通りの結果を残すことが出来ませんでした。予定では入出力が可能となると思っていたのですがこれでは無理があるのでしょうか?
ソースは以下の通りです。ヘッダファイルは ここか頂いたものを使用しています。http://www.vector.co.jp/soft/win95/prog/se224900.html 
何か問題がありましたら指摘をお願いします。

#include <Windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <erslib.h>

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
  HANDLE      hComm;
  BYTE      bSendBuffer[256];
  DWORD      dwSendSize;
  DCB        dcb;
  COMMTIMEOUTS  Timeout;
  BOOL      Ret;
  int        n;

//ポートの初期化
hComm = CreateFile("com",
            GENERIC_READ | GENERIC_WRITE,
            FILE_SHARE_READ | FILE_SHARE_WRITE,
            NULL,
            OPEN_EXISTING,
            FILE_ATTRIBUTE_NORMAL,
            NULL);

if(hComm == INVALID_HANDLE_VALUE)
{
//エラー処理
//必要なら GetLastError() をチェックする。
  printf("Port could not open.\n");
  exit(0);
}

//送受信バッファ初期化
Ret = SetupComm(hComm, 4096, 4096);
if(Ret == FALSE)
{
  printf("SetupComm failed.\n");
  CloseHandle(hComm);
  exit(0);
}

Ret = PurgeComm(hComm, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR |
PURGE_RXCLEAR);

  if(Ret == FALSE)
  {
    printf("PurgeComm failed.\n");
    CloseHandle(hComm);
    exit(0);
  }

//タイムアウト設定
Timeout.ReadIntervalTimeout = 0xFFFFFFFF;
Timeout.ReadTotalTimeoutMultiplier = 0;
Timeout.ReadTotalTimeoutConstant = 1000;
Timeout.WriteTotalTimeoutMultiplier = 0;
Timeout.WriteTotalTimeoutConstant = 1000;

Ret = SetCommTimeouts(hComm, &Timeout);
if(Ret == FALSE)
{
  printf("SetCommTimeouts failed.\n");
  CloseHandle(hComm);
  exit(0);
}

//通信設定
Ret = GetCommState(hComm, &dcb);
if(Ret = FALSE)
{
  printf("GetCommState failed.\n");
  CloseHandle(hComm);
  exit(0);
}

  dcb.BaudRate = 19200;
  dcb.Parity = 0;
  dcb.StopBits = ONESTOPBIT;
  dcb.ByteSize = 8;

  Ret = SetCommState(hComm, &dcb);
  if(Ret == FALSE)
  {
    printf("SetCommState failed.\n");
    CloseHandle(hComm);
    exit(0);
  }

//送信データ生成
for(n = 0; n < 256; n++)
  bSendBuffer[n] = n;

//データ送信
Ret = EscapeCommFunction(hComm, SETRTS);
if(Ret == FALSE)
{
  printf("EscapeCommFunction failed.\n");
  CloseHandle(hComm);
  exit(0);
}
Ret = WriteFile(hComm, bSendBuffer, 256, &dwSendSize, NULL);
  if(Ret == FALSE)
  {
    printf("WriteFile filed.\n");
    CloseHandle(hComm);
    exit(0);
  }

//終了処理
CloseHandle(hComm);
}


みい  2005-02-23 21:44:33  No: 56502

> ですが新たにデバッグで上手くいかなかったため期待通りの結果を残すことが出来ませんでした。
最後まで処理が進んだにもかかわらず送信できなかったのでしょうか。
それとも途中のexitで抜けたのでしょうか。
ソースだけではなくきちんと問題点も書いておいて下さいね。

> hComm = CreateFile("com",
ここは実際のソースそのままなのでしょうか。
実際のポート名称が"COM1"とかじゃなくて"com"なのかしら?


沢庵  2005-02-23 22:33:17  No: 56503

みいさんいつもお返事有難う御座います。
>最後まで処理が進んだにもかかわらず送信できなかったのでしょうか。
>それとも途中のexitで抜けたのでしょうか。
これに対しましてのデバッグの返答が以下のようになっていました。

'sriaru.exe': 'c:\Documents and Settings\小畑\My Documents\Visual Studio Projects\sriaru\Debug\sriaru.exe' を読み込みました。シンボルが読み込まれました。
'sriaru.exe': 'C:\WINNT\system32\NTDLL.DLL' を読み込みました。必要な DBG ファイルが見つからないか、開けません。
'sriaru.exe': 'C:\WINNT\system32\KERNEL32.DLL' を読み込みました。必要な DBG ファイルが見つからないか、開けません。
プログラム '[1040] sriaru.exe: ネイティブ' はコード 0 (0x0) で終了しました。

素人的な考えですがヘッダファイルで定義されているDBG ファイルと自分で作成したソースのでなにかくい違いなものがあったからではないかと考えています。
>実際のポート名称が"COM1"とかじゃなくて"com"なのかしら?

これに対しましては、いちお"COM5"で通信しようと思ってます。しかしサンプルや他のサイトをみてみますと"COM1"からの通信をするケースがありますが何か理由があるのでしょうか?
全然検討違いかもしれませんがそこらへんの考えを教えて下さい。


REE  2005-02-24 00:23:03  No: 56504

>'sriaru.exe': 'c:\Documents and Settings\小畑\My Documents\Visual Studio Projects\sriaru\Debug\sriaru.exe' を読み込みました。シンボルが読み込まれました。
>(略)

これらのメッセージはエラーメッセージではありませんので、気にする必要はありません。

但し、ソース中で、異常終了時には、0以外を返すようにすれば、最後の「コード 0 (0x0) で終了しました。」の部分で、異常終了したのか、最後まで行ったのか分かるようになります。例:exit(1)
場所ごとに数字を変えれば、どこで終了したかが、一目瞭然になります。

>これに対しましては、いちお"COM5"で通信しようと思ってます。しかしサンプルや他のサイトをみてみますと"COM1"からの通信をするケースがありますが何か理由があるのでしょうか?

サンプルとして、一番若い番号のポートが使われているだけです。
実際には、通信相手が接続されているポートを指定する必要があります。


沢庵  2005-02-24 01:08:56  No: 56505

お返事有難う御座います。
問題がないということがわかって"ホッ"としました。
ですがまだ問題として物理的な送信の仕方がよくわかりません。
(本当に素人ですみません)
以前にマイコン(H8,PIC)からCOMを使用してハイパーターミナルで通信はした経験がありますが(データを送って出力させ、次のデータを送るまでそれを維持する実験)、今回の場合ハイパーターミナル以外の状態で通信をするのが目的ですがそれがさっぱりわかりません。最初は兎に角サンプルや掲示板を参考にして送信データを画面に出力させたかったのですが先ほどのソースを実行しても何が起こったのか理解できなくてあたふたしております。
お手数ですがどうがいいアドバイスを下さい。


REE  2005-02-24 03:53:32  No: 56506

送信データはシリアル通信先に行くので、そちらで確認してください。

また、新たなアドバイスを求める前に、前のアドバイスを実行してください。


tetrapod  2005-02-24 04:33:41  No: 56507

printf を使いたいなら Win32 Application ではなくて Win32 Console App にしないと。
# っていうかシリアル通信にこだわる前にもっとなすべきことがあるような気が...


沢庵  2005-02-24 04:54:36  No: 56508

>また、新たなアドバイスを求める前に、前のアドバイスを実行してください。
折角教えてもらっているのに対して自分は先走りすぎました。すみませんでした。
>最後の「コード 0 (0x0) で終了しました。」の部分で、異常終了したのか、最後まで行ったのか分かるようになります。例:exit(1)
こちらの例を見本に突き止めてみたところ、最初のエラー処理のところで
"プログラム '[1096] sriaru.exe: ネイティブ' はコード 1 (0x1) で終了しました。"という文が現れました。ということはこの部分で強制的に終了させられて上手く結果が出ないのでしょうか?問題のあったソースは以下の通りです。

if(ers_hcom == INVALID_HANDLE_VALUE)
{
//エラー処理
//必要なら GetLastError() をチェックする。
  printf("Port could not open.\n");
  exit(0);
}


みい  2005-02-24 05:09:04  No: 56509

> > hComm = CreateFile("com",
> ここは実際のソースそのままなのでしょうか。
> 実際のポート名称が"COM1"とかじゃなくて"com"なのかしら?
意図が分かってもらえてなかったみたい。
COM5をオープンしたいのならCOM5が実在かつ"COM5"を指定してますか?
"com"というポート名称が実在しないなら当然エラーになりますよ。


沢庵  2005-02-24 06:49:18  No: 56510

tetrapodさんお返事有難う御座います。
># っていうかシリアル通信にこだわる前にもっとなすべきことがあるような気が...
tetrapodさんが言うように確かにシリアル通信をする前にもっとWindowsの基本を学ぶべきですが、恥ずかしながら今回は訳あって付け焼刃の状態で通信に取り込んでいるのが現状です。
しかしシリアル通信に拘るのは勝手ながらどうしてもやりとげたいのです。
(理由を書かなくてすみません)


沢庵  2005-02-24 07:31:07  No: 56511

みいさんこちらの理解不足ですみませんでした。
COMの設定は相方のPCに合わせるのですね。勝手にソースの方では決められないということでよかったでようか?
自分の先走った行動や知識不足で困らせることが多々あるかもしれませんがこれからもご支援のほどを宜しくお願いします。


とおりすがり  2005-02-24 11:47:51  No: 56512

あなたが基本を学ばないのは勝手ですが、COMポートというものがどういうものか、
Windows上でどういう風に設定されているか、ぐらいは学ばなければどうにもなりません。

>COMの設定は相方のPCに合わせるのですね。

相方って何じゃ??って感じですが、自分のPCのどのCOMポートを使って通信したいのかを
決定するのは、あなた以外にはできません。


沢庵  2005-02-24 19:05:09  No: 56513

とおりすがりさんご意見有難うざいます。
>Windows上でどういう風に設定されているか、ぐらいは学ばなければどうにもなりません。
すみませんでした。COMについてもう少し自分なりに学ぶことにします。


沢庵  2005-03-03 00:38:15  No: 56514

以前シリアル通信の質問を掲示してた沢庵です。
  マイコン(H8/3052)とPC間をデータの受け渡しできるようにシリアル通信したいのですが送受信ともに上手くいきません。
  自分の考えでは
  CreateFile()
       ↓
  SetCommState()
       ↓
  WriteFile
       ↓
  ReadFile
  の各設定及びH8からの情報を格納するための変数とprintf関数を作ればできると思うのですがそれだけでは無理なのでしょうか?誰かマイコンとPC間の通信について教えてくれませんか。


tetrapod  2005-03-03 02:24:09  No: 56515

えー、そもそも RS-232C (っーか EIA-232) が何者か、理解してます?
http://www.fukufukudenshi.com/LineMonitor/RS-232C.html

プログラムを作る以前に、やらねばならんことが山積みな気がしますが、
いちいち全部フォローして回る気はまったく無いし、不可能です。

とりあえず
・ハードウェア的に接続がされて/できているか?
・通信条件/フォーマット等は決めたか?
・ハイパーターミナル等、信頼できるソフトを使って通信できるようになったか?
ココまで出来ることを確認した上で自作ソフトの作成に入るべきです。
ワケも判らずただ闇雲にソフト作ったって何の役にも立たないです。


沢庵  2005-03-03 09:06:22  No: 56516

失礼しました。RS-232Cについての認識はシリアルポートに繋ぐ為のコードぐらいしか考えていませんでした。質問にあった
>ハードウェア的に接続がされて/できているか?
についてはH8からは9ピンのシリアルポートを使用します。PCはUSBから9ピン変換コネクタを使用することでお互いをシリアル通信可能にします。
>通信条件/フォーマット等は決めたか?
については通信条件は
  Comm_DCB.BaudRate = 19200;       /*ボーレート*/
  Comm_DCB.ByteSize = 8;          /*データビット*/
  Comm_DCB.Parity = NOPARITY;     /*パリティ*/
  Comm_DCB.StopBits = ONESTOPBIT; /*ストップビット*/
  Comm_DCB.fBinary=0;
  Comm_DCB.fParity=NULL;
でやろうと思います。
>ハイパーターミナル等、信頼できるソフトを使って通信できるようになったか?
これについてはH8からの出力情報をハイパーターミナルで受けとることが可能でした。目標はPCとH8間のシリアル通信を文字列で行いたいのですがそれは無理なのでしょうか?もし可能ならば教えて頂けないでしょうか


tetrapod  2005-03-03 17:15:17  No: 56517

そういう次元の話をしているのではなくて、まずは EIA232 についてもっと理解してください。

何も考えずに線をつないだだけでは RS232C って決して動きません。
クロスケーブルとストレートケーブルを正しく選択しなければいけないのです。
特に今回の場合は自作のマイコン機器が相手なのですよね。
正しいケーブルを作る/使う/設計するのはあなたの責任です。
そもそもマイコンの RxD/TxD 端子をそのまま取り出しても RS232C の電気条件は満たしません。
きっちり電気的条件を満たす回路が相手側にありますか?

次に通信条件ですが、「通信」というからには一人では出来ないわけで、
相手もその条件を満たしてくれなければなりません。
調歩同期における通信条件ってのは、言ってみれば「自分がしゃべる言語」みたいなものです。
あなたの作ったプログラムは英語をしゃべり、通信相手は中国語をしゃべる
ではお互い意味不明なデータにしかなりません。

そもそも相手(=マイコン) 側は通信できるようになっているのですよね?

1.声が届くようになる(=電気的に正しく接続される) かつ
2.同じ言語をしゃべる(=通信条件が合致する) ようになった上で、
3.意思疎通する(=目的とするデータ通信をする) 必要があります。

1,2が出来ないうちに 3 だけやりたい、なんて無理な話。

もしかして秋月の H8/3052 マイコンキットとか?
# こっちもテスト用に便利に使わせてもらっていますけど...


沢庵  2005-03-03 20:23:07  No: 56518

わかり易く説明していただき有難う御座います。
  シリアル通信の知識不足及び認識の甘さを反省します。宜しければもう少し教え  て頂けないでしょうか?

  >きっちり電気的条件を満たす回路が相手側にありますか?
  これはADM3202ANのようなインターフェースICののことを言っているのでしょう  か?
  >もしかして秋月の H8/3052 マイコンキットとか?
  はい、そうです。あとUSB・シリアル変換ケーブルも秋月で購入したものを使  用しています。EIA232はストレートケーブルを使用しているため受信が終わるま  で送信は出来ない一方通行的なものですが何か問題はあるのでしょうか?


tetrapod  2005-03-03 21:19:31  No: 56519

えー、なんでも聞く前に調べましょう。
キットが手元にあるなら回路図もあるはず。
見て判らないようなら徹底的に調べてください。

あと誤解だけ訂正。
ストレートケーブルでも全二重通信は出来ます。


沢庵  2005-03-03 22:11:41  No: 56520

色々と有難う御座います。


  2005-03-04 00:43:36  No: 56521

通りすがりで無責任に発言するのはどうかと思った
のですが困っている?様なので。
プログラムのコーディングの話じゃないんですが。

いきなりUSB変換器(仮想COM)を使用しないで、普通
にシリアルポートを使用して確認した方がいいんじ
ゃないですか?
間に一杯はさむとわけわからなくないですか?
(動かない時に「このUSB変換器うごいてるのか?」
と気になり出すと、私はもう駄目です・・・)
まーシリアルポートが無いのかもしれませんが。

あと、いきなりPC側から送受信するプログラムを作
ると送信出来てないから応答が来ないのか、送信は
出来ているけど受信が出来ていないのかわからなく
ないですか?
自信が無いのであれば、まず送信or受信の片方を動
くようにしたらどうでしょう?

あと、タイムアウトの設定(SetCommTimeouts)はした
方がいいかもです。


沢庵  2005-03-05 01:32:09  No: 56522

返事が遅れてすみません。秀さん助言を有難う御座います。
tetrapodさんが言ってくれたようにいきなりサイトのサンプルソースや参考サイトを見ながらソースの開発をしていくのは無謀でした。だからシリアル通信について最初から学んでいきたいと思います。よってこの質問はこれで解決とさせてもらいます。今まで質問にお付き合いしていただいた皆様本当に有難う御座いました。


沢庵  2005-03-05 01:33:37  No: 56523

チェック入れました


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加