PSoCをはじめよう
by K.I
2005/01/01? 〜
Index
- PastelMagicの桑野さんの本、「はじめてのPSoC」が出た。やっぱり紙になってると良いね。
- 最近はサーバの設定に嵌まって電気工作やってなかった。→やっぱり半田ゴテ握らないとダメだな。
- すっかり忘れちゃってるので、「はじめてのPSoC」を見ながら再スタートします。
[top]
- インベンションボード上のCY8C27443を使った方が簡単で良いんだけど、今度は手持ちのCY8C27443を単体で動かしたいので、PSoCライタを用意しよう。
- って言っても、インベンションボードはPSoCライタの機能も持ってるので、5ピンのヘッダを立てるだけだ。
→10Pのフラットケーブルの片側だけ使って接続する。
- PSoC Invention Board Programmerを立ち上げて、
- Externalをチェックする → Connectのチェックが外れる
- 再度、Connectをチェックする。→ここで、PSoC missingと出る場合は配線を確認!
- FileOpenで、HEXファイル或はROMファイルを読み込み
- Programで、書き込み →Inventionボード上のLED(D2)が点灯
- 書き込みが終わったら、Connectのチェックを外すと、そのまま動作確認できる1。
- 書き込みに使用するport1-0とport1-1を使わないようにすれば、ライタを繋いだままでデバック出来るから凄く便利だ。
- もちろん、InventionボードにはPSoCが載ってるから、Externalをチェックしなければ、そのまま書込み可能だ。
1実は以前はこれを知らなかったので、いちいちUSBケーブル抜いてました。。。
[top]
- はじめてのPSoCの回路を真似して、Port0にいろいろ繋げられるようにヘッダを立てることにした。
- 同じ回路にしとけばサンプルプログラムもそのまま動くし、なんてズルイことを考えました。
- で、以下のような実験基板にしました。
→訂正:本当は水晶の両端に付いてる容量はVcc側に接続します。
- LM35はないので、LM45を繋ぐことにして。
- これで、はじめてのPSoCの1章〜5章まで対応?だ。
- 外部発振用に水晶付けることを考えているが、付いてても書き込めるのかな?→とりあえず最初は無しでやってみよう。
- こう書くと、もしかすると実験基板は絶対必要と思っちゃうといけないので、一応書いておきます。
- インベンションボードを手に入れた場合は、実験基板を作らなくてもブレッドボードで配線しても、ぜんぜんOKだと思う。
- いろいろ試す場合は、逆にブレッドボードの方が良い。
- 特に最初のLED点滅ぐらいは、ブレッドボードで作ってみると、PSoCの簡便性をより感じられるかもしれない。
[top]
- 作成した実験基板で、はじめてのPSoCのサンプルを、ざっと試してみた。
- 一応、復習を兼ねてちゃんとデザイナーを起動してPWM16を配置、配線。
- グローバルリソース、PWM16_1,2を設定
- プログラムで、PWM16_1,2をスタートさせて
- すんなり動きました。実験基板の配線は大丈夫だな。
- しかし、ソースのコメントが化けてるのは何故かな?フォント変えてもダメだし。
- うーん、これは自分の環境の問題かな?多分Sambaのサーバにソース入れたからか?
- CDROMのサンプルをコピーしてコンパイルのみしました。(手抜き)
- LEDを正弦波でドライブしたから何だと思ってましたが、やってみると結構ふわっと光るのがいい感じです。
- この章は、BPFの設計が肝みたい。これは、PSoC Designerと一緒にインストールされるExcelファイルで計算出来る。
- このBPFの定数だと、中心周波数の50×4倍のクロックをSCFに与えれば良い。
- 言いかえれば、クロックを変えるだけでBPFの中心周波数を可変出来る。
- この章はデジタル入出力と割り込みの説明。以前は結構苦労したけど。
- でも今回は手抜きしてサンプルをコピー。→あれ、でもSW2しか効かないなぁ。
- 何故か、割り込みベクタの設定がなかったので、boot.asmのGPIOインタラプトで、ljmp _isr_pioを追加して動作するようになった。
- LM35が無いので、手持ちの LM45を接続する。
- カタログスペックも、ほとんど同じみたいだから、そのまま動くだろう。
- とりあえず、簡単に動作した。
- 手で暖めると、ちゃんと温度が上昇するのが分かる。うーん、このバーグラフは なかなか良いなぁ。
- この章は、AD変換とLCD表示が肝心かな。AD変換は後でちゃんと理解しよう。
- SCFだから細かい段々はあるけど、きれいな正弦波や三角波が出ている。
- この章は正弦波ドライブの応用かな。
- これは周波数を変えてもBPFの定数はそのままで、常に200倍のクロックをSCFに与えるだけ。やっぱりこれって凄いよね。
- この回路はいろいろ応用出来そうな感じがする。
- この回路は、周波数設定をもうちょっと細かくとれるようにすれば、実験用オシレータとして実用的に使えそうだ。
- 一気に5章までのサンプルを作ってみて、あらためてPSoCの能力と使いやすさを感じることが出来た。
- サンプルの回路は配線を極力少なく考えられており、またそのほとんどが共通なので、実験基板が作り易いのが有難い。
- サンプルは、すぐ試せるものばかりだし、すぐ応用出来そうな回路もある。PSoCの入門に持っていて損はないと思う。
- 欲を言えば、機能別に説明されたリファレンス的な本も欲しいかも。
[top]
- サンプルだけ動かしていてもつまらないので、いろいろやってみよう。
- ということで、以前、秋月で買ったロータリーエンコーダを使ってみよう。
- プルアップしておいて、スイッチが入った時にGNDに落ちるように接続すれば、以下のように動作する。
- まぁ単にスイッチが2つ入っていて、タイミングをずらしてスイッチがONになるだけっていう感じだ。
- 自分が買ったものは、クリック感があって↓の状態でしか停止しない。→通常は、スイッチが両方切れた状態だ。
- ひょっとすると、テストオシレータの回路でそのまま動作しないだろうか?
- やってみましたが、どちらに回しても全然動かない。これは、まぁしょうが無いよね。
- 実はロータリーエンコーダは、最初うまく動作しなかった。つまらない失敗だったけど反省のために、記録。。。
- いくら考えても全く分からないので、半信半疑でロータリースイッチの信号を調べてみることにした。
- あぁ、何だこれ。何でこんな信号なんだろう。ちょっと壊れてるのかなぁ。
- 2つのスイッチが、ほぼ同時に変化してるから、波形が分かっていても安定して動作させることが出来ない。1つのスイッチだけにチャタが入るなら考え易いんだけど。。。
あぁ、勘違い
- いろんな方法で、やってみたんだけど、やっぱり安定動作にならない。
- この際、ディレイでも付けるかと思ったけど、秋月のキットではちゃんと動作してるんだよなぁ。どうしてるんだろ。
- そんなこんなで、部品箱をごそごそ探していると、ロータリーエンコーダのデータシートが出てきた。
- 実はデータシートが見付からなかったので、適当に調べて中心がCommonと判断して接続していたんだけど。。。あれ、Commonが中心じゃない。。。
- 結局、後ろからみてALPHAと書いてあるその下のピンが、左からC,B,A(CがCommon)でした。
- CをCommonにすると、嘘のように安定して動くようになった。うーん、またやったか。。。
- テストオシレータは、元々タイマ割込みでスイッチを読み込んでいる。
- このままでも動きそうなんだけど、ロータリーエンコーダだと、スイッチが同時にONになるために動かないようだ。
- だから、もう片方のスイッチがOFF状態であることを確認するだけ2で動くようになる。
cfreq = 0;
set_freq(cfreq);
psw = pdat;
while(1) {
csw = pdat; // スイッチ情報取得
onsw = ((psw ^ csw) & ~csw); // '1'から'0'に変化したものを抽出s
psw = csw;
if (onsw & (SW_UP | SW_DOWN)) { // UP/DOWNスイッチのいずれかが押された
if ((onsw & SW_UP) && (csw & SW_DOWN)) {
cfreq = (cfreq+1) % NUM_FREQ; // count up!
}
if ((onsw & SW_DOWN) && (csw & SW_UP)) {
cfreq = (cfreq-1+ NUM_FREQ) % NUM_FREQ; // count down!
}
set_freq(cfreq);
}
}
- 結構安定して動作する。当然タクトスイッチでも、ちゃんと動作する。
cfreq = 0;
set_freq(cfreq);
psw = 0xff;
while(1) {
csw = PRT0DR; // get current SW
if ((csw & SW_UP) && (csw & SW_DOWN)) { // current SW all off?
if ((~psw & SW_UP) || (~psw & SW_DOWN)) {
if (~psw & SW_UP) { // past SW_UP on?
cfreq = (cfreq+1) % NUM_FREQ; // count up!
}
if (~psw & SW_DOWN) { // past SW_DOWN on?
cfreq = (cfreq-1+ NUM_FREQ) % NUM_FREQ; // count down!
}
set_freq(cfreq);
}
}
psw = csw; // save past SW
}
- とりあえず動作した。タクトスイッチでもちゃんと動作する。
- 手抜きでチャタ処理はせず、LCD出力に時間が掛かるので、それで誤魔化す。→早く回すと追従しないけど。。。
- やはり、チャタ処理は必要かな。でも、ディレイ付け過ぎると、早く回した時にうまく反応しなくなりそう。
- やっぱりロータリースイッチからの割り込みで動作させた方が良いだろうか?
- それぞれのスイッチの立ち下がり(或は立上り)時に割り込みが掛かるようにして、もう一方のスイッチの状態によりUp/Downを判断すれば良いかな。
- タクトスイッチと兼用にしないならば、割り込みはどちらかのスイッチだけでも大丈夫かもしれない。
- set_freq内で、LCD表示せずmainで表示するようにして3、以下のようにI/O割り込みで動かしてみる。
#pragma interrupt_handler PSoC_GPIO_ISR() →boot.asmにも割込みベクタが必要
void PSoC_GPIO_ISR()
{
unsigned char cdat;
cdat = PRT0DR;
if ((~cdat & SW_DOWN) && (cdat & SW_UP)) {
cfreq = (cfreq-1+ NUM_FREQ) % NUM_FREQ; // count down!
}
if ((~cdat & SW_UP) && (cdat & SW_DOWN)) {
cfreq = (cfreq+1) % NUM_FREQ; // count up!
}
set_freq(cfreq);
}
:
略
:
INT_MSK0=INT_MSK0_GPIO; // I/O割込み許可
- これは割込みなしよりはマシだが、いまいち安定じゃない。
- ロータリーエンコーダはI/O割込みで動かすのが良いと思っていたんだけど、実際にやってみると、この方法は、ちょっと欠点がありそうだ。
- スイッチのチャタがあるから、割込み後にある程度のディレイをおいて、再確認する必要がありそう。
- だけど、ディレイはCPU時間の無駄だし、それならタイマ割込みの方がスマートだよね。
- 結局、元々のオリジナルのタイマ割込みが一番良さそう。
2if文以外は、オリジナルのままです。カウントUPDOWNのやり方は自分流に書き換えたけど。まぁ意味なし。
3LCD表示は時間が掛かるから、速く回した時に、追い付かなくなる。
[top]
- PICだと、最初にコンフィグレーションレジスタに発振回路の選択を書き込むだけなので簡単に考えていた。
- でもPSoCの場合は、発振回路も動的に切替えられるようだ。そのためにちょっと手順が必要らしい。
- 英文マニュアルを読んで、自分なりに理解したこと。(間違ってるかも)
- 通常、ILO(Internal Low speed Oscillator)→32kHzが動作している。
- IMO(Internal Main Oscillator)→24MHzは、ILOにLockさせることが出来る?
- ECO(32kHz Crystal Oscillator)で、外部に32kHzの水晶を繋ぐだけで発振出来る。
- ILOで起動後にECOに切替える。ECOでIMOをPLLでLockさせることが出来る。
- 起動時は、ILOで動作を開始する。
- ECO_EXビットをセットして、外部に水晶が接続されていることを指定。
- OSC_CR0のSleep時間の設定
- OSC_CR0の32kSelectビットをセット
- 3で設定したスリープ時間で、外部水晶発振回路が動作を開始して切り替わる。スリープの間は、ILOも動き続ける。
- PLLモードの場合は、IMOがロックするまで待つようにする。
- 5,6は、自信が無い(というかもっと詳しく書いてあったけど良く分からなかった)けど、おおよそは合ってるかな?
- XtalIN(P1[1])-XtalOUT(P1[0])に32kHzの水晶を繋ぐ。
- PLLを使わない場合は、それぞれ3.5pFの容量を接続。(28PDIPの場合)
- PLLを使う場合は、それぞ12pF,100pFの容量を接続。→現状は、10pF,100pFを接続
AN2027には、他にもいろいろ書いてあるので、良く読んだ方が良さそうだ。
- で、配線してみたけど。水晶繋がってると書き込み出来ないじゃん。→心配だったんだけど、やはりconnect出来ない。
- それで、切り離せるようにヘッダピンに付けてみたけど、今度は繋いだままでも書けるようになった。何か間違えたのか、気のせいだったのかな?
AN2014をみると、とりあえずは、水晶を接続したままでも書き込めそうな気がする。→いや、実際書き込めてるんですが。
- また、テストオシレータの回路で、試してみることにした。
- 手順からすれば、以下のように設定しなければならないと思うけど、
CPU_SCR1 |= 0x04; // ECO_Ex
OSC_CR0 |= 0x40; // PLL_Mode
OSC_CR0 |= 0x80; // 32K_Select
- PSoCデザイナで設定すれば、そんなことしなくても良いみたい。
Global Resource |
32K_Select | External |
PLL_Mode | Ext Lock |
- ECO_Exは、32K_SelectをExternalにすると、自動的に設定されるようだ。(たぶん)
- 発振が安定してからECOに切替えるための、SleepTimerの設定も自動的にやるみたいだ(これもたぶん)
- IMOはPLLでロックしないと多分正確にならないと思うので、Ext_Lockとする。
- X'talの接続されている端子は以下のように設定。
Port | Select | Drive |
P1[0] | XtalOut | High Z |
P1[1] | XtalIn | High Z |
- しかしテストオシレータの周波数をみると不正確(約15%ズレてる)なままなので、発振はしていないみたいだ。
- 発振していないのでは無く、Lockしていないだけか?
- PLL_ModeをDisableにすると、テストオシレータの周波数が正確(1%程度)になる。
- なぜPLLがOFFなのに、出力が正確になるのかなぁ?→もしOFFで良いならPLLの意味は?
- 8C25KDataSheetの ClockTreeをみると4、やはりPLLでLockしないと意味が無い気がする。
- PRT1DRのピンをHにしてVccに繋ぐ(Provide a Local Bypass)は必須なのかなぁ。→設定間違えると壊すかも。。
- 発振回路への電源のインピーダンスを下げる意味があるんだろうけど、結構トリッキーなやり方だよね。
- でも試しでも、こんなのやりたくないなぁ。もし間違えて、Lを出力したら。。。
- 最初は見逃していたけど、CY8C27XXXのpdfにもクロック系統の図があった。
- でも、これを見てもいまいち分からない。というか疑問に思うことが多い。
- ILOではPLLロック出来ないみたいだけど、それじゃILOはシステムクロックと同期していないのかなぁ。
- ・TCLKって何?
- そもそも、この図の32kHzのClock出力って、何処で使うの?
- PLLロック掛けない場合でも、何らかの方法で同期を取ってるんだろうか?
- 多分 SYSCLKが24MHzで、SYSCLKX2が48MHzってことだと 思うんだけど。。
- それなら何で、この図では接続して描かれていないんだろう。。。
- もしかすると、PSoCデザイナの設定では出来ないような接続が存在するのかなぁ。
- 試しに32kHzの水晶の代わりに40kHzの水晶を繋いでみる。
- 予想ではテストオシレータの設定周波数が、その分大きくなるんじゃないかな→SystemClockによって周波数が決まるはずなので。
- 本当は、ほんの少しだけ周波数の違う水晶があるといいんだけど。。
- 32kHz用の発振回路だから、うまく発振するかどうか分からないが、何か変化するだろう。
- テストオシレータの出力周波数を調べてみた。
- でも、40kHzの水晶を付けても、32kHzと同じ気がする。じゃ、水晶なしだったら、、、あれ。。
- 32k_SelectとPLL_modeの設定と、水晶の組合せを調べ直してみた。
- →テストオシレータの出力を10kHzに設定した場合の出力周波数。
32k_Select | PLL_mode | 32kHz水晶 | 40kHz水晶 | 水晶なし |
External | Ext_Lock | 8.51kHz | 8.51kHz | 8.51kHz |
| Disable | 10.05kHz | 10.05kHz | 10.04kHz |
| | | | |
Internal | Ext_Lock | 8.51kHz | 8.51kHz | 8.51kHz |
| Disable | 10.04kHz | 10.04kHz | 10.05kHz |
- PLL_modeの設定によって変化するだけで、他の設定や水晶は無関係。。。
- PLL_modeがdisableの場合は、PSoCのトリミングデータが使われるから、ある程度正確になる。
- PLL_modeがExt_Lockの場合は、外部発振に依存するのでトリミングデータは使われなくなる。
- しかし現状は外部発振出来ていないので、ILOからECOへの切替えがされず、トリミングされないILOの精度で出力されている。ってことかな。。
- 水晶発振の接続自体は簡単なので、間違いなさそうなんだけど、、、
- ここまで書いてみて、ちょっと大事なことに気が付いた。
32k_Select | PLL_mode | 32kHz水晶 | 40kHz水晶 | 水晶なし |
External | Ext_Lock | 9.98〜10.02kHz | 12.20〜12.23kHz | 8.92〜9.07kHz |
| Disable | 10.08kHz | 10.07kHz | 10.08kHz |
| | | | |
Internal | Ext_Lock | 8.53kHz | 8.54kHz | 8.54kHz |
| Disable | 10.08kHz | 10.08kHz | 10.08kHz |
- なるほど、32k_Select→External、PLL_mode→Ext_Lockで良いみたいだ。
- 周波数の変動が少しあるけど、如何にもPLL動作している感じだ。
- 秋月のテスターに付いてる周波数カウンタなので、あまり正確じゃないかもしれないけど。
- 何故ダメだったかというと、Inventionボード経由で電源を供給していたので、発振回路にInventionボードがぶら下がったままでした。
- これじゃ、発振するわけないよねぇ。。。こんな失敗は普通しないか。。
- ACアダプタで電源を加えて、Inventionボードを外せば大丈夫でした。
- AN2027には、32k_Select→Internal、PLL_mode→Ext_Lockはinvalid configurationって書いてある5。
- 実質上、以下の2通りの選択ということになりそうだ。
- 32k_Select→Internal、PLL_mode→Disableで、ILOによる内部発振
- 32k_Select→External、PLL_mode→Ext_Lockの、ECOによる外部発振
4古い仕様の方が読み易いんじゃないかなぁ。新しい仕様は回りくどい書き方のような。。。
5じゃ、32k_Select→external、PLL_mode→Disableは意味あるのかなぁ。
[top]
[電子工作関連に戻る]