PICでUSBを!(知識ゼロからのスタートです)
PIC18F14K50のUSB機能を100%自前のソフトで制御する試みです。しかもアセンブラで!
当記事は2009年12月から「TTLでCPUをつくろう!」というタイトルの もとにほとんど毎日連載をしてきたものを再編集したものです。 2011.7.12

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

PIC18F2550では大きすぎて、計画中のTK80互換マイコンボードND80ZVには組み込めそうにないことがわかりました。
USB機能内蔵のPICにはPIC18F4550、PIC18F2550のほかに20pinのPIC18F14K50があることはちょっと前から知っていました。しかしUSBに関する部分がPIC18F2550とはかなり異なっているようです。
案の定しっかり泥沼にはまってしまいました。

[第75回]

●USBのためのCPUクロック

前回はPIC18F14K50を使うことを前提にして、そうするとI/Oの数が不足してしまいますから、CPUとの間でのパラレル伝送を現行の8ビットから4ビットに変更するようにプログラムを変更して、とりあえずはまだPIC18F2550のままなのですが、その動作テストがうまくいきました、というところまで書きました。

昨年10月からおよそ半年をかけて、やっとPIC18F2550でUSB(HID)の送受信に成功するところまできたことでもありますし、スタートしたときはPIC18F4550だったのですがPIC18F4550からPIC18F2550へはほとんど変更らしい変更もなくすんなりできたのですけれど、ここからさらに、PIC18F2550からPIC18F14K50への変更を行うことにつきましては、いささか気が重かったのですねえ。

もともとPICをナニするということが本来の目的ではなかったわけですし、あんなこんなで予想だにしなかった泥沼につぐ泥沼に手足を取られていささかうんざりしてしまいましたから、もうこの辺でいいじゃないの、という気分になってきておりました。
そういう精神状態でありますから、なんとなく気が乗らなかったわけですけれど、半分はいやいやながらも、こうやって4ビットでのデータ伝送もできてしまいますと、せっかくここまできたのに、PIC18F14K50に全然タッチしないままで済ます、というのもちょいと惜しい、などという別の気の迷いも出て来てしまいます。

PIC18F2550に比べますと、PIC18F14K50は、第一印象としては、なんだかちょいとムリをしているような感じで、使うのにもなかなか骨が折れそう、といったところが気にはなりました。
で、まあ、とりあえず、ちょいとさわってみて、あまり納得がいかないようでしたら、やっぱりPIC18F2550を使うことにして、基板配線を工夫してなんとか28pinを乗せられるように考えることにいたしましょう。

すでに説明しましたようにPIC18F14K50はUSBメモリのアドレスと、そのメモリサイズがPIC18F2550とは全く異なっています。
しかしそれにつきましては、いうなれば機械的な変更作業でクリアできるはず、なのですから、当初からあまり問題視はしておりませんでした。

しかしながら、CPUクロック。
これはちょいと問題だなあ。
というわけで、まずは、そのあたりから、そろりそろりと首をつっこむことにいたしました。
まだいきなりUSBの本拠地には突入などいたしません。

とはいえ、もちろん、PIC18F14K50を使ってUSBをナニすることが目的ですから、そこのところをふまえた上で、まずはCPUクロックの説明から取りかかることにいたしまします。

USBを使わない、ということでしたなら、いまさらPICのクロックについてどうこう言うことはない、でありましょう。
それは18Fであっても、16Fであっても似たようなものなのです。
適当な値のクリスタルを外付けするだけで、簡単に動作してくれますし、クリスタルを外付けしなくても、内蔵の発振回路を使って自前でCPUクロックを供給してくれるものも多くなりました。
しかし、USBを使う、ということになりますと、今までのPICとはいきなり様子が異なってきてしまいます。

PIC18F2550については、[第58回]から[第63回]で簡単なプログラムについての説明をいたしました。
そこでは、USBを使わない、ごく普通のプログラムをPIC18F2550に書いての動作テストをしました。
[第58回]のテストでは外付けのクリスタルも不要な内部発振回路によるクロックを使いました。

内部発振回路とはいっても、なんと8MHzまでのクロックが選択でき、クロックの精度も通常の使用には差し支えない程度の精度はありますから、これはなかなかに便利です。
ということで、とりあえずの動作テストとしては、その内部発振回路によるクロックでよかったのですけれど、USBを使おうとしますと、残念ながらこのクロックでは動作させることができません。

PIC18F2550でUSBプログラムを実行させるためには、48MHzのクロックが必要になります(Full Speedモード)。
CPUそのものの動作としては48MHzものクロックは必要ないのですが、PIC18F2550に内蔵されているUSBロジック回路には、48MHzが必要なのです。

USB信号は12MHzです(Full Speedモード)から、その4倍の周波数ということになります。
PICはCPUクロックの4クロックが1マシンサイクルになっています。
PIC18F2550に内蔵されているUSBロジック回路もPICCPUと良く似たアーキテクチャで作られているのかも知れません。

それはともかくとして、12MHzならばなんとかなりますが、48MHzとなると、これは普通のTTLなどのはるかに及ばない高い周波数です。
このような高い周波数のクロックを外部から供給するとなると、もうのっけから敷居が高くなってしまいます。

幸いPIC18F2550のクロック回路にはPLL回路が内蔵されていて、低い周波数を供給しても、そこから48MHzを作り出してくれます。

そのあたりの設定はconfigワードで設定することになります。

●PIC18F2550のUSBのためのクロックの設定(DataSheetから)

PIC18F2550のData Sheetで、その説明を見てみることにいたしましょう。

[出典]Microchip社PIC18F2455/2550/4450/4550DataSheet

普通のPICと違って、USBを扱うためには、CPUクロックのほかに、USBのLow Speedモード(6MHz)とFull Speedモード(12MHz)の両方のクロックが必要になってきます。
PIC18F2455/2550/4450/4550は(いちいちこのように書くのは面倒ですから、以下はPIC18F2550とだけ書くことにしてしまいます)、USBのFull Speedモードに対応するために、48MHzのクロック回路を用意している、てなことが書いてあります。
PIC18F2550には12種の異なるクロックモードがあって、う?twelve?
でも1から10までしか書いてありません。2つ足りないじゃないの。
ここらあたりがMicrochipのDataSheetのチャランポランなところで、そもそもDataSheetに書いてある表現のままConfigに書いてもたいていはエラーになってしまうのですよねえ。
このOscillator Typeに関して言えば、Configにそのまま書いて通るのは”HS”だけです。

ちなみにインクルードファイルP18f2550.incを覗いてみますと。

;   Oscillator Selection bits:
;     FOSC = XT_XT         XT oscillator, XT used by USB
;     FOSC = XTPLL_XT      XT oscillator, PLL enabled, XT used by USB
;     FOSC = ECIO_EC       External clock, port function on RA6, EC used by USB
;     FOSC = EC_EC         External clock, CLKOUT on RA6, EC used by USB
;     FOSC = ECPLLIO_EC    External clock, PLL enabled, port function on RA6, EC used by USB
;     FOSC = ECPLL_EC      External clock, PLL enabled, CLKOUT on RA6, EC used by USB
;     FOSC = INTOSCIO_EC   Internal oscillator, port function on RA6, EC used by USB
;     FOSC = INTOSC_EC     Internal oscillator, CLKOUT on RA6, EC used by USB
;     FOSC = INTOSC_XT     Internal oscillator, XT used by USB
;     FOSC = INTOSC_HS     Internal oscillator, HS used by USB
;     FOSC = HS            HS oscillator, HS used by USB
;     FOSC = HSPLL_HS      HS oscillator, PLL enabled, HS used by USB
;

おお。ちゃんと12通りありました。
P18f2550.incは、MPLABをインストールしたときにできるMPASM Suiteフォルダにあります。

PIC18F2550ではUSBを使わない場合でも、上のいずれかのモードを設定する必要があります。
そこに書いてありますように、内蔵発振モード(Internal oscillator)を選択した場合には、それをそのままUSBソースクロックとして使うことはできません。
内蔵発振モードを選択しておいて、USBを使うためには、外部からUSB用にクロックを供給する(EC)か、クリスタルを外付け(XT、HS)しなければなりません。
そんな面倒なことをわざわざしますか、ねえ。

ということなので、USBを使う場合には、外部からクロックを供給するか、クリスタルを外付けするか、のいずれかとなります。

もしもUSBを使わない、ということでしたなら、そして外部からクロックを供給するか、クリスタルを外付けするということでしたなら、Configには上の中のEC、XT、HSを含む記述のいずれかを記載するだけで動作してくれます(本当はCPUDIVの設定が必要ですけれど)。
また同様にして、USBを使わないで内蔵発振モードを使う場合には、INTOSCを含む記述のいずれかをConfigに書いた上で、プログラムの中で、OSCCONレジスタに周波数パラメータを設定するだけで動作してくれます([第63回]のプログラムリスト参照)。

しかし、USBを使うためには、それだけでは足りません。
外部入力クロック、あるいは外付けするクリスタルの周波数によって、さらなるConfigの設定が必要です。


[出典]Microchip社PIC18F2455/2550/4450/4550DataSheet

TABLE2−3が外部入力クロックまたは外付けクリスタルの周波数とConfigの設定値を説明している表なのですが、これを見ただけでは、なんじゃこりゃあ、という感じです。
あ。この表はもう1ページ前の部分がありますが、ここでは省略してあります。
左のマスが入力周波数です。
省略した表は、48MHzと24MHzです。

最初私はこの表の意味するところが全く理解できませんでした。
USB(Full Speedモード)は48MHzが必要らしいということはわかりましたから、この表の右端の48MHzに該当する設定を選択しておりました。
たとえば4MHzのクリスタルを外付けした場合には、PLLDIV=’000’、FOSC=XTPLL、CPUDIV=’00’です。
これはとんでもない勘違いでしたが、むむ、説明が悪いのだ。

まあそれでもCPUは動くのですけれど、USBのためにはこのほかにUSBDIVというものも設定が必要です。
毎度のことなのですけれど、MicrochipのDataSheetはぎっしりてんこもりでボリュームはすごいものなのですけれど、それでいて肝心のことが書いてなかったり、どこを読めばよいのかさっぱりわからなかったり、ということがよくあって、いらいらさせられてしまいます。

表の下部のLegendも、あんた、いったい、何を言ってるの?という感じでいまいちよくわかりません。

実は、この表の前にある説明文と、さらにその数ページ前にある図(FIG2−1)をよーく眺めておりましたら、やっと意味がわかってきました。


[出典]Microchip社PIC18F2455/2550/4450/4550DataSheet


[出典]Microchip社PIC18F2455/2550/4450/4550DataSheet

ここではUSBのLow Speedモード(6MHz)とFull Speedモード(12MHz)を分けて考える必要があります。
そこが理解できないと、表の意味がわかりません。
表の下部のLegendはそのことを言っていたのです。
う?
LEGEND?
I AM LEGEND?????
伝説う?まさかねえ…。
Webの辞書の訳では伝説しか出てきませんでした。
CONCISEで引いてみましたら、図表の説明、凡例という意味もありました。納得。

図(FIG2−1)を見ましたら、PIC18F2550のUSBクロック供給回路にはシカケがあることがわかりました。
まずはFull Speed(12MHz)について、です。
外部または水晶発振から得られる周波数は最初のPLL Prescalerによって分周されて4MHzになります(4MHzにしなければなりません)。
その4MHzはPLL回路によって96MHzにアップされます(すごい!)。
そしてそれが2分周されてUSBのための48MHzになります。
一方、CPUに対しては、その96MHzがPLL Postscalerによって分周されて16、24、32、48MHzのいずれかの周波数として供給されます。
つまり入力されるもとのクロック周波数に対応するPLLプリスケーラの値を指定することのみによって必ず48MHzが供給されます。
USB(Full Speedモード)に対してはそれ以外の選択はありません。
そして同じソースを使う限り、CPUのクロックもまた、16、24、32、48MHzのいずれかに限定されます。

次に、Low Speed(6MHz)について。
上の説明によりますと、Low Speedモードに対してはシステムクロックを4分周した6MHzを供給する。と書いてあります。
Full SpeedモードではCPUクロックは16、24、32、48MHzのいずれを選択してもよかったのですが、Low SpeedモードではCPUクロックは24MHzに限定されます。
図(FIG2−1)で見ると、FSEN=0で選択されるフローが、Low Speedモードのようです。

ところが。
PIC18F2550のConfigには、FSENビットなんて無いのです。
どうなっているのでしょう。
これじゃLow Speedモードは使えませんですよねえ。
ま、私としては、Full Speedモードが使えればそれでよろしいのですけれど。

Configの設定に必要なパラメータで、さきほどお見せしましたFOSC以外のものを、またP18f2550.incから拾い出してみました。

;
;   PLL Prescaler Selection bits:
;     PLLDIV = 1           No prescale (4 MHz oscillator input drives PLL directly)
;     PLLDIV = 2           Divide by 2 (8 MHz oscillator input)
;     PLLDIV = 3           Divide by 3 (12 MHz oscillator input)
;     PLLDIV = 4           Divide by 4 (16 MHz oscillator input)
;     PLLDIV = 5           Divide by 5 (20 MHz oscillator input)
;     PLLDIV = 6           Divide by 6 (24 MHz oscillator input)
;     PLLDIV = 10          Divide by 10 (40 MHz oscillator input)
;     PLLDIV = 12          Divide by 12 (48 MHz oscillator input)
;
;   CPU System Clock Postscaler:
;     CPUDIV = OSC1_PLL2   [OSC1/OSC2 Src: /1][96 MHz PLL Src: /2]
;     CPUDIV = OSC2_PLL3   [OSC1/OSC2 Src: /2][96 MHz PLL Src: /3]
;     CPUDIV = OSC3_PLL4   [OSC1/OSC2 Src: /3][96 MHz PLL Src: /4]
;     CPUDIV = OSC4_PLL6   [OSC1/OSC2 Src: /4][96 MHz PLL Src: /6]
;
;   USB Clock Selection bit (used in Full Speed USB mode only; UCFG:FSEN = 1):
;     USBDIV = 1           USB clock source comes directly from the primary oscillator block with no postscale
;     USBDIV = 2           USB clock source comes from the 96 MHz PLL divided by 2
;

●PIC18F2550のテストプログラム

以上を整理したうえで、また簡単なテストプログラム書いてみました。
[第59回]のプログラム([第63回]で少し手直し)と同じものですが、Configの設定を変更してあります。
前回は内部発振クロックの8MHzを使いました。
今回は4MHzクリスタルを外につけて、CPUクロックは48MHzを指定しました。
もとのプログラムでは外部MCLRをOFFにしましたが、それはPIN数の少ないPIC18F14K50の使用を考えたためでした。
しかしそれだけではどの道足りないことがわかってCPUとの間のデータ伝送を4ビットに変更することにしたことと、その後のいろいろなテストの過程でやはり外部からリセットをかける必要が出てきたことから、今回のテストではMCLR端子には外部プルアップ抵抗をつけて、ごく一般的な回路として使用することにしました。
そのため、前回のプログラムではConfigで指定していたMCLRE=OFFは外しました。

;;;pic p18f2550 test program
;f2550test3
;4/25 5/18
;
	#include<p18f2550.inc>
;
;cpuclock=48MHz 4MHz crystal
;
	CONFIG PLLDIV=1,USBDIV=2,CPUDIV=OSC1_PLL2,FOSC = XTPLL_XT,WDT=OFF,LVP=OFF          
;
	org 00
st0
	movlw 0f
	movwf ADCON1;porta,b,e are digital
	movlw 0;porta-c are output
	movwf TRISA
	movwf TRISB
	movwf TRISC
;
	movlw 1
loop
	xorwf PORTA
	goto loop
;
	end

今回のテストに使った基板です。

[第59回]の基板に4MHzクリスタルとプルアップ抵抗を追加してあります。

こちらは基板の裏側です。


プログラムを実行中のRA0からの出力波形です。

[第59回]の波形と比べてみてください。
PORTAのビット0は3マシンクロックごとに1と0が反転して出力されます。
外付けしたクリスタルは4MHzですがPLL回路によって、CPUクロックは48MHzになっているはずです。
ということは1クロックが1/48μsecということです。
PICの1マシンクロックは4CPUクロックですから、1/12μsecです。
そしてその3マシンクロックは、1/4μsecになります。
250nsecです。
おお。間違いなく48MHzで動作しています。
正直言って、これはすごい。ちょいと感動、です。
CPUをつくろう!第502回(2010.5.19upload)を再編集

PICでUSBを![第75回]
2011.7.12upload

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