MSP430開発入門講座(1) ボタンでLEDをon/off(GPIO)
概要
基礎の基礎 『ボタンを押したら緑点灯/赤消灯, 離したらその逆』を 作ります。 大まかなポイントは次のとおり。
- ピンの設定をする。
- 入力ピン(ボタン)を読む。
- 出力ピンに出力する。
ピンの設定をする
PxSEL, P1SEL2: どのペリフェラルに割り当てるのか。
多くのマイコンは1本のピンに複数の役割が割り当てられており、
使う前にプログラム中で設定する必要があります
(注: MSP430は違いますが、一部のマイコンにはプログラム中からは
設定不可能で、プログラムを書き込み時に行うものもあります)。
MSP430の場合、ピン機能の設定を行うのは PxSEL, PxSEL2
レジスタ(x はポート番号で1か2)です。
具体的にどのような値にするかというと (MSP430 は品種毎にピン機能が変わってきますので)、 個別品種のデータシートを見る必要があります。 例えばLaunchPad付属の MSP430G2231 を 使うなら msp430g2231.pdf です。一番最後の方の “APPLICATION INFORMATION” の表に具体的な設定例が書いてあります(Table 13〜)。
では実際の例で考えましょう。LaunchPad を見ると、シルク印刷から LED はP1.0, P1.6 (それぞれ、 ポート1の第0ビット、ポート1の第6ビット)につながっており、 タクトスイッチはP1.3につながっていることがわかります。 では、まず P1.0 を出力ポートに設定しましょう。 msp430g2231.pdf の Table 13 にはこんなふうに書いてあります。 (あ、このデバイスには PxSEL2 はないのね。)
ポートP1, bit0の機能(msp430g2231.pdfより抜粋)
| PIN NAME(P1.x) | x | FUNCTION | P1DIR.x | P1SEL.x |
|---|---|---|---|---|
| P1.0/ | 0 | P1.0(I/O) | I: 0; O: 1; | 0 |
| TA0CLK/ | 0 | TA0CLK | 0 | 1 |
| ACLK | 0 | ACLK | 1 | 1 |
FUNCTION列とP1SEL.x列に注目してください。 今はディジタルI/Oポートとして使いたいので、 [FUNCTION]↓[P1.0(I/O)]→と目を動かすと P1SEL0 を 0 にすればいいことがわかります。 同様に もう一つの LED とタクトスイッチについても、 P1SEL.6=0, P1SEL.3=0 ということがわかります。 以上を行うには次のようなコードを書けばいいです。
P1SEL &= ~(BIT0 + BIT6 + BIT3);
え? BIT0, BIT6, BIT3 って(想像はつくけど)何よ、ですか?
これらは mspgcc の中で定義されている定数です。詳しくは
/opt/msp430-gcc-4.4.3/msp430/include/を探索
してください。はい、ご想像のとおりの値です。
ところで、これらの設定(P1SEL.x = 0)は、 実はデフォルト(正しくは PUC (power up clear) 時設定 なので、電源入れてそのまま使う分には必要ありません。
PxDIR: 入力か、出力か
これは単純。 PxDIR が 0 のビットは入力ピン。1のビットは出力ピンになります。 デフォルト(PUC時設定)は0です。
今回は P1.0, P1.6 が LED なので出力、P1.3 がスイッチなので 入力です。だからこんなコードになります。
P1DIR |= BIT0 + BIT6;
P1DIR &= ~BIT3; // PUC を前提とするなら不要
PxREN, PxOUT: プルアップ/ダウンもできます
ふつう、CMOSの入力ピンは未接続だと電位が安定せず 0だか1だか不定になってしまいます。そこで抵抗器を使って プルアップ/ダウンします。最近のマイコンは このプルアップ/ダウン抵抗を内蔵しているものも多く、MSP430も 例外ではありません(「プルアップだけ」というマイコンも多いの ですが、MSP430はすべてのI/Oについて両方を選択できます。うれしい)。 それを設定するのが PxREN レジスタです。 PxREN を 0にするとプルアップ/ダウン抵抗が無効に、 1だと有効になります。
そして、プルアップなのかダウンなのかを決めるのが PxOUT レジスタ です。PxOUT は出力値を決めるレジスタなのですが、pullup/pulldown 選択もするんですね。 PxOUT は 0がプルダウン、1でプルアップです。
LaunchPad の場合、 回路図 を見ると タクトスイッチまわりは
のように、単にグラウンドに落ちているだけです。ですからプルアップが 必要です。こんなコードになります。
P1REN |= BIT3; // enable pullup/pulldown
P1OUT |= BIT3; // select pull-UP
入力ピンを読む
入力に設定されたピンの値を読むには PxIN を読むだけで ok です。 コードはこんな感じです。
if((P1IN & BIT3) == 0){
// ボタン押された処理
}
出力ピンに出力する
出力に設定されたピンに値を出力するには PxOUT に書き込むだけで ok です。 コードはこんな感じです。
P1OUT |= BIT6; // turn on GREEN
P1OUT &= ~BIT0; // turn off RED
忘れちゃいけない重要な初期設定 〜ウォッチドッグタイマ〜
ウォッチドッグ(番犬)タイマとは、暴走等の監視のための仕組みで 大昔から大抵のマイコンについている機能です。タイマ犬に一定の時間以内に 餌を与え続けないとリセットがかかってしまいます。『プログラムが正常動作 しているときは餌を与え続けられるが、暴走等したら餌がなくなりリセット される(ことで強制的に正常状態に復帰できる)だろう』というロジックです。 当然のことながら リセット時にはデフォルトで動作開始 します。 MSP430の Watchdog Timer+ はもう少しいろいろ高機能ですが、いずれにせよ 今回は不要なので最初に disable しておきましょう。 詳細は MSP430x2xx Family User’s Guide の第10章を見てください。
WDTCTL = WDTPW + WDTHOLD; // shut up the dog
コンパイルと実行
『ボタンを押したら緑点灯/赤消灯, 離したらその逆』 を実現するプログラム(tutorial01.c)は次のようになります。 今回は内容から自明なとおりもちろん無限ループですが、今後も基本的に 無限ループで終わります。
return 0;は単なる飾り
です。だって return しようにも戻る先の OS がありませんから
(逆に下手に return すると無意味なバイト列に突入して暴走します)。
// tutorial01.c by Yagshi 2011
#include <msp430.h>
int main(void)
{
WDTCTL = WDTPW + WDTHOLD; // shut up the dog
P1SEL &= ~(BIT0 + BIT6 + BIT3);
P1DIR |= BIT0 + BIT6;
P1DIR &= ~BIT3;
P1REN |= BIT3; // enable pullup/pulldown
P1OUT |= BIT3; // select pull-UP
for (;;) {
if ((P1IN & BIT3) == 0) {
P1OUT &= ~BIT0;
P1OUT |= BIT6;
} else {
P1OUT &= ~BIT6;
P1OUT |= BIT0;
}
}
return 0;
}
コンパイルするために Makefile を作りましょう。Makefile はこんなんで
充分です。最後の -mmcu のところでターゲットデバイスを指定します。
使いたい石そのものがなかったら
/usr/msp430/include/ の中を見回して、適当に近いものを
書いておけば大抵問題ありません。
CC=msp430-gcc
CFLAGS=-Os -Wall -mmcu=msp430g2231
さあ、コンパイル〜実行しましょう。LaunchPadをUSBにつなげたら、 何とたったの2コマンド!
$ <span class="red">make tutorial01</span>
msp430-gcc -Os -Wall -mmcu=msp430x2012 tutorial01.c -o tutorial01
$ <span class="red">mspdebug rf2500 'prog tutorial01'</span>
(まず赤のLEDが光ると思います。そしたらスイッチ押してみましょう。)