マイコンプログラミング その4
前回ポート出力によるLED点灯を行いました。今回は続きでタイマーを使ってLEDを点滅させたいと思います。(いわゆるLチカですね)
点滅のためのタイマーですが、CMT(コンペアマッチタイマー)を使用します。このタイマーは一定周期でカウンタがカウントアップするもので、例えば0.1秒周期でカウントアップする場合は、カウンタが600になった時が60秒(1分)経過した事になります。
開発環境はルネサス純正のHEWを使用しています。
CMTの準備
まずはプロテクトを解除して、レジスタに設定の書き込みができる状態にします。前回同様にプロテクトレジスタに値を設定します。RX210マイコンにはCMT0とCMT1と2つタイマーがあり、それぞれのタイマーにチャンネル0と1が用意されています。今回はCMT0のチャンネル0を使用したいと思います。
CMTモジュールはデフォルトではストップ状態なので、消費電力低減機能の設定でCMTモジュールを使える状態にします。このため、今回はPRC0ビットだけではなくPRC1ビットも書き込み許可設定にします。レジスタには「0xA503」を書き込みます。
CMTのモジュールストップを解除するために、以下のレジスタを設定します。
MSTPA15ビットを0にする事で、今回使用するCMT0モジュールのストップ状態を解除でき、CMT0モジュールを動かすことが可能になります。
CMTの設定
CMTは周辺モジュールクロックBのクロックで動作します。クロックソースはシステムクロック同様に、メインクロックを64分周したものを使用します。
64分周にする設定は、以下のレジスタで行います。
上記レジスタのPCKBビットの設定で分周比を指定します。今回は分周比を64としたいので設定を「6」とします。
最終的なタイマーカウントのクロックは、周辺モジュールクロックBをさらに分周したものを使用します。このためさらに以下のレジスタで分周設定を行います。
周辺モジュールクロックBへ指定した分周比でクロック入力します。
CKSビットの設定で分周比を指定します。今回は分周比を512としたいので設定を「3」とします。コンペアマッチによる割り込み許可設定も行いたいので、CMIEビットも1に設定しておきます。
メインクロック20MHzを64分周して、さらにこのクロックを512分周したものがCMT0に入力するクロックとなるので
20MHz / 64 = 312.5KHz
312.5KHz / 512 = 610Hz
より、610Hzとなることが分かります。
今回1秒間隔でLEDを点滅させようと思います。
610Hzの周期は
1/610Hz = 0.0016秒
なので、625回カウントアップすれば1秒となります。
上記の計算結果625を、カウンタとの比較値としてCMCORレジスタに設定します。
最後にCMT0のカウントアップを開始をするために、以下のレジスタのSTR0ビットを1にします。
割り込み設定
カウンタとの比較値設定ができました。タイマー動作が開始すると0.0016秒毎にカウントアップして、比較値とカウンタ値を比較します。
比較値625とカウンタ値が同じになったら、コンペアマッチ割り込みという割り込みを発生させて、1秒経過した事が分かるようにします。
割り込みを発生させるための設定を行います。割り込みコントローラで割り込みを制御しています。
IER(割り込み要求許可レジスタ)とIPR(割り込み要因プライオリティレジスタ)の設定を行います。
コンペアマッチ割り込みの許可をするため1を設定します。HEWではIERレジスタアクセス用のマクロが用意されているのでこれを使用します。
IEN(CMT0, CMI0) = 1; /* CMT0のチャンネル0 */
IERレジスタ同様に、IPRレジスタもマクロが用意されているのでこれを使用します。優先順位は最高の0x0Fを設定します。
IPR(CMT0, CMI0) = 0x0F; /* CMT0のチャンネル0 */
最後に、コンペアマッチ割り込み発生時に呼ばれる関数を作成します。
HEWで用意されていた、CMT0割り込みハンドラ「Excep_CMTU0_CMT0」に割り込み発生時に呼びたい自作した関数「interrupt_cmt」を設定しています。
/***********************************************************************/
/* */
/* FILE :intprg.c */
/* DATE :Tue, Oct 06, 2020 */
/* DESCRIPTION :Interrupt Program */
/* CPU TYPE :RX210 */
/* */
/* This file is generated by Renesas Project Generator (Ver.4.53). */
/* NOTE:THIS IS A TYPICAL EXAMPLE. */
/* */
/***********************************************************************/
#include "iodefine.h"
#include <machine.h>
#include "vect.h"
#pragma section IntPRG
extern void interrupt_cmt(void);
:
:
// CMTU0_CMT0
void Excep_CMTU0_CMT0(void){ interrupt_cmt(); }
:
:
「interrupt_cmt」関数が1秒ごとに呼ばれることになります。処理内容は以下のように、LEDを接続したポートを関数が呼ばれる毎にON・OFFしている単純なものです。
void interrupt_cmt(void)
{
if(PORT3.PODR.BIT.B4 == 1)
{
PORT3.PODR.BIT.B4 = 0;
}
else
{
PORT3.PODR.BIT.B4 = 1;
}
}
最後に
ソースコード全体を載せます。
/***********************************************************************/
/* */
/* FILE :Test.c */
/* DATE :Tue, Oct 06, 2020 */
/* DESCRIPTION :Main Program */
/* CPU TYPE :RX210 */
/* */
/* This file is generated by Renesas Project Generator (Ver.4.53). */
/* NOTE:THIS IS A TYPICAL EXAMPLE. */
/* */
/***********************************************************************/
//#include "typedefine.h"
#ifdef __cplusplus
//#include <ios> // Remove the comment when you use ios
//_SINT ios_base::Init::init_cnt; // Remove the comment when you use ios
#endif
#include "iodefine.h"
#include <machine.h>
void main(void);
void HardwareSetup(void);
#ifdef __cplusplus
extern "C" {
void abort(void);
}
#endif
/****************************************/
/* main関数 */
/****************************************/
void main(void)
{
PORT3.PODR.BIT.B4 = 0;
// プログラムが暴走しないように無限ループ
while(1)
;
}
/****************************************/
/* ハードウェアの初期化 */
/****************************************/
void HardwareSetup(void)
{
int i;
// クロックソース選択の保護解除
SYSTEM.PRCR.WORD = 0xA503;
// システムクロック(ICK)を64分周に設定
SYSTEM.SCKCR.BIT.ICK = 6;
// 周辺モジュールクロックBを64分周に設定
SYSTEM.SCKCR.BIT.PCKB = 6;
// クロックソースをメインクロックに設定
SYSTEM.SCKCR3.BIT.CKSEL = 2;
// 設定完了待ち
while(SYSTEM.SCKCR3.BIT.CKSEL != 2)
;
// メインクロックの発振動作
SYSTEM.MOSCCR.BIT.MOSTP = 0;
// メインクロック発振安定時間
SYSTEM.MOSCWTCR.BIT.MSTS = 0x0F;
// コンペマッチタイマー0のモジュールストップ状態解除
SYSTEM.MSTPCRA.BIT.MSTPA15 = 0;
// クロックソース選択の保護
SYSTEM.PRCR.WORD = 0xA500;
// P34を汎用入出力に設定
PORT3.PMR.BIT.B4 = 0x00;
// P34を出力に設定
PORT3.PDR.BIT.B4 = 1;
// コンペマッチタイマー0の割り込み優先順位を最高に設定
IPR(CMT0, CMI0) = 0x0F;
// コンペマッチタイマー0の割り込み要求許可設定
IEN(CMT0, CMI0) = 0x1;
// コンペマッチタイマー0の周期を周辺モジュールクロックを512分周
CMT0.CMCR.BIT.CKS = 3;
// コンペマッチタイマー0の割り込み許可
CMT0.CMCR.BIT.CMIE = 1;
// コンペアマッチの周期を設定
CMT0.CMCOR = 0x271;
// カウンタクリア
CMT0.CMCNT = 0;
// コンペマッチタイマー0をカウント開始
CMT.CMSTR0.BIT.STR0 = 1;
}
/****************************************/
/* CMT0の割り込み */
/****************************************/
void interrupt_cmt(void)
{
if(PORT3.PODR.BIT.B4 == 1)
{
PORT3.PODR.BIT.B4 = 0;
}
else
{
PORT3.PODR.BIT.B4 = 1;
}
}
#ifdef __cplusplus
void abort(void)
{
}
#endif
/***********************************************************************/
/* */
/* FILE :intprg.c */
/* DATE :Tue, Oct 06, 2020 */
/* DESCRIPTION :Interrupt Program */
/* CPU TYPE :RX210 */
/* */
/* This file is generated by Renesas Project Generator (Ver.4.53). */
/* NOTE:THIS IS A TYPICAL EXAMPLE. */
/* */
/***********************************************************************/
#include "iodefine.h"
#include <machine.h>
#include "vect.h"
#pragma section IntPRG
extern void interrupt_cmt(void);
:
:
// CMTU0_CMT0
void Excep_CMTU0_CMT0(void){ interrupt_cmt(); }
:
:
この記事が気に入ったらサポートをしてみませんか?