LPC1343 GPIO割り込み処理 (Interrupt)

出来た事

GPIOの割り込み処理

-.GPIOをスイッチにしてLPC expressoのLEDをON-OFFさせる

開発Listへ戻る

久方ぶりにLPC1343 expressoを動かす意欲がわいてきました。
かなりのブランクなので、且つもともとC言語も良くわかってないので
感覚をつかむまで時間がかかりました。

今回は、LPC1343 expresso基板のLED (LED2 PIO0_7についてるやつ)を
GPIOをスイッチにしてON-OFFさせてみようと思います。

こんなイメージ

スイッチに使用するGPIOはPIO3.3にしました。理由はGNDに近いからです。

あとはexample codeを利用して作成です。
example codeはココのサイトから入手可能です。
LPC1300の部分の 

□サンプルコード/ LPCXpresso LPC1343
CMSIS 1.3 + ペリファラル・ドライバ。

ってやつをダウンロードしてZIP解凍後に
GPIOフォルダ→srcフォルダと開いていけば
中にgpio.c, gpio.h, gpiotest.cが見つかります。

gpio.c, gpio.hをプロジェクトのsrcフォルダにドラッグアンドドロップします。

であとはmain.cを以下のようにすればOK!

コード

#ifdef __USE_CMSIS
#include "LPC13xx.h"
#endif

#include
#include
#include "gpio.h"
__CRP const unsigned int CRP_WORD = CRP_NO_CRP ;

int main(void) {

GPIOInit();

GPIOSetDir( PORT0, 7, 1 ); // LED pin as output
GPIOSetValue( PORT0, 7, 0 );

LPC_IOCON->PIO3_3 = 0xd0; // Default setting = Pull up
GPIOSetDir( PORT3, 3, 0 );/* use port3_3 as input event, interrupt test. */

GPIOSetInterrupt( PORT3, 3, 0, 0,1 );/* port3_3, single edge trigger, active high. */
GPIOIntEnable( PORT3, 3 );

// Enter an infinite loop, just incrementing a counter
volatile static int i = 0 ;
while(1) {i++ ;}
return 0 ;
}


void PIOINT3_IRQHandler(void){
uint32_t regVal;

regVal = GPIOIntStatus( PORT3, 3 );
if ( regVal )
{
GPIOIntClear( PORT3, 3 );
}

LPC_GPIO0->DATA ^=0x80;
return;
}

解説

example codeの関数をふんだんにつかっています。

まずイニシャライズ
GPIOInit();
gpio.c内に入っているのですが見てみると
GPIO部のclockと割り込みを有効にしているだけです。


次はLED pinの出力設定と初期設定
GPIOSetDir( PORT0, 7, 1 ); // LED pin as output
GPIOSetValue( PORT0, 7, 0 );
2つの関数はgpio.hに入っています。
port番号とpioの番号を指定して、入出力の設定、出力の場合の値設定ができます。
汎用化されていて使いやすいです。

スイッチ用(割り込み用)の信号設定です。
LPC_IOCON->PIO3_3 = 0xd0; // Default setting = Pull up
GPIOSetDir( PORT3, 3, 0 );/* use port3_3 as input event, interrupt test. */
PIO3_3を使用します。
デフォルトでプルアップなのですが、一応設定しておいたのと
入力に設定しています。

割り込みの設定です。
GPIOSetInterrupt( PORT3, 3, 0, 0,1 );/* port3_3, single edge trigger, active high. */
GPIOIntEnable( PORT3, 3 );

PIO3_3の割り込み設定をsingle edgeで rigingにしています。
カッコ内のPORT3,3 の後が Edge割り込みなのかLevel割り込み(=1)なのか?
次が、Single edgeかDouble edge(=1)か?
最後がActive Low or High(=1)です
そしてPIO3_3の割り込みを有効にしています。

これで設定は終わりで、
次は割り込みが入ったときの動作記載です。
void PIOINT3_IRQHandler(void){
この関数もgpio.cの中に記載されています。(無効化されています)

次は割り込みのステータスを確認して、割り込みのフラグをClearしています。
今回はPIO3_3だけしか使っていないのでステータスの確認は不要としても
良いと思いますが2本以上割り込みを使う場合、
たとえばPIO3_3,PIO3_2の2本を使う場合、PIO3_3の割り込みもPIO3_2の
割り込みも発生したら同じ PIOINT3_IRQHandler関数に飛びますので
どちらの割り込みなのかを判別する必要が発生します。
今回使用したサンプルコードはそのようなことを想定していると思います。
なおClearを忘れると、ずっと割り込み状態になるので注意!
regVal = GPIOIntStatus( PORT3, 3 );
if ( regVal )
{
GPIOIntClear( PORT3, 3 );
}

最後にLEDの出力を反転させて終わりです。
LPC_GPIO0->DATA ^=0x80;

mbed スタートアップ& サンプルプログラムの作成 

やったこと

1. mbed スタートアップ
  & サンプルプログラムの作成 

使用module
  キャラクターLCD (16x2), 温度センサー (LM60 秋月で100円)

最後のエントリーが2012年の7月15日で半年振りです。
やっぱり久しぶりだとブログサイトの使い方も忘れて大変。。


で、これからしばらくはmbedをやっていこうと思います。

なんてったって、コンパイラがcloudってところが、楽でよさそう。
コンパイル速度がマシン性能に拠らないし
PC変えたときに再インストとか必要ないし
時代的にはCloudでしょー

携帯のキャリア変えたときに
メールアドレス変わりましたメールを送って、
送りつけられた人々はイチイチ自分の端末いじって登録変更
送るほうも送られるほうも面倒です。
それがLINEみたいなCloudでベースであれば
一気に解決!


そんなことは、どうでも良いのですが
スタートは本から派なので、大型書店まで出かけて探してきました。

mbed参考書(超初心者向け)
超お手軽マイコンmbed入門: みんなで簡単ガジェット作り (マイコンと電子工作)
作者: 勝純一
出版社/メーカー: CQ出版

CQ出版でありがちな
最初のほうは分かるんだけど、直ぐに意味不明に陥る事は
(超初心者向け→上級者向けにジャンプ)
約半分の60ページまで読み進めた段階で大丈夫でした。

mbedからツイッターに送信方法なども記載があって
順番に進めて行きたいと思っとります。


準備物
mbedとBoard orange (共にスイッチサイエンス)がメイン。
2つとも購入しました。
mbed NXP LPC1768 : 5250yen
☆Board Orange 完成基板: 3900yen

Board Orangeには
キャラクターLCD (16x2)
MiniSD slot等が付属しています。

これに、自分で持っていた温度センサー LM60 (秋月 100yen)
を使って、
本に記載されている以下の項目を実行中です!

1. 温度センサーの値をLCDに表示
2. SD cardに温度センサーの値を記録

現時点で1まで簡単にできました。
本に書いてあることなのでコード紹介等はできませんが
後日オリジナルを作って紹介していきたいと思います。

LPC1343 ディープパワーダウンモード(Deep Power down mode)への移行と復帰

やったこと

1. ディープパワーダウンモード(Deep power down mode)への移行と復帰

開発Listへ戻る

使用したプロジェクトです。ご自由にダウンロードください
DeepPowerDown_SampleProject_withRef.zip 直

久しぶりにマイコンにさわりました〜。。
夏場は日が長くって運動やら何やら体が疲れてなかなかマイコンさわる気がおきない。。

とはいえ一ヶ月に最低一度はUPしようとDeep power downモードをやって
ブログを書き進める・・・

いつの間にか10,000カウント超えてる〜
ブログをはじめて半年ちょっと!嬉しいですね。
ありがたいことです。


で、今回はDeep power down モードですが
結果から言うと簡単でしたね。

カットアンドトライも無く,ググッて英語サイト調べる必要も無かったです。

下のようにやってすんなり出来ました。

1.アプリケーションノートのAN10973通りの記載

2.それでWAKEUP PINをプルアップ
(WAKEUP PINはLPC1343の場合P1.4です。)

3.プログラム走らせる→Deep power down modeに入る

4.P1.4をGNDにつなげる = Deep power down modeから復帰 = Chip reset


確認方法

Timerを使ったLEDの点滅を設定後に、Deep power down モードに入ります。
点滅の間隔を変化させることで復帰後のChip resetがわかるようにしています。

Power on(Chip reset) → 0.1s毎に点滅→0.5s毎に点滅→Deep power down

→Deep Power down モードに入ったので点滅しないことを確認します。
 Resetボタンを押しても何も変わらないことを確認します。

P1.4をGNDに接続することでDeep sleep modeから抜けるようにします。
→Chip resetなので0.1s間隔での点滅開始を確認します。

回路: LEDの点滅は。LPCexpresso1343のP0.7についているLEDを使用します。
   Resetスイッチをつけます。(Reset動作確認したい場合)
   P1.4をプルアップしておきます。(黄色いWireと抵抗の部分)
   P1.4を直接ブレッドボードでワイヤを使ってGNDに接続しDeep Sleepから抜け出します。



コード
main.cを空にして、以下をCopy & Pasteすれば動きます。

#ifdef __USE_CMSIS
#include "LPC13xx.h"
#endif

#include
#include

__CRP const unsigned int CRP_WORD = CRP_NO_CRP ;


int main(void) {

// Test circuit code //
LPC_IOCON->PIO0_7 = 0x00; // set as GPIO (LPCexpresso LED control PIN)
LPC_GPIO0->DIR |= 0x80; // p0_7 as output
LPC_GPIO0->MASKED_ACCESS[0x080]=0x080; //P0_7=1(LED on)

// 32bit counter
NVIC_EnableIRQ(TIMER_32_1_IRQn); // enable Timer32_1 interrupt handler

LPC_SYSCON->SYSAHBCLKCTRL |=0x400; // Timer32B1 Turn ON
LPC_TMR32B1->PR =7200-1; // 0.1ms ,10kHz(Max 32bit dec:4294967295)
LPC_TMR32B1->MCR=0x003; // Reset timer on MR0 and interrupt
LPC_TMR32B1->MR0 = 1000; // 0.1sec
LPC_TMR32B1->TCR =2; // TCR Reset
LPC_TMR32B1->IR =0x0F; // Clear interrupt flag
LPC_TMR32B1->TCR =1; // TCR start


// Enter an infinite loop, just incrementing a counter
volatile static int i = 0 ;
while(1) {
i++ ;
}
return 0 ;
}


void TIMER32_1_IRQHandler(void) {
static int i=0;

LPC_GPIO0->DATA ^=0x80; // Toggle P0_7

if(i<=100){
i++;
}

if(i==20){
LPC_TMR32B1->MR0 = 5000; //Change interval 0.1sec-> 0.5sec
}

if(i==31){
//Go to Deep Power down mode
LPC_PMU->PCON = (1<<1) | (1<<11);
SCB->SCR |=(1<<2);
LPC_SYSCON->PDRUNCFG &= ~( (1<<0) | (1<<1));
__WFI();
}

LPC_TMR32B1->IR =0x0F; // Clear interrupt flag
}

コード解説 

コード内のコメントで十分ではないかと思います。
タイマーの割り込みで20回0.1秒で点滅させた後に
10回0.5秒で点滅させPower down突入

パワーダウンモード突入部分は
アプリケーションノートのAN10973通りの記載です。

使用したプロジェクトです。ご自由にダウンロードください
DeepPowerDown_SampleProject_withRef.zip 直

開発Listにもどる

LPC1343 ディープスリープモード(Deep Sleep mode)移行 とGPIOからの復帰

やったこと

1. ディープスリープモード(Deep Sleep mode)へ移行とGPIOからの復帰

開発Listへ戻る

前回はSleep modeを行ったので
次はDeep Sleep modeを試してみたいと思います。

Sleep modeよりもめんどくさかった。。。

まず、マニュアル UM10375を見てもよくわからないので
アプリケーションノートのAN10973を見るわけですが
こいつにもDeep Sleep modeの入り方のサンプルはあっても、復帰のさせ方のサンプルは無く・・
たらい回しにされたのに目的達成できず!
なんだか公務員関係の施設に行ったときのような対応に感じるのです。
(あくまでイメージです。。あしからず!)

結局のところ、英語でググってNXPのCommunityのスレッドを参考に試してみてわかったという感じです。
やっぱりインターネットってスゲー、グローバルってスゲーとつくづく思います。

前置きはこれくらいで、本題です。

Deep sleep modeですがマニュアルを読むと

  • レジスタ情報やSRAMの情報は維持されたまま、ほぼ全部がストップする。
  • "ほぼ"に入らないファンクションはBOD(電圧降下検出)とWatch dog

ということらしいです。

復帰方法は以下4種類のようです。

  • PIO0_〜PIO0_11, PIO1_0計13本のGPIOのどれか一つを利用 ←今回はコレを確認
  • BOD回路からのリセット
  • Watch Dog Timerからのリセット
  • Reset pinからのリセット


確認方法

Timerを使ったLEDの点滅を設定後に、Deep sleep modeに入ります。
→Deep sleep modeに入ったので点滅しないことを確認します。
P0.2をGNDに接続することでDeep sleep modeから抜けるようにします。
→点滅開始を確認します。

回路: 特別なものはありません。LPCexpresso1343のP0.7についているLEDを使用します。
   またP0.2 (SSEL)を直接ブレッドボードでワイヤを使ってGNDに接続しDeep Sleepから抜け出します。

動作イメージ図


コード
main.cを空にして、以下をCopy & Pasteすれば動きます。

#ifdef __USE_CMSIS
#include "LPC13xx.h"
#endif

#include
#include

// Variable to store CRP value in. Will be placed automatically
// by the linker when "Enable Code Read Protect" selected.
// See crp.h header for more information
__CRP const unsigned int CRP_WORD = CRP_NO_CRP ;



int main(void) {

// Test circuit code //
LPC_IOCON->PIO0_7 = 0x00; // set as GPIO (LPCexpresso LED control PIN)
LPC_GPIO0->DIR |= 0x80; // p0_7 as output
LPC_GPIO0->MASKED_ACCESS[0x080]=0x080; //P0_7=1(LED on)

// 32bit counter
NVIC_EnableIRQ(TIMER_32_1_IRQn); // enable Timer32_1 interrupt handler

LPC_SYSCON->SYSAHBCLKCTRL |=0x400; // Timer32B1 Turn ON
LPC_TMR32B1->PR =7200-1; // 0.1ms ,10kHz(Max 32bit dec:4294967295)
LPC_TMR32B1->MCR=0x003; // Reset timer on MR0 and interrupt
LPC_TMR32B1->MR0 = 5000; // 0.5sec
LPC_TMR32B1->TCR =2; // TCR Reset
LPC_TMR32B1->IR =0x0F; // Clear interrupt flag
LPC_TMR32B1->TCR =1; // TCR start


// Deep Sleep mode code//
LPC_SYSCON->PDRUNCFG &= ~( (1<<0) | (1<<1) | (1<<2));

//Switch MAINCLK to IRC clock
LPC_SYSCON->MAINCLKSEL =0;
LPC_SYSCON->MAINCLKUEN =0;
LPC_SYSCON->MAINCLKUEN =1;
while(!(LPC_SYSCON->MAINCLKUEN & 0x01));

LPC_SYSCON->PDSLEEPCFG = 0x00000FFF; // BOD & Watch dog both off

//Specify peripherals to be powerd up again when wake up
LPC_SYSCON->PDAWAKECFG = LPC_SYSCON->PDRUNCFG;


LPC_SYSCON->STARTAPRP0 &=~(1<<2);//Falling Edge of P0.2 is Wake up logic
LPC_SYSCON->STARTRSRP0CLR |= (1<<2); // Clear pending bit of P0.2
LPC_SYSCON->STARTERP0 |=(1<<2);// Enable Start Logic of P0.2
NVIC_ClearPendingIRQ(WAKEUP2_IRQn);
NVIC_EnableIRQ(WAKEUP2_IRQn);

SCB->SCR |=(1<<2); // Set deepsleep bit

__WFI(); // Go to Deep Sleep mode


// Enter an infinite loop, just incrementing a counter
volatile static int i = 0 ;
while(1) {
i++ ;
}
return 0 ;
}


void WAKEUP_IRQHandler(void) {

LPC_SYSCON->STARTRSRP0CLR |= (1<<2); //Clear pending bit of P0.2
LPC_SYSCON->STARTERP0 &=~(1<<2); //Disable Start logic of P0.2

// Change MAINCLK to System PLL clock
LPC_SYSCON->MAINCLKSEL =3;
LPC_SYSCON->MAINCLKUEN =0;
LPC_SYSCON->MAINCLKUEN =1;
while(!(LPC_SYSCON->MAINCLKUEN & 0x01));
}


void TIMER32_1_IRQHandler(void) {

LPC_GPIO0->DATA ^=0x80; // Toggle P0_7
LPC_TMR32B1->IR =0x0F; // Clear interrupt flag
}

コード解説 
TimerやLEDの動作は割愛してDeepSleepの動作のみ説明します。

まず、RCクロックとFlashのパワーをONにします。リセットバリューでオンになっているようですので
明示的に行っているようです。

LPC_SYSCON->PDRUNCFG &= ~( (1<<0) | (1<<1) | (1<<2));


次はメインクロックをRCクロックに変えています。
MAINCLKENを0→1にする件はマニュアルに指示があります(UM10375の3.5.15項)
ちなみにRCクロックにする理由は低消費電力にするためです。
以下の記載をコメントアウトして試しましたがちゃんと動作しました。
(PLLクロックを使ってもDeep Sleepに入って復帰できます)

LPC_SYSCON->MAINCLKSEL =0;
LPC_SYSCON->MAINCLKUEN =0;
LPC_SYSCON->MAINCLKUEN =1;
while(!(LPC_SYSCON->MAINCLKUEN & 0x01));


BODとWatch dogのコントロールです。
DeepSleep中でもBODとWatch Dogを動かすかを選択します。今回は両方OFFです。
選択方法はアプリケーションノートのAN10973に載ってます。

LPC_SYSCON->PDSLEEPCFG = 0x00000FFF; // BOD & Watch dog both off


Deep sleepから復帰するときに、Power ONする設定です。こいつが無いと動かなかったです。

LPC_SYSCON->PDAWAKECFG = LPC_SYSCON->PDRUNCFG;


P0.2でWake upするための設定です。
Falling edgeでWake upするようにしています。
Pending bitのClearも必要です。Status registerの初期値が不安定で
Start logic(Wake up条件)が入った状態となっていた場合、直ぐに割り込み状態に遷移してしまいます。
割り込みを有効にする前にしっかりとクリアしておく必要があります。
STARTERP0でスタートロジックを受け付けるようにします。
その後割り込みを有効化します。どのPIOを利用するかでWAKEUP2_IRQnの数字の部分が変わることに注意です。
(マニュアルではP0.1〜P0.11,P1.0の13本が使えるということでした)

LPC_SYSCON->STARTAPRP0 &=~(1<<2);//Falling Edge of P0.2 is Wake up logic
LPC_SYSCON->STARTRSRP0CLR |= (1<<2); // Clear pending bit of P0.2
LPC_SYSCON->STARTERP0 |=(1<<2);// Enable Start Logic of P0.2
NVIC_ClearPendingIRQ(WAKEUP2_IRQn);
NVIC_EnableIRQ(WAKEUP2_IRQn);


そしてSleep modeをDeep sleepに設定して眠りに落ちます。

SCB->SCR |=(1<<2); // Set deepsleep bit
__WFI(); // Go to Deep Sleep mode


Wake upの方法です。
まず、関数名ですがWAKEUPとなっています。WAKEUP2では無いところに注意です。
最初の2行です。
Pending bitをClearは念のためみたいなものです。(Start logicをDisableすれば不要です)
Start logicをDisableすることでこの割り込みには入ってこないようになります。
(Start logicのDisableなしで、Pending bitをClearしないと
割り込み処理を抜けてから直ぐまた割り込み処理に入るループになりました)
ちなみに割り込み名にWAKEUPとついているのでSleepに入っているときだけ有効!というわけではありません。
WAKEUPしている通常状態でも条件になれば割り込みが入ります。
なのでDisableすることが必要です
(今回も__WFI();をコメントアウトしてSleepに入らずにあらかたの動作確認をしていました)

void WAKEUP_IRQHandler(void) {
LPC_SYSCON->STARTRSRP0CLR |= (1<<2); //Clear pending bit of P0.2
LPC_SYSCON->STARTERP0 &=~(1<<2); //Disable Start logic of P0.2

// Change MAINCLK to System PLL clock
LPC_SYSCON->MAINCLKSEL =3;
LPC_SYSCON->MAINCLKUEN =0;
LPC_SYSCON->MAINCLKUEN =1;
while(!(LPC_SYSCON->MAINCLKUEN & 0x01));
}

WAKEUPから復帰でき無い状態だと、ROM焼きができません。
その場合はFT/GPIO pinをGNDにすることで解決できます。
(参考以前のエントリ: LPC1343 SWDIOをGPIOに設定したときのリカバリ法

Deep Sleepの時の電力まで確認する設備が無いのでやりませんが
LPC_SYSCON->PDRUNCFGで余分なものをパワーダウンすれば電力はもっと減るんじゃないかと思います。


開発Listにもどる

LPC1343 スリープモード(Sleep mode )

やったこと

1. スリープモード(Sleep mode)使用

開発Listへ戻る

LPC1343のスリープモード(Sleep mode)

スリープモードを調べていくことにしました。
マニュアル(UM10375)を見ると3つのモードがあるようです。

1)スリープモード (Sleep mode)
2)ディープスリープモード(Deep sleep mode)
3)ディープパワーダウンモード(Deep power down mode)


今回はスリープモードをやっていきます。

スリープモードは

  • .MCUのコアがストップするが周辺機能(Timerとか)は動いている
  • .Interruptが入るとスリープモードから抜ける。

Interruptが入るまでコードの次の行に進まないという事なようです。


使い方
マニュアルを見ると使い方が書いてあります。(UM10375 3.9.2.2項)
1)PCONレジスタのDPDEN bitを0にする
2)ARM Coretex-M3 SCRレジスタのSLEEPDEEP bitを0にする
3)ARM Coretex-M3 Wait-For-Interrupt インストラクションを使う

1)はレジスタの説明がユーザマニュアルに書いてあるのでOKなんですが
2),3)が良くわかりません。

キーワードをイロイロ入れてググッて見たところ
LPC13xxでのローパワーモードとWake upについての資料をみつけました
(AN10973)

上記の2)ですがSLEEPDEEP bitはSCRレジスタの第2ビットで書き方は
SCB->SCR &= ~(1<<2); // Clear SLEEPDEEP bit
です。

3)については
__WFI();
で良いようです


確認方法

LPC1343 Expressoに内蔵されているP0.7でコントロールするLEDと
さらに追加でP0.6でコントロールするLEDを追加し
2つのLEDで確認します。

2つのLEDとスリープの関係は以下のようにします。
LED0.7を点灯させ
Timerをスタートさせた後でスリープ状態にします。
5秒後のタイマーのinterruptでLED0.7を消灯
スリープから復帰後にLED0.6を点灯させます。
LED0.7とLED0.6が交互に点灯するという感じで見えます。

スリープがなければLED0.7とLED0.6はほぼ同時に点灯し
Timerで5秒カウント後にLED0.7だけ消えます。

コード

#ifdef __USE_CMSIS
#include "LPC13xx.h"
#endif

#include
#include

// Variable to store CRP value in. Will be placed automatically
// by the linker when "Enable Code Read Protect" selected.
// See crp.h header for more information
__CRP const unsigned int CRP_WORD = CRP_NO_CRP ;

int main(void) {
LPC_PMU->PCON &= 0xFFC; // Clear flag bit, DPDEN bit set 0
SCB->SCR &= ~(1<<2); // Clear SLEEPDEEP bit,

LPC_IOCON->PIO0_6 = 0x00; // set as GPIO (Additional LED control PIN)
LPC_IOCON->PIO0_7 = 0x00; // set as GPIO (LPCexpresso LED control PIN)
LPC_GPIO0->DIR |= 0xC0; // P0_6 & p0_7 as output

LPC_GPIO0->MASKED_ACCESS[0x0C0]=0x080; //P0_6=0(LED off) P0_7=1(LED on)
// 32bit counter
NVIC_EnableIRQ(TIMER_32_1_IRQn); // enable Timer32_1 interrupt handler

LPC_SYSCON->SYSAHBCLKCTRL |=0x400; // Timer32B1 Turn ON

LPC_TMR32B1->PR =7200-1; // 0.1ms ,10kHz(Max 32bit dec:4294967295)
LPC_TMR32B1->MCR=0x005; // Stop timer on MR0 and interrupt
LPC_TMR32B1->MR0 = 50000;// 5sec
LPC_TMR32B1->TCR =2; // TCR Reset
LPC_TMR32B1->IR =0x0F; // Clear interrupt flag
LPC_TMR32B1->TCR =1; // TCR start

__WFI(); // Go to Sleep mode

LPC_GPIO0->DATA |=0x40; // P0_6=1(LED on)

// Enter an infinite loop, just incrementing a counter
volatile static int i = 0 ;
while(1) {
i++ ;
}
return 0 ;
}

void TIMER32_1_IRQHandler(void) {

LPC_GPIO0->DATA ^=0x80; // Toggle P0_7
LPC_TMR32B1->IR=0x0F; //clear interrupt flag
}


コード解説 

大体コメントでわかるかなー、と思います
しいて言えば、PCONの設定ではスリープ状態のFlagのクリアとDPDEN bitの0 setを同時にしています。

LPC_PMU->PCON &= 0xFFC; // Clear Flag bit, DPEEN bit set 0

__WFI();をコメントアウト有り無しで確認したところ
先に説明したとおりの動作になりました。

AN10973にはDeep sleep mode, Deep power down modeも説明が載っていたので
試していこうと思います。

開発Listにもどる

USBオシロスコープ PicoScope2204

秋月電子でUSBのオシロを購入しました。

オシロスコープは結構安いのが出ていて
小型のデジタルオシロはハンテック製のが29,800円で売っていたりします。
こちら

デジタルオシロだと置き場に困るということと、
出張とかでも使えそうなんで、私の場合はUSBタイプを選択です。

必要なスペックは人それぞれですが
私の場合はそんなに早い周波数を見るつもりはなかったので
10MHz帯域の一番安いもので十分と判断しました。

PicoScope2204 (秋月 18,000円)

プローブがついていないので2ch分=2本購入

高性能オシロスコープ・プローブ(秋月 1,000円 x2)
Pico高性能プローブ1400円というのもありましたが
1000円のものでも使えるようです(どこかのブログ記事にあったので。。)

インストール! (所要時間5分)
私のPCはwin6 64bitで、秋月のHPには
"PicoTechnology社より64bit対応のPicoScope6をダウンロードしてください"
とありましたが、
付属のCDは既にアップデートされているようで日本語対応のPicoscope6が入っていました。
なので、CD入れて操作のガイドに従うだけで問題なくセットアップできました!

UPBオシロの外観

測定画面
LPC1343から周期100msのPWMを2本出力し、波形を測定しました。
いい感じです!

LPC1343 TimerのIRフラグとGPIO MASKED_ACCESS

やったこと

1. TimerのIR(interrupt)フラグを利用して2本のPWMコントロール
2. PWMはMASKED_ACCESS機能を利用してコントロール

開発Listへ戻る

コンセプト
たいしたことじゃないんですけど
スイッチ回路のコントロールで下みたいなタイミングを作りたかったので
Timer32を使って作ってみたのです。
またGPIOのHigh LowをコントロールするときにMASKED_ACCESSというやり方で
変更したいBitだけ指定して変更するというやり方を試してみました。


接続図
P2.4とP2.5をGPIOにしてLEDの点滅を目視で確認する形にしました。


コード

#ifdef __USE_CMSIS
#include "LPC13xx.h"
#endif

#include
#include

// Variable to store CRP value in. Will be placed automatically
// by the linker when "Enable Code Read Protect" selected.
// See crp.h header for more information
__CRP const unsigned int CRP_WORD = CRP_NO_CRP ;


int main(void) {
int s=0;

//PIO setting
LPC_IOCON->PIO2_4 =0x00; // PIO0_4 as GPIO
LPC_IOCON->PIO2_5 =0x00; // PIO0_5 as GPIO
LPC_GPIO2->DIR |=0xFF; // PIO0_4 & 0_5 as output

LPC_GPIO2->DATA =0xFF; // Check MASKED_ACCESS
LPC_GPIO2->MASKED_ACCESS[0x030]=0x000; // Check MASKED_ACCESS
LPC_GPIO2->MASKED_ACCESS[0x030]=0x010; // Check MASKED_ACCESS
s=LPC_GPIO2->MASKED_ACCESS[0x030]; //Check MASKED_ACCESS

// 32bit counter
NVIC_EnableIRQ(TIMER_32_1_IRQn); // enable Timer32_1 interrupt handler

LPC_SYSCON->SYSAHBCLKCTRL |=0x400; // Timer32B1 Turn ON

LPC_TMR32B1->PR =7200-1; // 0.1ms ,10kHz(Max 32bit dec:4294967295)

LPC_TMR32B1->MCR=0x003; // Reset timer on MR0 and interrupt
LPC_TMR32B1->MCR|=0x008; // Interrupt on MR1 no reset
LPC_TMR32B1->MCR|=0x040; // Interrupt on MR2 no reset
LPC_TMR32B1->MCR|=0x200; // Interrupt on MR3 no reset

LPC_TMR32B1->MR0 = 100000; // 10sec
LPC_TMR32B1->MR1 = 80000; // 8sec
LPC_TMR32B1->MR2 = 50000; // 5sec
LPC_TMR32B1->MR3 = 30000; // 3sec


LPC_TMR32B1->TCR =2; // TCR Reset
LPC_TMR32B1->IR =0x0F; // Clear interrupt flag
LPC_TMR32B1->TCR =1; // TCR start

// Enter an infinite loop, just incrementing a counter
volatile static int i = 0 ;
while(1) {
i++ ;
}
return 0 ;
}

void TIMER32_1_IRQHandler(void) {
int t = 0 ;

t=LPC_TMR32B1->IR; //Copy IR flag

if(t==0x1){ //match on MR0
LPC_GPIO2->MASKED_ACCESS[0x030]=0x020;
}else if(t==0x2){ // match on MR1
LPC_GPIO2->MASKED_ACCESS[0x030]=0x030;
}else if(t==0x4){ // match on MR2
LPC_GPIO2->MASKED_ACCESS[0x030]=0x010;
}else if(t==0x8){ // match on MR2
LPC_GPIO2->MASKED_ACCESS[0x030]=0x030;
}


LPC_TMR32B1->IR=0x0F; //clear interrupt flag
}


コード解説 

大体コメントでわかるかなー、ということで今回調べて使ってみた部分だけ開設します。

・MASKED_ACCESS確認
 GPIO2.4, 2.5だけ変化させるようにコントロールします。

まずGPIO2のDATAをわかりやすくするためにFFにしておきます。
GPIO2のDATAレジスタがFFFになっていることがわかります。
LPC_GPIO2->DATA =0xFF; // Check MASKED_ACCESS


次にMASKED_ACCESSでPIO2.4, 2.5の部分だけ00にします。
LPC_GPIO2->MASKED_ACCESS[0x030]=0x000; // Check MASKED_ACCESS


GPIO2のDATAレジスタがFFF→FCFになって
4bitと5bitが0になっていることがわかります。
"=0x00"となっているにもかかわらず、[0x030]で1になっている
4bit目と5bit目だけ変わっています。


もう一度確認、今度は2.4=1, 2.5=0を入れてみます。 LPC_GPIO2->MASKED_ACCESS[0x030]=0x000; // Check MASKED_ACCESS


今度はMASKED_ACCESSでDATAを取り出します。
初期値に0を入れておいた"s"という関数に4bit目、5bit目のみ
取り出します。

s=LPC_GPIO2->MASKED_ACCESS[0x030]; //Check MASKED_ACCESS

GPIO2のDATAは0xFDFでしたがsの値は0x10になっています。
4bit目と5bit目のみを抽出したからです。


次はTimer interruptを使ったPWM操作です。
4つのMRポイントを使って以下のようにコントロールしています。
MR0がリセットポイントです。


MRの値はLEDを目視で確認するために秒単位で設定しています。

インターラプトの割り込み処理では
どのインターラプトフラグがHighになっているかをif文で
判別してMASKED_ACCESSでPWMをコントロールしています。
そして最後にMR0-3同時にinterrupt flagをclearしています。

void TIMER32_1_IRQHandler(void) {
int t = 0 ;

t=LPC_TMR32B1->IR; //Copy IR flag

if(t==0x1){ //match on MR0
LPC_GPIO2->MASKED_ACCESS[0x030]=0x020;
}else if(t==0x2){ // match on MR1
LPC_GPIO2->MASKED_ACCESS[0x030]=0x030;
}else if(t==0x4){ // match on MR2
LPC_GPIO2->MASKED_ACCESS[0x030]=0x010;
}else if(t==0x8){ // match on MR2
LPC_GPIO2->MASKED_ACCESS[0x030]=0x030;
}


LPC_TMR32B1->IR=0x0F; //clear interrupt flag
}


開発Listにもどる