[[FrontPage]] #contents 2013/02/16からのアクセス回数 &counter; 今回は、大野さんの「アナログ・マイコン!?PSoCに目覚める本」の6章に挑戦します。 ** プログラミングだけでポートを操作 [#z28fb073] 最初は、ピンの設定とプログラムだけでIOを制御するじゃんけんゲームが紹介されています。 回路は、以下の様になっています。 &ref(fig6_6.png); ブレッドボードで組んだ回路は以下の様になりました。 デジタルの回路では、10KΩ, 4.7KΩ, 1KΩ, 470Ωの4種類を用意しておけば、実験ができます。 今回の回路では、330Ωとありますが、ここでは470Ωを代わりに使っています。 &ref(B6_1.png); *** IOピンの設定と制御 [#ib2ca5cd] IOポートには、以下の設定が可能ですが、 | 名称 | 種別 | 概要 |h | Hight Z | 入力 | ディジタル入力 | | High Z Analog | 入力 | アナログ入力 | | Open Drain Hight | 出力 | ハイ側オープン・ドレイン | | Open Drain Low | 出力 | ロー側オープン・ドレイン | | Pull Down | 出力 | プルアップ&ロー側オープン・ドレイン | | Pull Up | 出力 | プルアップ&ハイ側オープン・ドレイン | | Strong | 出力 | ディジタル出力 | | Strong Slow | 出力 | ディジタル出力 | 大野さんの本では、 - 出力: Strong - 入力: High Z - スイッチ: Pull Up を使っているそうです。 ピンのIO設定は、縦に隠れているPinout-プロジェクト名のタグをクリックすると表示されます。 今回は、P0[7], P0[5], P[3]のLED制御のピンをStrong出力で初期値0とします。 P2[1]をプルアップ出力で初期値1にします。 &ref(L6_1_pin_setting.png); *** main関数の定義 [#c05b658c] 本題のmain関数ですが、ポートのデータレジスタは、PRTnDRでnにポート番号を指定します。 6章レッスン1では、スイッチは、P2[1]なので、PRT2DRの2bit目の値をチェックするため、0x2とのアンドを取ります。 スイッチが押されるとP2[1]が0となるので、それまで待つ場合には、 #pre{{ while ((PRT2DR & 0x2) != 0) continue; }} とします。 また、LED点灯するのは、P0[7], P0[5], P0[3]なので、PRT0DRに0x8(4bit目)をセットして順番に2ビットシフトすることで、 P0[3], P0[5], P0[7]へと点灯するLEDをシフトさせています。 main関数は、以下の様になっています。 #pre{{ void main(void) { // M8C_EnableGInt ; // Uncomment this line to enable Global Interrupts // Insert your main routine code here. BYTE i = 0x8; WORD dly; for (;;) { while((PRT2DR & 0x2) != 0)continue; // スイッチが押されるまで待つ for (dly = 0; dly < 500; dly++)continue; // ディレイ10msくらい while ((PRT2DR & 0x2) == 0) { // スイッチが押されている間、パラパラ点灯 PRT0DR = i; i = i << 2; if (i == 0) i = 0x8; for (dly = 0; dly < 1000; dly++)continue;// ディレイ20msくらい } for (dly = 0; dly < 500; dly++)continue; // ディレイ10msくらい } } }} ** キャラクタLCDに文字を表示 [#k60b078f] 次のレッスン6_2は、「キャラクタLCDに文字を表示」でした。 通常のLCDをそのままブレッドボードで使うと配線がめんどうなので、 後閑さんの「C言語によるPICプログラミング入門」で紹介されていた3行表示のLCDを用意しておくと便利です。 ((単にキャラクターLCDにコントラスト用の半固定抵抗を付け、コネクターケーブルを付けてだけです)) &ref(LCD.png); この液晶は、DB7, DB6, DB5, DB4の4bitのデータバスでも表示ができるので、電子工作でよく使われます。 &ref(3LineLCD-sch.png); コネクターの配線は、以下の様にしています。 - 1(白)5V - 2 DB7 - 3 DB6 - 4 DB5 - 5 DB4 - 6 E - 7 RS - 8, 9 は未接続 - 10 GND PSoCとLCDの接続以下の様にします。 &ref(fig6_7.png); *** モジュールの配置 [#r891e232] Misc DigitalからLCDを配置します。 LCDモジュールはディジタルブロックを使用しないのでブロック図にはでませんが、Parameterタブが表示されいますので、 以下の様にPort2を出力ポートに設定します。 &ref(L6_2_Param_Setting.png); *** main関数 [#h56ce36b] main関数で文字列を出力します。 #pre{{ void main(void) { // M8C_EnableGInt ; // Uncomment this line to enable Global Interrupts // Insert your main routine code here. char str[] = "Welcome"; int i = 0x2011; LCD_1_Start(); LCD_1_Position(0, 4); LCD_1_PrString(str); // RAM文字列表示 LCD_1_Position(1, 0); LCD_1_PrCString("PSoC World"); // ROM文字列PSoC Worldを表示 LCD_1_Position(1, 11); LCD_1_PrHexInt(i); // 2バイト16進数を表示 } }} *** 実行結果 [#wcf04998] PSoCにプログラムを書き込み、電源を入れると以下の様に表示されました。 &ref(B6_2.png); ** 割り込みを使う [#bfd335f0] 6章の最後は、関門の割り込みでです。 ブレッドボードは、レッスン4_1を使用します。 Counter8は、4kHzで動作するように設定し、割り込みで0と1を交互に出力することで2kHzの 周波数を出力するプログラムを作成します。 *** ユーザモジュールの配置 [#x7b8e2c3] デジタルブロックにCounter8を配置します。今回は割り込みを使うので、配線はしません。 &ref(L6_3D_Block.png); P0[2]にAGNDを出力するようにセットします。 &ref(L6_3A_Block.png); グローバルセッティングは、VC2が400kHzとなるようにVC1=6, VC2=10にセットします。 &ref(L6_3_Global_Setting.png); Counter8の設定は、Counter8のTerminal Countに99((100-1))とし、4kHzになるように設定します。 &ref(L6_3_Counter8_param.png); P0[0]の出力をStrongに変更します。 &ref(L6_3_pin_setting.png); Generate Configurationのメニューを実行して、Counter8のアセンブラコードが作成されます。 &ref(L6_3_Workspace.png); Counter8_1INT.asmの74に以下のようにカスタムコード(Cの関数へのジャンプ命令)を書きます。 #pre{{ ;--------------------------------------------------- ; Insert your custom assembly code above this banner ;--------------------------------------------------- ljmp _Counter8_1_Int }} Build->Compileを選択してCounter8_1INT.asmをコンパイルします。 *** Cでの割り込み関数の定義 [#xd1a7e03] Cで割り込み関数を定義する場合、#pragma宣言で割り込み関数であることを明記します。 関数名には、Counter8_1INT.asmで宣言した関数の先頭の_を除いた名前を指定します。 #pre{{ #pragma interrupt_handler Counter8_1_Int // 割り込み関数宣言 void Counter8_1_Int(void) { // 割り込み関数本体 PRT0DR ^= 0x1; // ビット0を反転 } }} main関数の定義は、以下の様にします。 #pre{{ void main(void) { // M8C_EnableGInt ; // Uncomment this line to enable Global Interrupts // Insert your main routine code here. Counter8_1_Start(); Counter8_1_EnableInt(); // Counter8_1を割り込み許可する M8C_EnableGInt; // PSoCの割り込みを許可するマクロ while(1) continue; } }} *** 動作チェック [#e40a7f44] プログラムを書き込み、動かすとピーとなります。 P0[2]とP0[0]の周波数をテスターで調べて1.990と2kHzに近い値となっており、 無事割り込みが働いていることを確認することができました。 &ref(L6_3_running.png); ** コメント [#lcdd875f] #vote(おもしろかった[3],そうでもない[0],わかりずらい[0]) #vote(おもしろかった[4],そうでもない[0],わかりずらい[0]) 皆様のご意見、ご希望をお待ちしております。 #comment_kcaptcha