H8マイコン基礎
上野未恵
p.3 開発環境構築
p.11 入出力の設定の仕方
p.17 デバッグ環境構築・実行手順
p.34 タイマの設定の仕方
p.43 割り込みの設定の仕方
目次
開発環境構築
【目標】
・データシートや回路図を読んで簡単な入出力を実装できるようになる
・タイマが動作するしくみ(コンペアマッチ・オーバーフロー)を知る
・割り込み関数が呼ばれる処理の流れを理解する
【対象者】
・マイクロコントローラを初めて学習する方
・C言語の文法を一通り学んでいる方
【使用するマイコン】
・H8/36064
【参考書籍】
・書籍「はじめてのH8マイコン」
はじめに
H8マイコン(ライントレーサー)の開発環境構築
・HEW
統合開発環境(エディタ・コンパイラ・リンカ)
HEWでマイコンを動かすためのプログラムを作成したり、ビルドを行う。
・H8 Writer
H8マイコンのフラッシュROMにプログラム(.mot)を書き込むソフトウェア。
※FDTもH8 Writerと同様にROMに書き込むソフトウェアだが、今回は使用しない。
<必要な開発環境>
H8マイコン(ライントレーサー)の開発環境構築
<実行するまでのステップ>
開発環境の準備から実際に実行する前での全体の流れは、次の通りになる。
開発環境を準備
プロジェクトワークスペースの作成
コーディング
メモリマップやオプション設定
ビルド
マイコン(ROM)に書き込む
HEWを入手・起動させる
マイコンを動かすプログラムを
「1つ」のプロジェクトに作成していく
プログラムをC言語で実装する
セクションやインクルードパス等を
必要に応じて設定する
マイコンを動かすための処理を
行う
ビルドで作成されたmotファイルをH8 Writerで
H8マイコンのROMにダウンロードする
コンパイルだけだと
必要なファイルを関連
付ける「リンク」ができない
デバッグしたい場合には、モニタプログラムをROMに書き込み、デバッグしたいプログラムをRAMに配置。
※詳細はp.17以降を参照
H8マイコン(ライントレーサー)の開発環境構築~実行の流れ
①HEWを開き、「ファイル>新規ワークスペース>プロジェクト」を選択し、次の通りに設定する。
今回使用するH8マイコンは
H8/36064なので
CPUシリーズ ⇒ 300H
CPUタイプ ⇒ 36064
を選択する
プロジェクトの名前を記載
LEDを点滅させるプログラムを例に、開発環境の構築から実行までの順序を記載する。
H8マイコン(ライントレーサー)の開発環境構築~実行の流れ
②main関数内に処理を書いていく
ここに実行したい処理を書く。
C言語ではmain関数が必ず1つ
必要である。
例) LEDを点滅させるソースコード
「LED.c」ファイル
H8マイコン(ライントレーサー)の開発環境構築~実行の流れ
③メニューバーより「ビルド > ビルド」でプロジェクトをビルドを行う。
「Build Finished」および 「0 Errors」と
なっていれば、ビルドが通っている証拠。
「Warnings」に関しては、一応あっても
なくても実行することは可能である。
※ただしソースコードやWarningの内容にもよるが、一概に正しく動作するとは断言できない。
H8マイコン(ライントレーサー)の開発環境構築~実行の流れ
④H8 Writerを開き、ビルドで作成されたmodファイルを選択した後、「書き込み」を選択する。
※ライントレーサーによっては「USB HID」になったり、「シリアルポート:COM」でも5以外になることがある
ライントレーサーはPCに接続しておくこと。
「自動取得」を押すと通信できる箇所が勝手に選ばれる。
失敗したら再度コネクタを接続しなおす。
作成したプロジェクト(LED)の直下のLEDフォルダの中のDebugフォルダに
ビルドで作られたmotファイルがある
選択
入出力の設定の仕方
入出力の設定の流れ
LED、スイッチ、モータ、センサ等を使って動かしたい
LED
入出力の設定は
入出力装置から繋がっているI/Oポートに対応する
CPUの「レジスタ」のビットの設定値を変えるとできる
スイッチ
モータ
センサ
I/Oポートやレジスタ、ビットがどこに対応しているかは
「データシート」と「回路図」で確認する
P60
P74
PB0
P30
P61
I/Oポート
入出力装置
信号線(端子)
I/Oレジスタで制御
CPU
I/Oレジスタ
※I/Oレジスタの最小の構成単位は「ビット」
直接I/Oポートを操作するプログラムはないが…
I/Oポート・レジスタの対応確認(回路図)
例)1つのLEDを光らせるプログラム(sample.c)の作成
マイコンの回路図からLEDのI/Oポートを確認する
H8_36064_回路図.pdf または 書籍「はじめてのH8マイコン」p.26、27を参考
I/Oポート名
LED1 ⇒ P60
LED2 ⇒ P64
LEDは2つ付いているので、
I/Oポートが「P64」を今回は使用する
LED
I/Oポート・レジスタの対応確認(データシート)
例)1つのLEDを光らせるプログラム(sample.c)の作成
I/Oポート「P64」に対応するI/Oレジスタの確認をする
H8_36064_データシート.pdf を参考
「ポート6」の「4ビット目」に対応している
「レジスタ」と「設定値」を探す
レジスタには次の2種類があり、
これらをプログラムで書いて設定する
・ポートコントロールレジスタ(PCR) ⇒ 入力・出力を決定
・ポートデータレジスタ(PDR) ⇒ 入力値の読み出し
出力値(電圧High/Low)の設定
P64 ⇒ ポート:6 ビット:4
P67
P66
P65
P64
P63
P62
P61
P60
7
6
5
4
3
2
1
0
ビット
PCR
P67
P66
P65
P64
P63
P62
P61
P60
7
6
5
4
3
2
1
0
ビット
PDR
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
LEDを光らせる ⇒ 1 にして出力を有効化
LEDを光らせる ⇒ 0(Low) で点灯、1(High) で消灯
電圧は通常Highになっていて、
電位差(Low)が生じると光る
I/Oポート・レジスタの対応確認(データシート) 補足
データシート(H8_36064_データシート.pdf)で確認する箇所
PCRについて
PDRについて
I/Oポート・レジスタの設定の仕方(プログラム)
例)1つのLEDを光らせるプログラム(sample.c)の作成
LEDのI/Oポートに対応するI/Oレジスタとそこに入れる値が
わかったので次はC言語で実装していく。
「sample」プロジェクトを作成する(プロジェクト作成はp参照)
簡単に設定するために、「iodefine.h」をインクルードする
<sample.cの先頭行に追加>
#include “iodefine.h”
I/Oレジスタの値を設定する
<main関数中に追加>
IO.PCR6 = 0x10;
IO.PDR6.BIT.B4 = 0;
iodefine.h
構造およびマクロで設定されている箇所
16進数表記
4ビット目を1にする
16進数表記
0で電圧をLowにする
0x (青枠内の値) (緑枠内の値)
7
6
5
4
3
2
1
0
ビット
上位
下位
※あとはビルドしてH8 WriterでROMに書き込む
デバッグ環境構築~デバッグ実施
デバッグとは
【デバッグ方法】
・デバッグとは、意図通りにプログラムが動いているのかを確かめることを指す。
・デバッグする方法には主に下記の2つが挙げられる。
①ソースコードに実行を一時停止するブレークポイントを張り、1行もしくは複数行を
手動で実行するステップ実行(ステップイン、ステップオーバー)する方法
②LEDやモーター等のモジュールが動くことで実行されたことを確認する方法
【デバッグの実施】
・今回無料インストール版のHEWではデバッグの機能が制限されているため、
上記のデバッグ方法①については次のページに記載された別の方法で実施。
・下記の注意点を1点でも満たさない場合は、デバッグ方法②を実施。
・プッシュスイッチを使用しない
・ビルドしたプログラムはRAMの容量(2KB)を
超えていないこと。
※理由はp.20に記載
デバッグを行う際の注意点
注意点を満たさない場合は
LEDを光らせることで、特定の
処理が実行されたことを確認
デバッグの流れ
無料インストール版のHEWだけで実装・ビルド・デバッグが完結できれば良い・・・・が、
H8マイコンの動作は、無料版HEWではブレークポイント・ステップ実行等で確認することができない。
HEW・H8 Writer・Hterm・モニタプログラムを用いて、
H8マイコンのRAMに作成したプログラムを書き込んでデバッグしていく。
ROM
RAM
プログラムを作成しても正しく動いている保証もなければ、どこにバグが潜んでいるのかも一見しても不明。
意図通りのプログラムに修正するための「デバッグ」が必要。
モニタプログラム
作成したプログラム
①HEWでプログラム作成
②H8 Writer でROMに書込み
③Hterm(デバッグ環境)が
動作できるようになる
④Htermで作成したプログラムを
RAMに書込むとデバッグできる
デバッグについての補足
・プッシュスイッチを使用しない
・ビルドしたプログラムはRAMの容量(2KB)を
超えていないこと
デバッグの注意点
プッシュスイッチはモニタ(Hterm)が「強制実行停止」処理を
行う仕様になっているため、デバッグできない。
また、RAMに入れられるサイズは2MBなので、
2MBを超えるプログラムをデバッグすることはできない。
理由
デバッグ環境構築の準備
・Hterm
モニタプログラム専用の通信ソフトウェア(ROMにモニタプログラムが書き込まれて初めて動作する)。
RAMに書き込んでデバッグしたいプログラムをステップ実行したり、レジスタの内容を表示できる。
・モニタプログラム
⇒Htermを動かすためのプログラム(MONITOR.mot) 。
<デバッグ環境構築に必要なもの>
デバッグ環境構築の手順
試したデバッグ環境構築
①Htermを入手する
②モニタプログラム「monitor.hew」をHEWで開く
デバッグ環境構築の手順
③2ファイルを修正する
c
monitor.c
「#incude “3554.h”」を「#include “36064s.h”」に変更「WDT.TCSRWD.BYTE=0x92;」をmonitor();の前に2つ追記※
monitor.sub
・8行目の数値を「36064」に変更
⇒ローバー用のマイコンに設定
・10行目の数値を「13」に変更
⇒ビットレートを19200[bit/s]に設定
※H8/36064にはウォッチドッグタイマ(WDT)というマイコンの暴走を検知する機能が備わっている。
モニタプログラムにとってWDTはモニタ動作を邪魔になるので停止させる
デバッグ環境構築の手順
④モニタプログラムをビルドする
<補足>
モニタプログラムとは、H8マイコンをシリアル
ポート経由でPC(Hterm)からH8マイコンの状態を
監視したり制御するプログラムのこと。
ROMにモニタプログラムを書き込んでおくことで
デバッグを行える状態にする。
デバッグしたいプログラムはRAMを用いて
確認していく。
プログラムは書籍「はじめてのH8マイコン」p.35~p.44の通りに作成・ビルド
デバッグ環境構築の手順
⑤次に作りたいプログラムを実装する
例) LEDをチカチカ光らせるプログラムを下記の通りに作成する
sample.c
v
v
v
v
resetprg.c
簡易に扱うためのIOレジスタの定義
仮想ベクタを設定するため
(vect=0)をコメントアウト
デバッグを止めないためにも
ウォッチドックタイマを停止させる
仮想ベクタを設定。
#pragmaでセクションV0(CV0としての後に設定)に指定する。
一番最初に読まれると、PowerON_Reset関数に飛ぶ。
デバッグ環境構築の手順
<HEWが自動生成するファイルについて>
実際にいじるのは下記のファイル。
・sample.c(プロジェクト名.c)
⇒main関数
・resetprg.c
⇒仮想ベクタの設定、ウォッチドッグタイマの追記等
・intprg.c(必要なときのみ)
⇒割り込みハンドラの設定
※割り込みを使用する場合、別のファイルを用いても差し支えはない
上記以外のファイルは参考にする程度。
必要ならばモジュール分割(別のファイルに関数を
記載)してもOK。
デバッグ環境構築の手順
⑥RAMへ書き込むための設定を行っていく
ビルドのする前にRAMで動かすためのアドレス設定を行う。
メニューバー「ビルド>H8S,H8/300 Standard toolchain」を選択
タブ「最適化リンカ」のカテゴリ「セクション」を選択
セクションとは、メモリ(ROMとRAM)に
おけるプログラム、変数、定数等の配置を決めている割り当てのこと
実装完了
デバッグ環境構築の手順
<セクション設定で行うことについて>
各アドレス(領域)には、ROMもしくはRAMにおいて変数・定数・
プログラム等を書き込む場所が割り当てられている。
「セクション」という単位で各アドレスに配置していくことで、
任意でROMまたはRAMにデータを書き込むことができる
今回はRAMに作成したプログラムを配置させたいので
右図のH8マイコン(H8/36064)に基づくと
アドレス H’F840 ~ H’FFFF の2KBの範囲内に
セクションを配置させれば良い。
※実際に割り当てるのはH’F840 ~ H’B80がほとんど
割り込みベクタ |
|
モニタ・プログラムの使用領域 |
(32Kバイト) |
|
|
未使用 |
|
内部I/Oレジスタ |
モニタ・プログラム使用領域 |
仮想ベクタ領域(CV0) |
|
ユーザ・プログラム領域 |
|
初期化データ領域(B) |
および |
初期化データ領域(R) |
動的領域(S) |
内部I/Oレジスタ |
ROM
RAM
H’0000
H’0042
H’7FFF
H’F700
H’F780
H’F840
H’F890
H’FB80
H’FE80
H’FF80
H’FFFF
アドレス
ここにプログラム等を配置。
セクションにはPRsetPRG、P、C、C$DSEC、C$BSEC、D等の名前がふられている。
H8/36064のメモリの配置
(ROMにモニタプログラムを書込み済み)
デバッグ環境構築の手順
具体的に設定していくと。。。
各行のSection名を
ダブルクリックして、
AdressとSectionを
修正する
「編集」で
配置も確認可
ROMに配置に
設定されている。
「PIntPRG」セクションは
割り込み関数等を
使用するときに設定する
RAMに配置に設定する。
「CV0」セクションは
割り込み関数等を
使用するときに設定する。
「PResetPRG」セクションは
電源が入って初めに実行される関数を格納。
デバッグ環境構築の手順
⑦作成したいプログラムのビルド後、H8 Writerを開いてROMにモニタプログラム(.mot)を書き込む
c
モニタプログラムの
motファイルを選択する
c
「書き込み」で実行
ROMへモニタプログラムが書き込こまれる
H8 Writerを開く
※通信方法はH8マイコンによって変わるので
「自動取得」でつながらなければ「USB HID」を選択
デバッグ環境構築の手順
⑧Htermを開き、デバッグしたいプログラムを準備する
(1)メニューバーの[通信]>[切断]を選択し
下記の画面の状態にする
(2)メニューバーの[ファイル]>[プロパティ]を選択し、
通信ポート(繋げているポート)とビットレート(19200)を
確認して[OK]を押す
デバッグ環境構築の手順
⑧Htermを開き、デバッグしたいプログラムを準備する
(3)「コマンド>Load」から既にビルド済のプログラム(.abs)を選択し開く
(4)ソースコードが展開される
※通信が途切れたりするときは、一度コネクタを
差し直すと成功するときがある。
デバッグ環境構築の手順
⑨Consoleでデバッグする
(1)ブレークポイントを張る
処理を止めたい箇所をダブルクリック
(2)Consoleで「G」と入力もしくは「F5」キーを押して
ブレークポイントまで処理を進める
「F8」キーは1行ずつ進んでいく。
関数の中に入っていくステップイン実行なので、
意図通り動いているかを1行ずつ確認/修正していく。
タイマの設定の仕方
タイマとは何か
タイマは名前の通り「時間をつくる」役割がある。
「時間をつくる」のは簡単なことではなく、手順が存在する。
例えば人ならば秒針を見て1分間を「1、2、3、4、・・・60」と秒数を数えるように、
タイマもクロック(周波数)を参考に数をカウントしていく。
具体的にどのようにカウントしていくのか?
大きな括りで言うと、関与しているのは次の4つ。
・システムクロック(CPUクロック)※
・内部クロック(タイマクロック)
・プリスケーラ
・カウンタ
※Φ(ファイ)と表記
クロック(周波数)が決まると、
「一定時間」の基準ができるため、
カウンタは数をカウントできる
周波数を決定
数をカウント
「1秒」を知るだけでも
そもそも時間間隔もこの時点では
決定されていなければ、どのように
カウントすればよいかさえ未決定
システムクロックとは?
水晶発振器からマイコンへ供給している「クロック周波数(Hz)」のこと。
水晶振動子
ビュートローバーでは12MHz(12 x 10^6 Hz)のクロック周波数が水晶振動子(OSC)から供給
プリスケーラ・内部クロック・タイマカウンタとは?
プリスケーラとは、入力されたシステムクロックの周波数を調整(遅く)するための回路のこと。
内部クロックとは、プリスケータで調整された周波数のことで、6種類存在する。
タイマカウンタとは、内部クロックをもとにカウントする機能のこと。
水晶振動子
プリスケーラ
タイマカウンタ
内部クロック
6種類の内部クロック:φ/128、φ/64、φ/32、φ/16、φ/8、φ/4
※φはシステムクロックの周波数のこと
内部クロック(周波数)
φ/128 φ/4
低 高
タイマの種類
H8/36064マイコンには5種類のタイマモジュールが存在する
※ただしウォッチドッグタイマは下記に記載なし
圧電ブザーの駆動に使用
タイマのブロック図(全体像)
矢印の方向へデータが送られたり出力処理が行われたりする
入出力端子
レジスタ
例)タイマV
タイマカウンタのしくみ
タイマカウンタは、内部クロックをもとにTCNTVレジスタでカウントアップを始める。
※TCNTVはレジスタの0x00から
カウントアップを始める
コンペアマッチAおよびBによって、タイマの出力値となるTMOVの値が0(Low)もしくは1(High)に決まる。
そしてこの出力値によって1周期がわかるので、
内部クロックの周波数f分の周期が繰り返されることで「1秒」を表現することができる
TCNTVの値がTCORAの設定値と一致したとき(コンペアマッチA)、TMOVの値を”1”に出力
TCNTVの値がTCORBの設定値と一致したとき(コンペアマッチB)、TMOVの値を”0”に出力
周期T = (1 / f)
カウントアップし続けるとオーバーフローしてしまうので、
コンペアマッチAのときにカウンタを0x00にクリアする
例)タイマVのコンペアマッチ
タイマカウンタのしくみ(補足)
システムクロック・内部クロック・TCNTVクロック入力の動き
システムクロック
例)タイマVのコンペアマッチ
タイマの設定の仕方
例)タイマVのコンペアマッチAを用いて、低音「ド」の音程でブザーを鳴らす
ブザーの音程を「ド」に設定する ⇒ 音程の設定はTCORA、 低音「ド」は179を値として設定
TV.TCORA = 179;
コンペアマッチAでTCNTVレジスタをクリアする
TV.TCRV0.BIT.CCLR = 1;
コンペアマッチAでトグル出力(音の出力)
TV.TCSRV.BIT.OS = 3;
TCNTVクロックとカウント条件(立ち下りエッジ:High→Lowのときにカウントする)の設定
TV.TCRV1.BIT.ICKS = 1;
内部クロックφ/128で動作開始
TV.TCRV0.BIT.CKS = 3;
※圧電ブザーは圧電素子に正(High)と負(Low)の電圧を
それぞれ繰り返しかけることで音が鳴る。
タイマで一定のタイミングで電圧を変化させることで鳴らす。
割り込みの設定の仕方
割り込み関数について
割り込み関数とは、ある条件になったときに優先的に処理を行う関数のこと。
処理が終わると、元々行っていた処理の割り込んだ位置に戻り、通常の処理に戻る.
Main関数
割り込み関数
割り込みの書き方
割り込みには「whileループで常に監視している」ケースと「割り込みのフラグが立ったきにとき割り込み関数に飛ぶ」ケースの2種類存在する。
「Whileループで常に監視している」ケース
例)プッシュスイッチが押されたらLEDが光る
Whie(1){
if(IO.PDR5.BIT.B5 == 0){
IO.PDR6.BIT.B0 = 0x00;
}else{
IO.PDR6.BIT.B0 = 0x01;
}
}
「割り込みフラグが」ケース
例)プッシュスイッチが押されたら処理を始める
割り込みフラグが立つ
割り込み関数へ