会員登録で5000円分が当たります

お世話になります、fujitomoです。
まだ実際にプログラムのコードを開発しているわけではないので、漠然としたイメージでの質問となるのですが、質問させて頂く内容は
USB機器で取得した測定データを、USB機器からアプリケーション(C++ MFCにて開発)に送信し、受信時に割り込み受信の処理をし、そのUSB機器から送信されたデータをリストやダイアログ上に表示させたいと思ってるのですが、その実際の実装方法の流れを教えていただければと思い、質問いたしました。
シリアル通信と同様にUSB用の割り込み受信関数といったようなものがあるのでしょうか?

全体の流れのイメージが掴めず、どこから着手していいか分からないため、ご存知の方がいらっしゃいましたら、ご回答宜しくお願い致します。

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

A 回答 (6件)

Windowsと仮定しますが、Windowsではアプリケーションが直接USB機器にアクセスする事は出来ません。



USB(と言うか、正確には「Windowsのカーネルシステムが認識しているUSBポート」ですが)は、Windowsのカーネルシステムが占有しています。

特定のアプリが特定のUSB機器を制御するには「その機器専用のデバイスドライバ」を介して行う事になります。

「Windowsのカーネルシステムが認識しているUSBポート」に「USB機器」が接続されると、Windowsのカーネルシステムは「お前は誰だ?」と、機器に問い合わせを行います(Inquiryコマンドの発行と機器問い合わせ)

そして、問い合わせた結果「お前を制御するデバイスドライバがインストールされてない」と判ると、デバイスドライバのインストールを要求して来ます。

なお、デバイスドライバがインストール済みであれば、認識後の初期化処理をデバイスドライバに行わせ、それ以降の機器アクセスはデバイスドライバに一任します。

で、無事にデバイスドライバがインストールされ、機器の初期化と認識が終わると、デバイスドライバは、アプリケーションで使用可能な「アプリ用のソフトウェア的なインターフェース」を提供します。

つまり「アプリがデバイスドライバを利用可能になる」わけです。

「アプリ用のソフトウェア的なインターフェース」が「その機器専用の物」なのであれば「デバイスドライバを作った人が勝手に決めて良い」ので、アプリからして見れば「デバイスドライバの仕様書の通りに、決められた通りにインターフェースを行う」しかありません。

「アプリ用のソフトウェア的なインターフェース」が「USBメモリのような、標準的な外部記憶装置としてのインターフェース」であれば、アプリケーションは「普通のファイルにアクセスするように、そのドライブ装置にアクセスするしかない」ので、悩む余地はありません。

そういう訳で、アプリを書くのは、そんなに大変ではありません。

問題なのは「その機器専用のデバイスドライバ」です。

BIOSを介して、または、Windowsのカーネルルーチンの呼び出しを駆使して、機器をコントロールしなければなりません。送信タイムアウトとか、受信タイムアウトとか、データのバッファリングとか、コマンドの強制中断とか、ユーザーによる機器の取り外し要求に対するデバドラの終了処理とか、機器に対するリセット指示とか、機器が応答しない処理とか、あらゆる場合についての機器の制御が要求されます。

それと同時に、アプリ側とのインターフェースも行わないとなりません。機器の機能を過不足なくユーザーに提供する為の、考えられる限りのインターフェースをアプリに提供しなければなりません。「この機器の、この機能は、パソコンと接続した場合は、デバイスドライバで未サポートなので使えません」じゃ困りますからね。

また「その機器が繋がっているUSBポートには、USBハブを介して、別のUSB機器が繋がっている」ので、例え割り込みで「受信したぞ~」って言われても、勝手にUSBポートにアクセスしに行ってはいけません。その割り込みは「他の機器が発した、他のデバイスドライバに対する割り込みで、自分宛じゃない」のかも知れませんから。

そんな訳で「もし、デバイスドライバの開発をする部署なのであれば、即死できる」と思います。デバドラの開発は「簡単に死ねるほど複雑」ですから。

とは言え「コード書いた人間に、デバドラのコードを書かせたりはしない筈」なので、ま「1年半は勉強のつもりで下積み」をやらされるでしょう。

大変でしょうが、がんばってくださいね。
    • good
    • 0

>USB用の割り込み受信関数といったようなものがあるのでしょうか?


USB機器にはデータ受信による割り込みはありませんよ。
「見かけ上でも」という問いに対しては、デバイスドライバ次第、としか答えられません。

割り込み転送というモードがありますが、本当の所はポーリングです。
つまりUSB機器は、「CPUからの問い合わせに対し、応答する」しか通信の方法がありません。
見かけ上、「データ受信による割り込み」を実現するには、

「その機器専用のデバイスドライバ」をつくり、デバイスドライバがたとえば16/1000秒毎にUSB機器に対し、「受信データありますか?」と問い合わせをし、「ある」と答えたとき、アプリケーションに対し割り込みをかける

ことで実現しています。
USBポートには複数のUSB機器がハブなどを通して接続されている可能性があるので、特定のUSB機器への問い合わせは、勝手にできません。デバイスドライバは、1ms(USB2では1/4ms)周期で繰り返し転送されている「フレーム」の予約席を確保し、確保したタイミングにすばやく、問い合わせをする必要があります。No3さんの回答のように、このデバイスドライバの作成は、「簡単に死ねるほど複雑」です。
    • good
    • 0

まず、USBにはいくつか転送モードがあります。


割り込み転送:HIDデバイスのような不定期通信。
バルク転送:データ保証あり。USBストレージに使用。
インタラプト転送:帯域保証のため、データエラーでも再送信はしない、USBカメラなど。
(コントロール転送は、この質疑では除外)
このどれもが、「USB機器から割り込み通信があった」ということをアプリケーションレベルでは通常取得することはできません。
たとえば、USBマウスを接続したとしても、OSからは「USBデバイス」として認識されますが、OS介してアプリから見ると「(USB接続された)マウス」でしかなく、扱いは「マウス」にしかならないからです。
つまり「USBデバイス」(それ以外の接続機器も)直接I/Fが何かということを知る術がないのです(COMポートは「COMポート」というH/WとしてOSがアプリに通知しているので別)。
そのため、割り込みタイミングを直接取得するためには一般的には専用のデバイスドライバ(とDLL[API])を作成し使用(提供)します。

尚、
>シリアル通信と同様にUSB用の割り込み受信関数といったようなものがあるのでしょうか?
「USBデバイス」というくくりからでは「ありません」というのが回答です。
USB-COM変換の場合はエミュレーションを行っているドライバー次第です。(アプリからは「COM」として見えているから)
その他のデバイスもやはり「ドライバー次第」という回答になります。
    • good
    • 0

訂正



誤:とは言え「コード書いた人間に
正:とは言え「コード書いた事のない人間に

申し訳ありませんでした。
    • good
    • 0

あ、こっちでした。


http://www.picfun.com/usbframe.html
すみません
    • good
    • 0

USBのプロトコルについては、


http://www.picfun.com/usb20frame.html
辺りをご覧になられてはいかがでしょうか?
    • good
    • 0

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

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

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

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

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

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...続きを読む

QVC++でUSB通信がしたいのですが

VCで作ったアプリケーションでデータ通信をしています。
今まではRS232Cを使っていて、これをUSB通信にしたいと思っているのですが、
なかなか参考になる資料が見つからなくて困っています。
なるべく簡単に出来る方法があったら教えてください。
あんまり難しいようなら諦めます。

Aベストアンサー

実際に使ったことはないのですが、フリー(らしい)ライブラリがありました。

後、自分で使った経験はないのですが、知り合いが仕事で使ったライブラリ
(こっちは有料)も紹介しておきます。

参考URL:http://www.otto.to/~kasiwano/toppage12.htm, http://www.bsquare.co.jp/products/winrtusb/winrtusb.htm

QHIDデバイスクラスの実装

USBのインタラプト方式を用いてマイコンからPCへのデータ転送を行いたいと考えています(因みにマイコンにはH8-3052F、開発環境にはルネサスのHEWを使用しています)。

マウスの(ようなもの)を作りたいので、HIDクラスを利用して実装できないかと考えています。が、手前で調べてみたところあまり参考になるサイトがなく、どうすれば良いやらわかりません・・

参考になる文献やサイトをご存知の方、またHIDクラスを扱ったことがあるという方、何か教えていただけないでしょうか。

Aベストアンサー

No.1です。

>僕が作りたいのはUSBマウス的なものです。HIDだし、転送方式もインタラプトなので、上のURLの質問者様と同じ様にHIDクラスを用いれば実装が楽になるのかなと考えました。
>…質問の解釈違いでしたらすいません。
実際にPCドライバ、及びUSBデバイスを組んだ開発者としての発言になりますが、
極端なことを書きますが、USBデバイス側から見ればデバイスクラスななんてはっきり言えばどうでもいいんですよ。
「PCでこんなことをしたい」→「だったら○○クラスでインターフェースクラス(データ転送)は△△だ」
というのが設計の基本ですから。
今回は「USBマウス的なもの」とのことですから、HIDクラスで問題ないと思います。

>・HIDクラスを使用する際、あらかじめ用意(インストール?)しておく必要がある物は?
OSが標準でHIDドライバーを用意しているのであれば特になし。

>・HIDクラスドライバを用いることで新たにドライバを開発する必要はなくなる。
デバイスはHIDとして認識されているので開発の必要はなし。

>HIDデバイスとして正しく実装されているものであれば、初めての接続時でも自動的にOS(?)が適切なクラスドライバを適用してくれるので、こちらでドライバを用意する必要がない。(クラスドライバはあらかじめsystem32フォルダなどに入っている???)
前述のとおり。OSが標準でHIDをサポートしているのであれば必要なし。

>・PICFUNや秋月のキット(AKI-H8-USB)のサンプルなどでバルク転送による通信を行うサンプルが公開されていますが、これをHIDデバイス用として流用しようとするのは可能か。また、可能ならどのあたりの処理部を修正・追加する必要があるのか。
流用は可能。
提示のキットは使用したことがないけど、同系列であればコンフィグレーションの変更と、送受信ルーチンの若干の変更可能。
重要なのはバルク(データ保障)ではなくインタラプト(割り込み)であること。この部分の処理は必要。

No.1です。

>僕が作りたいのはUSBマウス的なものです。HIDだし、転送方式もインタラプトなので、上のURLの質問者様と同じ様にHIDクラスを用いれば実装が楽になるのかなと考えました。
>…質問の解釈違いでしたらすいません。
実際にPCドライバ、及びUSBデバイスを組んだ開発者としての発言になりますが、
極端なことを書きますが、USBデバイス側から見ればデバイスクラスななんてはっきり言えばどうでもいいんですよ。
「PCでこんなことをしたい」→「だったら○○クラスでインターフェースクラス(データ転送...続きを読む

QDEVICECHANGE() の受け取り

常駐し、USBメモリなど追加された場合を検出したいです。
どうしたらいいでしょうか?
次のソースでwin32空きプロジェクトを作成します。

#include<windows.h>

int WINAPI WinMain(
HINSTANCE hInstance ,
HINSTANCE hPrevInstance ,
LPSTR lpCmdLine ,
int nCmdShow ) {

return 0;
}


ON_WM_DEVICECHANGE()
というメッセージを受け取るそうですがどうしたらいいでしょうか?
例えば、USBドライブを検出した場合、メッセージを表示するようにしたいです。

Aベストアンサー

#include <windows.h>
static LRESULT WINAPI WndProc(HWND,UINT,WPARAM,LPARAM);
static void reg();
int WINAPI WinMain(HINSTANCE ci,HINSTANCE pi,LPSTR cp,int sw)
{
  MSG m;
  reg();
  while(GetMessage(&m,NULL,0,0)) {
    TranslateMessage(&m);
    DispatchMessage(&m);
  }
  return 0;
}
static void reg() {
  WNDCLASSEX w;
  char c[] = {"a"};
  memset(&w,0,sizeof(w));
  w.cbSize = sizeof(WNDCLASSEX);
  w.lpfnWndProc = (WNDPROC)WndProc;
  w.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
  w.lpszClassName = c;
  RegisterClassEx(&w);
HWND h = CreateWindow(c,"監視",WS_OVERLAPPEDWINDOW,
                 0,0,0,0,NULL,NULL,NULL,NULL);
ShowWindow(h,SW_MINIMIZE);
}
static LRESULT WINAPI WndProc(HWND h,UINT m,WPARAM w,LPARAM l)
{
  switch(m)
  {
    case WM_DESTROY:
      PostQuitMessage(0);
      return 0;
    case WM_DEVICECHANGE:
      //★ここに処理を書く
      return 戻り値;
  }
  return DefWindowProc(h,m,w,l);
}

>どうすればメッセージをとれるか?
メッセージは勝手に飛び込んでくるのです。それを待ち構えます。
WindowsのGUIプログラムは受け身で物を考えないといけません。
このプログラムは×で閉じます。だから「常駐」ではありません。
★のところは別途調べてください。

#include <windows.h>
static LRESULT WINAPI WndProc(HWND,UINT,WPARAM,LPARAM);
static void reg();
int WINAPI WinMain(HINSTANCE ci,HINSTANCE pi,LPSTR cp,int sw)
{
  MSG m;
  reg();
  while(GetMessage(&m,NULL,0,0)) {
    TranslateMessage(&m);
    DispatchMessage(&m);
  }
  return 0;
}
static void reg() {
  WNDCLASSEX w;
  char c[] = {"a"};
  memset(&w,0,sizeof(w));
  w.cbSize = sizeof(WNDCLASSEX);
  w.lpfnWndProc = (WNDPROC)WndPro...続きを読む

QcharからLPTSTRへの変換方法

リストコントロールにchar型の変数の値を数値として表示させたいのですが、charからLPTSTRへの洗練された変換方法がよくわからないです。

char tempChar;
CString tempString;
tempString.Format("%s", tempChar);
LPTSTR lpsz = new TCHAR[tempString.GetLength()+1];
_tcscpy(lpsz, tempString);

こんなプログラムを考えてみたのですが、汚いような気がします。もっと簡単で洗練された変換方法はないのでしょうか?

Aベストアンサー

wsprintfを使ってはどうでしょうか?

char tmpChar = 100;//表示する数値
TCHAR buf[5];
wsprintf(buf, "%d", tempChar);

QManagementClassが見つからない。

ManagementClassが見つからない。

質問させてください。
C#でWMIを使用したプログラムを作成しています。
using System.Management;を記述して、ManagementClassを宣言したのですが、ビルド時に「ManagementClassが見つからない」という旨のエラーが出ます。

ネットで調べる限りではusing System.Management;を記述するだけでManagementClassを使用できるように思うのですが、まだ何か足らないのでしょうか?

どなたかお知恵をお貸しください。
よろしくお願いします。

Aベストアンサー

(1)ソリューションエクスプローラーにて該当プロジェクトの「参照設定」を右クリックし、「参照の追加」を選択。
(2)「.NET」タブの画面にて「System.Management」を選択し、「OK」ボタンをクリック。

以上で、ManegementClassが使えるようになります。

QwndProcを用いたUSBデバイスの抜差し検知

現在VC++2008のC++/CLIを用いてwindows form アプリケーションを作成しています。
USBカメラの抜挿しを検知しようと思い,http://d.hatena.ne.jp/shiwork/20100126/1264453129のサイトを参考にさせていただき,下記のコードを書きました。

#include <windows.h>
#include <Dbt.h>

virtual void WndProc(System::Windows::Forms::Message% m) override
{

 if(m.Msg == WM_DEVICECHANGE)
 {
   switch((int)(m.WParam))
   {
     case DBT_DEVICEREMOVECOMPLETE:
       MessageBox::Show("out");
       break;
     case DBT_DEVICEARRIVAL:
       MessageBox::Show("in");
       break;
   }
  }
  Form::WndProc(m);
}

このコードをステップ実行してみたところ,USBカメラを抜いても挿しても,m.WParamの値は '7'のままで変わりません。またswitchで一時停止し,F10で1ステップ実行したところ,すぐにswitchを抜けてしまい,条件式を全く評価していないようでした。
どのようにすれば,USBカメラの抜挿しを正常に検知できるでしょうか?

現在VC++2008のC++/CLIを用いてwindows form アプリケーションを作成しています。
USBカメラの抜挿しを検知しようと思い,http://d.hatena.ne.jp/shiwork/20100126/1264453129のサイトを参考にさせていただき,下記のコードを書きました。

#include <windows.h>
#include <Dbt.h>

virtual void WndProc(System::Windows::Forms::Message% m) override
{

 if(m.Msg == WM_DEVICECHANGE)
 {
   switch((int)(m.WParam))
   {
     case DBT_DEVICEREMOVECOMPLETE:
  ...続きを読む

Aベストアンサー

見直したハズですが、アホな誤字があったので訂正。

># 接続したUSB2.0 Cameraのプロパティ、詳細の「デバイカクラスGUID」の値。

「デバイス クラス GUID」です。

Qボタンの表示の色、フォントを変更したい

VC++でプログラミングしています。
MFCのダイアログベースのEXEを造っています。
ダイアログにはボタンとエディットボックスを貼り付けています。
私がやりたいのは以下のことです。

・ボタンの色を設定したい
・ボタン、エディットボックスに表示する文字の色を設定したい
・ボタン、エディットボックスに表示する文字のフォント(サイズ)を設定したい

プロパティでサイズ変更すると全体に反映されてしまうので、個々の
コントロールについて制御したいと思っています。

ヘルプで調べて、それらしい関数を見つけるのですが使い方がわかりません。
VCを始めたばかりで、クラスの理解がまだ浅いです。。。
関数の説明は理解できても、「じゃあ、コードはどう書くの?」という状態です。
「○○ は ×× のメンバではありません」と、よく怒られてます。。。

識者の方、ご教授願います。
コードがどうなるのか知りたいので、簡単なサンプルコードがあると助かります。

また、質問ではないのですが、「この関数は○○をする」というのではなく、
「○○をするにはこの関数を使う」という様に調べられる、お勧めの書籍、
Webなどがありましたら教えてください。
今後の勉強に役立てたいと思っています。

VC++でプログラミングしています。
MFCのダイアログベースのEXEを造っています。
ダイアログにはボタンとエディットボックスを貼り付けています。
私がやりたいのは以下のことです。

・ボタンの色を設定したい
・ボタン、エディットボックスに表示する文字の色を設定したい
・ボタン、エディットボックスに表示する文字のフォント(サイズ)を設定したい

プロパティでサイズ変更すると全体に反映されてしまうので、個々の
コントロールについて制御したいと思っています。

ヘルプで調べ...続きを読む

Aベストアンサー

下2つについては以下でいけると思います。

class CMyDlg : CDialog
{
public:

  CFont m_cFont; //Dlgクラスのメンバとして用意
/*
  他のメンバ
*/
  virtual BOOL OnInitDialog(); //初期化

};


BOOL CMyDlg::OnInitDialog()
{
  //TODO:ここでFontを設定しておく(文字の色、サイズなど)

  //Fontを設定
  ((CButton *)GetDlgItem(IDC_BUTTON))->SetFont(&m_cFont,TRUE);

  //TODO:その他の初期化

  return TRUE;
}
//見易さのために、全角スペースを使っています;;

一番上はBitmapを貼り付けるか、CWndのメンバ関数を使って
塗りつぶすかどうかだと思います。

MFCではなく、C++Builderのページなのですが、少しいじればMFCでも使えるので、参考URLに示しておきます。

参考URL:http://market.agr.tottori-u.ac.jp/ken/tech.html

下2つについては以下でいけると思います。

class CMyDlg : CDialog
{
public:

  CFont m_cFont; //Dlgクラスのメンバとして用意
/*
  他のメンバ
*/
  virtual BOOL OnInitDialog(); //初期化

};


BOOL CMyDlg::OnInitDialog()
{
  //TODO:ここでFontを設定しておく(文字の色、サイズなど)

  //Fontを設定
  ((CButton *)GetDlgItem(IDC_BUTTON))->SetFont(&m_cFont,TRUE);

  //TODO:その他の初期化

  return TRUE;
}
//見易さのために、全角スペースを使って...続きを読む

QUSBの通信プロトコルを学ぶには。

シリアルの通信をVisualBasicを使ってプログラムしましたが、シリアルインターフェイスがUSBに替わりつつあります。
いまのところ、変換アダプタを使って対応していますが、USBで直接通信させなくてはならないかと危惧しています。
VBよりもC++が向いていると言われました。
USBでの通信には一般にどんなソフトでコントロールするのでしょうか?
それと、通信プロトコルはどこで入手できますか。教えて下さい。

Aベストアンサー

書籍だったら参考URLの物が良いですよ。

また日本語だと下記ページが結構詳しく書いてあります。

http://www.picfun.com/usb03.html

http://www.picfun.com/usb00.html

参考URL:http://www.cqpub.co.jp/hanbai/books/33191.htm

Qシリアル通信の出力バッファと送信完了イベントについて

こんにちわ。よろしくお願いします。

どの言語として扱うか迷ったのですが、恐らくはC/C++が一番だろうと思ってここで質問させていただきます。

質問の内容ですが、現在、シリアル通信のアプリケーションを作っていまして、CreateFileの引数にFILE_FLAG_OVERLAPPEDを与えて非同期で読み書きを行うようにしています。
非同期ですので、OVERLAPPED構造体をstaticで宣言し、
WriteFile時に引数で与えています。
---
m_hComm = CreateFile( (const char*)pCom, GENERIC_READ|GENERIC_WRITE,0, NULL,OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL ) ;
WriteFile(m_hComm, pwData,dwLen, &dwWrite, &osWriter);
---

問題はここからで、OVERLAPPED構造体のイベントが、シグナル状態になり、GetOverlappedResult(m_hComm, &osWriter, &dwWrite, TRUE)を抜けるのはいいのですが、実際には送信は完了しておらず、GetCommStateで通信速度を変更すると送信途中のデータが化けて通信エラーになってしまいます。

どうやら、今使用しているPCのUARTの出力バッファが大きいのか、Windows側のバッファからUARTバッファに書き込みが完了した時点でWindowsはOVERLAPPED構造体のイベントをシグナルにしているようです。
(もちろんFIFOは切ってあります)

他のPCで確認したところ、問題ありませんでした。
もしどなたか、シリアルの出力バッファを監視するいい方法があったら教えていただけないでしょうか。

こんにちわ。よろしくお願いします。

どの言語として扱うか迷ったのですが、恐らくはC/C++が一番だろうと思ってここで質問させていただきます。

質問の内容ですが、現在、シリアル通信のアプリケーションを作っていまして、CreateFileの引数にFILE_FLAG_OVERLAPPEDを与えて非同期で読み書きを行うようにしています。
非同期ですので、OVERLAPPED構造体をstaticで宣言し、
WriteFile時に引数で与えています。
---
m_hComm = CreateFile( (const char*)pCom, GENERIC_READ|GENERIC_WRITE,0, NULL,OPEN_EXI...続きを読む

Aベストアンサー

2400bpsで9文字の文字列を送出してからビットレートを57600bpsに変更する、という処理を5回繰り返すテストプログラムです。

ちょっと乱雑なソースですがご勘弁を。(インデントは全角スペースです。ご注意ください。)

int main(int argc, char** argv)
{
  for (int i = 0; i < 5; ++i) {
    HANDLE hFile;
    DWORD dw;

    hFile = CreateFile(
      "com1",
      GENERIC_WRITE,
      0,
      NULL,
      OPEN_EXISTING,
      0,
      NULL
    );

    DCB dcb = { sizeof(DCB) };
    GetCommState(hFile, &dcb);
    dcb.BaudRate = CBR_2400;
    SetCommState(hFile, &dcb);

    char buf[100];
    sprintf(buf, "%d ABCDE\r\n", i);
    WriteFile(hFile, buf, lstrlen(buf), &dw, NULL);
    // "# ABCDE\r\n" totals 9 bytes, or 90 bits.
    // At 2400bps, 90 bits need 37.5ms to be transmitted.

#if 0
    CloseHandle(hFile);
    hFile = CreateFile(
      "com1",
      GENERIC_WRITE,
      0,
      NULL,
      OPEN_EXISTING,
      0,
      NULL
    );
#endif

    Sleep(15); // 37 makes mess, 38 ok.
    dcb.BaudRate = CBR_57600;
    SetCommState(hFile, &dcb);

    Sleep(100);
    CloseHandle(hFile);
  }

  return 0;
}

同期処理にしていますが、同じ現象が発生しています。

9文字(90ビット)を2400bpsで送出すると37.5msかかる計算になるのですが、このプログラム中にあるSleep(15)の15を37にすると文字化けが発生し、38にすると文字化けが発生しないので、おおよそ計算どおりと言えるかと思います。

ここで#if 0の行を#if 1に変更すると、Sleep(15)がSleep(0)でも文字化けは発生しなくなります。つまり、デバイスのハンドルをcloseするときにはバッファがflushされるということです。

close時は必ずflushする、という記述に行き当たったわけではないので、closeさえすれば万事OKという保証はできませんが、ドライバの動作としては妥当だと思います。

#実は、「試したいこと」とはこれではなくてDevice Power Stateの変更だったのですが、そのテストをする前になんだかいい感じの結果になってしまったので(^^;

2400bpsで9文字の文字列を送出してからビットレートを57600bpsに変更する、という処理を5回繰り返すテストプログラムです。

ちょっと乱雑なソースですがご勘弁を。(インデントは全角スペースです。ご注意ください。)

int main(int argc, char** argv)
{
  for (int i = 0; i < 5; ++i) {
    HANDLE hFile;
    DWORD dw;

    hFile = CreateFile(
      "com1",
      GENERIC_WRITE,
      0,
      NULL,
      OPEN_EXISTING,
      ...続きを読む


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

人気Q&Aランキング