SPIのソフトのはなし
SPIとは
[Serial Peripheral Interface]の略で、クロック同期型の3線式シリアル通信です。
ハード的には
クロック(SCK)に加えデーター出力(SO)、データー入力(SI)とチップセレクト(#CS)が設けられ、3線+チップセレクトなので3線式と呼ばれています。PLL-ICやADC-ICなど I2Cよりも多く使われています。
以前紹介したPLL+VCOのIC ADF4360 はこのインターフェイスを使っており、過去H8 で5個の PLL-ICを制御したこともあり、比較的簡単にコントロール出来ますので、今回はソフト部分を紹介します。
ソフト的には
今回のADF4360は、3種類の24ビットのデーターをレジスタに設定することで機能しますが、そのデーター転送の基本ルーチンとしてまず8ビット転送の out_byte( int data ) を説明します。
out_byte( int data )
{
int i ;
for( i=0x80 ;i > 0 ; ){
IO.PDR1.BIT.B0 = 0; /* CLK Low */
if( data >= i ){
IO.PDR1.BIT.B1 = 1; /* Data = 1 */
data = data - i ;
} else {
IO.PDR1.BIT.B1 = 0; /* Data = 0 */
}
IO.PDR1.BIT.B0 = 1; /* CLK High */
i = i >> 1 ;
}
}
ループ変数 i に 0x80 を代入して 8Bit のMSB から data を比較していきます。
i と data の and をとる方法もありますが、今回は大きさを比較して 元の data から比較後Bitが立っていた場合に i を引いてゆくのと i を右にシフトしていくことで各ビットの High/Low を送信します。(High時にはDOが立ち上がりますのでレベルが立ち上がるまでに時間がかかります。クロックを立ち上げるまですこし時間をかせぐ狙いもありますが..)クロックの Low 時点でデーターを変化させ、確定後 Highにすることでタイミングを知らせます。
全体のデーターを送るのは以下のルーチンです。
out_pll( )
{
int i ;
IO.PDR5.BIT.B2 = 0 ; /* PLL CS Low */
out_byte( 0x00 ) ; /* at Ref 20MHz */
out_byte( 0x0f ) ; /* Ref= 20KHz */
out_byte( 0xa1 ) ; /* Send R-Counter DATA */
IO.PDR1.BIT.B0 = 0; /* CLK Low */
IO.PDR5.BIT.B2 = 1 ; /* PLL CS High */
for ( i=0;i<100;++i) { } / * Wait */
IO.PDR5.BIT.B2 = 0 ; /* PLL CS Low */
out_byte( 0xc7 ) ;
out_byte( 0xf1 ) ;
out_byte( 0x20 ) ; /* Send Control DATA */
IO.PDR1.BIT.B0 = 0; /* CLK Low */
IO.PDR5.BIT.B2 = 1 ; /* PLL CS High */
for ( i=0;i<100;++i) { } / * Wait */
IO.PDR5.BIT.B2 = 0 ; /* PLL CS Low */
out_byte( pll_buff[0] ) ;
out_byte( pll_buff[1] ) ;
out_byte( pll_buff[2] ) ; /* Send Divider Data */
IO.PDR1.BIT.B0 = 0; /* CLK Low */
IO.PDR5.BIT.B2 = 1 ; /* PLL CS High */
}
各24ビットのデーターは out_byte() を3回呼んで送っています。この間に CS ポートを Lowにしておきますと、 CS の Highにするタイミングで各レジスタにラッチされます。PLL-ICが3つのレジスタを区別するには送られてきた24ビットの最後の2ビットを使って判断しています。
今回周波数を決めるデバイダーデーターは pll_buff[] という配列変数にしておき、周波数変更時にこの変数を修正してこのルーチンを呼びます。このICの仕様により、リファレンスデーターが変わらなければ、デバイダデーターだけ送っても良いですが、伝送時間はさほど問題ない場合は全てを送った方が確実です。
関連・参考文書
RFワールド NO.8
2章でADF4360を使ったRF信号発生器の製作記事が紹介されています。 USB-パラレル変換モジュールを使ってパソコンからコントロールできるようにしていますが、PLL-ICのレジスタ表や全体回路図・ハード的解説もあって参考になります。
| 固定リンク
「DIGITAL」カテゴリの記事
- 謹賀新年 2024(2024.01.03)
- I2C信号を見る はなし(2022.09.13)
- TTL レベルのはなし ふたたび(2022.02.13)
- 2022 新年あけましておめでとうございます。(2022.01.04)
- 12Bit DAコンバーターのはなし(2016.08.12)
コメント
H8/3664でL6470を使ってステッピングモータを制御したいのですが、L6470がSPI通信でないと動かないことを知りました。
H8のSCIを使ってSPI通信を行うことは可能でしょうか?
よろしくお願いいたします。
投稿: sa | 2014年8月26日 (火) 12時15分
私も一時 SCI でSPI が出来ないか検討してみました。数バイト連続送信する場合、SCIのハードウェアで行うと、1バイトごと送信完了の確認にレジスタをチェックして待っていなければならず、結局ループでWait していることになるので、ハードでやるにしても思ったほど高速化出来ないのではと思いました。
それで、自分でコントロール出来る、上記のソフトでポート制御の方法でアクセスしました。
割り込み機能などを使えば、SCI でうまく使えるかも知れませんが、ちょっとハードルが高そうでしたので、ソフトで作った方が結局楽でしたね。
ハード的にはクロック出力も出せるので、可能かと思われますが、データーシートでも機能的にSPI と言っていないので難しいのではないかと思います。データ送信順序も H8では LSB から始まりますが、L6470 は MSBから始まるようなので、その辺りも変換も必要ですね。
投稿: SUDOTECK | 2014年8月26日 (火) 22時33分
返信ありがとうございました。
ポート制御の方法でやってみたいと思います。
また何かあればお力をお貸しいただけると幸いです。
投稿: sa | 2014年8月27日 (水) 09時44分
PLLICであるADF4110ファミリーのCLK、LE,DATAを制御するのにSPI通信を用いなければならないのですが、制御のやり方がよく分かりません。
24bitのデータを送信するのは何を使えばよいのか(例えばArduinoやADSPのようなマイクロコントローラを使えばよいか)。またマイコンなどを制御するソフトには何を用いればよいでしょうか。
質問が多くなってしまったのですが、ご教授お願いいたします。
投稿: sakamoto | 2018年5月 8日 (火) 21時40分
SPI通信は Arduino なら比較的簡単に出来るようです。ライブラリも豊富ですので、本やWEBで探してみたらどうでしょう。開発言語はやはり C言語がポピュラーです。
24Bit通信はそんなに難しく考えないで 8Bitを3回通信すると思えば、たいしたことはありません。SPIはデーターが相手にCLOCKと同期して伝送していくイメージなので、最終的に相手に渡ったときのデーターを考えて送れば問題無いです。
頑張って下さい。
投稿: SUDOTECK | 2018年5月 8日 (火) 22時00分
返信ありがとうございました。
追加の質問になってしまうのですが、ADF4110ファミリーのICではMISOやMOSIのようなピンがないのですがどのようにマイコンとICをつなぐのでしょうか?
また各ラッチの制御とCLK、LE、DATAピンの関係性が分かりません。
返信のほどお願いいたします。
投稿: sakamoto | 2018年5月 9日 (水) 14時36分
SPIで言うと、MOSI( Master Out Slave In)がマスターからスレーブへの送信なので PLLのDATAに接続、MISO(MasterIn SlaveOut)がスレーブからマスターへの返信なので、PLLはこの信号を持ってないので未接続。SCKがマスターとスレーブを同期させるためのクロック信号なのでCLKと接続。どのデバイスと通信するかをSSにより決定するので、LEに接続します。
ここで電源電圧が5V同士ならば問題無いですが、PLLを3.3Vなどで使う場合は抵抗などで分圧するか、PLL側を 3.3Vにプルアップして、マイコン側にダイオードでLOWに引き込むなどの対策を取ります。
投稿: SUDOTECK | 2018年5月 9日 (水) 17時02分
迅速な返信ありがとうございます。
だいぶ理解が進みました。
また疑問点が出たらお力添えしていただけるとありがたいです。
投稿: sakamoto | 2018年5月 9日 (水) 21時48分