PSoCを使ってみよう
by K.I
2004/06/01 〜
Index
- CypressのPSoCを使ってみる。気の向いた時だけやるから、なかなか進まないかも。
- これはワンチップマイコンだが、アナログのモジュールがいろいろ載っていて組み合わせて使えるらしい。良く分かんないが、面白そうだと思っていたけど、なかなか手が出なかった。
- PastelMagicに丁寧な 解説があったのと、書き込み用のファームを焼いた石を安く販売していたので、早速注文してみた。
- もっと早く見つけてれば良かったなぁ。ミニディベロップメントキットは、品切れだった。トラ技の記事をちょっと見た時はとっつきにくそうと感じたので、出遅れちゃったなぁ。
- PSoC Designerは Cypressから落したVer4.1をインストールしてあったので、インベンションセット附属のCD-ROMのInvention Board Programmerのみインストールした。
[top]
- PastelMagicの桑野さんが、おまけで基板を送ってくれていた。これはファームが違うみたいでInvention_Boardとしては使えない。差替えすれば動くようだが、パッケージもピン配置も全然違うし、ちょっと難しそうだ。とりあえず、これはとっておいて別に基板を作成することにする。
- 使えなくても実際の基板をみるとやる気が出てくる。部品取り用としては、ちょっともったい感じがする。
- それにしてもUSBのmini-Bのコネクタは小さくて良い1なぁ。
- PastelMagicで購入した28pinのCY8C27443限定の開発キットのファームで、互換基板を作成する。
- 開発用キットのファームが焼いてある64013は、SOICとPDIPで全然ピン配置が違っている。それに配線が結構省略されていてなんか分かり難いので、PDIP用に書き直してみた。
- 改めて見てみると必要な配線は結構少ない。これならブレッドボードでも十分組めそうだ。
- でもUSBのコネクタ等の配線が面倒なので、結局ユニバーサルボードに適当に配線することにした。
- 6MHzの水晶は、秋月の通販で見つからなかった。仕方がないので6MHzのセラロックを注文した。一応は発振はするんじゃないかなぁ。多分。。。
- 部品を集めて配線も終わったので、 PastelMagicの解説を見ながら、その通りにやってみた。
- ここで紹介されているものは、内蔵OSCを256分周したクロックを作り、2つのPWMモジュールを繋いでLEDを点灯させるというものだ。
- 難しい感じがしていたけど、やってみると案外簡単だった。迷いそうなところをちゃんと解説してあるので、全然迷わないで済んだ。
- 配線はしてあるんだから、何もプログラムは必要なさそうにも思うんだけど、デフォルトでは、各モジュールはOFF状態になっているらしい。
- このプログラムは単に割り込みしないようにしてから、モジュールを起動しているだけみたいだ。
- Invention Board Programmerを起動して、hexファイルを読み込み、プログラムしてみた。そしたらチェックsumがfailになって、書き込みに失敗したようだ。
Programming Failed, checksums do not match
CheckSum=0000 Buffer=5F6F
がっかりしたけど、一応USBケーブルを抜き差ししてみると、LEDがちゃんと点滅している。もう一度、Programmerを起動して書き直すと今度はエラーは出なかった。
- とりあえずは、InventionBoardは動作しているようだ。セラロックでも何とかなったみたい。そのままやっただけなんだけど、一発で動いて良かった2なぁ。
- 何回か書き直してみたが、4〜5回に1回は書き込み時にfailが出るようだ。多分セラロックを使ってる所為だろうなー。でもエラーが出ても実際には書き込まれているみたいなので、よしとする。6MHzの水晶を手に入れたら、ちゃんと入れ換えよう。
- PSoCデザイナはとっつきにくい感じだけど、やってみると案外分かり易い。
- モジュールの接続や配線は、自由自在というわけじゃないみたいなので、PSoCの構造に慣れないとなかなか使いこなせない気がする。
- でもワンチップマイコンとして考えれば、性能的には悪くない。それに加えていろいろ使えるんだから凄いなぁ。
- 自分でプログラムするためには、まずM8のアーキテクチャを知ることが必要かな。
- やっとPICに慣れてきたとこだけど、ちょっとやってみるかなぁ。。
- インベンションセットのSOIC版が出たので、それも手に入れて換装してみた。
- ピンヘッダが邪魔で、CY7C64013を外すのはちょっと面倒だった。→ちょっと無理矢理やって、2箇所程パターンが剥がれちゃった。
- 半田付けも半田を付け過ぎたけど、狭くて吸い取り器が使い難くてまいった。
- とりあえずチュートリアルは動いた。何とか換装成功かな。やっぱりモジュールになってるとブレッドボードが使えて楽に配線出来るなぁ。
- でも、SOIC版にまた基板が付いてきた。うーん、またSOIC版のファームを買って入れ換えたくなるなぁ。キリが無いから、やらないけど。。。
1欲しくて探してみたけど売ってるところは少ない。Digi-Keyだと買えそうだけど手数料とか送料が高い。
2新しいことをやると大概はうまく行かないので、簡単に諦めてしまうことが多い。うまく行くと調子にのって失敗することもあるけど。。。
[top]
- Compiler keyを入れて、Cも使えることを確認した。
- とりあえずPICでやってることと同じことをやってみようかな3。
- 早速、LCDユーザーモジュールを使ってみることにした。秋月のLCDモジュールと同じタイプ用なのが嬉しい。
- LCDモジュールはピン配置は大体決まっているんだけど、使うポートは選べるので、Port1を使うことにして、適当にごにょごにょ配線する。
- IC_SDATAとIC_SCLKと干渉すると嫌なので、LCDのD4とD5には1kの抵抗をかますことにした。
- プログラムは、LCDモジュールのExampleをそのまんま使わせてもらう。
char str[ ] = "User Module"; // Define "RAM" based string
LCD_1_Start(); // Initialize LCD hardware
LCD_1_Position(0,4); // Position cursor @ row 0, col 4
LCD_1_PrCString("PsoC LCD"); // Print a constant "ROM" string
LCD_1_Position(1,2); // Position cursor @ row 1, col 2
LCD_1_PrString(str); // Print "RAM" based string.
- で、あっさり表示出来た。まぁ、PICで使い慣れてるということもあるけど。
- これはソフトモジュールなので、PSoCのモジュールは一切使っていないんだけど、部品を置いただけみたいなイメージで簡単に出来た。
- PICだってCで書けば同じなんだけど、モジュールになっていることで、ちょっとだけ電子ブロック感覚になるから不思議だ。
- FlashTempモジュールを使ってみる。でも、ちょっといまいち。
- コンパイルは通るんだけど、動かしても何故かFlashTemp_fIsDataがtrueにならない。使い方が間違ってるのかなぁ。
- FlashTemp_Start以外に、なにか設定が必要なのかな?
- FlashTempのデータシートにあるサンプルでは、どうしてもflsDataがtrueにならない。
- スタートしてから、flsDataが1になるまで待つ事にすることで、とりあえずデータが読めるようにはなった。→でも、いまいちFlashTempの読み方が分からない。こんなんで良いのか?
#include <m8c.h> // part specific constants and macros
#include "PSoCAPI.h" // PSoC API definitions for all User Modules
void main()
{
char i;
char t;
M8C_EnableGInt; //これは必要なのか?
LCD_1_Start();
LCD_1_Position(0,4);
LCD_1_PrCString("PSoC test");
LCD_1_Position(1,2);
LCD_1_PrCString("FlashTemp");
FlashTemp_1_Start(); //スタートさせる
while (TRUE) {
if (FlashTemp_1_fIsData()) { //flsDataが1になるまで待つ
t = FlashTemp_1_cGetData(); //データ取り込み
if (!i++) { //表示が速過ぎるので
LCD_1_Position(1,12);
LCD_1_PrHexInt(t); //256回に1回だけ表示
}
FlashTemp_1_Start(); //またスタートする
}
}
}
- 値は取れるものの、同じぐらいの値を繰り返しているだけ。手で温めても変化する感じが全く無い。。。
Parameter | Value | Min | Max |
Column Clock | 24M/16/2=750k | 125k | 960k |
(VC2) | 24M/16/4=375k | | |
| 24M/16/8=187.5k | | |
| | | |
Sample Rate | 375k/255/4=368 | | 900sps |
- クロックを変えても、あまり変化無い。
- 750kだと、0x1E,0x1B,0x17を繰返し
- 187.5kだと、ずーっと0x10のまま、時々0x14,0x17になる。
Global Resource |
CPU clock | 24MHz(SysClk/1) |
32K_Select | Internal |
PLL_Mode | Diable |
Sleep_Timer | 512_Hz |
VC1=SysClk/N | 16 |
VC2=VC1/N | 8 |
VC3 Source | SysClk/1 |
VC3 Divider | 1 |
SysClk Source | Internal 24_MHz |
SysClk*2 Disable | No |
Analog Power | SC On/Ref Low |
Ref MUX | (Vdd/2) ± BandGap |
| (2 BandGap) ± BandGap |
| |
AGndBypass | Disable |
Op-Amp Bias | Low |
A_Buff_Power | Low |
SwitchModePump | OFF |
Trip Voltage(LVD(SMP)) | 4.64V(5.00V) |
LVD Throttle Back | Disable |
Supply Voltage | 5.0V |
Watchdog Enable | Disable |
- 何か足りないのかな? 何か勘違いしていることがあるのかなぁ。
- と、悩んでいたら、PastelMagicの桑野さんから温度センサを使った例をもらいました。
- 基本的なやりかたは間違っていない気がする。
- 違うのは、ディレイを挟んでいることかなぁ。
- でも、ポート0をシフトさせてるのは何なんだろう。
- いずれにしても、シリアルポートで接続出来るようにして、試してみたい。
- まず、動く状態から始めないと、どうも良く分からないので。(シリアル通信に続く)
- 桑野さんからもらったプロジェクトには、UARTモジュールが使ってあったので、この際なので、シリアル通信も試してみる事にした。
- RS-232Cをドライブするトランシーバチップを挟んだだけです。
- ハーフピッチのユニバーサルボードを使ってみたんだけど、配線し難くて疲れた〜。もうハーフピッチのユニバーサルはやりたくないなぁ。
- HyperTerminalを接続すると、データが送られてくるのが確認出来た。
- 値としては、自分で試したのと、大きな違いは無いような気がする。→やはり手で暖めたぐらいじゃ、ほとんど変化しない?
- やはり、同じような値を繰り返しているような感じだ。どうして10、14、17、1B、1Eっていうような離散的なデータだけが出てくるんだろ。→シリアル通信だと、表示でどんな風にデータが繰り返されるかが一目瞭然なのが良いなぁ。
- 半田ごてを近づけて暫くすると、22ぐらいまで上がった。いまいち信用出来ないんだけど、これで良いのかなぁ。。。
- 正確な温度を取るためには、まだ何か必要みたいだ。
- と思っていましたが、良くデータシートを見ると、Resolutionは3.3℃になってる。。。
- そういう目でPDIPの方でも追試してみましたが、同様の結果でした。温度が変わらなかったのは、変化させるためには少なくとも3.3℃温度を上げる必要があることと、ちょっと触り難い構造だったのが原因みたい。。。
- でも3.3℃という仕様はちょっと粗過ぎるような気がする。→多分精度があまりとれないからなんだろうけど。
- ということで、貰い物ですが、とりあえずはシリアル通信も確認出来ました。
- 離散的な数値を返すことから、摂氏のデータを返すと一応納得したものの、零下になるとどうなるか追試してみました。
- ビニール袋に氷と塩を入れたものを当てると、数値がFF,FC,F8,F5と下がっていき、氷の当て方をいろいろ変えると、最大でF1まで下がりました。これで-15℃ですね。
- 理論的には塩と氷で-21℃まで下がるみたいですが、まぁ良い線までいってるんじゃないかなーと思います。
- PDIPの方もやりたかったんだけど、LCDの下にあるんで、氷を当てることが出来なかった。。。
- I2Cのハードモジュールは、ポート1の5,7か、0,1にしか割り当てられない。LCDをポート1に割り当てたのは失敗だったかも。→ソフトモジュールだったら大丈夫なので、そちらで試すか。。。
- 秋月のリアルタイムクロックモジュールRTC-8564NBを繋いでみる→とりあえずInventionBoardの方で
- ちゃんと設定するのは面倒。なんか簡単に確認出来ないかなぁ。仕様を眺めてみると、CLKOUTという端子に1Hzを出す事が出来そうだ。
- I2Cは、マスターがスタートコンディッションを出してから、ストップコンディッションを出すまで、バスを占有するような仕様かぁ。。。(トラ技の2000年8月号を見ながら)
- スタートして、スレーブアドレス→レジスタアドレス→コマンドと書き込んでから、ストップを発行すれば良さそうだ。
- RTC-8564のスレーブアドレスは1010001だが、これは0x51かな?それともR/Wビットを付けて0xA2と指定すべきなのかなぁ。
- CLKOUTのレジスタアドレスは、0x0D
- 1Hz出力のコマンドは、0x83
#include <m8c.h> // part specific constants and macros
#include "PSoCAPI.h" // PSoC API definitions for all User Modules
BYTE rxBuf[8];
const BYTE txCBuf[] = { 0x0D, // Register-address 0x0D
0x83 }; // CLKOUT frequency 1Hz
void main()
{
BYTE status; // I2C communication status
I2Cm_1_Start(); // Initialize I2C Master interface
// Set CLKOUT frequency 1Hz (Slave-address 0x51)
status = I2Cm_1_bWriteCBytes(0x51,txCBuf,2,I2Cm_1_CompleteXfer);
I2Cm_1_SendStop();
}
- 案ずるより生むが易し。1Hzの点滅を確認。→まぁ、これ以上無いぐらい単純なプログラムだから、動くのは当たり前か。スレーブアドレスは、0x51でした。
- LCDモジュールって、5Vじゃないと動かないけど、PSoCのSMPが使えないだろうか?
- 仕様をみると、5Vで5mAぐらいしか取れないけど、どうなのかなぁ。
PSoCならPWMモジュールとTr1個でも出来そうだけど、やっぱり専用の端子があって簡単に出来るのは良いなぁ。
- まず、LCDのバックライトをOFFにする。
- PSoC Designerで、とりあえずSMPをONにして、2.2uHとショットキ繋いで、3Vでやってみたけど、3Vしか出ない。何故なんだろう。。。
- LEDで消費しているのか?→電源のインジケータのLEDの接続を切ってみる→ダメ
- インダクタの値が悪い?→220uHでもNG
- VLD ThrottleBacを試しにEnableにしてもダメだなぁ
- SMPをONにしても、全く電圧に変化が無い気がする。ちゃんとスイッチング動作してるのかなぁ。
これは、何か根本的に足りないものがありそうだ。スイッチングを確認してみよう。
- SMP端子とVDDの間に10kΩの抵抗を入れて、VDDに3Vを繋ぐ。
- SMP端子に周波数カウンタを繋ぐと、、、1.289MHzか。それらしいなぁ。。。
- でも、インダクタ(1uH,10uH)を繋ぐと、210〜220KHzぐらいまで落ちる。→電圧が十分に上がっていないのに、何故か間欠的に動作している?
- FlashTempを動かしていたので、Startしないようにしてみる→やっぱりダメだ。。
- 意外と電流を消費しているものがあるのかなぁ。SOICのInventionBoardの方でやってみるか。。。
クロックを遅くしてみる
- doggieさんと、桑野さんから、クロックを下げた方が良いとアドバイスがあり、早速ためしてみた。
- 元々、24MHzのインターナルクロックを使っていたが、12MHzにして書き込んでみたら、あっさり動作した。安定して5Vが出ているようだ。LCDも表示されている。
- 現状は、1uHのチップインダクタと、220uFのコンデンサが接続された状態。SMPのスイッチングのクロックは、1.221MHzで安定している。
- うーん、こんな簡単なことだったんだ。速いクロックの方が良いという頭があって、遅くするのは、思いつかなかった。。。
- クロックによる電流消費か。。。そうかもしれないなぁ。
SMPのインダクタ
- SMPのインダクタは、どれぐらいが良いのかな?
- PSoCの仕様では、2.2uH,1uFでの規定があるからそれぐらいか。
- InventionBoardの方で、ブレッドボードに組んでみよう。
- 容量は20uF載ってるからそのまま、インダクタだけ変えて試す。(チップインダクタ使用)
インダクタ | test1 | test2 | test3 |
1uH | 4.37V | 4.87V | 4.97V |
2.2uH | 4.61V | 4.97V | 4.97V |
10uH | 4.84V | 4.93V | 4.97V |
100uH | 4.03V | 4.03V | 4.04V |
- test1 →あれ電圧出ないなー。SMPの配線がICクリップだと長過ぎるかな?
- test2 →6cmぐらいの線に変えよう。まだちょっと低い。。。
- test3 →極力、配線を短くした。やっとそれらしい値になった。
- SMPの配線長がこんなに効くとは思わなかった。スイッチングの線は短い方が良いとは思うけど。。。ブレッドボードでは要注意だなぁ。
- やっぱり、数uH程度が適当みたいだなぁ。100uHだと全然ダメだ。
- どれぐらい電流取れるかやってみよう。VDDに200Ω+5KΩ可変抵抗+電流計繋いで、4.9Vに下がるまで、電流流してみる。
インダクタ | 電流値 |
1uH | 3.57mA |
2.2uH | 9.26mA |
10uH | -- |
100uH | -- |
- で、何で2つしかないかというと、なんか壊れたみたい。。。無理させた所為なのか、或はちょっとショートさせちゃったのか4、、、SMPの電圧もちょっと低くなっちゃった。。。
- まぁ、1uHよりは2uHの方が良さそうなのは分かった。やはり、5mAぐらい取るのが限界かな?(仕様書でも分かる程度のことだなぁ。ガッカリ)
- 完全に壊れた訳じゃなさそうだけど、SMP端子はちょっとダメかも。。。
- とりあえず入力装置として、I/Oポートにタクトスイッチを配線する。
- PSoCデザイナで、I/Oポートの割り込みを設定すると、boot.asmに ljmp PSoC_GPIO_ISR が記述され、psocgpioint.asmが追加される。
- 次に、boot.asmの、割り込みベクタを以下のように書き換える。
org 1Ch //GPIO Interrupt Vector
// ljmp PSoC_GPIO_ISR // asmのハンドラを
call _gpio_handler // Cで書いたものに置き換える
reti
コンパイルしてもエラーは出ないんだけど、動かない。。。
- 割り込み許可をしなければならない気がする。M8C_EnableGIntだけじゃダメみたいだ。訳も分からず、INT_MSK0 = INT_MSK0_GPIOとかやってみたけどダメだ。どうしろって言うんだろう。
- あれ、でもPull-Upしてるはずのピンの電圧は出てないなぁ。これ、ちゃんと設定されてるのかなぁ。
割込み許可
- マニュアルを見ると、GPIOの割り込みは以下のようなステップでやれと書いてあるが、、
- GPIOの割込みモードを設定 → PRTxICx →これはデザイナで設定してる
- GPIOのbit毎の割込みを許可 → PRTxIE →これも設定されてるみたいだし
- GPIO割込みのマスクbitを設定 → INT_MSK0 = INT_MSK0_GPIO; →で良いと思うが
- 全体の割込みを許可 → M8C_EnableGInt;
- ピンの設定は、自動的にpsocconfigtbl.asmに設定されてるみたいだし。。。
- 割込みの手順は、間違ってないんじゃないかな? やろうとしていることは、
- Pull-Upされた入力ピンに、FallingEdgeで割込みを設定しておいて、入力ピンをGndに落して、割込みルーチンに飛ぶかどうかってことなんだけど。。。
- しかし、Pull-Upしてるのに何で、電圧出ないんだろう。→1mVも無い。。。
- 試しに、さらに2.2kΩでPull-Upしてみるが数mVぐらいにしかならない。どうもLowレベルにドライブされているようだ。Pull-Upって入力ポートじゃないのかなぁ?出力でPull-Upなんて考えられないけど。。。
- 割り込みじゃなくて、単にPRTxDRxを読んでもLのままで、Hにすることが出来ない。
Pull-Upはやめた
- 仕方が無いので、ポートの設定はHigh-Zに変更して、外部にPull-Up抵抗を付けることにした。こうすると、ちゃんと5VになるしPull-Up抵抗を外すと、フローティングになってるみたいだ。
- 普通に入力は出来るようになったので、割り込み設定も戻してみた。→1回だけ、割込みルーチンが実行された!
- 割込み設定自体は、そんなに間違ってなかったみたいだ。
- 多分、割り込みをクリアしなきゃいけないんだろうなぁ。とりあえず、ひと安心。
Pull-Upのやり方
- ectoyfanさんから、Pull-Upの時にLにドライブするのは仕様だという指摘があって、そんな馬鹿なと思ったけど、全くその通りだった。
- じゃ、Pull-Up出来ないのってガッカリしかけたが、考えたらHは抵抗ドライブだから、データをHにセットすれば良いのかもということで試してみました。
- あっさり動作。ドライブ設定をPull-Upにして、データを1にセットすると、Pull-Upされた入力として使用出来ました。
- PSoCのやり方は最初はちょっと理解し難いけど、これは凄く自由度の高い方法だよね。
- 割り込みが掛かるようになったのは良いんだけど、どうやってクリアするのか。
- INT_CLR0のbit5をクリアすれば良さそうだけど、それでも再度割り込みを掛けることが出来ない。
- ループ処理を行ないながら割り込み掛けても、割り込み処理後にちゃんとループ処理に戻ってるからreturnしているみたいだし。
- INV_VCは次に実行されるべき割り込みベクトルだと思うが、読んでみると0になってる。→つまり、もう割り込み待ちは無いということだよなぁ。
- asmで、retiを実行してみたり、再度INT_MSKやGIEをセットしてもダメ。
- 1回は確実に割り込み出来るんだけど、どうすれば再度割り込みを掛けられるようになるんだろ?
- そもそも、インタラプトベクトルに飛んできた時点で、割り込みのフラグはクリアされてるんじゃないの? RETIを実行すれば十分じゃないのかなぁ。
アセンブラで書いてみる
- 手詰りだ。。。仕方ない、割り込みをアセンブラで書いてみよう。
- M8のアセンブラは初めてだが、結構分かり易いニーモニックなので、さらっと書けた。
push A //Aを使うので退避
mov A, reg[PRT0DR] //Port0の
xor A, 0x03 //bit0,1を反転して
mov reg[PRT0DR], A //元に戻すだけ
pop A //退避したAも戻す
reti //割り込みから復帰
- あっさり動いた。。。何故???うーん、全く同じことやってるはずだよなぁ。
- 自動的に作成されるpsocgpioint.asmのPSoC_GPIO_ISR経由で、callしてみたが、やはりダメ。
- 割り込みハンドラは、アセンブラで書かなきゃダメなのかなぁ。。。Cで書きたいなぁ。。。
ljmpするだけでした
- ectoyfanさんと、JunkBoxさんからljmpすれば良いって言われて、それはもう試したよなぁと思いながらやってみると動きました。(やったつもりだったのに、lcallとかもやってみたのに、、、)
- 結局、PICでは必要な割り込みフラグのクリアのような操作は不要だった。これは、割り込みベクタがあるからだろうなぁ。
- 電池駆動ならスリープは必須なので、これは試しておかないと。
- 確かにスリープしてGPIOでWake-Upしているようだが、、、
- 不可解な動作。SLEEPタイマで繰返しリセットされてるような。。。
- SLEEPタイマもenableになってるのかなぁ。そもそもSLEEPタイマをオンにしただけ?じゃ単純にSLEEPするのってどうするんだ?
- これはこれで面白いんだけど。。。
- なんか眠くなってきたので、今日はここまでにしておこう。
まるで暗号
- 何故、定期的にリセットのような動作をするかが分からない。。。
- SLEEPは良くわからないので、英文の説明を読むが余計分からなくなる。
- とりあえず、関係ありそうな部分を適当にざっと意訳5したのをメモしておこう。頭の中で考えるよりはマシかも。。。(しかし、この英文はネイティブの人でもきっと分かり難いと思うなぁ。。。)
- SLEEPタイマは常に有効である。ICEでSTOP、或はCPU_SCR0のSTOPビットがセットされている場合を除いては。
- 通常、STOPビットのセットは行なわない方が良い。次のインストラクションはリセットによる割り込みベクタのエントリになる。
- SLEEPはCPU_SCR0のSLEEPビットをセットすることで開始され、任意の有効にされた割り込みでクリアされる。
- このビットは登録後にブロックされ、またSLEEPシーケンスの完了までクリアされない。これは、PowerDownの不安定な状態でSLEEPが中断されるのを防ぐ。割り込みが未決でEnable状態の時、完了するまでSLEEPしない。というか、SLEEPビットをセット出来ない。
- SLEEPからのWake-Upを有効にするのにGIEは必ずしも必要では無い。個々の割り込みの割り込みマスクのセットにより有効になる。もしGIEがセットされない場合は、システムはISRをサービスしない。しかしながらシステムは起きて、SLEEPしたポイントからの命令を実行するだろう。この場合、ユーザはマニュアルで未決の割り込みを取り除くか、或はGIEをセットしてシステムにISRを実行させる必要がある。もし、未決の割り込みを取り除かない場合、それは連続的に繰り返される。SLEEPビットがセットされ、スリープシーケンス実行、すぐにデバイスはスリープ状態になり未決の割り込みによりSLEEPビットはクリアされ、スリープを抜ける。
- Wake-Up後に、SLEEPの直後の命令が実行される。システムがスリープする前に、スリープ直後の命令を持ってくるためで、割り込みによりWake-Upした場合は、前もって持ってきた命令を実行し、その後にISRが実行される。(もしGIEがセットされない場合は、単に継続される)
- SLEEPビットのセットの前にGIEを無効にすれば安全。スリープの準備の際に割り込みが入ると、準備されずにSLEEPに入るかもしれない。準備の前にGIEを無効にして、準備が終ったら、GIEをセットすると良い。
- デバイスの起動時には、WDTは無効になっている。PORSビットをクリアすることでWDTは有効になる。
- WDTは、RES_WDTレジスタへの書き込みでリセットされる。38Hの書き込みでSLEEPタイマもリセットされる。
- 何か問題があってWDTがクリアされない場合は、WDRが発生する。WDRは他のリセットと同じ効果を持つが、RAMの初期化は無効に出来る。
- RES_WDTへの書き込みは効果が無かった。しかし、この訳がある程度合ってるとすると、ちょっと変な仕様ではあるなぁ。Wake-Up後にSLEEP直後の命令が実行されるっていう処は関係あるかな?。。。。。うーん、わからん。でも眠いので寝る。
WDTでした
- 落ち着いて良く考えてみる。
- こうしなきゃ、でした。終り。
- データを記録するのに、PICではEEPROMを使うことが多いが、PSoCではEEPROMを持っていない。代わりに、プログラムメモリ上にデータを保存するソフトモジュールがあるので、それを使ってみよう。
- プログラムの起動時に、EEPROMモジュールからデータを読み込むようにする。
char line[21];
E2PROM_1_E2Read( 0, line, 20 );
プログラムでデータを編集したら、保存は以下のようにするだけだ。
E2PROM_1_bE2Write(0,line, 20, 25);
思いの他簡単だったが、初期値の設定はプログラムでやるしかないように見える。単に初期値書き込みたいんだけど6。他に方法無いのかなぁ。。。
- ソフトモジュールとしては、初期値をデザイナで設定出来るようになってると、良いんだけどなぁ。 → こうすれば良いようです
- しかし、この4番目のargumentは何なんだろう。cTemperatureって、温度?何のために?
テストプログラム
- 現状のテストプログラム。簡単だけど7、とりあえずGPIO割り込みとEEPROMモジュール、それにスリープも使ってるので、少しは何かの参考になるかもしれない。
- ポートの設定は、デザイナでやってる。
- ポート0の下位2ビット分、StrongドライブでLED2個
- ポート1にLCDモジュール
- ポート2の上位6ビット分、pull-up抵抗ドライブ、FallingEdge割り込みでタクトスイッチ6個
//----------------------------------------------------------------------------
// C main line
//----------------------------------------------------------------------------
#include <m8c.h> // part specific constants and macros
#include "PSoCAPI.h" // PSoC API definitions for all User Modules
#include "psocgpioint.h"
#pragma interrupt_handler gpio_handler //割り込みハンドラの指定
char line[21]; //20文字分のバッファ
unsigned char x=0; //X方向カーソル位置
unsigned char key;
void gpio_handler() //GPIO割り込みハンドラ(スリープよりwake-up)
{
PRT0DR ^= 0x03; //LED2個を単に反転させる
key = ~PRT2DR; //キー入力
if (key & Right_MASK) x = (x+1)%20; //右カーソル移動
if (key & Left_MASK) x = (20+x-1)%20; //左カーソル移動
if (key & Up_MASK) line[x] = (line[x]-'0'+1)%10+'0'; //データUp
if (key & Down_MASK) line[x] = (10+line[x]-'0'-1)%10+'0'; //データdown
if (key & OK_MASK) E2PROM_1_bE2Write(0,line, 20, 25); //Flash書き込み
if (key & Cancel_MASK) E2PROM_1_E2Read( 0, line, 20 ); //Flash読み込み
}
void main()
{
LCD_1_Start(); //LCD設定
LCD_1_Position(0,1);
LCD_1_PrCString("PSoC EEPROM Module"); //1行目に表題表示
PRT0DR &= ~0x02; //LED1消灯
PRT0DR |= 0x01; //LED0点灯させる
PRT2DR |= 0xfc; //タクトスイッチ6個分プルアップ
E2PROM_1_E2Read( 0, line, 20 ); //起動時にFlashを読んで表示
INT_MSK0 = INT_MSK0_GPIO; //GPIO割り込みを許可
M8C_EnableGInt; //グローバル割り込み許可
while(1) {
LCD_1_Position(1,0); //2行目に
LCD_1_PrString(line); //20文字分データ表示
LCD_1_Position(1,x); //カーソル位置に移動
CPU_SCR0 |= CPU_SCR0_SLEEP_MASK; //スリープする
}
}
- 起動すると、EEPROMモジュールから20個分データを読み込み表示する。
- 左右にカーソルを動かし、上下で値をセットして、OKでEEPROMへ書き込み
- キー処理はちょっと汚いなぁ。チャタリング処理もしてません。
LCDのカーソル表示
- LCDモジュールでは、カーソルは表示されないように設定されてるみたいだ。
- 後から思ったけど、これってCプログラムから LCD_1_Control(0x0f)とすれば良いだけだなぁ。何故そうしなかったんだろ?
3というか、アナログは良く分かんないので。。。
4途中で配線短くしたからなぁ。ショットキの足でそのままInventionBoardを跨いで繋いでたのが失敗かな。。。
5あくまで、いい加減な意訳です。くれぐれも信用しないように。。。
6PICだったら0x2100に書き込んどけば良いよね。そんな感じでやりたいんだけど。。。
7分かってしまえば簡単なんだけど、ここまで分かるのに結構掛かったなぁ。。。
[top]
- もっと、ソフトモジュールあれば良いのに。例えば、
- 7segment LEDドライバ
- テンキーマトリクス
- ロータリーエンコーダ
- とかどうだろう。うーん、でもいざ考えてみるとあまり良い物を思いつかない。単純なデジタルだけだし。。。
- 自分でユーザーモジュール作れれば良いなぁ。→無駄にモジュール作りに凝ってしまう危険性はあるかな。
- USBのハードモジュールは欲しい。→ブートローダのようなものを書けば、書き込みも単体で出来るっていうことだと良いなぁ。
- PSoCデザインコンテストのページに載ってる、 これって、電波時計だよね。ラジオは相当ゲインが無いとダメだと思うんだけど、どうなんだろ。
- でも実用性は別としても、PSoCで電波時計を作っちゃうのは凄いなぁ。 受信モジュールを使ったものと性能的に比べて見たいなぁ。これを見ても構成が完全には理解出来ないのは情けない。しかしブロックダイアグラムは書いて欲しいなぁ。プロジェクトファイルは、どっかに無いのかなぁ。
[top]
PSoC関連のリンクです。PastelMagicのBBSに出入りされている方が多いです。
[top]
[電子工作関連に戻る]