LEDチカチカ(非RTOS) †構成 †LPC1769には、基板上に最初からLEDがついています。 LPC1769のピンアサインについては、インストールされた中にある、Getting StartedのPDFを見てください。 LEDの記載を見ると、P0[22]と書いてあるのがわかります。 このピンの出力を、周期的に変化させてやれば、LEDチカチカが実現できることになります。 プロジェクト †まずは、新規プロジェクトを作りましょう。 MCUはLPC1769を選び、CMSIS Library to link project toは、CMSISv2p00_LPC17XXが選択されていることを確認してください。 プロジェクトが作成されたら、右クリックからプロパティを開きます。 次に、「C/C++ General」の「Paths and Symbols」を開いて、includeとライブラリの設定をします。 まず、IncludesタブのLanguagesがGNU Cのところを選択すると、既に/CMSISv2p00_LPC17xx/incの設定が入っているかと思います。 次にLibrariesタブの設定ですが、ここもすでに、CMSISv2p00_LPC17xxの設定が入っていると思います。 最後に、Libraries Pathsの設定も同様にします。 ここまでで、プロジェクトの設定は終わりですので、反映させて一旦ビルドをかけてみましょう。 「Project References」で指定した、CMSISv2p00_LPC17xxと、DriverLibのそれぞれのインクリメンタルビルドが行われてから、ledtest01のビルドが行われます。 ソースコード †以下、ソースコード。 // TODO: insert other include files here #include "lpc17xx_pinsel.h" #include "lpc17xx_gpio.h" 次に、指定時間waitするためのカウンタをグローバル変数として用意し、そのカウンタをインクリメントする割り込み関数、実際のwaitを行う関数をそれぞれ用意します。 // TODO: insert other definitions and declarations here volatile uint32_t msTicks = 0; void SysTick_Handler(void) { msTicks++; } void systick_delay (uint32_t delayTicks) { uint32_t currentTicks = msTicks; while ((msTicks - currentTicks) < delayTicks); } そして、メイン関数は以下のようになります。 int main(void) { // TODO: insert code here PINSEL_CFG_Type pincfg; // ピン設定構造体 uint32_t state = 0; // LED初期化 pincfg.Funcnum = PINSEL_FUNC_0; pincfg.OpenDrain = PINSEL_PINMODE_NORMAL; pincfg.Pinmode = PINSEL_PINMODE_PULLUP; pincfg.Portnum = PINSEL_PORT_0; pincfg.Pinnum = PINSEL_PIN_22; PINSEL_ConfigPin(&pincfg); GPIO_SetDir(PINSEL_PORT_0, (1 << PINSEL_PIN_22), 1 ); GPIO_SetValue(PINSEL_PORT_0, (1 << PINSEL_PIN_22)); SysTick_Config(SystemCoreClock / 1000); while (1) { systick_delay(500); state = GPIO_ReadValue(PINSEL_PORT_0); GPIO_ClearValue(PINSEL_PORT_0, state & (1 << PINSEL_PIN_22)); GPIO_SetValue(PINSEL_PORT_0, ~state & (1 << PINSEL_PIN_22)); } return 0; } ソースコード解説 †まず、メイン関数の先頭からですが、LEDを使用するために、LEDがつながっているポート0の22番ピンの設定をします。 typedef struct { uint8_t Portnum; /**< Port Number, should be PINSEL_PORT_x, where x should be in range from 0 to 4 */ uint8_t Pinnum; /**< Pin Number, should be PINSEL_PIN_x, where x should be in range from 0 to 31 */ uint8_t Funcnum; /**< Function Number, should be PINSEL_FUNC_x, where x should be in range from 0 to 3 */ uint8_t Pinmode; /**< Pin Mode, should be: - PINSEL_PINMODE_PULLUP: Internal pull-up resistor - PINSEL_PINMODE_TRISTATE: Tri-state - PINSEL_PINMODE_PULLDOWN: Internal pull-down resistor */ uint8_t OpenDrain; /**< OpenDrain mode, should be: - PINSEL_PINMODE_NORMAL: Pin is in the normal (not open drain) mode - PINSEL_PINMODE_OPENDRAIN: Pin is in the open drain mode */ } PINSEL_CFG_Type; PINSELやGPIOの定義は、DriverLibの中にあるヘッダの定義です。 どのような設定をすればいいかは、ユーザーマニュアルを見て確認します。 ユーザーマニュアルはNXP社のHPから検索してダウンロードできます。 落としたら、「Chapter 8: LPC17xx Pin connect block」を開きます。 「Table 80」を見ると、P0[22]は、Function00(0)の時はGPIO(汎用的なI/Oピン)として、Function01(1)の時はRTS1、Function11(3)の時はTD1として動作するように書かれています。 この、RTS1やTD1というのは何かというのは、「Table 73. Pin description」に記載があり、RTS1はUART1という機能のTD1はCAN1という機能の出力ピンとして使えるというのがわかります。 今回は、GPIOとしてこのピンを使いますので、機能は0番を指定する必要があり、PINSEL_CFG_TypeのFuncnumにはPINSEL_FUNC_0(0)を設定します。 最後に、この構造体を指定してPINSEL_ConfigPinを呼べば、これでP0[22]のピンを使用する準備は整いました。 次に、そのピンに対して、実際に操作を行います。 GPIO_SetDirは、指定したポートの、立てたビットのピンの入出力を設定します。 これでH/Lを出力できるようになったので、まずはLEDをON状態に初期化します。 ユーザーマニュアルの「Chapter 9: LPC17xx General Purpose Input/Output (GPIO)」を読むと理解が深まると思いますが、GPIOのレジスタには、SETレジスタとCLRレジスタがあり、これをラッパーしているのが前述の命令ということになります。 まずはON状態で初期化するので、GPIO_SetValueにPINSEL_PORT_0の、PINSEL_PIN_22ビットのピンを指定すれば、この時点でLEDが点灯します。 次に、SysTick_Configで、1msの割り込みを発生させます。 SysTick_Configは、引数に指定したクロックで割り込みを発生させます。 引数にmsを指定すればいいSYSTICK_InternalInitよりわかりにくいですが、こちらを選んだのには理由がありますので、後述します。 SysTick_Configは、System Tick Timerの割り込みを発生させますが、この割り込み時に実行される関数は、今回のledtest01プロジェクトを作成した時に自動的に生成されている、cr_startup_lpc176x.c内に書かれています。 今回、同名のSysTick_Handlerという関数を作った事により、WEAK付きの元々の関数は無視され、新たに作成した関数がSystem Tick Timerの割り込みでコールされるようになります。 さて、後は、無限ループの中身ですが、最初は1msの割り込みカウンタが引数の500回を超えるまでwaitするサブ関数です。 waitが終わったら、その時のポート0の状態を読み出し、ローカル変数に保存しています。 次に、22番ピンがHighであればLowにするため、22番ピンの元の状態を指定してGPIO_ClearValueを呼びます。 さらに、22番ピンがLowであればHighにするため、22番ピンの元の状態を反転させたものを指定してGPIO_SetValueを呼びます。 実行・デバッグ †ソースが出来て、ビルドが通ったら、いよいよ実行です。 初回は、ドライバのインストールなどがあり、時間がかかるかもしれません。 無事に実行できると、自動的にmain関数の先頭でbreakがかかります。 Resume(F8)を押せば、LEDが点滅します。 お手軽にIDEでデバッグ出来るのは楽でいいですね。 クロックの設定 †デバッガで停止中に、SysTick_Configの引数に指定している、SystemCoreClockにカーソルをあててみて下さい。 実はこのLPC1769、このままでは100MHzでしか動作していません。 この設定は、CMSISv2p00_LPC17xxライブラリの方で行われています。 #define CLOCK_SETUP 1 #define SCS_Val 0x00000020 #define CLKSRCSEL_Val 0x00000001 #define PLL0_SETUP 1 #define PLL0CFG_Val 0x00050077 //#define PLL0CFG_Val 0x00050063 #define PLL1_SETUP 1 #define PLL1CFG_Val 0x00000023 #define CCLKCFG_Val 0x00000003 #define USBCLKCFG_Val 0x00000000 #define PCLKSEL0_Val 0x00000000 #define PCLKSEL1_Val 0x00000000 #define PCONP_Val 0x042887DE #define CLKOUTCFG_Val 0x00000000 これで、120MHzで動作するようになりました。 PS3とLinux、電子工作も-LPCXpresso LPC1769の120MHzクロック設定 以上で、非RTOS版のLEDチカチカは終了です。 |