こんにちは,しんしーです!
infineon製のマイコンを使って,簡単にLED制御ができる手順を説明します。
この方法で実装から動作確認まで数分(ツールのインストール時間は含まず)で出来ます。ソフト組込を勉強したり,趣味でちょっと作ってみたりするのにオススメです。
- 使用するキットについて
- 開発統合環境DAVEを使ってソフト生成
- ソフトの書き込み/Debug
- 生成したLED制御の解説
すぐに使える導入キット
今回使用したキットは,infineon製のXMC1300シリーズのマイコンが実装されたものです。公式サイトはこちら

キットの主な特徴は2つあります。
- マイコン,LED6個,可変抵抗器が実装されている
- ソフト書き込み,Debug用の回路付き
あとはソフトを書き込んで,動作させることが可能です。
通信回路の基板とマイコン側の基板は折って分けることができます。折って分けてしまっても,通信側とマイコン側を接続するケーブルが入っています。ただし,USBケーブルが入っていなかったのでMicro USBが別途必要になります。

マイコンは特徴として,Arm Cortex-M0コアで動作周波数が32MHzです。タイマー,AD変換,CORDIC/DIVIDERなどの周辺機能が備わっています。モーターを制御出来るくらいの性能があります。
統合開発環境DAVEの操作方法
公式サイトからDAVEをダウンロードすることができます。公式サイトはこちら
フォームへの記入が求められるので,適当に入れてください。インストールが完了したらDAVEを起動します。
プロジェクトの作成
インストールした開発環境DAVEを起動します。

画面左上の「File」タブをクリックします。その後,「New」にカーソルを合わせるとメニューが表示されます。
その中の「DAVE Project…」をクリックします。

New DAVE Project画面が表示されます。Project Nameにプロジェクト名を入れてください。名前はどういったプロジェクトかわかるようにすると良いと思います。
Project Typeは「Easy Start Project」を選んでください。選択したら「Next」をクリックして下さい。

次に使用するマイコンを選択します。今回のキットに実装されたマイコンは,XMC1302の38ピンで,メモリサイズが200KBです。
そのため,XMC1300シリーズの中から「XMC1302-T038x0200」を選択します。その他は何も変更せず「Finish」をクリックして下さい。

先程まで空だった,C/C++ Projectsタブに先程作成したプロジェクトが入っている事を確認して下さい。
青枠のように数個のフォルダとファイルが作成されます。この中の「EasyMain.c」に簡単なLED制御のコードが記述されたファイルになります。

ソフトの作成と書き込み方法
先程の手順で作成したプロジェクトは,すでにLED制御するためのコードがEasyMain.cファイルに記述されています。そのため,何もコードを書くことなくLED制御を確認することができます。
書き込むためには,コードが記述されたファイルをマイコンに書き込むためのファイルに変換する必要があります。
変換作業はボタン1つで出来ます。Editタブの下にあるトンカチのようなアイコンをクリックします。

この変換作業はビルドと呼ばれ,コードに問題がないかチェックをしながらソフトに変換していきます。青枠のようにコードサイズ,及びfilename「プロジェクト名.elf」が表示されます。このファイルがソフトになります。

今回はすでに出来ているソフトなのでエラーは出ていませんが,変更を加えたり,1から作る際に間違いが含まれていると,エラーを表示してくれます。
接続ができたら,Projectタブの下にある虫みたいなアイコンをクリックします。

Debugの設定画面が開きます。未設定の場合に表示されるため,設定すると次回からはこの画面は出ません。
「GDB SEGGER J-Link Debugging」をダブルクリックして下さい。

するとDebug画面への切り替え確認が表示されます。青枠のチェックを入れれば,次回以降の表示されなくなります。「Yes」をクリックして下さい。

debug画面に切り替わります。基本的には赤枠内のボタンを使って操作します。主に実行ボタン(三角)と停止ボタン(四角)を使います。実行することでソフトがマイコンに書き込まれます。
実行後,キットの6つのLEDが順番に点灯し,消灯を繰り返します。可変抵抗器を変更すると点灯・消灯の間隔が速くなったり,遅くなったりします。

debugは追加した機能や自作したソフトを確認するのに便利な機能です。ステップ実行させて1つ1つの処理を確認したり,ブレークポイントを設けて特定の位置で停止させるなどが可能です。
EasyStartで生成されたLED制御
プロジェクト作成時に生成されたEasyMain.cにLED制御が記述されています。記述場所はSysTick_Handlerという関数内です。この関数は決められた周期(インターバル)で処理されます。
関数の処理は以下の通りです。
void SysTick_Handler(void)
{
static uint32_t ticks_uart = 0;
static uint32_t ticks_led = 0;
static uint8_t active_led = 1;
static uint8_t message = 0;
static const char *messages[] =
{
"Visit www.infineon.com/XMC\r\n",
"Visit www.infineonforums.com\r\n\r\n"
};
uint8_t i;
uint32_t adc_result;
uint32_t ticks_led_event = TICKS_LED_EVENT;
adc_result = VADC_G1->RES[0];
// Check if result is valid
if (adc_result & VADC_G_RES_VF_Msk)
{
adc_result &= VADC_G_RES_RESULT_Msk;
adc_result = (adc_result >> 4);
ticks_led_event += adc_result;
}
// Update LED status
ticks_led++;
if (ticks_led >= ticks_led_event )
{
switch (active_led)
{
case 1:
P0_0_toggle();
break;
case 2:
P0_1_toggle();
break;
case 3:
P0_6_toggle();
break;
case 4:
P0_7_toggle();
break;
case 5:
P0_8_toggle();
break;
case 6:
P0_9_toggle();
break;
default:
break;
}
if (active_led == NUM_LEDS)
{
active_led = 1;
}
else
{
active_led++;
}
ticks_led = 0;
}
// Update UART message
ticks_uart++;
if (ticks_uart == TICKS_UART_EVENT)
{
for(i = 0; i < strlen(messages[message]); i++)
{
USIC0_CH1->IN[0] = messages[message][i];
}
message ^= 1;
ticks_uart = 0;
}
}
LED点灯・消灯の間隔
コードを一部抜粋して解説します。このコードの意味を把握することで,好きなように間隔を変更することができます。
/* ①点灯・消灯の間隔を決める初期値 */
#define TICKS_LED_EVENT (100)
/* ②関数内で使用する変数の宣言と初期化 */
uint32_t adc_result;
uint32_t ticks_led_event = TICKS_LED_EVENT;
/* ③AD変換結果をadc_resultに引き渡し */
adc_result = VADC_G1->RES[0];
/* ④点灯・消灯の間隔を更新 */
if (adc_result & VADC_G_RES_VF_Msk)
{
adc_result &= VADC_G_RES_RESULT_Msk;
adc_result = (adc_result >> 4);
ticks_led_event += adc_result;
}
#defineは数値を文字に置き換えてくれます。数字だけでは意味が分かりませんが,文字で置くことで数字に意味を持たせてくれる役割があります。
SysTick_Handlerという関数は2ms毎に処理されるため,200ms間隔でLEDが点灯・消灯するように設定されます。
このTICKS_LED_EVENTの大きさを変えるとLEDの点灯・消灯間隔を変更することができます。
2つの変数を宣言しています。
- AD変換の結果を格納する変数(符号なし32bit)
- LEDの点灯・消灯間隔(符号なし32bit)
2つ目の変数はTICKS_LED_EVENTで定義された数値を,関数が呼ばれるごとに初期値としています。
可変抵抗器によって変化した電圧をAD変換により,その数値をデジタル値に変えてマイコンに取り込んでいます。
この変換した結果が格納されたレジスタ(VADC_G1->RES[0])の値をadc_resultに引き渡しています。
これにより,AD変換結果を計算に使うことができます。
if文の条件「adc_result & VADC_G_RES_VF_Msk」は,AD変換した結果がレジスタに格納したか否かを確認します。
変換が終了していれば,if文の中の処理が実行されます。
まず1行目の「adc_result &= VADC_G_RES_RESULT_Msk」は,変換結果の値のみ抽出します。
2行目の「adc_result = (adc_result >> 4)」は,右に4bitシフトすることで8bit分のデータに変換しています。
3行目の「ticks_led_event += adc_result」は,200ms間隔に初期化された変数にAD変換結果を加算します。この処理により可変抵抗器を変化させると,LEDの点灯・消灯間隔が更新されます。
LED点灯・消灯の制御
コードを一部抜粋して解説します。このコードの意味を把握することで,好きなようにLEDの点灯・消灯を変更することができます。
// Update LED status
/* ①時間測定 */
ticks_led++;
/* ②制御間隔の確認 */
if (ticks_led >= ticks_led_event )
{
/* ③LEDの選択 */
switch (active_led)
{
case 1:
P0_0_toggle(); /* ④LEDの点灯・消灯 */
break;
}
/* ⑤LEDの対象更新 */
if (active_led == NUM_LEDS) /* NUM_LEDS = 6 */
{
active_led = 1;
}
else
{
active_led++;
}
/* ⑥インターバルの初期化 */
ticks_led = 0;
}
ticks_led++の「++」は,変数の値を1プラス(インクリメント)する役割があります。
SysTick_Handlerという関数は2ms毎に処理されるため,その都度,値がインクリメントされます。これにより,2ms単位で時間を計測することができます。
if文の条件「ticks_led >= ticks_led_event」は,2ms単位で計測した時間ticks_ledと,制御間隔の時間であるticks_led_eventを比較します。
比較した結果,計測時間が制御間隔の時間の値以上であれば,if文の中の処理が実行されます。
switch case文を使用して,LEDを選択します。この条件分岐はif文でも記述可能ですが,より一目でわかりやすいのがswitch case文です。
switchの後に続く括弧内が条件となっており,今回は「active_led」という変数が条件になっています。active_led=1の時,case 1に記述された処理(breakまで)が実行されます。
active_ledの値の切り替え方やcaseに応じたLEDの選択により,LEDの点灯・消灯制御を好きなように変更することができます。
P0_0_toggle()は,予め用意されたXMCのAPIです。
処理内容は,「Port0の0番ピン」に対して,High(1)ならLow(0)を,LowならHighを出力するようにレジスタを設定してくれます。言い換えるとLEDがOFFならONに,ONならOFFにしてくれます。
if文で記述してもできますが,予めポートに機能が備わっていると,レジスタの操作だけで出力を制御することができます。
if文の条件「active_led == NUM_LEDS」は,LEDを選択するactive_ledの値とNUM_LEDSが等しいかを判断します。(個人的には等号は使わず,≧が良いと思います)
NUM_LEDSは実装されたLEDの数である6が定義されています。これによりactive_ledの数が6になったら1に戻し,6以外ならばactive_ledをインクリメントします。
ticks_ledは時間測定用に値がインクリメントされます(①時間測定)。
この時間が制御間隔の時間以上であれば,LED制御が実施されます(②制御間隔の確認)。
このままでは常にSysTick_Handlerという関数が実行されるたびに,②の条件が成立してしまいます(制御間隔が決められた間隔にならない)。
そのため,②の条件成立時に時間測定用の変数を0に初期化します。これにより所定の間隔で処理することができます。
まとめ
XMC 1300シリーズのキットを使用したLED制御を紹介しました。プロジェクトを作るだけで,すぐにLEDを点灯・消灯させることができます。
このソフトをベースにして,制御を変更して自分オリジナルのLEDの制御も作れます。
LED制御は,infineon製に限らず,STM製やRENESAS製などでも,同じように記述すれば作れるので参考にしてみて下さい。
コメント