マイクロマウス研修 Part5(岩本)


こんにちは岩本です。
今回は、プログラム編です。

前回、ランプを光らせましたが、作られたプログラムをビルドしただけなので、プログラムの内容は全然わかりませんでした。
私は、プログラム初心者なので、どうやって勉強していこうかと思っていたところ、ちょうど良い教材をオーム社より出版されている事を教えていただきました。
本の名称は『マイクロマウスではじめよう ロボットプログラミング入門』というものです。PI:CO用の教材のため、めちゃめちゃ詳しく書いてありますので参考になります。(以下、教科書と表記する。)

まずは、最初から自分でプログラムを書いていこうと思います。
≪ファイル⇒新規作成⇒ 新しいプロジェクトを作成≫から新規プロジェクトを作成します。(教科書70Pを参照)

 

次にPI:COに使用しているマイコン[R5F5631MDxFM(64pin)]を選択し、プロジェクト名を決めて作成します。

 

作成すると、下図のように最初からいくつかのファイルが生成されます。
この中には、マイコン毎に決められた定義がされています。
詳細は、長くなるので必要な時に別途捕捉します。

 

ここに、サンプルプログラムのSTEP1のプログラムを書いていこうと思います。
まず、試しにサンプルプログラムの文章をそのまま書き写してみます。
このプログラムはWhile(1)で{}内を無限ループさせるプログラムのようです。
whileの()内が1で無限ループとなるのは、条件書式は成立した時には値1,不成立の時には値0になるためです。
{}内を見ていくとLED0~3を点灯させて、待ち時間として、iが0~8388607(0x7fffffは16進数です。)をカウントする間、点灯させ続けるようにしているようです。
その後、同じようにLED0~3を消灯させて、待ち時間として、iが0~8388607をカウントする間、消灯させ続けるというもののようです。
ここで、この画面だけでは分からないものが3種類あります。

①LED0~3の定義は?
②init_allの定義は?
③include先の定義は?

 

①LED0~3の定義は?
色々分からない定義がありますが、取り敢えずそのままビルドしてみます。
するとビルドエラーになると思います。エラーメッセージを見ると、LED0~3が定義されていないようです。
ちなみにエラーしたときは、ネットでエラーコードを調べると何が原因か出てくるので、それを参考にしています。

 

エラーが起きた時は、どうやって定義されているのかをサンプルプログラムで確認しながら定義していくと理解が深まると思います。
サンプルプログラムでは、portdef.hの中でdefineで定義されていました。defineは、ファイルを跨いで定義するときなどに使用します。
ifdefの部分は、少し変わったif文です。”PORTDEF”がdefineしてあったらifdefとelseの間の部分が適用されて、defineされていなかったらelseとendifの間の部分が適用されます。
この分を書く意味は同じ定義を何度も定義させないようにするのに役に立ちます。一応無くてもビルドは通ります。

 

portdef.hは自動生成されていないものですので、≪プロジェクトツリーを右クリック⇒追加⇒新しいファイルを追加≫から新しいファイルを生成します。
定義などは、.hのヘッダファイルに記載すします。

 

LED0~3の()内に記載されているPORTB.PODR.BIT.B0等は何かというと、マイコンのレジスタのポートを指しています。
レジスターとは、1bitを記憶して処理するCPU内部の装置です。(参考:教科書33P)
マイコンの中には複数のレジスターが存在し、レジスター1つ1つに別の固定のアドレスが決められています。
今回のマイコンの場合、ここのレジスターに与えられた値が0(Low)なら0V、1(Hight)なら3.3Vの電圧が出力されます。このレジスターに値1を入力すると、対応するLEDが光ります。
しかし、毎回PORTB.PODR.BIT.B0とフルネームを記載するのは面倒くさいし分かりにくいので、LED0~3と名前を付けなおしています。
次にPORTB.PODR.BIT.B0と言う構造体についてですが、これはiodefineファイルの中でstructとunionを使って定義されています。
structは、構造体を作るための定義で、複数の変数を1つに纏めるための関数です。
unionは、全体と部分を1つに纏める定義です。
今回の例だとunionの中に更にstructで更に構造体を作っている為、下記の様に2種類のパターンを作ることが出来ます。

(1)st_portbの中のPODRの中のBYTEというパターン
(2)st_portbの中のPODRの中のBITの中のB0(~B7)というパターン

(1)の場合だとB0~B7全てに対して定義することが出来ます。(今回は、charの為8ビット以内で定義します。)
(2)の場合だとB0~B7に対して1個づつ定義することが出来ます。
(参考:教科書57P)

 

st_portbはiodefineの下の方でPORTBと定義されています。こうやって、PORTB.PODR.BIT.B0でレジスターにアクセスしています。

 

なんとなくレジスターの事が分かってくると、1つの入出力ポートに対して、PDRやPODRやPIDRと小分けになっているのは何故だろうと思えてきます。
色々調べているとどうやら、1つの入出力ポートに対して、複数のレジスタが存在する様です。(参考:教科書95P)
PODRというのは、汎用ポート用の出力レジスターです。
PIDRというのは、入力データ用のレジスターです。
PDRというのは、下図のように3ステートバッファと言う回路の時、イネーブル付きバッファーの部分を制御できます。下図の例だと、1が入力されている場合は、PODRの出力信号が端子に出力されます。0の場合は、オープン(ハイインピーダンス)状態となり、入出力できない状態になります。つまり、PODRから何も出力されていない状態(=0)、PODRから出力されている場合(=1)、PDRから0が入力されている場合(無)の3種類の状態が作れます。
信号の入出力をPDRを使ってしっかりと決めないと故障の原因になるため、しっかりと設定してください。(例:PODRと端子側の両方から電圧がかかると故障の原因になります。)


マイクロマウスではじめよう ロボットプログラミング入門 95P参照≫

 

少し長くなってしまいましたので、今回はここまにします。

 

参考資料
PI:CO追加ファイルについて

 

 

 

 


Posted in Pi:Co Classic3 製作記