2023.1.6
前へ
次へ
ホームページトップへ戻る


PIC−USBIO using BASIC

〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
USBインターフェースを内蔵したPICを使ってWindowsパソコンで外部回路を制御するための各種I/O基板の製作記事です。
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜

[第148回]



●PICUSBIO−03(97)ICモード(19)送受信プログラム

[第144回]でマスターが送信してスレーブが受信するプログラムを作ってテストしました。
[第146回]ではその逆のプログラム、スレーブが送信してマスターが受信するプログラムを作ってテストをしました。
今回はその2組のプログラムをマスター側とスレーブ側でそれぞれ結合してそれぞれを1本のプログラムにしてテストをしてみました。
最も単純な考え方としてはマスター側もスレーブ側もそれぞれ2本のプログラムを単純にくっつけて1本にした上で最初のプログラムと次のプログラムの間にSTOP文を置くという簡便な方法もあります。
そのようにしておいてプログラムを実行すると前半部分が実行されたあとSTOP文でブレークします。
そのあとSTOP文の次の行に対してGOTO文を実行すれば後半部分が実行されます。
実際にそのようにして試してみてうまく動作することを確認しました。
しかしそれでは実用的ではありません。
途中のSTOP文は省いて最初から最後まで1本のプログラムにしてそれで動作するようにすべきです。
そこでSTOP文を省いて実行してみたところやっぱり後半部分に入ったところで止まってしまいました。
やはり前半と後半のつなぎの部分には工夫が必要でした。

下は最終的に正しく最後まで動作することを確認したプログラムです。
プログラムが今までより長くなって1画面では表示できませんのでテキストで示します。
まずはマスター側のプログラムです。
   10 picout TRISB,$ff
   20 picout SSPCON1,0
   30 picout SSPSTAT,$80
   40 picout SSPCON1,$28
   50 picout SSPADD,$77
   60 picout SSPCON2,1:'START
   70 picout SSPBUF,$00:'address write
   80 if and(picin(SSPSTAT),1)=1 goto 80
   90 picout SSPBUF,$41
  100 if and(picin(SSPSTAT),1)=1 goto 100
  110 picout SSPBUF,$42
  120 if and(picin(SSPSTAT),1)=1 goto 120
  130 picout SSPCON2,4:'STOP
  140 print hex$(picin(SSPSTAT)):'dummy
  150 print hex$(picin(SSPCON1)):'dummy
  160 print hex$(picin(SSPCON2)):'dummy
  170 picout SSPCON2,$01:'start
  180 picout SSPBUF,$01:'address read
  190 if and(picin(SSPSTAT),1)=1 goto 190
  200 picout SSPCON2,$08:'receive enable
  210 if and(picin(SSPSTAT),1)=0 goto 210
  220 print hex$(picin(SSPBUF))
  230 picout SSPCON2,$10:'ack
  240 picout SSPCON2,$08
  250 if and(picin(SSPSTAT),1)=0 goto 250
  260 print hex$(picin(SSPBUF))
  270 picout SSPCON2,$30:'nack
  280 picout SSPCON2,4:'STOP

130行のSTOPはSTOP文ではありません。
前半のプログラムの最後にマスターが発行するSTOPコンディションです。
10行からその130行までがマスターが送信してスレーブがそれを受信するモードでのマスター側のプログラムです。
この部分は[第144回]のマスター側のプログラムと同じです。
ただしもとのプログラムに20行を追加してあります(このことについては前回の「WCOL」のところを参照してください)。
プログラムの後半部分は170行から280行までです。
ここはスレーブが送信してマスターが受信するモードのマスター側のプログラムです。
この部分は[第146回]のマスター側のプログラムと同じです。
ただしもとのプログラムの初期設定部分(10行〜50行)は不要なので省いてあります。
今回のプログラムの190行はもとのプログラムにはありませんがスレーブ側のタイミングの遅れを考慮して念のために入れて有ります。
180行のスレーブアドレスの送信が完了してBFフラグがクリアされるまで待ちます。
もうひとつ追加しているところがあります。
140行〜160行です。
ここがないとスレーブ側のプログラムが後半に入ったところでこけてしまいます。
スレーブ側のプログラムで、STOPコンディションを確認してから次のSTARTコンディション、スレーブアドレスの受信をするところまでが間に合わないときがあります。
STOPコンディションによってCKPビットがクリアされてしまいクロックストレッチングが解除されてしまうためだと思うのですが、それ以後にスレーブ側で実行が遅れると受信エラーになってしまいます。
STOPコンディションを使わないでRSEN(リピーテッドスタートコンディション、SSPCON2レジスタのbit1)を使えばよいかと思ったのですがうまくいきませんでした(使い方に問題があったのかもしれません)。
簡便な方法としてダミー命令で時間を稼ぐことにしました。
それが140行〜160行です。
picin関数は実行時間がかかります(約6〜8msec、[第129回]参照])。
それを利用しました。
こんなに入れなくてもよいかもしれませんが念のためです。
これで20〜25msecほどの遅延になります。
これを入れることで正常に動作することが確認できました。

次はスレーブ側のプログラムです。
   10 picout TRISB,$ff
   20 picout SSPCON1,0
   30 picout SSPSTAT,$80
   40 picout SSPCON1,$26
   50 picout SSPCON2,$81
   60 if and(picin(SSPSTAT),1)=0 goto 60
   70 print hex$(picin(SSPBUF))
   80 picout SSPCON1,$36:'CKP=1
   90 if and(picin(SSPSTAT),1)=0 goto 90
  100 print hex$(picin(SSPBUF))
  110 picout SSPCON1,$36:'CKP=1
  120 if and(picin(SSPSTAT),1)=0 goto 120
  130 print hex$(picin(SSPBUF))
  140 picout SSPCON1,$36:'CKP=1
  150 if and(picin(SSPSTAT),$10)=0   goto 150
  160 print "stop detect"
  170 if and(picin(SSPSTAT),1)=0 goto 170
  180 print hex$(picin(SSPBUF)):'address
  190 picout SSPBUF,$61:'a
  200 picout SSPCON1,$36:'CKP=1
  210 if and(picin(SSPCON1),$10)=$10 goto 210
  220 picout SSPBUF,$62:'b
  230 picout SSPCON1,$36:'CKP=1
  240 if and(picin(SSPSTAT),1)=1 goto 240
  250 if and(picin(SSPSTAT),$10)=0 goto 250:'stop

10行から160行までがマスターが送信してスレーブがそれを受信するモードでのスレーブ側のプログラムです。
この部分は[第144回]のスレーブ側のプログラムと同じです。
ただしもとのプログラムの40行で$36になっていたところを$26にしてあります。
ここは$36にしなくてもよいことがわかりましたのでそのようにしてあります。
160行はもとのプログラムではSTOP文でしたがここはPRINT文に変更しました。
プログラムの後半部分は170行から250行までです。
ここはスレーブが送信してマスターが受信するモードのスレーブ側のプログラムです。
この部分は[第146回]のスレーブ側のプログラムと同じです。
ただしもとのプログラムの初期設定部分(10行〜50行)は不要なので省いてあります。
今回のプログラムは最後のところに240行があります(ここで送信完了を見ています)がこれは不要だったと思います。

プログラムを実行しました。

左側(マスター側)の画面で実行後に表示されている3バイトのデータ(88、28、00)は140行〜160行のダミー命令での表示です。
その下の61(’a’)と62(’b’)がスレーブから送信されたデータです。
右側(スレーブ側)の最初の’00’はゼネラルコールアドレスで最後の’01’はスレーブアドレス+R/W(=1)です。
41(’A’)と42(’B’)がマスターから送信されたデータです。

上で240行は「多分不要だったと思います」と書きました。
ただ思っただけで済ませてはいけません。
念のために240行をコメント文にして実行してみました。

同じ結果になりました。

PIC−USBIO using BASIC[第148回]
2023.1.6upload

前へ
次へ
ホームページトップへ戻る