C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[5]: マイコン(PIC)とのシリアル通信


(過去ログ 36 を表示中)

[トピック内 6 記事 (1 - 6 表示)]  << 0 >>

■18563 / inTopicNo.1)  マイコン(PIC)とのシリアル通信
  
□投稿者/ れれれ (55回)-(2008/05/14(Wed) 21:30:04)

分類:[C#] 

お世話になっていますれれれです。

早速質問なのですが、いまマイコン(PIC)とPCでシリアル通信しようとしています。
マイコンからは66byteの文字データが1byteづつ送られてきます。
PC用のプログラムは

        private void button_eeprom_read_Click(object sender, EventArgs e)
        {
            
                string eepromdata;
                request = new byte[1];
                eeprom_data = new byte[66];
                request[0] = 114; 
                serialPort1.Write(request, 0, 1);  //マイコンへのデータ要求フラグ、マイコンがこれを受信するとPCにデータ送信

                serialPort1.Read(eeprom_data, 0, 66);
            
        }

なのですがデータ自体はちゃんと送られてきます
しかしそのデータがおかしくて
プログラムを起動して受信すると1回目が送られてくるデータの1バイト分しかeeprom_data[0]に入りません。残りは全部0です
2回目ボタン押すと、残りの65バイト分がeeprom_data[0]〜eeprom[64]に入ります。最後の1バイト分は0です。
つまり1回目が66バイト格納するはずが1バイトしか格納されず、結果としてバッファがずれてしまい1つ遅れているのです。

マイコンのほうの送るデータを変えて受信しようとしても1回遅れて変更されたデータが送られてきます。
マイコンのほうは制御文字についてはNULL(\0)以外送っていません。
こんなことは初めてです。
どうすればいいでしょうか?

引用返信 編集キー/
■18565 / inTopicNo.2)  Re[1]: マイコン(PIC)とのシリアル通信
□投稿者/ れい (535回)-(2008/05/14(Wed) 21:41:54)
No18563 (れれれ さん) に返信
> 2回目ボタン押すと、残りの65バイト分がeeprom_data[0]〜eeprom[64]に入ります。最後の1バイト分は0です。
> つまり1回目が66バイト格納するはずが1バイトしか格納されず、結果としてバッファがずれてしまい1つ遅れているのです。

Readの戻り値をチェックしましょう。
通常、Readは何バイト読みこむのか不定です。
引用返信 編集キー/
■18605 / inTopicNo.3)  Re[2]: マイコン(PIC)とのシリアル通信
□投稿者/ 組込系の人 (49回)-(2008/05/15(Thu) 08:59:53)
// 受信処理
private string RsRcv(){
    byte[] buff = new byte[66];
    int rcv_cnt = 0;

    while(rcv_cnt < 66){
        if(serialPort1.BytesToRead > 0){
            serialPort1.Read(buff, rcv_cnt, 1);
            rcv_cnt++;
        }
    }

    return Encoding.GetEncoding("shift-jis").GetString(buff, 0, 66 );
}


こんな感じでどうでしょうか?
returnの部分は、C#初めてすぐの頃に必死に調べて書いた物をそのままコピペ。。。あってるのか?w

通信のタイムアウトとかは考慮してないので、その辺は適当に・・・・

引用返信 編集キー/
■18620 / inTopicNo.4)  Re[3]: マイコン(PIC)とのシリアル通信
□投稿者/ れい (536回)-(2008/05/15(Thu) 10:03:55)
No18605 (組込系の人 さん) に返信
> こんな感じでどうでしょうか?

serialPort1のクラスが不明なので正確なところはわかりませんが、
たぶんダメですね。

StreamのRead/Writeの実装にはいくつかの流儀があります。
昔はいろいろありましたが、
最近は以下の振る舞いが一般的です。

・Readが戻るのは
「バッファがいっぱいになる」
「エラーが発生する」
「ストリームが終わっている(戻り値=0)」
「1バイト以上読み取る(戻り値=読み取ったバイト数)」

・Writeが戻るのは
「バッファを全て書き終わる」
「エラーが発生する」

です。
.Netでもこれが採用されています。
なので、読み取りが0バイトであるかどうか、常に確認しないといけません。
また、読み取りはなるべく同時にたくさん行うとよいでしょう。

> byte[] buffer = new byte[66];
> int pointer = 0;
> int receivebytes = 0;
>
> while(pointer < buffer.Length){
> receivebytes = serialPort1.Read(buffer, pointer, buffer.Length - pointer);
> if (receivebytes==0) throw new XXXException();
> pointer += receivebytes;
> }
>

引用返信 編集キー/
■18627 / inTopicNo.5)  Re[4]: マイコン(PIC)とのシリアル通信
□投稿者/ 組込系の人 (52回)-(2008/05/15(Thu) 10:19:10)
No18620 (れい さん) に返信
> ■No18605 (組込系の人 さん) に返信
>>こんな感じでどうでしょうか?
>
> serialPort1のクラスが不明なので正確なところはわかりませんが、
> たぶんダメですね。

すいません。自分はSystem.IO.Ports.SerialPortと仮定して話してました。



>
> StreamのRead/Writeの実装にはいくつかの流儀があります。
> 昔はいろいろありましたが、
> 最近は以下の振る舞いが一般的です。
>
> ・Readが戻るのは
> 「バッファがいっぱいになる」
> 「エラーが発生する」
> 「ストリームが終わっている(戻り値=0)」
> 「1バイト以上読み取る(戻り値=読み取ったバイト数)」
>
> ・Writeが戻るのは
> 「バッファを全て書き終わる」
> 「エラーが発生する」
>
> です。
> .Netでもこれが採用されています。
> なので、読み取りが0バイトであるかどうか、常に確認しないといけません。
> また、読み取りはなるべく同時にたくさん行うとよいでしょう。
>
>> byte[] buffer = new byte[66];
>> int pointer = 0;
>> int receivebytes = 0;
>>
>> while(pointer < buffer.Length){
>> receivebytes = serialPort1.Read(buffer, pointer, buffer.Length - pointer);
>> if (receivebytes==0) throw new XXXException();
>> pointer += receivebytes;
>> }
>>
>

RS232通信なんかやってると、良くSTXだのETXだのの処理で1文字ずつやりたいので
読み込み時に1文字づつ取ってました。
通信が連続していても、ETX受信直後にACK応答を返さないといけないとか
その他もろもろの制約でこのような処理になっていたような・・・
自分が使っているところでは、1文字読み取ったあとに、
ごちゃごちゃと処理をしています。例として示すには不適切でした。

たしかに読み込みは一気にやって読み取った後に1文字づつ解析すればいいですね。
引用返信 編集キー/
■18642 / inTopicNo.6)  Re[5]: マイコン(PIC)とのシリアル通信
□投稿者/ れれれ (56回)-(2008/05/15(Thu) 11:03:08)
No18627 (組込系の人 さん) に返信
No18620 (れい さん) に返信
お二方が示してくれた例のどちらでも1回で受信できました。
ありがとうございます。
解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -