今度はLPC810でテストした”Blinky”を読む。
“Blinky”は次の3つのソースファイルで構成されている。
1. cr_startup_lpc8xx.c
2. crp.c
3. main.c
まずはmain関数のあるmain.cから。
/****************************************************************************
* $Id:: blinky.c 3634 2012-10-31 00:09:55Z usb00423 $
* Project: NXP LPC8xx Blinky example
*
* Description:
* This file contains LED blink code example which include timer,
* GPIO initialization, and clock monitoring.
*
****************************************************************************
略
****************************************************************************/
#ifdef __USE_CMSIS
#include "LPC8xx.h"
#endif
#include "lpc8xx_clkconfig.h"
#include "lpc8xx_gpio.h"
#include "lpc8xx_mrt.h"
extern uint32_t mrt_counter;
/* Main Program */
int main (void) {
uint32_t regVal;
SystemCoreClockUpdate();
/* Config CLKOUT, mostly used for debugging. */
regVal = LPC_SWM->PINASSIGN8 & ~( 0xFF << 16 );
LPC_SWM->PINASSIGN8 = regVal | ( 12 << 16 ); /* P0.12 is CLKOUT, ASSIGN(23:16). */
CLKOUT_Setup( CLKOUTCLK_SRC_MAIN_CLK );
#if 0
regVal = LPC_SWM->PINASSIGN0 & ~( (0xFF << 0) | (0xFF << 8) );
LPC_SWM->PINASSIGN0 = regVal | ( (2 << 0) | (3 << 8) ); /* P0.2 is UART0 TX, ASSIGN(7:0); P0.3 is UART0 RX. ASSIGN(15:8). */
#endif
/* Enable AHB clock to the GPIO domain. */
LPC_SYSCON->SYSAHBCLKCTRL |= (1<<6);
/* Set port p0.0 to output */
GPIOSetDir( 0, 0, 1 );
/* Set port p0.16 to output */
GPIOSetDir( 0, 16, 1 );
/* Set port p0.17 to output */
GPIOSetDir( 0, 17, 1 );
init_mrt(0x8000);
while (1) /* Loop forever */
{
/* I/O configuration and LED setting pending. */
if ( (mrt_counter > 0) && (mrt_counter <= 200) )
{
GPIOSetBitValue( 0, 0, 0 );
}
if ( (mrt_counter > 200) && (mrt_counter <= 400) )
{
GPIOSetBitValue( 0, 0, 1 );
}
if ( (mrt_counter > 400) && (mrt_counter <= 600) )
{
GPIOSetBitValue( 0, 16, 0 );
}
if ( (mrt_counter > 600) && (mrt_counter <= 800) )
{
GPIOSetBitValue( 0, 16, 1 );
}
if ( (mrt_counter > 800) && (mrt_counter <= 1000) )
{
GPIOSetBitValue( 0, 17, 0 );
}
if ( (mrt_counter > 1000) && (mrt_counter <= 1200) )
{
GPIOSetBitValue( 0, 17, 1 );
}
else if ( mrt_counter > 1200 )
{
mrt_counter = 0;
}
}
}
main関数の頭からざーっと見ていくと、クロックの設定をして、LPC_SWM->PINASSIGN8関連のところはクロックをP0.12ピンに出力する?
LPC_SYSCON->SYSAHBCLKCTRL |= (1<<6);ここは飛ばして。
GPIOSetDir( 0, 0, 1 );ここでGPIOの入出力を設定。ここではGPIO P0.0ピンを"出力"に設定。
init_mrt(0x8000);ここも飛ばして。
while (1)でループ。
ループ内でmrt_counterの値によってGPIOSetBitValue( 0, 0, 0 );とか、GPIOSetBitValue( 0, 0, 1 );でGPIO P0.0(P0.16, P0.17も)をLOにしたりHIGHにしている。
mrt_counterは1200より大きくなると0にクリアする。
では、さっき飛ばしたinit_mrt(0x8000);の定義を見てみると、lpc800_driver_libプロジェクトの"lpc8xx_mrt.c"で定義されている。
void init_mrt(uint32_t TimerInterval)となっていて、処理内容としてはタイマーを設定していて、インターバルは引数で指定している。
で、同ソースファイルのちょっと上にvoid MRT_IRQHandler(void)が定義されていて、その中で mrt_counterがカウントアップされている。
次はLPC_SYSCON->SYSAHBCLKCTRL |= (1<<6);この行。
SYSAHBCLKCTRLは意味がわからないので、ユーザーズマニュアルを見るとp.36のTable 30にあって、6ビットを1にしているので、GPIOポートレジスタおよびGPIOピン1割り込みレジスタのクロックを有効にしているということ(?)。
と、ここまで読んできてSYSAHBCLKCTRLでググってたら詳しく解説しているサイトを見つけました。
このサンプルでは元々LPC812用でしたが、私のソースコードはLPC810用にGPIO p0.7をp0.0に書き換えています。
この行LPC_SYSCON->SYSAHBCLKCTRL |= (1<<6);の意味は、GPIOにクロックを供給することでGPIOが有効になるということのようです。
で、その上のLPC_SWM->PINASSIGN8関連のところは予想通りp0.12ピンにクロックを出力しているようです。
ただし、この機能はデバッグのためのようで、GPIOにクロックを出力する必要性は無いようです。
先のサイトではUARTのページのおまけの項でボード上のLEDが点灯するからくりのところで解説しています。
まぁ、大体の雰囲気はつかめたから"Blinky"はこれで終わり。
次は自分で新しいプロジェクト(I2CでMPU-6050を使う)を作りたい。