[[lbed]] #contents 2013/07/14からのアクセス回数 &counter; ** 実験ワークベンチ [#f00e8ff5] プログラムを作成する場合には、いろいろな実験に必要な部品を装備した 実験ワークベンチを用意すると便利です。 今回は、トラ技の2012/11号で付録についてきたMyARM基板とLPC-Link ((LPC11U14ボードのデバッガ部分)) を使用します。 写真では、LPC11U14のデバッガ部分を切り離して使用していますが、表面の結線部分をカッターで切断するだけでも大丈夫です。 (([[LPC-Link2>http://akizukidenshi.com/catalog/g/gM-06706/]]という多機能なデバッガが手頃な値段で販売されているので、こちらを使ってもよいでしょう。)) &ref(MyARMandLPC-LINK.png); 子供たちでも組み込みの実験をするには、安価でソースレベルのデバッグが可能な環境が不可欠です。 そのため、1台2000円のLPC11U14ボードをワークベンチにするのではなく、 DIPタイプで1個110円の[[LPC1114FN28>http://akizukidenshi.com/catalog/g/gI-06071/]] は、外部クリスタルなしでも動作するので、子供たちの電子工作にうってつけです。 ** プログラミング環境 [#x407d0b7] 無償のプログラムミング環境LPCXpressoを以下のページからユーザ登録し、LPCXpressoをダウンロードしてください。 - http://lpcxpresso.code-red-tech.com/LPCXpresso/ Windowsを使用の方は、シリアル通信用のチップPL2303のドライバーをダウンロードしてください。 - http://www.prolific.com.tw/ ** プロジェクトのインポート [#f2ffcd7a] プロジェクトを新規に作成すると細かな設定ミスで動作しないことがありますので、 ここでは、LBEDのトップページにあるLBED.ZIPを解凍して、ローカルのディレクトリー ((ディレクトリ名に日本語が入らない場所に展開してください。)) に入れたところから説明します。((新規にプロジェクトを用意する方法は、[[マイコン風雲録>http://avr.paslog.jp/article/1854933.html]]を参照にしてください。)) 私の使っているLPCXpressoのバージョンは、4.2.2です。 最初に、LPCXpressoを起動して、以下の手順でプロジェクトをインポートしてください。 - FIleメニュー→import…を選択し、GeneralからExisting Projects into Workspaceを選択し、Nextボタンを押します - Browse…ボタンからLBEDを展開したディレクトリからCMSISv2p00_LPC11xxを選択し、開くボタンを押します - Finishボタンを押すと、Project ExploerにインポートしたCMSISv2p00_LPC11xxが表示されます - 同様に、LBED_LPC11xx, LBED_USERLIB, LBED_MAINをインポートします *** LEDチカチカをコンパイルする [#t04ded10] LBED_MAIN/srcにあるTestOLED.cppをnot_usedに移動し、代わりにTestLED.cppをsrcに移動します。 &ref(TestLEDProj.png); LBED_MAINを選択し、右クリックしてBuild Projectを選択します。 Console画面に #pre{{ make --no-print-directory post-build Performing post-build steps arm-none-eabi-size "LBED_MAIN.axf"; # arm-none-eabi-objcopy -O binary "LBED_MAIN.axf" "LBED_MAIN.bin" ; checksum -p LPC1114FN_102 -d "LBED_MAIN.bin"; text data bss dec hexfilename 1600 4 28 1632 660LBED_MAIN.axf }} と表示されたらビルド成功です。 *** LEDチカチカを動かす [#r56f0295] MyARM基板への電源は、LPC-Linkから供給します。 JP3をショートします。 LPC-LinkとMyARMの接続は、以下のようにします。 - LPC-Link 1番をMyARMのCN1の3.3Vに接続 - LPC-Link 2番をMyARMのCN1のSWDに接続 - LPC-Link 3番をMyARMのCN1のSWCに接続 - LPC-Link 10番をMyARMのCN1のGNDに接続 LPC-LinkをUSBに接続し、MyARMのLED3が点灯すれば接続完了です。 これで、LBED_MAINを選択し、トップのツールバーの虫のようなアイコンをクリックします。 &ref(toolbtns.png); 自動的にプログラムがMyARMに書き込まれ、以下のようなデバッガが画面が表示されます。 &ref(debugger.jpg); 緑の▲をクリックするとプログラムが動き出し、LED2が1秒間隔で点滅します。 ** ライブラリの構成 [#t3cfc097] LBEDのクラスライブラリは、以下の4つのプロジェクトから構成されています。 - CMSISv2p00_LPC11xx: LPC11xx用のCMSISでクリスタルなしで動作するように一部を変更 - LBED_LPC11xx: LBED用のライブラリ本体 - LBED_USERLIB: TexLCD, LM73, MARMEX_OB_oledのユーザライブラリ - LBED_MAIN: テスト用のメインプログラム(not_usedのファイルと入れ替えながら使用) ベースとなるDigitalOut, BusOut, PinNamesは、「そらみみの声」の [[IDEを使わずにLPCXpresso LPC1768のプログラムを開発する>http://www.soramimi.jp/lpcxpresso/gnu/index.html]] を参考にさせて頂きました。 *** ピンの設定 [#n93d02f5] MyARMは、できるだけピンの配置をmbedと合わせるように作られています。 ピンの番号付けは、mbedにならって左端から反時計回りに1番から40番まで番号付けしました。 &ref(pin_layout.png); p5からp30までは、LBED_LPC11xx/inc/PinNames.hで実際のビン番号にマップされています。 *** wait関数 [#tfd9d2a7] mbedのwait_ms, wait_usとwaitの初期化関数wait_init関数をCで実装しました。 ただし、wait_usは8MHzの4クロックでループを回ると仮定して、ビジーウェイトで実装しました。 wait_usは、周辺機器の初期化に使用されるケースが多く、MPUが変わったときには変更が必要です。 wait_api.h #pre{{ void wait_ms(int ms); void wait_us(int us); void wait_init(void); }} *** DigitalOut [#y14377ce] DigitalOutのsetupをGPIOとして使えるピンをチェックし、_gpioにポートのアドレス、_ioにIOのアドレスを セットし、最後に_gpiio->DIRで出力用にセットしています。 setup #pre{{ void DigitalOut::setup(PinName pin, const char* name) { _pin = pin; _gpio = 0; _mask = 0; _io = 0; if (_pin >= P0_0 && _pin <= P0_31) { _gpio = LPC_GPIO0; _mask = 1 << (_pin - P0_0); switch(_pin - P0_0) { case 1: _io = &LPC_IOCON->PIO0_1; *_io = 0xd0; break; case 2: _io = &LPC_IOCON->PIO0_2; *_io = 0xd0; break; case 3: _io = &LPC_IOCON->PIO0_3; *_io = 0xd0; break; case 4: _io = &LPC_IOCON->PIO0_4; *_io = 0xd0; break; case 5: _io = &LPC_IOCON->PIO0_5; *_io = 0xd0; break; case 6: _io = &LPC_IOCON->PIO0_6; *_io = 0xd0; break; case 7: _io = &LPC_IOCON->PIO0_7; *_io = 0xd0; break; case 8: _io = &LPC_IOCON->PIO0_8; *_io = 0xd0; break; case 9: _io = &LPC_IOCON->PIO0_9; *_io = 0xd0; break; case 10: _io = &LPC_IOCON->SWCLK_PIO0_10; *_io = 0xd0; break; case 11: _io = &LPC_IOCON->R_PIO0_11; *_io = 0xd0; break; } } else if (_pin >= P1_0 && _pin <= P1_31) { _gpio = LPC_GPIO1; _mask = 1 << (_pin - P1_0); switch(_pin - P1_0) { case 0: _io = &LPC_IOCON->R_PIO1_0; *_io = 0xd0; break; case 1: _io = &LPC_IOCON->R_PIO1_1; *_io = 0xd0; break; case 2: _io = &LPC_IOCON->R_PIO1_2; *_io = 0xd0; break; case 3: _io = &LPC_IOCON->SWDIO_PIO1_3; *_io = 0xd0; break; case 4: _io = &LPC_IOCON->PIO1_4; *_io = 0xd0; break; case 5: _io = &LPC_IOCON->PIO1_5; *_io = 0xd0; break; case 6: _io = &LPC_IOCON->PIO1_6; *_io = 0xd0; break; case 7: _io = &LPC_IOCON->PIO1_7; *_io = 0xd0; break; case 8: _io = &LPC_IOCON->PIO1_8; *_io = 0xd0; break; case 9: _io = &LPC_IOCON->PIO1_9; *_io = 0xd0; break; } } else if (_pin >= P2_0 && _pin <= P2_31) { _gpio = LPC_GPIO2; _mask = 1 << (_pin - P2_0); } else if (_pin >= P3_0 && _pin <= P3_31) { _gpio = LPC_GPIO3; _mask = 1 << (_pin - P3_0); } if (_gpio) { _gpio->DIR |= _mask; } } }} DigitalOut.hには、read, write, =, intを定義しています。 #pre{{ void write(int value) { if (_gpio) { if (value) { _gpio->DATA |= _mask; } else { _gpio->DATA &= ~ _mask; } } } int read() { return _gpio && (_gpio->DATA & _mask) ? 1 : 0; } DigitalOut& operator = (int value) { write(value); return *this; } DigitalOut& operator = (DigitalOut& rhs) { write(rhs.read()); return *this; } operator int() { return read(); } }} *** たったこれだけ? [#z9d1dcbd] 最初のLEDチカチカに関連するプログラムは、本当にこれだけです。 *** 注意 [#j23f4920] Ram領域が足りないとのリンクエラーが発生したので、調べたところ以下のサイトに説明がありました。 http://todotani.cocolog-nifty.com/blog/2011/10/lpcxpresso-idec.html この対処のために、pure_virtual.cpp #pre{{ extern "C" void __cxa_pure_virtual() { while (1); } }} を定義しました。 ** コメント [#na1ae117] #vote(おもしろかった[2],そうでもない[0],わかりずらい[0]) #vote(おもしろかった[3],そうでもない[0],わかりずらい[0]) 皆様のご意見、ご希望をお待ちしております。 #comment_kcaptcha