【第8話】マイコンに書き込むプログラムについて
「暁美ほむら。君はつくづく訳のわからない要求をしてくるね?PICマイコンを教えてる間もまどかと一緒に布団で寝たいから、分身を出してくれって?そんなの無理に決まっているじゃないか?」
「・・・ってどうやら耳を貸すつもりはないらしいね?君を見ていると人類の欲望とはいかに理不尽なものかが良く理解できる。」
「これでいいかい?暁美ほむら?しかし、わざわざ視力落として眼鏡にする必要はない気がするけど、僕の関与するところではないね。」
「これでいいわ。もう一人の私が一緒だから鹿目さんに心配かけずに済むわ。」
「マイコンに書き込む用のプログラムをまず用意しなくちゃいけないわ。ええっと・・」
(手にしているクラブで一体どうするつもりでしょうか(;´∀`))
「ほむらちゃん?もう寝ようよ?布団にいないから起きてきちゃたよ~」
「あれ?鹿目さん、寝ていたんじゃ??」
「分身って実はすぐわかっちゃったよ!ウェヒヒ~」
「ほむらちゃん、ひとりぼっちはだめだよ?私も一緒に覚えたいよぉ?」
「その約束はちゃんと覚えているわ。準備が整ったら呼ぶつもりだったの。」
「そうだったんだね。置いてきぼりにされたんだと焦っちゃったよ~」
「心配させてごめんさい。ちゃんと教えるから心配しないで。」
「ウェヒヒ!そういえば、ほむらちゃんのお道具箱にこんなのが入っていたよ?」
「それは豆電球に相当するものだけど、後でちゃんと説明するわ。」
「ほむらちゃん!どう?」
「あら、可愛いわ!鹿目さん!その使い方は全く考えもしなかったわ!」
「ウェヒヒ~!」
「でも、それってどこかで見たような気がするわ」
「これだよ!ほむらちゃん」
「あ、これは私がこの間アキハバラに行った時に貰ってきたフリーペーパーね。良く似てるわ。でも鹿目さんの方がずっと可愛いわ。」
「ほむらちゃん///」
「鹿目さん、これから説明するわね?」
「準備はバッチリだよ~ほむらちゃん。」
「わかったわ。さっきの赤い豆電球(発光ダイオード)を覚えてる?」
「うん。」
「光らせるにはどうしたいいかわかるかしら?」
「う・・・ん??電池かな???」
「そうね、理科の授業で確かにやったわ。でも残念ながら違うの。豆電球に直接電池を繋げるのは、本当はやってはいけないことだったの。」
「え?そうなの??」
「豆電球はたまたま、電池の電圧・・ごめんなさい、血圧って例えるとわかりやすいかしら?」
「ほむらちゃん、大丈夫だよ~血が流れる時の血管に伝わる圧力のことだよね?」
「そのとおりよ。それを電気に置き換えてくれればバッチリよ。この電圧に豆電球は耐えられるから、壊れることなく光り続ける事ができるわ。」
「じゃあ?ほむらちゃん?」
「察しがいいわ、鹿目さん。電子部品はデリケートだから、電池の電圧ぐらいでも簡単に壊れてしまう事もあるわ。先ほどの赤い豆電球もその一つなの。」
「ほむらちゃん?そしたら、どうしたらいいの??」
「確かに疑問よね。大丈夫、ちゃんと説明していくから安心してね。」
「うん!」
「この図を見ながら説明していくわね。赤い矢印と青い矢印がそれぞれ電池の+極、-極だとイメージしてくれるとわかりやすいかしら?」
「うん。ここまでは大丈夫だよ!」
「赤い豆電球ともうひとつ繋がっているのがあるの。」
「抵抗??」
「そう。この抵抗がとても大事な役割を果たすの。抵抗を通すことで適切な電圧に調節することができて、部品を安全に動作させることができるの。今回は赤い豆電球がそれにあたるわね。」
「理科でやった豆電球はソケットから垂れている配線をどちらの向きに電池に繋げても光ったけれど、この赤い豆電球は繋げる向きが決まっているの」
「アノード?カソード?って書かれているよ?」
「アノードが+側、カソード側が-側というイメージで大丈夫よ。足が長い「ア」ノードって覚えておくと迷わないかも」
「でもほむらちゃん?これだと、ただ光るだけだよね??」
「そうね。でも今話したところは後で基本になるところだから、忘れないでね。でないと、部品が魔女化しちゃうわ」
「?!」
「でも恐がらなくても大丈夫よ。今話した抵抗をきちんと繋げる事を忘れなければ大丈夫。」
「うん。わかったよ~!」
「この回路だと、鹿目さんの言う通りね。電源が入っている時にただ光るだけ。点滅させたり、一定時間で点灯させる事はできないわ。」
「そこで、この黒い小さなものが活躍するのよ。」
「小っちゃくてかわいいね~。」
「見た目はかわいいけど、とても働き者よ。これから使っていく『マイコン』って呼ばれるものなの。」
「マイコン??」
「マイクロコンピューターの略よ。でも難しくはないの。鹿目さんのおうちににもパソコンがあるでしょう?」
「うん。ノートパソコンがあるよ~。」
「パソコンでwebページみたり、メールしたりするときにマウスやキーボードで画面のボタンを押したり、文字を入力したりするでしょう?」
「いつもやっているよ~」
「ボタンを押すだけでwebページが見れたりするのは、ボタンを押せば、そのように動作するように作られているからなの。」
「でも、この黒いのにはボタンはないよ??」
「そうね。ボタンはないわね。だから押すボタンも自分で作成することになるわ。」
「なんだか難しそう・・・」
「鹿目さん、大丈夫よ。ボタンを作るのも後でちゃんと説明するから安心して。」
「うん!」
「このマイコンは何も動作しないパソコンだとイメージしてくれるとわかりやすいかしら?」
「うん。わかりやすいよ~」
「動かすには動かすように指示する手順をこのマイコンに教えてあげないといけないの。その手順が『プログラム』って呼ばれているの。」
「あ、なんか聞いたことがあるよ~。少し前にほむらちゃんに完成品でちょっと説明してもらったよ。ボタンを押すと数字が動いたりしてたよ~。」
「そう。そうやって動くように組んだものがプログラムね。まずはプログラム作成からやっていきましょう。」
「プログラムを作成する前に実は用意しておかないといけないことがあるわ。それがこの回路なの。」
「???」
「赤い豆電球から一気に難しくなちゃったわね。でも大丈夫。さっきの赤い豆電球の説明は思い出せる?」
「うん。足の長い方が+側だよね?」
「そのとおり。アノード側ね。今回はこの赤い豆電球8つが一塊になったものを使うわ。それがこの上面が「8.」になっている部品よ。」
「ほむらちゃん?これって、デジタル時計に使われているあれかな?」
「そう。数字を表示する為に光る部分が7つに分かれているから、7セグメント、7セグって呼ばれているの。」
「分かれている一つ一つが赤い豆電球の変形したものとイメージすれば大丈夫よ。そしてこの部品からは10本の足が伸びているわ。」
「でも、ほむらちゃん?赤い豆電球って2本足だよね??8つってことは16本足がないといけないから足りないよ???」
「確かにそうね。実は10本の足のうち、8本はアノード側の足なの。残り2本がカソード側の足になっていて、カソード側の足がこの2本にまとまっている構造になっているの。」
「でもそれだと、光らせたい部分はどうやって光らせるの??」
「電気の流れをこの回路で説明するとわかりやすいわね。」
「さっきの回路に電気の流れを示したのが、黄色い矢印よ。」
「1,2、3って番号があるよ?」
「そう。それが電気の流れる順番なの。さっきの働き者の小さい黒いのが、『PIC16F873A』ね。パソコンでいうところの機種名みたいなものよ。」
「ほかにも機種があるの?ほむらちゃん?」
「パソコンと同じように、機能にそれほど違いはないのだけど、機種によって数十本出ている銀色の足、ピンと呼ばれるものが8本だったり、18本だったり様々なの。ピンもそれぞれ用途が割り振られているけれど、難しく考えなくても大丈夫。最初は必要なピンの数がわかれば心配しなくても大丈夫。」
「でもほむらちゃん?この図だと緑の1番ってなっているピンから電気が流れるみたいだけど、どうやるの??」
「どうやればよいかを指示しないといけないわね。」
「あ!プログラムだね~!ほむらちゃん?」
「そのとおりよ!。この緑の1番になっているピンから電気を流してくれるようにマイコン(小さな黒い働き者)に指示するプログラムを作りましょう。」
「プログラムにはこの緑の1番になっているピンから電気を流すのともう一つ指示をさせないといけないわ。黄土色の矢印があるのがわかるかしら?」
「斜めの矢印で横に『スイッチON!』って書かれているよ?」
「そう、それね。もう一つの部品を話さないといけないわね。」
「こっちも小っちゃくて可愛いね~。さっきの働き者とは違うの??」
「こちらも働き者だけど、役割はもっと単純なの。3本の足が出ているのだけど、さっきの回路を見ながら説明していくわね。」
「うん!」
「黒い部分を真上から見ると、半円状になってるのだけど、平らになっている方を鹿目さんの方に向けるとわかりやすいわ。」
「図と同じ向きだね~」
「そのとおりよ。図の電気の流れの2番ってなっている矢印に注目してほしいの。1番から7セグに入った電気が2番の順に流れてるわね。どこに流れていくかわかるかしら?」
「あ!この3本足の真ん中の足に流れているね~ほむらちゃん?」
「そう!3番って書かれているところへ電気が流れるのだけど、この3本足にただ繋げただけだと流れないのよ。」
「だから、スイッチをONにしないとだめなんだね~?」
「さすが、鹿目さん。吞みこみが早いわ!」
「ウェヒヒ~♪」
「スイッチをONにするには、こちらからもマイコンから電気を流すように指示してあげないといけないわ。3本足の一番右側の足にその電気が流れるとスイッチON状態になって、2番から3番の順に電気が流れるようにする部品よ。この部品は『トランジスタ』って呼ばれているわ。」
「作成するプログラムは、マイコンの緑の1番となっているピンから電気が流れるようにするのと、スイッチONにするための電気をPICマイコンのピンから電気を流すように、マイコンに指示させないといけないわ。この2つだけを忘れなければ、難しくないわ。一緒にやっていきましょう。鹿目さん?」
「うん!一緒に!ほむらちゃん~!」
「前回コンパイラの準備でインストールした『MPLAB X IDE』って名前のソフトを使うの。これでマイコンに動作指示するプログラムを書いていくの。」
「でも難しくないわ。初回だけちょっと設定が必要なのだけど、ちゃんと説明していくから心配しないで。鹿目さん?」
「わかったよ~ほむらちゃん!」
「ソフトを開いたところよ。色々とごちゃごちゃしているのは私がさっきまで使っていたから気にしなくて大丈夫。使うところは少ないからすぐに慣れるわ。」
「使う順番に①~③から振ってみたわ。①全体がタンスだとイメージしてくれれるとわかりやすいかしら?タンスに必要な引き出しとその名前をこの部分で設定するの。引き出しのことを『プロジェクト』、その名前が『プロジェクト名』って呼ばれているの。」
「うん。ここまで大丈夫だよ~。」
「①をよく見てもらうと、いくつもの「+」があるのがわかるかしら?」
「その横に名前があるよ?これがプロジェクト名なの?ほむらちゃん?」
「鹿目さん、流石だわ!」
「ウェヒヒ~♪」
「まずはこれからプログラムを入れる引き出しと名前を新しく設定していきましょ。」
「画面上の方に横一列で英単語が並んでいるけれど、ここがメニューバーって呼ばれるところなの。」
「私のパソコンでも同じ場所が日本語になっているよ?」
「日本語版があればいいのだけど、今回使うこのソフトは海外版だからちょっと分かり辛いけれど、慣れてくれば大丈夫よ。」
「一番左の[File]→[New Project]をクリックして新しいプロジェクトを設定していくの。」
「するとこんなウィンドウが開くわ。ここではプロジェクトの種類を設定するの。普通にプログラムを作成するから、左側は「Microchip Embeded」、右側は「Standalone Project」を選んだら、下の[Next>]をクリックよ。」
「次がプログラムを書き込むデバイスの設定ね。つまり使うマイコンの機種名を設定しないといけないわ。特に説明はしていなかったけれど、今回使う『PIC16F873A』はミドルレンジって呼ばれるシリーズのひとつなの。パソコンでいうところのロースペックやハイスペックと同様の意味よ。」
「上の枠で「Mid-Range 8bit~」を選択すると、下の枠で選択肢を下までスクロールすると「PIC16F873A」という項目があるはずよ。選択したら、下の[Next>]をクリックね。」
「次が使用するライターの設定ね。パソコンから接続するライター、PICKit3を通じてマイコンに作成したプログラムを書き込むわ。[PICKit3]を選択して、[Next>]で次に進みましょ。ここまで駆け足で来ちゃったけど、鹿目さん、大丈夫?」
「大丈夫だよ~ほむらちゃん」
「ここでは使用するコンパイラの設定をするわ。右側には既にインストールされているコンパイラが表示されているの。『XC8』というコンパイラを使っていくから事前にインストールしてあるわ。(※MPLAB X IDEにはXC8コンパイラが付属していないので、別途ダウンロードとインストールが必要)[XC8~]を選択して[Next>」で次に行きましょ。」
「最後にプロジェクト名の設定ね。自由に名前を作れるわ。下の[Encoding]はプログラム作成で使う文字コードの設定ね。[Shift-JIS]か[UTF-8]を選択しておけば、特にコメント(後述で説明)が文字化けすることもないと思うわ。」
「設定が終わったわ。先ほどの①の枠を見てみると?」
「あ!さっき設定した名前のが出来てるね~ウェヒヒ!」
「この『madoka』プロジェクトを今後は使っていくことになるの。この引き出しを開け閉めする感じよ。」
「ほむらちゃん?、さらに下に6つに分かれているよ??」
「引き出しの中が6つの仕切りに分かれている感じをイメージできるかしら?」
「うん!」
「6つの仕切りのうちで使うのはこの[Source Files]だけよ。ここにプログラムを作成していくの。」
「プログラムを作成するために新しくファイルを作るわ。「C言語」って呼ばれる言語で作成していくの。だから、[C Source File]を選択よ。」
「そうすると、右側に何も書かれていない真っ白なスペースができたわ。」
「ここにプログラムを書いていくんだね?ほむらちゃん?」
「その通りよ。」
「さっきも触れたけど、②でプログラムを書いていくの。書き終わったら、このプログラムをマイコンが分かる言語に翻訳してあげないといけないわ。この翻訳作業をコンパイルって呼ぶんだけど、それをしてくれるのがコンパイラ、つまり今回なら「XC8」というコンパイラが活躍するわね。」
「プログラム作成後にちゃんと説明するけれど、③の金づちとフォルダのボタンを押すと、コンパイルが始まるの。コンパイルが完了すると、コンパイルされたファイルが別の場所に作られるのよ。」
「そのファイルをマイコンに書き込むんだね~?」
「鹿目さん、流石よ。でも書き込むためには今開いているソフトとは別のソフトを使わないといけないんだけど、それもあとで説明するわね。」
「うん!」
「それじゃ、プログラムを書いていきましょ。」
#include <xc.h>
「プログラムの1行目にはこれを書くわ。」
「これはどういう意味なの?ほむらちゃん??」
「xc.hのhは『ヘッダファイル』って呼ばれるものなんだけど、プログラムを動かすために必要なパーツを呼び出しているの。どのプログラムでも共通で使うものだから、それぞれのプログラムで長々と書かなくても、こう書けば済むの。」
「xcってなってるけど、ほかにもあるの??」
「鹿目さん、いい質問ね。xcの部分は本来は使うマイコンの機種名を書くの。PIC16F873Aで説明しようと思ったのだけど、ピン数が少ないPIC16F628Aを使うことにするわね。これだとPIC16F628A以外のマイコンの場合は、その都度修正しないといけないから面倒よね?」
「じゃあ?xcってどのマイコンでも使える共通のヘッダファイルなの??」
「鹿目さん、半分正解ね。正確にはそれぞれのマイコンのヘッダファイルの親玉にあたるわ。xc.hと書くと、xc.hから適合するマイコンのヘッダファイルを自動で読み取って、必要なヘッダファイルの中身を呼び出してくれるの。」
#pragma config FOSC = INTOSCIO
#pragma config WRT = OFF
#pragma config WDTE = OFF
#pragma config PWRTE = ON
#pragma config BOREN = ON
#pragma config LVP = OFF
#pragma config CP = OFF
「見やすいように1行改行して、3行目以降にはこの7行を書いていくの。」
「ONとかOFFとかってあるよ??」
「マイコンの動作設定をする部分ね。鹿目さんのパソコンでもマウスで右クリックすると「設定」、「プロパティー」なんてメニューはないかしら?」
「うん。あるよ~!」
「それに相当する部分ね。ただパソコンのそれとはちょっと違っていて、大きく2種類に分かれているの。勝手に名付けてしまうと、ハード系とソフト系ね。」
「ここで設定するのはハード系で、マイコンにコンセントや電池からの電源が投入された直後の動作設定がメインになるの。今後説明で出てくるタイマー機能を使うと注意しないといけないのだけど、今は気にしなくても大丈夫。」
「ソフト系はこの後の説明で改めてするからここでは飛ばすわね。」
「わかったよ~」
「7行一気に出てきたけれど、気にするのは最初の「FOSC」だけなの。」
「うん。」
「タイマー機能の説明でも登場するけれど、今は「FOSC=INTOSCIO」にしているの。こうするとPICマイコン側の周波数を使う設定になるのだけど、これついてはこの後に説明するわね。先頭行に「//」(半角スラッシュ2つ)を入れると、その行はプログラムではなくて単なるコメント扱いになるの。」
//水晶発振を使う場合はLPにする
#pragma config FOSC = INTOSCIO
「例えば、先ほどのFOSCの行にこういう感じで説明を入れるの。こうしてプログラムにそれぞれコメントしておけば、後で見返したり、修正するときにもメモ代わりとして大いに役立つわ。」
「FOSC = INTOSCIO以外にもあるの??ほむらちゃん?」
「そうよ。水晶発振というマイコン外部の電子部品の周波数を使う場合にはFOSC = LPって変えるのだけど、まだ気にしなくても大丈夫よ。」
「WRTの行以降はこのままよ。周波数を読み取るなどのもっと難しいプログラムを作るような場合でないとここ以降の設定は弄ることはないの。」
「ほむらちゃん、わかったよ~」
「なら次にいきましょ。」
//PICマイコンのシステム周波数を設定。Hz単位。(20MHzの場合)
#define _XTAL_FREQ 20000000
「上の//はコメントだよね?ほむらちゃん?」
「そうよ。プログラムは下の#define~の部分ね。実は後で使う関数を動かすのに必要なの。この関数を使う場合は、_XTAL_FREQが計算式として使われるんだけど、『変数』って言葉を聞いたことがあるかしら?鹿目さん?」
「う・・・ん??わからないよ??」
「変数っていうのは、好きな数字を入れる箱だと思ってほしいの。ここまでは大丈夫かしら?」
「うん、大丈夫だよ~」
「『madoka』って変数をつくるとするわね?たとえば『madoka +1』という計算式があるとすれば、madokaに1という数字を入れてあげると、計算式はいくつになるかしら?」
「2になるよ。ほむらちゃん~」
「その通りよ。これが変数って呼ばれるものの使い方なの。同じ変数なら、例えば、madoka -1 やmadoka + 10という別の計算式も計算できるわね?」
「うん。」
「同じ数字で計算したいのに、これら計算式に変数であるmadokaを使わないとしたら、どうかしら?」
「madokaってなっている部分すべてに同じ数字をいれてあげないとだめだね?ほむらちゃん?」
「そうね。計算式が1つや2つならまだしも、プログラムが長くなってくるといくつも計算式が出てくるわ。その計算式それぞれに同じ数字を入れていくと大変な手間だし、プログラムがちゃんと動かない原因にもなりやすいの。」
「じゃあ、ほむらちゃん?_XTAL_FREQも変数なの?」
「正確には変数ではないのだけど、イメージとしてはそれに近いわ。変数の場合はそこに入っている数字等を使って計算する場合に使われるけれど_XTAL_FREQは決まった箇所に同じ数字を入れる場合に使われるので、定数って呼ぶべきね。違いはその数字で計算するか、しないかの違いだけ。」
「???」
「混乱させてしまったわね。ごめんなさい。今回説明するところはさっき話した変数と思って大丈夫よ。さっき鹿目さんが『madokaってなっている部分に同じ数字をいれないといけない』って言っていたのを覚えてるかしら?」
「うん。だって変数使わないとすべての場所に同じ数字を入れないといけないよね?」
「その考え方が「定数」なの。「変数」と似ているんだけど、分かりやすいかしら?」
「わかったよ~ほむらちゃん」
「その定数なんだけど、正確には「マクロ」って呼ばれるんだけどこれは覚えていなくても大丈夫よ。こういう機能があるんだって覚えてくれれば大丈夫。」
「うん。ところで、PICマイコンのシステム周波数って??」
「ごめんなさい。肝心の説明が抜けていたわね。周波数についてちゃんと説明するわね。鹿目さんのパソコンに四角い銀色のシールが貼っていないかしら?」
「ロゴみたいなのがあって、下に英語と数字でなんか書いてあったよ?」
「その英語と数字の表記が鹿目さんのパソコンを動かすための人間の脳に相当する、CPUって呼ばれる部品の機種名なの。その機種名でネット検索すると必ず機種名の横に1GHzとか、3GHzって表記がされているの。」
「それが周波数なの??」
「そうよ。この周波数の数字を見ることで、CPUの計算能力が分かるの。数字が大きいほど計算能力が高速なのは直感的にわかるかしら?」
「うん。時々ニュースでスーパーコンピュータについて見かけるからわかるよ~」
「そのスーパーコンピューターも鹿目さんが使っているパソコンのCPUを寄せ集めたものだから、周波数が高いほど計算が速いの。でも計算が速いって言われてもちょっと実感がわかないと思わない?」
「うん。それずっと気になっていたよ。」
「そうよね。周波数っていうのは、1秒間にどれくらいの振動があるかを数字で表したものなの。単位はHz。ヘルツって読むわ。」
「じゃあ、1Hzは1秒間に1回振動するってことなの??」
「そう。2000Hzだったら?」
「1秒間に2000回振動だね?ほむらちゃん?」
「そうね。2000Hzだったら、1回の振動で1つの命令をこなせるとしたら1秒間に2000の命令をこなす事が出来る、つまり計算できる能力があるわ。」
「ほむらちゃん?そしたら、PICマイコンのシステム周波数も同じなの?」
「_XTAL_FREQの横に20000000、20000000Hzってなっているから確かに1秒間に2000万回の計算、命令が出来るって思えるわ。でもちょっと違うの。」
「どういうことなの??」
「パソコンのCPUとは処理方法がちょっと違っていて、マイコンの場合は4回振動して1つの命令を処理する仕組みになっているの。1回あたりの振動をクロックって呼ぶのだけど、4回振動だから、4クロックで1命令を処理するって表現するわ。」
「じゃあ、1秒間に500万回計算が出来るの??」
「流石よ!鹿目さん!」
「ウェヒヒ~!」
「1秒間に500万回命令を処理できるから、1つの命令の実行に要する時間は500万分の1秒という、目にもとまらぬ速さで処理されるの。この計算が後のタイマー機能で大事になるけれど、今は覚えてなくても大丈夫。」
「うん。」
「システム周波数の数値がある関数を使うのに必要になる事だけ覚えておいてほしいの。」
「わかったよ~」
unsigned char seg1;
unsigned char p[10] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
void main(void) {
TRISA = 0x00; //PORTA全てのピン(RA0〜RA7)は「0」。つまり出力設定。
TRISB = 0x00; //PORTB全てのピン(RB0〜RB7)は「0」。つまり出力設定。
PORTA = 0x00; //PORTA全てのピンを「0」に設定
PORTB = 0x00; //PORTB全てのピンを「0」に設定
seg1 = 0;
while(1) {
PORTA = 0x01;
if(seg1 > 9){
seg1 = 0;
}
PORTB = p[seg1]; //配列p[]のビットパターンで7セグが点灯
__delay_ms(1000); //1000ミリ秒=1秒間何もしない
seg1++;
}
}
「一気に行が増えたけれど、これが今回動かすプログラムの本体にあたるの。」
「ふええ・・。」
「大丈夫よ。上から順番に説明するから安心して。」
unsigned char seg1;
「この行だけど、見慣れない英単語が3つ並んでるわね?」
「うん・・」
「ちゃんと説明するから心配しないで?鹿目さん?」
「大丈夫だよ~!」
「鹿目さん。unbelievableって単語は覚えているかしら?」
「確か・・えっと・・・『信じられない』って意味だっけ?」
「その通りよ!。この単語は先頭の「un」が後の単語を否定する意味なの。believableで信じられるって意味だから、その否定で『信じられない』。」
「じゃあ、unsignedもsignedって単語の否定なの?ほむらちゃん?」
「察しがいいわ。鹿目さん。でも署名とかサインの意味ではなくてあるものを設定するって意味が近いわ。」
「設定??」
「そう。マイコンで扱える数値の範囲を設定するの。私たちが脳で考える数値は無限に大きな数を扱えるけれど、マイコンやパソコンなんかの脳に相当するCPUでは扱える数値に限界があるの。」
「CPUって言葉は、スーパーコンピュータのニュースで聞いたことがあるよ?」
「そのCPUね。CPUが扱える数値の範囲は何ビットかで決まってくるのだけど、順番に説明していくわね。」
「うん!」
「鹿目さんや私が普段の生活で数字の計算するときを思い出してほしいの。例えば、0から1ずつ足し算していくとして、9の次はいくつになるかしら?」
「10だよ!」
「そうね。なら99の次は?」
「100だよ!」
「ところで、1の位の次は何の位?」
「え?10の位だよ?ほむらちゃん?」
「そうね。改めて質問されるのは不思議に思うのも無理はないわね。でも1の位の次が10の位になる理由って考えたことがあるかしら?」
「そういえば、考えたことがないかも・・」
「1の位、10の位、100の位・・・実はある規則で増えているの。」
「ある規則?」
「そう。1の10倍、10の10倍・・ってそれぞれ隣の位は10倍で増えているの。」
「あ!だから100の位の次は1000の位だね~!」
「その通りよ。鹿目さん。それぞれの位に0~9の10種類の数字を入れることで私たちは普段の生活で何も考えずに計算したりしてるわね。9まで10種類の数字が進めば、隣の位が1増える。この繰り返しになってるわね。」
「うん。ここまでは大丈夫だよ?」
「たとえば、99って数字を考えてみて?これはどの位にどんな数字が入るかしら?」
「えっと・・・10の位に9と1の位に9だよね?」
「そうよ。何も考えずにすぐにわかるわね。でもなぜかしら?」
「え?だって、右から1の位、10の位だからだよ?」
「そうね。10の位は9。1の位は9。だからこういう形でも表現できるわ。10×9+1×9=99。」
「そういえば、小学校でそうやって習ったね~。」
「この表現がとても大切なの。ところで先ほどのコンピュータで使われる脳に相当するCPUは残念ながら、0と1の2種類の数字しか使えないの。」
「それじゃあ、2以上の数字はどうやって扱うの??」
「それがコンピュータと私たちで慣れている数の世界の違いなの。」
「でも計算するなら、0~9までの数字があればいいと思うんだけど??」
「確かにそうね。コンピュータが初めて開発された当時は私たちが普段の生活で扱うように0~9までの数字で計算できるように設計されたものもあったわ。でもコンピュータでは数値そのものの計算の他に、文字や図形などの目に見える情報も扱う必要が出てきたの。そうしたときに、私たちが普段使っている数の世界では色々と不都合が出てきたのね。」
「不都合なこと?」
「そう。ところで1の位が0~9まで進んで、また0になると10の位が1になるわよね?10種類の数字が1周する毎に隣の位が1ずつ増えていく。この私たちが慣れ親しんでいる数の世界は「10進法」とか「10進数」って呼ばれているの。」
「なんだか聞きなれないね?ほむらちゃん?」
「確かにそうね。だからコンピュータが扱う0と1だけの2種類の数の世界では2種類の数字が1周すれば、また0に戻って隣の位が1になる。その繰り返しになるわ。だからこちらは「2進法」や「2進数」って呼ばれるの。」
「先ほどの不都合な事に話を戻るわね。数字の計算以外の文字や図形をコンピュータが扱う時も、実は数値にして計算させてその結果を文字や図形という形で画面に表示しているの。でも人間の脳とは違って、コンピュータが計算するために限られた環境(メモリなど)で行う必要があるから、効率的にそして操作する人間がわかりやすい設計でないといけないわ。」
「???」
「ちょっと混乱してきたわね。ごめんなさい。数字だけの計算だけだったら「10進数」でも「2進数」でも大丈夫ってことは何となく整理できたかしら?」
「うん!そこまでは大丈夫だよ?」
「問題はそれ以外なの。例えばリンゴを見て、これがリンゴかどうかなんて考える事はあるかしら?」
「え?呼んだかい?」
「なになに?お菓子ならいつでも来ちゃいますよ~?」
「ごめんなさい。リンゴはないの。その代わり、このお菓子をあげるわ。」
「わーい!お菓子~お菓子~!」
(鹿目さんの言った通り、用意しておいて正解だったわね)
(ウェヒヒ!実はほむらちゃんに教えてもらったんだよ~)
「さて、どこまでお話をしましたっけ?」
「リンゴのところだよ?ほむらちゃん?」
「そうだったわね。鹿目さんはリンゴを見て、これがリンゴかどうかをしばらく考える事はあるかしら?」
「え?ないよ??だってそれがリンゴだったら、リンゴだよ??」
「確かにそうね。それは鹿目さんが鹿目さんの目から入ったリンゴの映像を鹿目さんの脳が瞬時に読み取って答えを出しているからなの。でもコンピュータの脳であるCPUは違うわ。」
「リンゴだってすぐにはわからないの??」
「というより、鹿目さんのように目から情報を読み取る形じゃないの。最近のAI(人工知能)では人間が見るようにカメラの映像情報から読み取る技術も開発されては来てるけれど、まだまだ大半のコンピュータは人によって入力されたデータを数値に直して計算して答えを出す仕組みなの。」
「それじゃあ、パソコンの画面で見えるリンゴの画像は数値なの??」
「極端にいえば、そうなるわね。パソコンなどのコンピュータは与えられたデータを計算して画像や文字として見えるように結果を表示しているに過ぎないの。だから人間のようにこれがリンゴとしては認識していないわ。」
「でもそれでも計算なんだから、10進数のままでもいいんじゃないの??」
「そうね。計算だけなら問題ないわ。でも、今回のプログラムの後の説明でもするけれど、10進数だと色々と不便な部分が出てくるの。わかりやすく豆電球の回路で使う様なスイッチを思い出してほしいの。」
「金属の板を押している間だけ、豆電球が付くものだよね?」
「そう。でもこれを人の手ではなくてマイコン側でやってもらうために、プログラムでその指示を送ってあげないといけないわ。でも難しくはないわ。」
「専用の指示があるの??ほむらちゃん??」
「指示を数字で送るの。スイッチをオフなら0、スイッチをオンなら1よ。」
「ほむらちゃん?そしたら、残りの2~9は何に使うの??」
「使わないわ。スイッチだけでなく、これから使うデジタル数字で使う7セグの点灯でも、0と1さえあれば実現できるの。」
「でもほむらちゃん?文字や画像はどうするの??」
「今回のプログラムでは登場しないけれど、実は文字もその文字を表現するための特定のコードが数字として割り振られていて、それは「文字コード」って呼ばれるの。コンピュータはその文字コードを読み取って、その文字を画面に表示する仕組みね。」
「画像の場合は、例えばリンゴの絵をスケッチする時を想像してみて。」
「うん。」
「鹿目さんは見たままのリンゴを脳が瞬時に読み取りながらスケッチするけどコンピュータは先ほどもお話ししたけれど、人の目のようにはいかないの。」
「じゃあ?どうやって??」
「リンゴの絵全体に細かい格子を重ねると、それを見ながら別の白い紙にリンゴのドット絵を複写できるわね?」
「うん!」
「その細かい格子ひとつひとつに数値が入っていて、それが文字コードの様に色を表す数値になっているの。」
「だから、リンゴの絵が表示できるんだね?ほむらちゃん?」
「その通りよ!流石だわ、鹿目さん!」
「ウェヒヒ!」
「先程のスイッチの場合はどうかしら?0と1だけしか使っていないわね?」
「うん。残りの2~9は暇そうにしてるよね??」
「そうね。使わないけれどその分だけ余分に作業机のスペースをとっている感じかしら?作業机は広いほうがいいけれど、コンピュータでは無限に広くとはいかないの。広いだけ、コンピュータが読みにいくのに時間がかかるから、これはプログラムの実行速度にも影響するの。」
「でもほむらちゃん?0と1だけでも数値は表せるの??」
「たとえば、先ほどの99で再度考えていきましょ。」
「うん。」
「私たちが普段使っている数の世界では1の位、10の位、100の位・・というふうに10倍ずつ増えていくものだったわね?」
「うん、そうだよ~」
「コンピュータが扱う0と1だけ数の世界では、1の位、2の位、4の位・・・と2倍ずつ増えていくの。それぞれの位には0か1しか入らないわ。」
「でもほむらちゃん?最初の右端の9は1の位に入らないよ??」
「10進数で慣れていると確かにそう不思議に思うのも無理ないわね。今この99が2進数ではなくて、10進数だって事を忘れていないかしら?」
「あ!そうだった~」
「まず右から左へ1の位、2の位、4の位・・と2倍ずつ増やして128の位まで書き並べてみて?鹿目さん?」
128 64 32 16 8 4 2 1
「こんな感じかな?ほむらちゃん?」
「それで大丈夫よ。そしたらそれぞれの位の下に1を書き込んでみて。」
128 64 32 16 8 4 2 1
1 1 1 1 1 1 1 1
「できたよ?」
「そしたら、それぞれの位とその下の数字を掛け算してみましょ。」
128 64 32 16 8 4 2 1
× × × × × × × ×
1 1 1 1 1 1 1 1
=128 =64 =32 =16 =8 =4 =2 =1
「計算したよ?」
「そしたら、99より大きい数は1から0にしましょ。大きい数は幾つかしら?」
「128だね~!だから、128は0だね?」
「そのとおりね。そしたら64からどんどん順に右に足していって、99に一番近い数まで1にしていきましょ。」
「えっと・・・64+32=96。だから64と32も1だね。でも次の16を足すと112になるから99よりも大きくなるから16は0だね??ほむらちゃん?」
「そのとおりよ!だから今のところ、こうなるわね。」
128 64 32 16 8 4 2 1
0 1 1 0 1 1 1 1
「そしたら、残りの4についても同じように計算していきましょ。」
「えっと??あ!4があるから、4以外の1,2,8も0になるね!」
「流石よ!鹿目さん!だから最終的にこうなるわね。」
128 64 32 16 8 4 2 1
0 1 1 0 0 1 0 0
「私たちが普段10進数で使っている99という数字はコンピュータが使っている2進数では一番左の0を除いて『1100100』と表現されるの。」
「同じ数字なのに、なんだか見慣れないね?」
「0~9までの数字を普段使っているから慣れないのも仕方ないわ。私たちに理解できる普段の数字との変換にはちょっと手間がかかるけれど、0と1だけの数字だけできちんと普段使っている99という数字も表現できるの。」
「うん。できたね~」
「それだけじゃないの。先程のスイッチの話を思い出して。あれも0と1さえあれば、オフとオンを表現できるわね。あとは操作するスイッチの数だけ左へ並べていけば、幾つでもスイッチ操作を指示ができるわ。今回だと1の位、2の位・・・128の位の7つまであるから、7つのスイッチを同時に操作指示できることになるわ。」
「人の指だとなかなか難しいね?ほむらちゃん?」
「確かにそうね。でもピアノの鍵盤操作なら鹿目さんの方が勝つわね。」
「え?なんで??だってほむらちゃん、さっき幾つでもスイッチ操作ができるって言ってたよ??」
「ごめんなさい、少し混乱させたわね・・。理論上は可能なんだけど実際は使うコンピュータのCPU性能で限界があるの。今回のマイコンだと8つのスイッチまでしか操作できないの。つまり8本の指までしか使えないの。」
「そっか!こちらは10本の指でピアノを弾くからこっちが勝つね~!」
「この1本の指で出来る単位を「ビット」って呼んでいるの。先ほどの例だと7つのスイッチ、つまり7本の指で操作できるから7ビットになるわ。」
「ということは、マイコンは8ビットだね!ほむらちゃん?」
「そういうことよ!同時に扱える数値も範囲が決まってくるわ。」
「さっきのunsignedの話だね?」
「そうよ。鹿目さんに先ほど計算してもらった1の位~128の位の全ての位を0にすると10進数では幾つになるかしら?」
「えっと、0は掛け算しても0だから・・「0」になるよ?」
「逆にすべての位を1にしたら?」
「128+64+32+16+8+4+2+1=255。「255」だね!」
「そう、だから8ビットで扱える数値の範囲は0~255って事になるわね。」
unsigned char seg1;
「先ほどのプログラム行に戻ってみましょ。先ほどは説明していなかったけれど、変数は「seg1」という名前で設定しているわ。「unsigned」は「符号設定なし」って意味で、つまり負の数は使いませんって意味なの。負の数は覚えているかしら?」
「うん!0よりも小さい数の頭に「-」が付けたものだよね?」
「そのとおりよ。逆に「signed」にすると「符号設定あり」で負の数も使いますよって意味になるの。」
「ほむらちゃん?そしたら、-255~255まで数値は扱えるの??」
「確かにそう思うわよね。でも鹿目さん、実は違うの。負の数を使う場合は、その数値に「-」があるかを区別しないといけないの。」
「どうすうるの??」
「一番大きな位だけは数値としては扱わない仕組みなの。今説明してきた8ビットなら128の位だけは数値ではないの。128の位にも0と1が使われるのだけど、それぞれ「負の数ではない」「負の数である」事を示しているの。」
「そしたら、1の位~64の位が数値になるの?」
「そのとおりよ。1の位~64の位をすべて1にすると幾つになるかしら?」
「えっと、1+2+4+8+16+32+64=127。「127」だね!」
「そう。だから「signed」にすると扱える数値の範囲が-127~127になるの。もっとも今回のプログラムではどちらに設定しても影響ないのだけど、今後の為に覚えておくといいと思うわ。」
「うん!ありがとう!ほむらちゃん!」
「どういたしまして。さて次に進みましょ。」
「ほむらちゃん?ところで「char」ってどういう意味なの??」
「ごめんなさい・・・説明が抜けていたわね。今回は「seg1」という名前で変数を設定しているってお話はしたっけ?」
「うん。さっき話してくれたよ~。」
「その設定した変数のデータサイズを決めるものなの。」
「データサイズ???」
「さっきの作業机のお話に戻ると、この作業机にどれだけのスペースを使うかというイメージだとわかりやすいかしら?」
「うん!」
「これもまた今回のプログラムでは影響ないのだけど、プログラムによってはこのデータサイズを適当に決めてしまうと重大なバグになる場合もあるの。具体的には別の変数がこの「seg1」って変数と絡むようなプログラムの場合なのだけど、今はそこまで気にしなくても大丈夫よ。作業机って例えで話してきたけれど、これはコンピュータの世界では「メモリー」って呼ばれるものよ。」
「携帯電話のメモリーカードも同じなの??」
「厳密には違うのだけど、私たちの脳のように一時的に何かを記憶するための空間だから、半分正解ね。メモリーはメモリーカードのように写真などを保存するのではなくて、計算するために数値を一時的に書き込むメモ用紙みたいものかしら?作業机が広ければ、一度に書き込めるメモ用紙も増えるけれど、目的のメモ用紙を探すのにも時間がかかっちゃうわね?」
「うん。メモ用紙が一杯に広がると探すのも大変だよね?」
「プログラムが複雑になってくると、設定する変数も1つや2つだけでは済まなくなって、幾つものの変数を扱う事になるの。使う変数が増えれば、その分だけデータサイズ、つまり限られた作業机のスペースを圧迫していくことになるわ。そうした場合に、それぞれの変数に必要最小限のデータサイズに設定する事がとても大事なるわ。ちょっと難しかったかしら?」
「大丈夫だよ~。変数が増えると計算用のメモ用紙も増えていくから、探すのが大変にならないようにメモ用紙の大きさ(データサイズ)を必要最小限にって事だよね??」
「理解が早いわ!流石よ!鹿目さん!」
「ウェヒヒ!」
「「char」の他にも「int」や「double」なんてのもあるのだけど、いずれもデータサイズ、つまり変数が使うメモ用紙の大きさを決めるものなの。どの大きさのものを設定するかは先ほどの「unsigned」にあったように、使う数値範囲によって決めればいいわ。データサイズの詳しいところは省くけれど、今回のプログラムでは変数「seg1」には0~9までの数値しか使わないから、変数のデータサイズはcharで設定しているわ。」
「うん。わかったよ~ほむらちゃん!」
「そしたら、次に進めましょ。」
unsigned char p[10] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
「ほむらちゃん?これもさっきと似ているけれど???」
「p[10]以降がごちゃごちゃしていて、ちょっと戸惑うわね。でもこれも変数の一種なの。」
「さっきのseg1とは違うの??」
「変数というよりは定数のほうが近いかしら?だいぶ前に戻るけれど、定数の話は覚えている?」
「プログラムの色んなところに同じ数字を入れるなら、数字の部分は変数にいしておけば、その変数に数字を入れるだけで済む話だっけ?ほむらちゃん?」
「変数madokaの話をちゃんと覚えているなんて流石だわ!その通りよ。変数や定数はプログラム行の最初の方でまとめて設定するのが基本なの。ところで変数p[10]なんだけど、変数seg1とは少し使い方が違っているの。」
「seg1というように、そのままではプログラムには使えないの??」
「そうなの。変数seg1は、そのままseg1と書けば計算してくれるわ。例えばseg1に1を入れたら、他の行にあるseg1も1になるし、seg1+1なら2と計算してくれるの。でもp[10]は同じ名前の変数が10個集まっているイメージかしらね。」
「同じ名前の変数??」
「10個の変数を設定することを考えてみましょ。その場合は同じ名前の変数は設定できないの。さっきのseg1なら、残りの9個の変数の名前はいずれも同じ名前にならないように設定してあげないといけないわ。seg2,seg3・・・のようにね。でもこれだと書き間違いを起こしやすいし、プログラムもより分かりにくく場合があるからお勧めできないわ。」
「そしたら、ほむらちゃん? p[10]はどうやって使うの??」
「変数の集合体をイメージするとわかりやすいかしら?同じデータサイズの変数の箱が横に10個隙間なく並んでいるの。」
「うん!わかりやすいよ~。」
「p[10]の[10]は、10個って意味なの。変数としてはp[0]~p[9]の10個が並んでいる感じかしらね。違いはそこだけで、使い方はさきほどのseg1と同じなの。p[2]に1が入っているなら、『p[2]+1』の計算式の答えは2になるわ。」
「でも、ほむらちゃん? 「0x3F」、「0x06」みたいのがずらっと並んでいるよ??」
「鹿目さん、いいところに目をつけているわ。流石よ!」
「ウェヒ!」
「その説明の前に、見方を説明しないといけなかったわね。」
unsigned char p[10] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
「これは、次のように置き換えるとわかりやすいわ。」
unsigned char p[10] = {p[0],p[1],p[2],p[3],p[4],p[5],p[6],p[7],p[8],p[9]};
「ほむらちゃん?p[0]に0x3Fが入っているということなの?」
「そのとおりよ、鹿目さん。入れたい値がすでに決まっている場合は、p[0]から順番にこうやって書いていけばいいの。」
「ほむらちゃん、入れたい値が決まっていない場合はどうしたらいいの?」
「よい質問だわ、鹿目さん。その場合は、さっきのseg1のようにこういうに書くの」
unsigned char p[10];
「そして実際に値を入れたい場所でつぎのように書けばいいわ。たとえば、p[0]に1を入れたい場合はこうなるの。あとでこの流れを説明するから、ちょうどよかったわ。」
p[0] = 1;
「さて、いよいよプログラム本体のところね。ここまでは鹿目さん、大丈夫?」
「うん、大丈夫だよ!ほむらちゃん!」
「なら、次に進みましょ。ここからがプログラム本体にあたるところね。今回のプログラムは、7セグの光らせたい場所をマイコンから光らせるのが目的だったわね。ちょっと長くなるけれど、改めて書き並べてみるわね。」
void main(void) {
TRISA = 0x00; //PORTA全てのピン(RA0〜RA7)は「0」。つまり出力設定。
TRISB = 0x00; //PORTB全てのピン(RB0〜RB7)は「0」。つまり出力設定。
PORTA = 0x00; //PORTA全てのピンを「0」に設定
PORTB = 0x00; //PORTB全てのピンを「0」に設定
seg1 = 0;
while(1) {
PORTA = 0x01;
if(seg1 > 9){
seg1 = 0;
}
PORTB = p[seg1]; //配列p[]のビットパターンで7セグが点灯
__delay_ms(1000); //1000ミリ秒=1秒間何もしない
seg1++;
}
「!?」
「落ち着いて、鹿目さん。ちゃんと説明するから大丈夫よ。」
「うん、わかったよ。ほむらちゃん。」
「まず、次の部分ね。」
void main(void) {
「void??」
「そうね、初めて見るとなんだかわからないわね。先頭のvoidは、関数の型名が書かれる部分なの。」
「関数の型名???」
「混乱させてしまったわね。鹿目さん、ごめんなさい。説明する前に実例を書いてみせるわね。こんな感じなの。」
int sum(void) {
「mainがsumに変わっているよ??ほむらちゃん?」
「いいところに気が付いたわ、鹿目さん。そう、実はこのsumが関数の名前なの。」
「ほむらちゃん、関数の名前は自由に決められるの?」
「条件さえ守れば、自由に名前をつけれらるの。」
「条件??」
「関数には2種類あるの。絶対に省略できない関数と自分で名前を決めて作る関数よ。絶対に省略できない関数は名前が決まっていて、これは名前を変える事ができないの。それが、先ほどのmainなの。」
「ほむらちゃん、さっきのvoid main(void) がそれなの?」
「そのとおりよ。鹿目さん。このmain関数から、たとえば先ほど説明したsumという名前の自分で作った関数を呼び出して処理をさせる、という感じになるの。混乱してしまうから、この辺りの説明はこの辺までにしておきましょ。ここまでは大丈夫?鹿目さん。」
「うん、なんとか大丈夫だよ、ほむらちゃん」
「main関数は必ずプログラムで処理がされる関数ってこと、必要に応じて、別の処理を書いた自分で名前を付けた関数を呼び出す、という流れだけを覚えておけば大丈夫。」
「ほむらちゃん、やっとわかったよ!」
「よかったわ、なら先に進みましょ。次がちょっとわかりにくい部分かもしれないわ。」
TRISA = 0x00; //PORTA全てのピン(RA0〜RA7)は「0」。つまり出力設定。
TRISB = 0x00; //PORTB全てのピン(RB0〜RB7)は「0」。つまり出力設定。
PORTA = 0x00; //PORTA全てのピンを「0」に設定
PORTB = 0x00; //PORTB全てのピンを「0」に設定
「TRISA?? PORTB???」
「これだけだと、謎のキーワードよね。だいぶ前に話が戻るけれど次の図は覚えているかしら?」
「うん、矢印の向きでそれぞれのマイコンのピンが入力用、出力用かがわかるって、ほむらちゃんに教えてもらったときだよ。」
「さすがだわ、鹿目さん。私なんかすぐに追い越されそうだわ。」
「ウェヒ?!そんなことないよ?!」
「両方向の矢印になっているピンは、入力用・出力用どちらでも利用が出来るって意味なの。だからプログラムでどちらにするかを設定することになるわ。それが、先ほどのTRISAとTRISBなの。」
「この部分かな?」
TRISA = 0x00; //PORTA全てのピン(RA0〜RA7)は「0」。つまり出力設定。
TRISB = 0x00; //PORTB全てのピン(RB0〜RB7)は「0」。つまり出力設定。
「そう。先ほどの図で赤く枠で囲っている部分が今回7セグ点灯で必要なピンなの。図の中で、RA0とか、RB0って表記になっているのがわかるかしら?」
「うん、RAやRBの後は数字になっているんだね?ほむらちゃん?」
「鹿目さん、よいところを見つけたわ。Aポートの場合はRA、Bポートの場合はRBという表記になっているのだけど、それぞれのポートは0から始まるのよ。」
「ほむらちゃん、そしたら、TRISBはBポートの設定するところなの?」
「鋭いわ、流石だわ、鹿目さん!」
「ウェヒヒ!」
「この表記だとわかりにくいから、ちょっと書き直してみましょうか。」
TRISB = 0x00;
「これだとちょっと説明がしやすいかしら。」
TRISB = 0b00000000;
「0x~で始まるのは、16進数という意味なんだけど、この部分は説明を省くわ。また前に戻っちゃうけれど、2進数の説明は覚えているかしら?」
「私やほむらちゃんが日常で使っている10進数ではなくて、コンピューターでは2進数を使っていることだよね?」
「そのとおりよ。2進数では10進数とちがって0と1の2種類しか数字は使わないの。スイッチの話で少しだけ触れたのだけど、2進数の方が理にかなっている良い例がまさにここなのよ。」
「数字だけじゃなくて、スイッチのオンとオフも2進数なら、10進数と比べて無駄なく表現できるってお話だったよね??ほむらちゃん?」
「理解がとても早いわ!鹿目さん、凄い!」
「あまり言われると照れちゃうよ、ほむらちゃん///]
「TRISBをわかりやすく書き直したこれだけど、実は2進数なの。0bの後に続く8つの0が2進数になっているのよ。」
TRISB = 0b00000000;
「ほむらちゃん、でもどうやって入力用とか出力用に設定していけばいいの??」
「これの見方なんだけど、一番右端の0がRB0なの。順番に左へRB1、RB2・・・RB7と全部で8つのピンに対応しているのよ。」
「ほむらちゃん、たとえばRB1のピンを入力用したい場合は、こういうふうに1にすればいいの?」
TRISB = 0b00000010;
「そのとおりよ、やっぱり鹿目さんに追い越されそうだわ」
「ウェヒ!?そんなことないよ!?」
「今回のプログラムにはないけれど、スイッチと繋げて、押された場合の入力判断なんかをするときには、鹿目さんが今やったような設定をするわ。」
「各ポートのピンの入力出力設定の次は、各ポートのピンの初期状態の設定になるわ。」
PORTA = 0x00; //PORTA全てのピンを「0」に設定
PORTB = 0x00; //PORTB全てのピンを「0」に設定
「ほむらちゃん?これだと7セグが全部消えた状態になるの??」
「これだけだと、ちょっとイメージがしづらいかもしれないわね。この図で説明していくわね。」
「鹿目さんが先ほど言っていた7セグの点灯、消灯はPORTBのことなの。」
「この図だとPORTBってどこにあるの??ほむらちゃん?」
「先ほどのマイコンの図をちょっと回転みるわね?」
「先ほどの配線図では説明が抜けていたわね。鹿目さん、ごめんなさい。配線図のマイコンは実はこの1番のピンが左下にある前提だったの。」
「ほむらちゃん、大丈夫だよ!これでPORTBがどこにあるのかよくわかるよ!配線図の緑色の数字が、PORTBだよね?」
「流石だわ!鹿目さん!」
「ウェヒヒ!」
「例えば、配線図の7セグのこの赤い部分だけを点灯させたい場合は、該当するPORTBのピンからマイコンに出力させるプログラムを作成するの。」
PORTB = 0x00; //PORTB全てのピンを「0」に設定
「ほむらちゃん?さっきのこの部分で設定するの??」
「鹿目さん、察しがいいわ!」
「ウェヒ!」
「まだ説明はしていなかったのだけど、この7セグには10本のピンが出ていて、どのピンが7セグのどの部分と繋がっているかが決まっているの」
「でも、ほむらちゃん??7セグにもマイコンの図にもないよ??」
「7セグのピンの割り当ては実は決まっていて、別で調べると出てくるのだけども、混乱しちゃうといけないから、今は省いておくわね?先に答えを明かすと、配線図の緑の数字「1」がそうなの。」
「マイコンのピンにも、7セグのピンにも同じ数字があるよ?ほむらちゃん?これは、同じ数字で繋げるってことなの??」
「理解が早いわ!鹿目さん!その通りよ!」
「ウェヒヒ!」
「マイコンの図でいえば、RB0。PORTBの0番ピンから出力信号を出すようにしてあげれば、7セグの赤いところが点灯するわ。」
PORTB = 0b00000001;
「マイコンのピンはRB0だから、ほむらちゃん、こうすればいいのかな?」
「正解だわ!鹿目さん!」
「ウェヒヒ!」
「でも、これは毎度書くのは大変だよ??数字とかはどうやって表示するの??」
PORTB = p[seg1]; //配列p[]のビットパターンで7セグが点灯
「それがプログラムのこの部分なの。」
「ビットパターン??」
「鹿目さん?さっき同じ大きさの箱が10個並んだイメージのお話は覚えている?」
「たしか、データサイズが同じ変数が10個並んでいるp[10]というものだったような??」
「よく覚えているわ!流石よ!鹿目さん!」
「ウェヒ!」
unsigned char p[10] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
「少し説明の流れが戻ってしまうけれど、この部分のことなの。0x~って並んでいるそれぞれが実は、7セグの数字になってるの。」
「ほむらちゃん?7セグの数字には見えないよ??」
「これだとピンとこないわね。一番左の0x3Fを例に説明するわね?」
「うん」
「0x3Fの0xは、16進数という意味なの。鹿目さん?2進数の話は覚えているかしら?」
「うん!私たちが使っている世界では0から9まで行くと桁が一つずつ繰り上がる10進数だけど、コンピュータの世界では、0から1で桁が一つずつ繰り上がる2進数だね!」
「鹿目さん、10進数と2進数の計算は見事だったわ!」
「ウェヒ!ほむらちゃんの説明がとてもわかりやすかったよ!」
「10進数と2進数で鹿目さんには計算してもらったけれど、今度は10進数と16進数の計算にもチャレンジしてみる?」
「ちゃんと、計算できるかな??」
「大丈夫。ちゃんと説明するから、安心して」
「うん!」
「2進数のときみたいに書き並べていくのだけど、まず16進数が0から15まで行くと桁が一つ繰り上がる、ところは初めに説明しておくわね?」
「うん、ここまでは大丈夫だよ!ほむらちゃん!」
「よかった。じゃあ、説明を続けていくわね?10進数のときは1の位の次は10の位、100の位と10倍ずつ増えていくわね?」
「うん」
「では2進数のときは?」
「2倍ずつ増えていくから、1の位の次は2の位、4の位って増えていくよ?」
「そのとおりよ。では16進数の場合はどうかしから?」
「あ!そうか、16倍ずつ位が増えていくんだね?ほむらちゃん!」
「流石よ!鹿目さん!」
「ウェヒヒ!」
「そしたら、話を戻すわね。先ほどの0x3Fだけれど、0xは16進数って意味で、それ以降が16進数で表記された数字なの。つまり3Fね。」
「でも、ほむらちゃん?数字なのにアルファベットがあるよ??」
「やっぱり着眼点が素晴らしいわ!鹿目さん!」
「ウェヒヒ!」
「16進数は0から15まで行くと桁が一つ増えるのだけど、10から15はそれぞれアルファベットのA~Fを使うことになっているのよ」
「ということはほむらちゃん?1桁目が15で、2桁目が3になるの??」
「その通りよ。これを踏まえて、1の位、16の位を右から書き並べてみましょうか?」
16 1
「こんな感じかな?」
「それでいいわ。その下に3とFを書き並べてみましょう」
16 1
3 F
「そしたら、Fは15に直して、それぞれの位で掛け算してみて?」
16 1
× ×
3 15
=48 =15
「できたよ?ほむらちゃん?」
「最後に掛け算した答えの足し算をしてみましょう。」
「48+15=63。ほむらちゃん、10進数だと63だね!」
「正解よ!鹿目さん!」
「ウェヒ!」
「10進数だと63とわかったところで、これは2進数にしたいのだけれど、鹿目さん?2進数の計算はまだ覚えているかしら?」
「大丈夫だよ!やってみるよ!確か、128の位までこうやって並べて…」
128 64 32 16 8 4 2 1
「その下に1を並べて」
128 64 32 16 8 4 2 1
1 1 1 1 1 1 1 1
「63より大きな位の1は0にして」
128 64 32 16 8 4 2 1
0 0 1 1 1 1 1 1
「これで一旦それぞれ掛け算だね?ほむらちゃん?」
128 64 32 16 8 4 2 1
× × × × × × × ×
0 0 1 1 1 1 1 1
=0 =0 =32 =16 =8 =4 =2 =1
「そう、その調子よ?鹿目さん!」
「うん!それぞれの数字が足し算すると、32+16+8+4+2+1=63。ということは、2進数だと00111111になるよ?ほむらちゃん?」
「そう、正解よ!」
「ウェヒ!でもほむらちゃん、7セグの数字には見えないよ??」
「そう、これだけでは確かにわかりにくいわね。だいぶ前に、7セグのピンの配置の説明を少しのは覚えているかしら?」
「確か、7セグのピンの配置は固定で決まっているってお話だったような?」
「そのとおりよ!やっぱり呑み込みが早いわ!鹿目さん!」
「そんなに言われると照れるよ、ほむらちゃん///」
「7セグのピンの配置は実はこうなっているの。」
「??」
「鹿目さん、大丈夫落ち着いて。ちゃんと説明するわね。」
「うん」
「8の字でアルファベットがそれぞれあるわね?」
「a~fまであるよ?」
「8の字の外側の黒い点にもアルファベットがあるわね?」
「本当だ!横倒しでa~fってあるね?」
「例えば、7セグのaを光らせたい場合のピン番号なのだけど、同じアルファベットがあるピンの番号は幾つかしら?」
「あ!7番にaがあるよ?ほむらちゃん?」
「そしたら、さきほどの配線図を見てみましょう?」
「そうか、ほむらちゃん?この緑の1~8は、ピン配置のa~gに対応してるのかな??」
「鋭いわ!流石、鹿目さん!」
「もうここまで来たら、説明が必要ないかもしれないけれど、進めていくわね?」
「うん!」
「少し戻って、さっき鹿目さんに16進数の計算をしてもらったわね?」
unsigned char p[10] {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
「この0x3Fを計算したよ??2進数だと、00111111だったよ?」
「その2進数の下に右からa~gを書き並べてみて?」
0 0 1 1 1 1 1 1
g f e d c b a
「ふふっ、鹿目さん。もうここまでくれば完璧よ?さっきの7セグのa~gで、1になっているアルファベットだけ赤く塗りつぶしてみて?」
「できたよ?あ!ほむらちゃん!数字の「0」になっているよ!」
unsigned char p[10] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
「先ほどの0x3Fが2進数では00111111。数字の「0」が点灯するビットパターンになっているの。0x06が「1」、0x5Bが「2」という感じに「9」までの並んでいるのよ。」
unsigned char p[10] = {p[0],p[1],p[2],p[3],p[4],p[5],p[6],p[7],p[8],p[9]};
「だから、ほむらちゃん。さっきこの説明をしていたんだね!数字の「7」を点灯したい場合は、p[7]だから、0x07だね!」
「その通りよ!もう私をとっくに追い越したわ!」
「ウェヒヒ!」
「そしたら、プログラムのところに話を戻りましょう?」
「うん!」
seg1 = 0;
while(1) {
PORTA = 0x01;
if(seg1 > 9){
seg1 = 0;
}
PORTB = p[seg1]; //配列p[]のビットパターンで7セグが点灯
__delay_ms(1000); //1000ミリ秒=1秒間何もしない
seg1++;
}
「先ほどの7セグの点灯の話から、改めてこれを見て?」
PORTB = p[seg1]; //配列p[]のビットパターンで7セグが点灯
「あ!さっきのp[0]とかをここに入れるのかな?ほむらちゃん?」
「その通りよ!」
「ウェヒ!」
「でも、ほむらちゃん?p[0]じゃなくて、p[seg1]ってなっているよ??」
「そうなの。そのseg1が注目するポイントになるの。説明しやすくするために、先ほどのプログラムをちょっと省略した形にしてみるわね。」
while(1) {
・・・
if(seg1 > 9){
seg1 = 0;
}
PORTB = p[seg1]; //配列p[]のビットパターンで7セグが点灯
・・・
seg1++;
}
「このように書かれているプログラムは、上から順番にコンピュータが読み取って処理するようになっているの。この説明はまだだったかしら?」
「うん」
「よく説明で登場するのが、滝の流れを使ったものね。滝は上から下に落ちて流れるわよね?」
「うん!」
「この滝の流れをイメージしつつ、seg1に注目してほしいの。」
seg1 = 0;
「ほむらちゃん、これかな?seg1と0は等しい??」
「数学だとそうなるわ。でもプログラムではちょっと意味合いが違うの。これは、変数seg1に0を代入せよって意味なの。」
「じゃあ、ほむらちゃん?ここでseg1は0になっているの?」
「その通りよ。それを覚えておいて次に進みましょう?」
「うん!」
while(1) {
・・・
if(seg1 > 9){
seg1 = 0;
}
PORTB = p[seg1]; //配列p[]のビットパターンで7セグが点灯
・・・
seg1++;
}
「いきなり長くなって、ちょっと混乱するかもしれないわね。」
「大丈夫だよ!ほむらちゃん!」
「よかった。まずはwhile(1)について、説明するわね?」
「うん!」
「while(1)は、「{」と「}」で挟まれた部分を無限にループして処理せよ、という命令なの。」
「ウェヒ?!ほむらちゃんの時間遡行みたい!」
「あら、鹿目さんにはもうバレていたのね。なんでもお見通しね。」
「ウェヒヒ!」
「でも安心して。時間遡行は繰り返すたびに同じ時間を繰りかえしているようでも、すこしずつ運命(状況)が変わってしまうけれど、このwhile(1)による無限ループは、ずっと同じ状態が繰りかえし続くのよ。」
「ほむらちゃんとは、同じ時間を繰り返しても私は構わないよ?ほむらちゃんと何度でもウェヒウェヒできるから!」
「鹿目さん!」
「ほむらちゃん!まるで、私とほむらちゃんみたいだね!」
「そういわれると、なんか照れるわね。」
「ウェヒ!」
「そしたら、次に進めるわね?」
「うん」
if(seg1 > 9){
seg1 = 0;
}
PORTB = p[seg1]; //配列p[]のビットパターンで7セグが点灯
seg1++;
「while(1)の「{」と「}」で挟まれた部分がこの部分になるのだけど、seg1にはどんな数字が今入っているか、覚えているかしら?」
「えっと、0だよ?ほむらちゃん?」
「うん。その通りね。次のif(seg1 > 9)の説明にするわね?これは条件文と呼ばれるものなの。滝の流れについては覚えているかしら?」
「うん。上から下に流れるんだよね?」
「そう。でもこの条件文に来ると、滝の流れが変わることがあるの。」
「??」
「混乱させてしまってごめんなさい。」
「大丈夫だよ!ほむらちゃん?」
「よかった。if(seg1 > 9)は、seg1が9より大きいかどうかを判断しているの。」
「9より大きいとどうなるの?」
if(seg1 > 9){
seg1 = 0;
}
「良い質問だわ!その場合は、「{」と「}」で挟まれたseg1=0;が実行されるの。つまり、seg1には0が入ることになるわ。」
「逆に9より小さい場合はどうなるの??」
if(seg1 > 9){
seg1 = 0;
}
PORTB = p[seg1]; //配列p[]のビットパターンで7セグが点灯
「その場合は、「{」と「}」で挟まれたseg1=0;は実行されずに、次のPORTB = p[seg1];から順番に下へ実行されることになるわ。」
「そっか、ほむらちゃん。今はseg1は0だから、seg1=0;は実行されないね?」
「その通りよ!だから、次のPORTB = p[seg1];が実行されるわね。」
PORTB = p[seg1];
「あれ?seg1が0ってことは、PORTBにはp[0]が入るの??」
「その通り! p[0]の説明は覚えているかしら?」
unsigned char p[10] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
「うん!これだよね?ほむらちゃん?あ、だから0x3FがPORTBに入るんだね?つまり、こういうことかな?ほむらちゃん?」
PORTB = 0x3F;
「その通り!流石よ!鹿目さん!」
「ウェヒ!」
seg1++;
「そして最後のseg1++;ね。ちょっと見慣れない表記で戸惑うかもしれないれど、難しくはないわ。変数にseg1に1を足してね、という命令なの。」
「えっと、今はseg1が0だから、0に1足して1になるの?」
「正解よ。ここでseg1は1になったわけね。そしてまた処理は上に戻ることになるの。」
「あれ?さっき上から下に処理は流れるって??」
「基本はそうなの。でもwhile(1)の話を思い出してみて?」
「あ、そうか無限ループだね?ほむらちゃん?」
while(1) {
・・・
if(seg1 > 9){
seg1 = 0;
}
PORTB = p[seg1]; //配列p[]のビットパターンで7セグが点灯
・・・
seg1++;
}
「そう。だからseg1++まで実行されると、while(1)の「{」と「}」で挟まれた部分を上から繰り返して下まで実行されることになるわ。」
PORTB = p[1];
「今度はseg1が1になっているから、PORTBは0x06だね?ほむらちゃん?」
「その通りよ!」
「ウェヒヒ!そしたら、この0x06だと7セグだと「1」と表示されるのかな?」
「そう。seg1が1ずつ足されて9まで行くとどうなるか、覚えているかしら?」
if(seg1 > 9){
seg1 = 0;
}
「seg1が10になるから、この条件文が実行されて、seg1が0になって、また0から9まで繰り返すんだね!これで7セグの「0」から「9」を繰り返して表示するんだね!」
「理解が早いわ!鹿目さん!」
「ウェヒヒ!」
「さて、プログラムの流れのイメージが掴めてきたところで、残りの細かい部分の説明に入るわね?」
「うん!」
seg1 = 0;
while(1) {
PORTA = 0x01;
if(seg1 > 9){
seg1 = 0;
}
PORTB = p[seg1]; //配列p[]のビットパターンで7セグが点灯
__delay_ms(1000); //1000ミリ秒=1秒間何もしない
seg1++;
}
「先ほどまでの説明だけだと、確かに7セグの「0」~「9」を順番に表示するのだけど、目には留まらぬ速さで順番に表示するから、おそらく数字の区別が付かずに7セグでは「8」と表示されているように見えることになるわ。」
「そしたら、どうしたらいいの??」
__delay_ms(1000); //1000ミリ秒=1秒間何もしない
「それがこれよ?鹿目さん。何も処理しない命令を間に挟んであげればいいのよ。これは元々用意されている命令で、実は呼び出して使っているの。」
「どこから呼び出しているの??ほむらちゃん?」
「一旦プログラムの全体を書き並べてみるわね?」
#include <xc.h>
#pragma config FOSC = INTOSCIO
#pragma config WRT = OFF
#pragma config WDTE = OFF
#pragma config PWRTE = ON
#pragma config BOREN = ON
#pragma config LVP = OFF
#pragma config CP = OFF
//PICマイコンのシステム周波数を設定。Hz単位。(20MHzの場合)
#define _XTAL_FREQ 20000000
unsigned char seg1;
unsigned char p[10] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
void main(void) {
TRISA = 0x00; //PORTA全てのピン(RA00RA7)は「0」。つまり出力設定。
TRISB = 0x00; //PORTB全てのピン(RB00RB7)は「0」。つまり出力設定。
PORTA = 0x00; //PORTA全てのピンを「0」に設定
PORTB = 0x00; //PORTB全てのピンを「0」に設定
seg1 = 0;
while(1) {
PORTA = 0x01;
if(seg1 > 9){
seg1 = 0;
}
PORTB = p[seg1]; //配列p[]のビットパターンで7セグが点灯
__delay_ms(1000); //1000ミリ秒=1秒間何もしない
seg1++;
}
}
「鹿目さん、結構前に触れたヘッダーファイルのところは覚えているかしら?」
#include <xc.h>
「ここの事だね?ほむらちゃん?本来は使うマイコンの機種に対応したヘッダーファイルを書く必要があるのだけど、このxc.hというヘッダーファイルを使えば、ここから対応したマイコンの機種のヘッダーファイルを自動で読み込んでくれるんだっけ?」
__delay_ms(1000); //1000ミリ秒=1秒間何もしない
「その通りよ!実は、このヘッダーファイルから自動で読み込んでくれるマイコンの機種に対応したヘッダーファイルに、この__delay_ms(1000);を含めて予め用意されいるの。」
//PICマイコンのシステム周波数を設定。Hz単位。(20MHzの場合)
#define _XTAL_FREQ 20000000
「ほむらちゃん?そういえば、周波数の話をしてくれたときに、ある関数を実行するのに、この記載が必要だって言われたけれど、もしかしてこの__delay_ms(1000);のことなのかな??」
「その通りよ!まさに、これから説明しようと思ったところだったわ!今回は予め用意された関数を使うから、それほど意識しなくても大丈夫なのだけど、時計やタイマーのように正確な1秒を発生させる関数を自分で作る場合は、この部分はちゃんと設定しないといけないわ。でもまだ気にしなくて大丈夫よ?」
「うん!」
//PICマイコンのシステム周波数を設定。Hz単位。(20MHzの場合)
#define _XTAL_FREQ 20000000
「ちゃんと説明していなかったけれど、今回説明で使っているマイコンは、周波数が20MHzなの。プログラムの中で、こうやってHzって単位で指定してあげるのよ。」
「ほむらちゃん?Hzって??初めて聞くよ??」
「周波数の話はまだ、覚えているかしら?鹿目さん?」
「確か1秒間に振動する回数を現したのが周波数だよね?ほむらちゃん?」
「やっぱり、凄いわ!鹿目さん!」
「ウェヒ!」
「そう、1秒間に振動する回数をHzって単位で示すの。そういえば、鹿目さん?周波数ではないけれど、1kmは何メートルだっけ?」
「え?1000メートルだよ?ほむらちゃん?」
「そう、周波数でも同じなの。では1kHzは何Hzになるかしら?」
「そっか。ほむらちゃん、1000倍だから1000Hzだね!」
「その通りよ!距離の単位ではkmくらいしか普段は馴染みがないけれども、コンピューターの世界ではもっと上の単位を表すものがあるの。」
「どんな単位なの??ほむらちゃん?」
「代表的なのが、「M」と書いて「メガ」と呼ぶ単位だわ。」
「メガ?」
「聞きなれない単位よね?先ほどのkHzは覚えている?鹿目さん?」
「うん、確か1000倍だよね、ほむらちゃん?」
「そう。メガは、さらに1000倍した単位なの。つまり100万倍になるの。」
「ほむらちゃん?じゃあ、1MHzは100万Hzなの?」
「流石!その通りよ、鹿目さん!」
「ウェヒ!」
「つまり、20MHz何Hzになるかしら?」
「そっか、20000000Hz(2000千万Hz)になるね!ほむらちゃん?」
//PICマイコンのシステム周波数を設定。Hz単位。(20MHzの場合)
#define _XTAL_FREQ 20000000
「だから、この記載なんだね?ほむらちゃん?」
「察しがいいわ!鹿目さん!」
「ウェヒヒ!」
「そして、ようやくこの関数を使うことができるの。」
__delay_ms(1000); //1000ミリ秒=1秒間何もしない
「何もしない、って命令をマイコンにするんだよね?」
「そう。(1000)ってなっているのは、何もしない時間を設定しているの。」
「ほむらちゃん?また見慣れない単位があるよ?ミリ??」
「こちらの単位も説明していなかったわね。これもコンピューターの世界で時間計算とかではよく見かける単位で「m」で「ミリ」と呼ぶわ」
「ほむらちゃん?この単位も1000倍なの??」
「鹿目さん、着眼点が凄いわ!」
「ウェヒ!」
「普段の私たちの生活では、時間は最小単位は秒で済むわ。でも、マイコンを含めたコンピューターの世界では、1秒よりも速い時間を扱うことが多いの。」
「1秒よりも速い時間??」
「鹿目さん?ストップウォッチって触ったことはあるかしら?」
「うん、ほむらちゃん。デジタル式のなら見たことがあるよ?」
「1秒よりも速い、コンマ何秒って表示は見た事があるかしら?」
「あ!そういえば、ストップウォッチの右端にものすごく早くカウントする数字があったよ!」
「鹿目さん、まさにそれなの。市販で売られているストップウォッチだとコンマ2桁くらいしか表示されないものがほとんどなのだけど、F1とかのカーレースだとさらに1桁増えてコンマ3桁まで計測するわ」
「テレビで1秒893みたいな表示を見たことがあるよ?ほむらちゃん?」
「そう、その893が、893ミリ秒なの。1000ミリ秒で1秒になるの。」
「ということは、1ミリ秒は1000分の1秒なの?ほむらちゃん?」
「その通りよ!鹿目さん!」
「ほむらちゃん、すごく速いね?1秒よりも1000倍速い世界なんて想像できないよ?」
「そんな目にも止まらぬ速さでマイコンは命令を処理する世界なの。」
「さて、これまで説明したプログラムを改めて全て書いておくわね。」
#include <xc.h>
#pragma config FOSC = INTOSCIO
#pragma config WRT = OFF
#pragma config WDTE = OFF
#pragma config PWRTE = ON
#pragma config BOREN = ON
#pragma config LVP = OFF
#pragma config CP = OFF
//PICマイコンのシステム周波数を設定。Hz単位。(20MHzの場合)
#define _XTAL_FREQ 20000000
unsigned char seg1;
unsigned char p[10] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
void main(void) {
TRISA = 0x00; //PORTA全てのピン(RA00RA7)は「0」。つまり出力設定。
TRISB = 0x00; //PORTB全てのピン(RB00RB7)は「0」。つまり出力設定。
PORTA = 0x00; //PORTA全てのピンを「0」に設定
PORTB = 0x00; //PORTB全てのピンを「0」に設定
seg1 = 0;
while(1) {
PORTA = 0x01;
if(seg1 > 9){
seg1 = 0;
}
PORTB = p[seg1]; //配列p[]のビットパターンで7セグが点灯
__delay_ms(1000); //1000ミリ秒=1秒間何もしない
seg1++;
}
}
「ほむらちゃんの丁寧な説明で、どんな風に動くプログラムかイメージができたよ?ウェヒヒ!」
「鹿目さんの吞み込みが素晴らしいからだわ。説明が長くなってごめんね。」
「え?なんでほむらちゃんが謝るの?こんなに優しく説明してくれるほむらちゃんだから、安心して電子工作に取り組めるよ!ウェヒヒ!」
「ありがとう、鹿目さん!プログラムの用意もできた事だし、この回路図でマイコンにこのプログラムを書き込んでいきましょう?」
「うん!」
(つづく)