tagCANDY CGI VBレスキュー(花ちゃん) の Visual Basic 2010 用 掲示板(VB.NET 掲示板) [ツリー表示へ]   [Home]
一括表示(VB.NET VB2005)
タイトルシリアル通信の割込み禁止
記事No9477
投稿日: 2009/10/18(Sun) 23:46
投稿者synt
お世話になります。
VB初心者ですがVB2005でマイコン基板とのシリアル通信ソフトを作成しております。
ネット情報や参考書を頼りにタイマを用いて、下記のような
送信割り込み、受信割り込み処理を作成したのですが、
割り込み禁止?の手続きがわからない為、途中で受信割り込みが
走ってしまい、うまくいかず困っています。
ご助言をお願いいたします。
〜〜〜〜〜以下抜粋〜〜〜〜〜〜〜〜〜〜
        ' 通信設定
        With SerialPort
            .PortName = com1
            .BaudRate = 38400                   ' 通信速度は38400bps
            .DataBits = 8                       ' データ長は8ビット
            .Parity = IO.Ports.Parity.Even      ' パリティチェック:偶数
            .StopBits = IO.Ports.StopBits.One   ' ストップビットは1
            .Handshake = IO.Ports.Handshake.None
                      ' ハードウェアによるハンドシェイクなし
       .ReceivedBytesThreshold = 1
        End With
        :

    '********************
    ' 送信割り込み
    '********************
    Private Sub tmrStmg_Tick(・・・) Handles tmrStmg.Tick
        :
        tmrStmg.Enabled = False ' 送信開始トリガクリア
        Call SendStart() '送信開始
        :
    End Sub
    '*****************
    ' 送信開始
    '*****************
    Private Function SendStart() As Object
        If SerialPort.IsOpen Then
            ' 送信開始
            Try
                SerialPort.Write(mSData, 0, mSDataL)←この処理の直後、受信割込発生
            Catch ex As Exception
                MessageBox.Show(・・・)
            End Try
        Else
        :
        End If
        :
    End Function
'**************************
' 受信割り込み
'**************************
    ' デリゲート型の宣言
    Delegate Sub RecieveDataDelegate(ByVal RecieveData As String)

    ' デリゲート型のプロシージャを宣言
    Private Sub SetRecieveData(ByVal DataString As String)
        _comdt_1.Text &= DataString
    End Sub

    ' SerialPortコントロールのDataReceivedイベントハンドラ
    Private Sub SerialPort_DataReceived(・・・) Handles ・・・

        ' デリゲート型の変数の宣言と生成
        Dim recieve As New RecieveDataDelegate(AddressOf SetRecieveData)
        Dim mRDataLen As Integer
        mRDataLen = SerialPort.ReceivedBytesThreshold
        Dim mRDataB(256) As Byte
        Try
            SerialPort.Read(mRDataB, 0, mRDataLen) ' 1バイトだけ受信
            If SerialPort.ReceivedBytesThreshold = 1 Then
          :
             SerialPort.ReceivedBytesThreshold = 4←この直後、再び受信割込発生
          :
          :
  

[ツリー表示へ]
タイトルRe: シリアル通信の割込み禁止
記事No9478
投稿日: 2009/10/19(Mon) 01:05
投稿者オショウ
> 割り込み禁止?の手続きがわからない為、途中で受信割り込みが
> 走ってしまい、うまくいかず困っています。

  数々シリアル通信のコードは書いてますが・・・
  わざわざ割り込み禁止にしなければならない理由
  が解りません。

  確かにシリアル通信は、全2重なので、送信しながらや
  受信しながら、反する受信する・送信するという機能は
  行えます。

  が、一般的にコマンド等文字列を送信し、相手から何等
  かの結果(ステータス)が返信されてこないと、次の送
  信は行いません。

  よって、動作は半2重的です。

  今回、問題になっているのは、送信の完了・受信の完了
  が正しく行えていない為に発生しているのでは?
  また、シリアル通信のタイムアウト設定が為されてませ
  んが、タイマーでタイムアウト処理を行わせることも、
  可能です。

  汎用的に行うのであれば、シリアル通信クラスのタイム
  アウト設定を使うより、送信完了後の受信タイムアウト
  にタイマー使う方がある意味便利です。

  それと、SerialPort_DataReceivedで、わざわざデリゲー
  ト使ってSetRecieveDataを行わせると、実際に受信バッ
  ファにデータが着ているにも関わらず受信動作が行われ
  るのが余計に遅延してしまいます。

  ReceivedBytesThreshold = 1
  と言う設定ですが、実際にDataReceivedのイベント処理
  に入った段階では、1バイト以上の受信データがバッファ
  に入っている場合もあります。

  シリアル通信は非同期処理なので、わざわざ割り込みを
  どうこうする細工を行うより、イベントが発生した時点
  で、バッファにあるデータを一気に読出し、アプリ内で
  の受信データ処理で細工をする方が安全です。

  因みにそのマイコンとの通信ですが、プロトコルが定義
  されていると思いますが、アスキー通信?バイナリ通信?

  またアスキー通信の場合、デリミタがあるならば、その
  デリミタを受信待ちさせるようにしてやれば、受信ルー
  チンが簡素化し高速化します。

以上。参考まで

[ツリー表示へ]
タイトルRe^2: シリアル通信の割込み禁止
記事No9483
投稿日: 2009/10/20(Tue) 22:29
投稿者synt
ご助言ありがとうございます。
ご助言どおりバッファデータをすべて取り出す方法でうまくいきそうです。
ところで
>それと、SerialPort_DataReceivedで、わざわざデリゲー
>ト使ってSetRecieveDataを行わせると、実際に受信バッ
>ファにデータが着ているにも関わらず受信動作が行われ
>るのが余計に遅延してしまいます。
とありましたのでデリゲートをはずしたところ、
_comdt_1.Textに受信データをセットするところでエラーになってしまいます。
デリゲートをうまく使わない方法があるのでしょうか?
(受信データをラベルやテキストボックスに貼り付ける処理で
いちいちデリゲート処理をするのが面倒なので・・・)

[ツリー表示へ]
タイトルRe^3: シリアル通信の割込み禁止
記事No9484
投稿日: 2009/10/21(Wed) 06:51
投稿者オショウ
> ご助言ありがとうございます。
> とありましたのでデリゲートをはずしたところ、
> _comdt_1.Textに受信データをセットするところでエラーになってしまいます。
> デリゲートをうまく使わない方法があるのでしょうか?

  SerialPortコントロールをフォームに貼っておられると
  思いましたが・・・

  私は通常、コントロールを貼らないでクラス生成して、
  送受信するプログラムを作りますので、デリゲートは必
  要だったのですが。

  コントロールでも『必要』であるなら、戻して下さい。

  因みに・・・

  SerialPort.ReceivedBytesThreshold が受信バイト数の
  ような使い方をされていますが、それは間違いです。
  BytesToRead で、実際に受信したバイト数を使うべきです。

  ReceivedBytesThreshold は、あくまで受信イベントを発生
  させる為のバイト数で、イベントが発生した時点ではそれ
  以上の受信データが既にバッファに溜まっているかもしれ
  ないからです。

  デリミタがあるプロトコルならば・・・
  .RadTo("デリミタ文字")
  とすればよいでしょう。

  尚、受信イベントを処理するルーチンでは・・・
  If e.EventType = SerialData.Chars Then 〜
  として、イベントの種類を確認して、データ受信の時のみ
  受信動作を行うようにして下さい。
  そうすれば、タイムアウト以外では、Try 〜 は必要なくな
  ります。

以上。参考まで

[ツリー表示へ]
タイトルRe^4: シリアル通信の割込み禁止
記事No9496
投稿日: 2009/10/24(Sat) 17:43
投稿者synt
オショウさん。ご助言、ありがとうございました。(ちなみにアスキー通信です)
過去ログも参照して受信イベントを下記のような感じに修正したのですが、
ComSerialPort.Read(mRDataB, 0, mRDataLen)のところで
例えばsz=C174,mRDataLen=4の時、
mRDataB(0)にしかデータが格納されていない場合があったり、
mRDataB(3)までうまく格納されている場合があったりで、困っております。
〜〜〜〜〜以下抜粋〜〜〜〜〜〜〜〜〜〜
Private Sub ComSerialPort_DataReceived(・・・

        Dim mRDataB(256) As Byte
        Dim sz As String
        Dim mRDataLen As Integer
        
        If e.EventType = IO.Ports.SerialData.Chars Then
            Try
                sz = ComSerialPort.ReadTo(vbCr)
                mRDataLen = Len(sz)
                ComSerialPort.Read(mRDataB, 0, mRDataLen)
            Catch ex As Exception
                sz = String.Empty
            End Try
            If sz <> String.Empty Then
      :
何が原因か分からず困惑しており、ご助言をお願い致します。

[ツリー表示へ]
タイトルRe^5: シリアル通信の割込み禁止
記事No9497
投稿日: 2009/10/24(Sat) 18:00
投稿者オショウ
>             Try
>                 sz = ComSerialPort.ReadTo(vbCr)
>                 mRDataLen = Len(sz)
>                 ComSerialPort.Read(mRDataB, 0, mRDataLen)
>             Catch ex As Exception
>                 sz = String.Empty
>             End Try
>             If sz <> String.Empty Then
>       :

  sz = ComSerialPort.ReadTo(vbCr) ここで、szに読み込んで
  いるのに・・・
  何故再度、ComSerialPort.Read(mRDataB, 0, mRDataLen) する
  必要があるんですか?

  受信イベントが発生した時点で、1バイト以上受信バッファに
  データがある状態で、vbCrまで待って全て読み込むと言う方法
  で、一連の文字情報が、szに読み込まれているのに、その後、
  再度、読み込み動作させたら、正常な1組のデータを読み捨て
  て次のデータ受信を行っていることになるので・・・

  おかしくなるのは当然・・・

>                 mRDataLen = Len(sz)
>                 ComSerialPort.Read(mRDataB, 0, mRDataLen)

  この2行は不必要ですネ!(多分)

※ 受信されるべきデータのプロトコルが解らないので完全か
  どうかは、再度検証して下さい。

以上。

[ツリー表示へ]
タイトルRe^6: シリアル通信の割込み禁止
記事No9524
投稿日: 2009/10/29(Thu) 01:00
投稿者synt
ご助言ありがとうございました。
素直にszに入っているデータを加工して使うようにしました。

[ツリー表示へ]