LPC810でLチカ色々(SCT)
2013年12月16日
一つ前の記事では、割込みも何も使わない最もシンプルな方法でGPIOを操作して、LEDをブリンクさせた。これは、単にLPC810へのプログラムの書き込みが出来ることを確認したに過ぎないので、もう少し高度なLEDブリンクを行なって、当面の目標(LPC810で作ってみたい、ある回路)に少しでも近づけたいと思う。
以前紹介したように、LPC810では、PWMの高機能版であるSCT(State Configurable Timer)が面白い。自分としては、是非これを使えるようにしておきたい。
まずは、Red State Machine file genaratorの設定は前と同じにした。ただし、maxcount=6000000とし、0.5秒に一度割り込みが起きる設定にしてある。ます、割り込みでソフト的にGPIOの出力をトグルして、ブリンクすることを試みた(注:正確な周期を生み出すには、5999999とするべきであろう)。
main.cは、以下の通り。
SCTを有効にするには、1)SCTにクロックを与える 2)halt状態を解除する の2つの手続きが必要なようである。また、割込みをSCT用に許可するようにしておく必要があった(いずれも、main()関数の冒頭)。割込み用の関数内では、LPC_SCT->EVFLAGの値を読み込んで、もう一度LPC_SCT->EVFLAGに入れ直す(?)必要があるようだ。この操作に何の意味があるのか、あとで調べておこう。いずれにしろ、このソースコードで、1秒おきのLEDブリンクが動いた。これで、SCTを用いた定期的な割込みのレッスンは、終了。
次に、普通のPWMを試してみる。まずは、定期的にトグルするモード。まずは、Red State Machineを書き換える。
イベントに、"TOGGLE Output pin 1"を追加してみた。始め、ここで言う"Output pin 1"が、GPIOの0_1と勘違いしており(LPC810のDIP-8の5番ピン)、「ん?動かない?」と思ったが、どうやら違うらしい。"Output pin 1"というのは、SCTにとっての1番ピンなのであって、それをSwitch Matrixという機構で、任意のピンに割り当てられるようである。それをふまえて作成したのが、次のmain.c
先のコードに対して、Switch Matrixの設定を、main()関数の冒頭部分に書き加えた。Switch Matrixの設定をどの様に行なうかは、User Manualを参照。これで、トグルモードも、レッスン修了。
次に、普通のPWMのモード。様々なデューティー比を取れるようにしてみる。
今度は、MATCH0/MATCH1という、2つのマッチを設定し、それぞれタイマー値がmaxcountもしくはmaxcount/2になる場合と設定した。MATCH0では出力をLに、MATCH1では出力をHにする設定。MATCH1でマッチする値を書き換えれば、デューティー比を変更することが出来る。main.cは、上記と同じ物。これもうまく動いたので、LPC810で無事にPWMを使えるようになったようだ。
最後に、普通のPWMでは出来ない、応用編を。タイマーの1サイクルの間に、LHLHと、2回ブリンクする様にしてみた。
MATCH0-3はそれぞれ、maxcount, maxcount/4, maxcount/2, maxcount*3/4でのマッチに設定し、L, H, L, Hと出力を切換えるようにした。これも無事に動作確認できた。
LPC810、面白いね。ここに書いた方法で、NTSCビデオのsyncシグナル部分を作成する予定。うまく行けば、32x24文字出力・PS/2キーボード入力のコンソールが、DIP-8の石一つで出来そうだ。
以前紹介したように、LPC810では、PWMの高機能版であるSCT(State Configurable Timer)が面白い。自分としては、是非これを使えるようにしておきたい。
まずは、Red State Machine file genaratorの設定は前と同じにした。ただし、maxcount=6000000とし、0.5秒に一度割り込みが起きる設定にしてある。ます、割り込みでソフト的にGPIOの出力をトグルして、ブリンクすることを試みた(注:正確な周期を生み出すには、5999999とするべきであろう)。
main.cは、以下の通り。
#ifdef __USE_CMSIS #include "LPC8xx.h" #endif #include <cr_section_macros.h> // TODO: insert other include files here #include "sct_fsm.h" // TODO: insert other definitions and declarations here void SCT_IRQHandler (void) { uint32_t status = LPC_SCT->EVFLAG; LPC_GPIO_PORT->NOT0 = 1<<0; // Toggle PIO0_0 /* Acknowledge interrupts */ LPC_SCT->EVFLAG = status; } int main(void) { // TODO: insert code here LPC_GPIO_PORT->DIR0 |= (1<<0); // PIO0_0: output // enable the SCT clock LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 8); sct_fsm_init(); // Enable SCT interrupt NVIC_EnableIRQ(SCT_IRQn); // unhalt the SCT by clearing bit 2 of the unified CTRL register LPC_SCT->CTRL_U &= ~(1 << 2); // Force the counter to be placed into memory // volatile static int i = 0 ; // Enter an infinite loop, just incrementing a counter while(1) { // for (i=0;i<100000;i++); } return 0 ; }
SCTを有効にするには、1)SCTにクロックを与える 2)halt状態を解除する の2つの手続きが必要なようである。また、割込みをSCT用に許可するようにしておく必要があった(いずれも、main()関数の冒頭)。割込み用の関数内では、LPC_SCT->EVFLAGの値を読み込んで、もう一度LPC_SCT->EVFLAGに入れ直す(?)必要があるようだ。この操作に何の意味があるのか、あとで調べておこう。いずれにしろ、このソースコードで、1秒おきのLEDブリンクが動いた。これで、SCTを用いた定期的な割込みのレッスンは、終了。
次に、普通のPWMを試してみる。まずは、定期的にトグルするモード。まずは、Red State Machineを書き換える。
イベントに、"TOGGLE Output pin 1"を追加してみた。始め、ここで言う"Output pin 1"が、GPIOの0_1と勘違いしており(LPC810のDIP-8の5番ピン)、「ん?動かない?」と思ったが、どうやら違うらしい。"Output pin 1"というのは、SCTにとっての1番ピンなのであって、それをSwitch Matrixという機構で、任意のピンに割り当てられるようである。それをふまえて作成したのが、次のmain.c
#ifdef __USE_CMSIS #include "LPC8xx.h" #endif #include <cr_section_macros.h> // TODO: insert other include files here #include "sct_fsm.h" // TODO: insert other definitions and declarations here void SCT_IRQHandler (void) { uint32_t status = LPC_SCT->EVFLAG; LPC_GPIO_PORT->NOT0 = 1<<0; // Toggle PIO0_0 /* Acknowledge interrupts */ LPC_SCT->EVFLAG = status; } int main(void) { // TODO: insert code here LPC_SYSCON->SYSAHBCLKCTRL |= (1<<7); /* Enable the Switch Matrix */ LPC_SWM->PINASSIGN7 = 0xFFFFFF01; /* SCT CTOUT_1 at P0.1 */ LPC_SYSCON->SYSAHBCLKCTRL &= ~(1<<7); /* Switch Matrix can be disabled to save current */ LPC_GPIO_PORT->DIR0 |= (1<<0); // PIO0_0: output // enable the SCT clock LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 8); sct_fsm_init(); // Enable SCT interrupt NVIC_EnableIRQ(SCT_IRQn); // unhalt the SCT by clearing bit 2 of the unified CTRL register LPC_SCT->CTRL_U &= ~(1 << 2); // Force the counter to be placed into memory // volatile static int i = 0 ; // Enter an infinite loop, just incrementing a counter while(1) { // for (i=0;i<100000;i++); } return 0 ; }
先のコードに対して、Switch Matrixの設定を、main()関数の冒頭部分に書き加えた。Switch Matrixの設定をどの様に行なうかは、User Manualを参照。これで、トグルモードも、レッスン修了。
次に、普通のPWMのモード。様々なデューティー比を取れるようにしてみる。
今度は、MATCH0/MATCH1という、2つのマッチを設定し、それぞれタイマー値がmaxcountもしくはmaxcount/2になる場合と設定した。MATCH0では出力をLに、MATCH1では出力をHにする設定。MATCH1でマッチする値を書き換えれば、デューティー比を変更することが出来る。main.cは、上記と同じ物。これもうまく動いたので、LPC810で無事にPWMを使えるようになったようだ。
最後に、普通のPWMでは出来ない、応用編を。タイマーの1サイクルの間に、LHLHと、2回ブリンクする様にしてみた。
MATCH0-3はそれぞれ、maxcount, maxcount/4, maxcount/2, maxcount*3/4でのマッチに設定し、L, H, L, Hと出力を切換えるようにした。これも無事に動作確認できた。
LPC810、面白いね。ここに書いた方法で、NTSCビデオのsyncシグナル部分を作成する予定。うまく行けば、32x24文字出力・PS/2キーボード入力のコンソールが、DIP-8の石一つで出来そうだ。