PIC初心者用掲示板

PICの初心者用の質問箱です。
何でもお気軽にどうぞ!

■最新ツリー一覧

□このツリー付近のツリー一覧

★新規ツリー作成

◆ 5973. PIC16F874でUSART使用時のRS485制御について [ra-ra2005/08/26 00:32


5973. PIC16F874でUSART使用時のRS485制御について [ra-ra2005/08/26 00:32
はじめまして。
ra-raと申します。
RS-485にてPIC16F874−PIC16F874にてPIC間通信のソフトを作成途中、
どうしても不具合が解決出来なく、皆様の
助言を頂けたらと思い投稿いたしました。
環境はCCS C(PCM VER3.32)+MPLAB7.2です。
仕様は以下の物です
 (1)マスタ :1台(セラロック20MHz)
 (2)スレーブ:1台でセラロック20MHz)
 (3)通信IC :MAX3082
 (4)ケーブル:シールド付ツイストペア(20センチ程度)
 (5)伝送速度:9600bps
 (6)通信プロトコル:内蔵のUSART使用
マスタ:スタート1、データ 6byte 、パリティE、ストップ1
スレーブ:スタート1、データ 10byte、パリティE、ストップ1
(7) 方式:半二重

  元は、PC ⇔ スレーブのものなのですが,今回はスレーブのハードをそのまま利用し、
  ソフトだけ変更しマスタを作成しております。
  スレーブのソフトは外部業者さんのソフトを現状量産しているまま利用するので、
  プロトコルの変更は出来ません。

以下のような不具合が起きます
(1)マスタ → スレーブに送信後、スレーブのアドレスにより返信がまちまちになって
しまいます。マスタ側・スレーブ側どちらでも確認したのですが、返信があった時の
送信データと無かった時の送信データは同じでした。どのスレーブアドレスに対しても
データの抜けや途中にヒゲが入ったりということはありませんでした。
スレーブ最大設定が63台なのですが、1に設定した場合は必ず毎ポーリングに返信があり、
1以外ですと、数ポーリング置きに返信がきます。

マスタ側はスレーブアドレス以外は固定データのみを送り続けるのみです。
関数の#use rs232(ENABLE = XXXXX)を使用し自動で送受信を切り替えています。
スレーブはマスタ受信から20msたって返信するようなので送信間隔は取りあえず300ms
とり、1ポーリング終了毎に500msおいています。

(2)受信割り込みを使用しているのですが、初めの1BYTE目は正常にストップ受信後、割り込み
が入るのですが、以降は連続して入り続けWDTで強制的にリセットになってしまいます。
受信バッファを2回空読みしてみたのですが、全く直りませんでした。


大変長文になってしまい申し訳ございません。
どうぞ宜しくお願い致します。





5974. Re: PIC16F874でUSART使用時のRS485制御について [JO_O2005/08/26 02:45
毎度JOです。
>>(6)通信プロトコル:内蔵のUSART使用
>>マスタ:スタート1、データ 6byte 、パリティE、ストップ1
内蔵のUSARTにはパリティがないので、プログラムによって実現しているのですね。

>>(4)ケーブル:シールド付ツイストペア(20センチ
規格には明示がありませんが、ツイストペア以外に
GNDを共通としたほうが、安定します。

通常485では、コントロールコード・局番・命令コード・データー・待ち時間・LFなど
フォーマットに決まりがあると思いますが、このあたりに問題はありませんか??

5975. Re: PIC16F874でUSART使用時のRS485制御について [ra-ra2005/08/26 09:18


Jo_JOさん
早々の助言ありがとうございます。

はい。パリティーはコンパイラの関数で挿入しております。

>>>コントロールコード・局番・命令コード・データー・待ち時間・LF

初めて耳にしました。
通信ICの仕様書を読み、DE、DIのHI、LOで送受信を切り替える必要がある
事だけ把握しておりました。
Jo_JOさんがおっしゃってるコントロールコードというのはこれにあたるもの
でしょうか。 
その他は全く考慮しておりません。
もう一度規格等の確認をしてみます。

メーリングリストで、少し前にいろいろな方法を拝見しておりましたが、
私の場合、ハード的な問題ではないと思うので途方に暮れておりました。
個人の趣味でPICは今までも使用経験がありますが、製品のソフトを作るのは
初めてで通信に触れたのも初めてです。
制御の対象が燃焼機器なのでソフトバグで一大事になりかねないので
再度よく確認してみます。

ありがとうございました。

5976. Re: PIC16F874でUSART使用時のRS485制御について [新参者] 2005/08/26 11:58
>以下のような不具合が起きます
> (1)マスタ → スレーブに送信後、スレーブのアドレスにより返信がまちまちになって
>しまいます。マスタ側・スレーブ側どちらでも確認したのですが、返信があった時の
>送信データと無かった時の送信データは同じでした。どのスレーブアドレスに対しても
>データの抜けや途中にヒゲが入ったりということはありませんでした。
>スレーブ最大設定が63台なのですが、1に設定した場合は必ず毎ポーリングに返信があり、
>1以外ですと、数ポーリング置きに返信がきます。


説明が良くわからないのですが、どのような動作を想定して不具合にあたるのでしょうか。
送信データ化けは無いようですけど、返信データ内容は確認してますか?

「1に設定」or「1以外」というのがマスタ側の運用局数(MAX-ID)指定のことで、
スレーブが「局番1」なら、あるいは至極まっとうな動作なのかもしれませんね。
(サイクリックな巡回トークン(送信)に対し、局番1のスレーブが応答)

でも文脈からするとスレーブ側アドレス(局番)の設定なのかな??

マスタ側プログラムはどの程度自分で組んだのでしょうか。
またプロトコル等は把握しているでしょうか。プログラムを再度確認・検討してください。


> (2)受信割り込みを使用しているのですが、初めの1BYTE目は正常にストップ受信後、割り込み
>が入るのですが、以降は連続して入り続けWDTで強制的にリセットになってしまいます。
>受信バッファを2回空読みしてみたのですが、全く直りませんでした。

「連続して入り続け」の意味がイマイチよくわかりません。

割込み処理は短時間で速やかに抜けるように組むのが良いと思います。
1BYTE目の受信割込み後、正常に割込み抜けているのか確認してください。
あるいは割込みルーチン内でgets()関数を使っているようなことありませんか?

受信バッファの空読みって、RCREGを(READ)参照してるのかな。それとも…getc()関数?

CCS-Cの標準入出力関数の動作など再確認してプログラムを見直してください。
http://www.picfun.com/c09.html

USARTの設定記述はどんな感じでしょうか。
例:#use rs232(baud=9600,bits=8,parity=E,xmit=PIN_C6,rcv=PIN_C7,enable=PIN_C5,restart_wdt,errors)

5977. Re: PIC16F874でUSART使用時のRS485制御について [ra-ra2005/08/26 13:43
新参者様>>
 沢山のアドバイスありがとうございます。
 訳のわからない説明ですみませんm(__)m
 
 求める動作は、マスターが指定アドレスのスレーブに送信したら必ず該当アドレスのスレーブからの返信が来る事です。
 現状ちゃんとデータが送信されても返信があったりなかったりします。

>送信データ化けは無いようですけど、返信データ内容は確認してますか?
 
→確認しました。マスターから1番のスレーブに送信した場合、返信があるスレーブは1番で、データ内容も正常でした。


>「1に設定」or「1以外」というのがマスタ側の運用局数(MAX-ID)指定のことで、>スレーブが「局番1」なら、あるいは至極まっとうな動作なのかもしれませんね。
→おっしゃる通りです。マスター側ではスレーブ接続数MAX(sl_connect)を設定し
  for(sl_pow=0x01; sl_pow <=sl_connect; sl_pow++)で1番から(sl_pow=0x01)スレーブ接続MAXまで送信を繰り返すようにしています。


プログラムは1から自分で組みましたが、送受信部分はコンパイラの関数に頼っています。
送信内容はは本来マスターとして使用しているPCの仕様書のプロトコルと同じにしています。
 送信は、送信データの配列から1バイトを6回繰り返し、300ms待ってからアドレスデータだけ変更してまた送信し、スレーブ接続MAX数まで送り終わったら500MS待っての繰り返してす。

>1BYTE目の受信割込み後、正常に割込み抜けているのか確認してください。
 →1バイト目のSTOP受信後に割り込みが入ってあとは抜けずにずっと割り込みが立ったままになってしまっています。RCREGを空にするまでクリアされないのかと思い rx_buffer[rx_coun++] = getc();で処理しています。

>USARTの設定記述はどんな感じでしょうか。
 以下のように設定しています。
#use rs232(ENABLE = PIN_C5, PARITY = E,BAUD = 9600, XMIT = PIN_C6, RCV = PIN_C7,errors)

本日オシロのTIME/DIVを2Sで確認していて気がついたのですが、6BYTE送信後、不定期に600msや900msの空白が入っていました。ソース上では一切入れていない時間です。
原因はまだわかっていないのですが、もしかしたらこれが原因かもしれません。

コンパイラのサンプルプログラムに"RS485.c"を発見したので参考に通信部を考え直している最中です。
通信は本当に難しいです・・・。

宜しくお願い致します。 

5978. Re: PIC16F874でUSART使用時のRS485制御について [cam009] 2005/08/26 16:34
rs232cは一度もやった事がないので、話半分に聞いてください。

>1バイト目のSTOP受信後に割り込みが入ってあとは抜けずにずっと割り込みが立ったままになってしまっています。

 ということですが、clear_interrupt(#INT_RDA)関数は使用されているんでしょうか。また使用する必要はないのでしょうか。

5982. Re: PIC16F874でUSART使用時のRS485制御について [新参者] 2005/08/27 00:31
5973.不具合(1)の件
> 求める動作は、マスターが指定アドレスのスレーブに送信したら必ず該当アドレスのスレーブからの返信が来る事です。
> 現状ちゃんとデータが送信されても返信があったりなかったりします。

実際にスレーブは何台接続されているのでしょうか。確か1台のみでは?

>→おっしゃる通りです。マスター側ではスレーブ接続数MAX(sl_connect)を設定し
>  for(sl_pow=0x01; sl_pow <=sl_connect; sl_pow++)で1番から(sl_pow=0x01)スレーブ接続MAXまで送信を繰り返すようにしています。

奇しくもマスター側の設定と動作は想像通りだったのですが…接続はスレーブ局番1のみとして
スレーブ局番2以降へのトークン送信時に、接続されていない局番から返信が無いのは
当然というオチかと考えたんですが…違いますか?
(例:sl_connect=3の時、スレーブ1台のみなら3回に1度しか返信無くて正常と思います)

不具合(2)の件
>>1BYTE目の受信割込み後、正常に割込み抜けているのか確認してください。
> →1バイト目のSTOP受信後に割り込みが入ってあとは抜けずにずっと割り込みが立ったままになってしまっています。RCREGを空にするまでクリアされないのかと思い rx_buffer[rx_coun++] = getc();で処理しています。

受信割込み処理内でgetc関数の実行は一度きり、となるようにすれば良いでしょう(推奨)
http://www.picfun.com/c09.html 【標準入出力関数】の説明にも書かれてますが
入力があるまで待つ関数なので RCREGが空の時に実行すると次byte受信まで関数を抜けません。
(割込み処理内でgets関数使用は論外)

割込み処理を抜けないのも、処理内のgetc関数で引っかかっているからだと思います。
受信割込み直後はデータがあるから良いとして、それ以外のタイミングでのgetc関数は
kbhit関数と組で使うべきです。

また WDT有効なら #use rs232() 関数記述にrestart_wdtを入れといた方が無難です。

受信処理プログラムを見直してみてください。

5995. Re: PIC16F874でUSART使用時のRS485制御について [ra-ra2005/08/29 13:21

cam009様、新参者様

大変丁寧に教えて頂きありがとうございました。
おかげで正常に動作するようになりました。

受信割り込みの不具合はkbhitとclear_interrupt(#INT_RDA)を追加し、GET(C)の処理を
1度だけにしたら解消しました。
clear_interrupt(#INT_RDA)を知らなくていろいろ試行錯誤していました・・・。

新参者様
  いつも、沢山のご指導を頂きありがとうございます。
 
>実際にスレーブは何台接続されているのでしょうか。確か1台のみでは?
>スレーブ局番2以降へのトークン送信時に、接続されていない局番から返信が無いのは
>当然というオチかと考えたんですが…違いますか?
 
 
スレーブの局番はスレーブ側で変更できるので、1番にしたり60番にしたりしてデバックして
いたのですが、局番によって返信があったり、なかったりしたのですが、これも割り込み処理部分
と、#use rs232() 関数記述にrestart_wdtを追加した所解消しました。


 職場で、PICやC言語の質問をしたり、アドバイスを頂ける人が居ないので大変勉強になりました。
 何日も解らなくて悩んで居た事でもわかると、こんなことだったのかと毎日一喜一憂です。
 また、使用している言語の関数を把握したり、デバイスのハード的な仕様の把握がとても大切なのだと
 思いました。
 本当にありがとうございました。