ナゾテックの名前で模型・ジオラマ用のLED電飾コントローラーや配線済みチップLEDの販売などを行っている者です。
想定読者
MicrochipのPICマイコンを使ってる・使いたいと言う人で、プログラムの作成や書き込みはどうやるのか?って人に。
C言語に付いては有る程度書ける人を想定しています。
また、マイコンの各種設定に付いてはMCC(MPLAB Code Configurator)を使っています。
目次
前準備
プロジェクトの作成
マイコンの設定
System Module設定
Pin設定
プログラムソースコードへの反映
配線をする
プログラムの書き込み
タイマーを使って見る
割込みハンドラを作成する
割込みの可否設定
前準備
Microchipのマイコンへのプログラムの書き込みにはMPLAB X IDEが必要なのでまずはそれをインストールしてください。
Microchip MPLAB X IDEのインストールと使い方の基礎
マイコンへの書き込みにはライターと呼ばれるデバイスも必要ですので、それを購入してください。
MicrochipのPICマイコンとMPLAB Snap インサーキット デバッガを繋ぐ
今回はLEDを一つチカチカさせるので、そのためのLED、抵抗、ブレッドボードなども必要です。
LEDはとりあえずこれ。
このLEDで電源が3Vだったら抵抗はいらないですけど、念の為に6.8Ωの抵抗を付けておきます。
もし電源を5Vにするなら150Ωくらいの抵抗が必要です。
プロジェクトの作成
MPLAB X IDEを起動してください。

スタートページタブを表示している人はこのような画面になります。
新規のプロジェクトを作るには下図のどちらかをクリックします。

このような画面が表示されます。

画面右下側の「MPLAB for VS CODE」の表示は出る場合と出ない場合が有るようです。気にしなくても良いです。
特に変更せず"Microchip Embedded"->"Application Project(s)"の選択のままNextをクリックしてください。
"Device"のところで実際に使用したいマイコンの型番を指定します。一覧から選択しても良いのですが選択肢が多すぎるので直接入力しちゃった方が早いと思います。

有る程度入力するとその下に絞り込まれた一覧が出てきますので、適当なところで選択しても良いですし、最後まで入力しても構いません。
今回は手元に有る"PIC16F1827"を使って見ます。
”Tool"のところは今のところ何もしなくて良いです。Nextをクリックしてください。

とりあえず関係ないのでそのままNextをクリックしてください。

コンパイラの選択を行います。ここでは8ビットコンパイラしかインストールして無いので一つしか表示されていませんが"XC8"のツリーにある"(v3.XX)"の表示の行を選択してNextをクリックしてください。
"pic-as"はアセンブラの選択になります。

プロジェクト名や保存先フォルダを設定します。

プロジェクト名は何でも良いですが半角英数のみにしておくのが無難です。ここでは例として"Project01_1827"などとしておきます。私はプロジェクト名に型番を入れおくのが分かりやすいと思うので入れています。
下の方に有る"Set as main project"はチェックOnにしておきましょう。
"Open MCC on Finish"のチェックは一旦Offにしてください。後から説明します。
"Encoding"はプログラムソースファイルの文字種形式の選択で、日本語のコメントなどを入れたい場合は"Shift-JIS"を選択。英数のみならデフォルトのままで構いません。ここでは"Shift-JIS"を選択しました。
私の環境ではWindowsで"UTF-32"を選択した場合にソースコードの表示がうまく行きませんでした。”Shift-JIS"の場合は問題有りませんでした。MacではUTF-32でも問題有りませんでした
Finishをクリックしてください。
こんな画面になります。
左側にプロジェクトのファイル構成を表すツリーと、その下にプロジェクトの設定やプログラムサイズなどが表示されます。

プロジェクトのツリーの"Source Files"の+マークを押して開いても何もない状態です。
マイコンの設定
PICマイコンを扱うにはマイコン自体の各種設定が必要になります。
たとえばCPUをどのくらいの速さで動作させるのか?どのピンをLED点灯に使うのか?どのピンをスイッチ入力に使うのか?などです。
以前はこれらの設定をちまちまとソースコードに書いていたのですが、今は"MPLAB CODE CONFIGURATOR(MCC)"と言うツールがあり、これを使えばGUI上で上記のような設定が行え、設定に応じたソースコードを自動出力してくれる優れものです。
MPLAB X IDEのウインドウを横に広げると下記のようなツールボタンが出てきます。

もし見えない場合はメニューの「Tools->Embedded->MPLAB Code Configurator・・・」をクリックしてください。
MCCには種類が有ってそれの選択画面になります。もちろん最新版が良いとは思うのですが、それはまたの機会に紹介します。今回はちょっと古いタイプの方を選択するので、下記画面の下に小さく表示されている"For MCC Classic Content:Clikc Here"となってるところをクリックしてください。

MCC Classicはもうすぐ終わっちゃうから新しい方が良いよ、と言う表示です。Nextをクリックしてください。

画面の右上の方の"Project Resources"のところとその右側の部分は連動しており、選択によって表示が切り替わります。

MCC Classicの少し詳しい操作方法
System Module設定
まずMCUの速度設定を行いましょう。"System Module"を選択してください。
正直なところここの部分の設定は詳しくは理解していません。とりあえず電子工作でそれほど高い精度の時計とか作るのでなければ「大体はこれで良いよね」の設定を使ってます。

"Oscillator Select"は"INTOSC oscillator"=PIC内臓のオシレーターを使うと言う意味。オシレーターはクロック信号を発生させるもので、マイコンはこのクロック信号のテンポに合わせて動作します。
"System Clock Select"は"FOSC"を選択。
"Internal Clock"がMCUが動作するスピードになります。これが小さいほど動作が遅くなりますが、消費電力が少なくなります。とりあえずLチカの場合は速度は関係ないし消費電力もあまり気にする必要が有りませんので、デフォルトの"500KHz"のままで良いでしょう。
他の設定値もそのままで大丈夫です。
Pin設定
Pin設定はマイコンの端子の働きを設定するものです。
たとえば端子に接続したLEDを光らせるには端子設定を"Output"に、端子にスイッチを繋いでOn/Offを検出したいなら"Input"に設定する必要が有ります。その他にもマイコンの機能単位にどの端子に出力するのか、どの端子から入力するのかを設定します。
設定画面はこちらです。

赤四角で囲った部分は赤丸で囲ったタブ("Pin Manager Grid View")をクリックすると表示されます。青四角の部分は青丸で囲ったタブ("Pin Module")をクリックすると表示されます。
他にも緑四角の部分("Package View")でも端子のI/O設定が可能になっています。
なお、赤枠で囲った部分の左上隅に"Package"とあってその横に"PDIP18"となっていますが、これはマイコンのパッケージ形式の指定で、これを変更すると緑枠のマイコンの図が変化します。今回はDIPパッケージを使うので、この指定になっています。
緑枠の中の図にはそれぞれ番号とアルファベットが振られています。白い四角の中の番号はピン番号です。その外側に"RA2"とか"RA1"などと書かれているのはポート番号です。ポートにはピンをいくつかのグループに分けてA,B,Cなどと命名されており、"RA0"はAポート0番ピンになります。
赤枠の中にもピン番号とポート番号が書かれています。

この図の赤枠部分がピン番号、青枠がポートAのピン番号、緑枠がポートBのピン番号になっています。
その下の紫枠のところで各ピンを入力・出力どちらにするのかを設定します。マイコンの他の機能を使うときはそれらの機能に対するピンの割り当てもここで行います。
ピンを出力にしたい場合は紫枠の下側の部分"Output"と書かれた行の鍵が開いているアイコンをクリックします。例えば"RA2"を出力に設定すると下図のように表示が変わります。

設定されている側が鍵が掛ったマークで緑色に、その逆側が黄色になります。
同時にPackage Viewのピンの表示が変わります。

1番ピンのところに"RA2|IO_RA2|GPIO"と表示されピンの色が緑になります。"RA2"はポート番号、"IO_RA2"はプログラム内で使用する場合のピンの名称、"GPIO"は入出力ピンとして使われていると言う表示です。
さらにPin Moduleの部分にも変化が有ります。

ここでは各ポートに対してもう少し細かい設定が出来るようになっています。
6番目の列に"Analog"とあり、そこのチェックがOnになっていますので、アナログ出力できるそうですが私はやったことが有りません。今回はLEDをOn/OffするだけですのでこのチェックはOffにしておきます。"Output"の列は当然On状態です。
4列目に"Custom Name"とあり、設定値が"IO_RA2"となっています。これはプログラム内でこのポートにアクセスする際の名称ですが、ここを変更する事で自由な名前にすることが可能です。
たとえば"LED01_Control"などにして見ます。

これは名前なので、他のピンの名前とダブらないようにしてください。
その右側に"Start High"の列が有りますが、これをOnにしておくとプログラムで何もしなくても最初からこのピンがHigh状態、つまり電圧が掛った状態になるので、LEDが繋がっていれば点灯すると言う事です。今回はOffにしておきます。
プログラムソースコードへの反映
これらのピン設定やその他のマイコンの設定を変更した場合は、必ずそれをソースコードに反映させる必要が有ります。そのためのボタンがIDEの左上側に有ります。

赤丸の付いた"Generate"ボタンです。これをクリックします。
IDE下側に結果が表示されます。

これにより、今行った各種の設定に応じたソースコードがプロジェクトフォルダに出力されます。
IDEの左上側の"Project"タブをクリックするとソースコードツリーが表示されます。

ここではツリー上の"Header Files","Source Files","MCC Generated Files"のツリーを展開した状態にしています。
"MCC Generate Files"のツリーの下に各種の設定用ソースコードが出力されており、"Source Files"の下の"main.c"がプログラムのメインコードになります。これをダブルクリックすると右側にソースコードが表示されます。

コードの下の方を見ると下記の様になっています。
void main(void)
{
// initialize the device
SYSTEM_Initialize();
// When using interrupts, you need to set the Global and Peripheral Interrupt Enable bits
// Use the following macros to:
// Enable the Global Interrupts
//INTERRUPT_GlobalInterruptEnable();
// Enable the Peripheral Interrupts
//INTERRUPT_PeripheralInterruptEnable();
// Disable the Global Interrupts
//INTERRUPT_GlobalInterruptDisable();
// Disable the Peripheral Interrupts
//INTERRUPT_PeripheralInterruptDisable();
while (1)
{
// Add your application code
}
}
4行目にSYSTEM_Initialize();と有りますが、これは先ほどMCCで設定したMCU速度やピンの入出力設定などからMCCが自動生成したマイコンの初期化プログラムを呼び出しているところです。とりあえずは気にしなくて良いです。
一番下あたりにあるwhile(1){}の部分がいわばプログラムの主たる部分です。もちろんここではまだ何もしていません。単に永久ループになっているだけです。
「永久ループ??」と思われた方もおられると思います。
マイコンは様々な状況に応じてその動作を変化させるものです。例えばボタンが押されたらLEDを点灯、離されたらLEDを消灯などで、そのボタンが押されたら・離されたらなどの変化をとらえるのがこのループになります。
配線をする
プログラムを書く前に部品の配線を行いましょう。
ここでブレッドボードの登場です。この記事の最初の方に解説記事へのリンクを貼ってますので参考にしてください。またSnapと呼ばれるプログラム書き込み機の使い方も読んでおいてください。
LEDは端子の長い方がアノード=プラス側なので、そちらをマイコンのピン側に、短い方(カソード=マイナス側)はブレッドボードの電源マイナス=GNDに繋ぎます。

今回使うLEDはVFが高めなので抵抗は無くても問題有りませんが、一応6.8Ωの物を入れておきます。抵抗はどちらに繋いでも良いのですが、今回はアノード側に繋ぎます。
マイコンのピン->抵抗->LEDのアノード->LED->LEDのカソード->ブレッドボードのGND
と言う流れになります。

Snapとの接続も含めた全体図です

LEDを点灯するプログラム
さてここまで来たら後はLEDを点灯するプログラムな訳ですが、LEDの点灯自体は何も難しいことは有りません。
MPLAB X IDEでプロジェクトのmain.cを開き、while(1)のちょっと前に下記のコードを書きましょう。
LED01_Control_SetHigh();
while (1)
(while(1)は元から有るコードですよ)とするだけです。LED01_Controlは先ほどピンにつけた名前です。このピンの名前+動作を書くことでピンに対する制御を行います。
SetHigh()はピンの電圧を上げると言う動作を行います。そうすればそのピンに接続されたLEDに電圧が掛り電流が流れてLEDが光ると言う事になります。
プログラムの書き込み
いよいよプログラムをマイコンに書き込んでみましょう。
SnapとPCをUSBマイクロケーブルで接続してください。もしかするとUSBドライバのインストールなどの画面が表示されるかも知れません。私の環境では以前にやってたのでスクリーンショットが撮れませんでした。申し訳ありませんがもしその場合は何とかやって見てください。
プログラムをマイコンに書き込み実行するにはIDE上部の下図の赤丸のボタンをクリックします。

下図のようなウインドウが出てくるかも知れません。これは書き込み機をどれにするのか尋ねる画面です。

ドロップダウンを開くと下図のようになっています。

ただし"Snap-SN:"の後ろに表示されている数字は皆さんのところとは違っているかもしれません。気にせず"Snap-SN:"の行を選択してOKをクリックしてください。
さらにこの画面が出ますが気にしなくてもいいので"Do not show this message again"のチェックをOnにしてからYesボタンをクリックしてください。

そうするとコンパイルが行われ、エラーが無ければ書き込みも行われIDEの下部に下図のような表示が現れて実際にLEDも光っているはずです。

青く見えますが白LEDです。撮影機材の問題だと思います。

もうちょっとプログラムを加えてみる
さすがにこれだけではつまらないと言うかシンプル過ぎるので、もう少しプログラムに手を加えて見ましょう。
たとえば1秒おきにLEDが点灯・消灯を繰り返すというもの(いやシンプルですけども・・・)にしましょう。
先ほどの場合はLEDを点けたら点けっぱなしだったのでループの外側に記述すればよかったのですが、次は「点灯->1秒待つ->消灯->1秒待つ」と言うプログラムを繰り返し実行するようにします。繰り返しは既に登場しているwhile(1)を使います。
では1秒待つとはどうするのか?これは指定秒数(ミリ秒とかナノ秒)待機すると言う関数を使いますが、前準備が必要です。
もしMCCを閉じている場合は再度MCCを起動してください。もし下図のタブが選択されていないときはタブを選択してください。

さらに少し下にある"Libraries"のツリーを開きます。

DELAYのアイテムの+マークをクリックします。

上の段の表示にDELAYが追加された状態になります。

もしこれを取り除きたければ、赤いXマークをクリックします。
これで待機関数を使う事が出来るようになりました。ソースコードは下記の様になります。
while (1)
{
LED01_Control_SetHigh();
DELAY_milliseconds(1000);
LED01_Control_SetLow();
DELAY_milliseconds(1000);
}
この"DELAY_milliseconds"が遅延関数でカッコ内に遅延したいミリ秒数を指定します。
余談
今回この記事を書くためにゼロからインストールしてプロジェクトもゼロから作成してますが、
今までは遅延関数は__delay_msと言うのを使ったのが使えませんでした。そこで上記の様にDELAYライブラリを加えてDELAY_millisecondsが使えるようになりましたが、面白いことに__delay_msも使えるようになってました。
また、__delay_msはパラメータが定数じゃないとエラーになってましたがDELAY_millisecondsは変数が使え、こちらの方が便利だなとは思ってます。
アニメーションGIFなので少し画像が荒いです。
タイマーを使って見る
次は遅延関数を使うのではなくタイマーを使って1秒待つと言うのをやって見ましょう。
タイマーを使うと上記の様に待機関数を使わずにタイマーが指定の秒数経ったら教えてくれるので、その時にLEDを点けたり消したりできます。
この指定の秒数経ったら教えてくれる、と言うのをタイマー割込みと呼びます。マイコンのプログラムでは割込みが多数登場するのでしっかり理解しましょう。実際には指定秒数経ったら設定したプログラム(関数)が実行されると言うものです。
プログラムと言うのはコードが書かれた順番に上から下へ実行されます。ループや関数呼び出しなどでその順序が変わることは有りますが、その後はやはり上から下へ動きます。
割込みとはそのプログラムの実行途中に文字通り「割り込んで」別の処理を行う事を指します。
たとえば、
a = a + 1;
b = a + 2;
c = b * 3;
見たいなコードを書いていて、この3行を実行しようとしている途中で割込みが発生すると、
a = a + 1;
<<<<割込み発生
b = a + 2;
c = b * 3;
この割込み発生したところで一旦指定した関数を実行し、それが終了したらまたこのコードに戻ってきて続きを実行するようになります。
ではまずタイマーの設定を行いましょう。またMCCを表示してResource Managerタブを開いてください。その中から"Peripherals"(ペリフェラル)を開きます。Peripheralsとは「周辺機器」の意味で、ここではマイコン内で使用できる各種の機能の事を表します。

ツリーを開いた下の方に"Timer"ツリーが有るのでそれも開きます。
DELAYの時と同様に緑の+マークをクリックして機能を追加します。タイマーには0~6まで有ります。細かい設定などが違いますが、とりあえず"Timer1"を追加しましょう。
追加すると上部のウインドウに"Timer1"が現れます。

タイマーの設定を行うには追加された"TMR1"をクリックします。すると画面右側にタイマー設定画面が表示されます。

ここで重要なのは右側の"Timer Period"の値です。ここでは"8 us ≦ 524.288 ms ≦ 524.288 ms"となっている部分の真ん中の入力できる部分。ここにタイマー割込みを発生させる秒数を指定します。なお、usはマイクロ秒、msはミリ秒です。指定できる値は左右に書かれた"8 us"以上、"524.288 ms"以下の範囲です。
1秒待ちたいのに、"524.288 ms"では不足ですから少し左側にある"Prescaler"(プリスケーラー)の設定を変えます。

プリスケーラーとはいわばタイマーの動きを遅くする設定です。例えばこの設定を1:2にするとタイマーに設定できる値の最大値が2倍の"1.048576 s"つまり約1秒になります。
この状態でタイマー設定値を"1 s"にします。
余談
タイマーの動きを遅くするには他の手も有ります。
たとえばMCUのクロック数を減らせばその分タイマー動作速度が遅くなります。
また、タイマーによっては"Postscaler"(ポストスケーラー)別の設定も有ります。
割込みハンドラを作成する
割込みが発生した時に呼び出される関数を「割込みハンドラ」と呼びます。
割込みハンドラは関数の形式が決まっていて、下記のような定義で書きます。なお、この記述方法はMCCを使ってコード生成を行った場合でのみ使えます。
void timer1Interrupt(void){
}
timer1Interruptはハンドラの名前なので好きな名前を付けて構いません。
これを書くのはmain.cのvoid main(void)の行の手前部分です。

とりあえず割込みハンドラの中身は後回しにして、このハンドラをタイマー割込みが発生した時に呼び出すようにするコードを記述します。
TMR1_SetInterruptHandler(timer1Interrupt);
TMR1_SetInterruptHandler関数はMCCが自動作成したもので、timer1Interruptは先ほど記述した割込みハンドラの名前です。
これは、void main(void)の中のwhile(1)の手前に書きます。

LEDの点灯・消灯を割込みハンドラで行うので、whileループ内の4行は削除します。

割込みでLEDを点灯・消灯する
先ほど記述したtimer1Interrupt関数は割込みによって1秒毎に呼び出されます。もしこの中のコードが、
void timer1Interrupt(void){
LED01_Control_SetHigh();
}
のようですと、呼び出されるたびにLEDをOnするだけなので、ずっと光りっぱなしです。
このような場合に便利なToggle(トグル)関数が用意されています。これは呼び出すたびに前回と逆のことを行うと言うような意味で、LEDの場合OnだったならOffにOffだったならOnにすると言う意味合いになります。
void timer1Interrupt(void){
LED01_Control_Toggle();
}
では書き込んで実行してみましょう。
今度はLEDが付かない状態だと思います。実は初期状態では割込みは発生しないようになっています。なので、これを発生させるようにコードを修正する必要が有ります。
割込みの可否設定
ソースコードのvoid mainの初めの方を見て見ましょう。

これらの部分もMCCが自動生成したコードで、この中で赤枠で囲んだ2行が割込みを許可するコードです。
この2行のコメントを外すことで割込み許可が実行され、タイマー割込みが発生するようになります。

では書き込んで実行してみましょう。今度はLEDがチカチカするようになってるはずです。
今回はここまでです。お疲れさまでした。



