RX220で1ms周期のタイマを作成してLチカ

# RX220で1ms周期のタイマを作成してLチカ
手始めに汎用I/Oとタイマの使い方の使い方を学ぶためにLチカする．
汎用I/O,タイマの順に書いていく．

## 環境
* マイコン：R5F52206BDFM([AKI-RX220ボード](http://akizukidenshi.com/catalog/g/gK-08769/))
* 開発環境：e2studio
* 書き込みソフト：RenesasFlashProgrammer(RFP)

# I/Oの設定
基本的にハードウェアマニュアルを見てガンバル．
設定の必要が有りそうな項目を以下にまとめる．(文章形式で読みにくい)

* PDR(ポート方向レジスタ)
* PODR(ポート出力データレジスタ)
* PIDR(ポート入力データレジスタ)
* ODRy(オープンドレイン制御レジスタy)
* PCR(プルアップ制御レジスタ)
* DSCR(駆動能力制御レジスタ)
* PMR(ポートモードレジスタ)

今回はLEDを光らせるだけなので何でもいいのでてきとうにP03でも使ってみる．
設定する必要が有るのは，「PDR,PODR」の2項目(だと思います)．

成果物は長かったので一番下に書いてあります．
以下必要なさそうな解説．

## PDR(ポート方向レジスタ)設定
このレジスタは0が入力，1が出力で初期値が0であると19.3.1 ポート方向レジスタ（PDR）に書いてある．
なので

``` C
PORT0.PDR.BIT.B3 = 1;
```
これでいい

## PODR(ポート出力データレジスタ)設定
このレジスタは0がLow(多分)，1がHigh(多分)で初期値が0であると19.3.2 ポート出力データレジスタ（PODR）に書いてある．
なので

``` C
PORT0.PODR.BIT.B3 = 1;
```
これでいい

# メインクロックの設定
リセット時はメインクロックの設定をしないと低速オンチップオシレータが優先されるらしい．このことを知らずに動かず(と思いつつ実は遅いだけ)非常に困った．
[ＲＸ２２０　マイコンのプログラムを作って、動かしてみよう](http://akizukidenshi.com/download/ds/akizuki/RX220_Programing.pdf)の64ページにすべて書いてありました．買ってないけどありがとうございます．
よって以下のコードを追加．
~~一応保護を解除したら保護しなおさないとダメ．面倒なので外したままだけどほんとはだめ．~~
**保護しなおさないと(他のタイマも使うときに何か問題が起こるようで)ダメでした．なんてこったい!**
**サボらず，忘れずに保護しましょう**
なおreset_program.cでHardwareSetupのコメントアウトを外すのとプロトタイプ宣言をしています．

``` C
void HardwareSetup()
{
	SYSTEM.PRCR.WORD = 0x0A50b;             //クロックソース選択の保護解除
	SYSTEM.SCKCR.LONG = 0x00001111;			//分周の設定
	SYSTEM.SCKCR3.WORD = 0x0200;			//メインクロックを使用する
	SYSTEM.MOSCCR.BYTE = 0;					//メインクロック発振器を動作させる
	SYSTEM.SOSCCR.BYTE = 0;					//サブクロック発振器を動作させる
	SYSTEM.PRCR.WORD = 0x0A500;             //クロックソース選択の保護
}
```

# タイマの設定
今回は普通のタイマ機能しか使わないので，コンペアマッチタイマで書いてみる．
ハードウェアマニュアルの上に書いてある順に調べてますが，記述する順番は変えてます．

最終的なコードはこちら．

``` C
void init_cmt0()
{
	SYSTEM.PRCR.WORD = 0x0A50b;             //クロックソース選択の保護解除
	MSTP(CMT0) = 0;							//CMT0を有効化
	SYSTEM.PRCR.WORD = 0x0A500;             //クロックソース選択の保護
	CMT0.CMCR.BIT.CKS = 0;					//1/2に分周されたものを1/8に分周→20Mhz->10Mhz->1.25MHz
	CMT0.CMCR.BIT.CMIE = 1;					//コンペアマッチ割り込みを許可する
	CMT0.CMCNT = 0;							//カウンタのリセット
	CMT0.CMCOR = 1250-1;					//1msで終了する
	IPR(CMT0,CMI0) = 4;						//CMI0の割り込み優先度を設定
	IEN(CMT0,CMI0) = 1;						//割り込みを許可する
}

void ms_wait(unsigned int ms){
	CMT.CMSTR0.BIT.STR0=1;					//コンペアマッチのカウントを開始する
  CMT0.CMCNT = 0;							//カウンタのリセット
	for(unsigned int i=0; i<ms; i++){
		while( IR(CMT0,CMI0) == 0 );
		CMT0.CMCNT = 0;							//カウンタのリセット
		IR(CMT0,CMI0) = 0;					//コンペアマッチフラグをクリア
	}
	CMT.CMSTR0.BIT.STR0=0;					//コンペアマッチのカウントを終える
}
```

## CMSTR0(コンペアマッチタイマスタートレジスタ設定)
CMSTR0.STR0は0だとカウント動作停止，1だとカウント動作開始とある．今回は１つしか使わないのでSTR0だけ設定．これはカウントをする直前/直後に弄る．

``` C
CMT.CMSTR0.BIT.STR0=1;					//コンペアマッチのカウントを開始する
```

## CMCR(コンペアマッチタイマコントロールレジスタ設定)
クロックの設定と割り込みの許可を行う．クロックは長い時間を測る気はないので精度でも出すべく分周を抑える(意味はない)．CMIEはコンペアマッチを使うなら許可しないとダメ．

``` C
CMT0.CMCR.BIT.CKS = 0;					//1/2に分周されたものを1/8に分周→20Mhz->10Mhz->1.25MHz
CMT0.CMCR.BIT.CMIE = 1;					//コンペアマッチ割り込みを許可する
```

## CMCNT,CMCOR(コンペアマッチカウンタ/コンスタントレジスタ設定)
コンペアマッチカウンタは0にしておく．コンスタントレジスタは1msで終えるために1250-1とする(←1.25Mhzでカウントしているため)．

``` C
CMT0.CMCNT = 0;							//カウンタのリセット
CMT0.CMCOR = 1250-1;					//1msで終了する
```

## コンペアマッチ許可
記述方法を調べるすべを知らないので，困った．いろいろ調べた結果これだけ書いておけばいいらしい．MSTPはCMT0を有効化する．IPRは優先度，IENは割り込みの許可．コメントそのままですね．

``` C
MSTP(CMT0) = 0;							//CMT0を有効化
IPR(CMT0,CMI0) = 4;						//CMI0の割り込み優先度を設定
IEN(CMT0,CMI0) = 1;						//割り込みを許可する
```

## 1ms待ち関数作成
whileの条件がみそ．．割り込みが起こるとCMI0の値が1に変わり，変わっているかを調べるためにICUにアクセスするマクロがIRであるらしい．ここでかなりはまった．
ついでにコンペアマッチフラグをクリアし忘れるとダメ．

コードをもっかい載せておく．

``` C
void ms_wait(unsigned int ms){
	CMT.CMSTR0.BIT.STR0=1;					//コンペアマッチのカウントを開始する
  CMT0.CMCNT = 0;							//カウンタのリセット
	for(int i=0; i<ms; i++){
		while( IR(CMT0,CMI0) == 0 );
		CMT0.CMCNT = 0;						//カウンタのリセット
		IR(CMT0,CMI0) = 0;					//コンペアマッチフラグをクリア
	}
	CMT.CMSTR0.BIT.STR0=0;					//コンペアマッチのカウントを終える
}
```

# Lチカ
長い道のりだったが，点滅した．以下にコードをまとめる(無駄に長い)．これ以外にreset_program.cのHardwareSetupのコメントアウトも解除してます．

``` C
void init_cmt0()
{
	MSTP(CMT0) = 0;							//CMT0を有効化
	CMT0.CMCR.BIT.CKS = 0;					//1/2に分周されたものを1/8に分周→20Mhz->10Mhz->1.25MHz
	CMT0.CMCR.BIT.CMIE = 0;					//コンペアマッチ割り込みを許可する
	CMT0.CMCNT = 0;							//カウンタのリセット
	CMT0.CMCOR = 1250-1;					//1msで終了する
	IPR(CMT0,CMI0) = 4;						//CMI0の割り込み優先度を設定
	IEN(CMT0,CMI0) = 1;						//割り込みを許可する
}

void ms_wait(unsigned int ms){
	CMT.CMSTR0.BIT.STR0=1;					//コンペアマッチのカウントを開始する
	CMT0.CMCNT = 0;							//カウンタのリセット
	for(int i=0; i<ms; i++){
		while( IR(CMT0,CMI0) == 0 );
		CMT0.CMCNT = 0;						//カウンタのリセット
		IR(CMT0,CMI0) = 0;					//コンペアマッチフラグをクリア
	}
	CMT.CMSTR0.BIT.STR0=0;					//コンペアマッチのカウントを終える
}

void HardwareSetup()
{
	SYSTEM.PRCR.WORD = 0x0A50b;             //クロックソース選択の保護解除
	SYSTEM.SCKCR.LONG = 0x00001111;			//分周の設定
	SYSTEM.SCKCR3.WORD = 0x0200;			//メインクロックを使用する
	SYSTEM.MOSCCR.BYTE = 0;					//メインクロック発振器を動作させる
	SYSTEM.SOSCCR.BYTE = 0;					//サブクロック発振器を動作させる
}
void main(void)
{
	PORT0.PDR.BIT.B3 = 1;

	init_cmt0();
	while(1){
		PORT0.PODR.BIT.B3 = 1;
		ms_wait(1000);
		PORT0.PODR.BIT.B3 = 0;
		ms_wait(1000);
	}
}
```

# 参考LINK
[時間を計る\[コンペアマッチタイマ\]\(RX62Nの記事です\)](http://www.haljion.net/index.php/2013-04-12-08-15-44/2014-10-06-04-17-44/rx62n/335-2014-11-12-21-55-38)
[ユーザーズマニュアル　ハードウェア編)](https://www.renesas.com/ja-jp/products/microcontrollers-microprocessors/rx/rx200/rx220.html)