ADコンバータ/INT
ADコンバータが6端子あります。AN0〜AN4とAN7です。どのように使えるか試してみます。
INT(割り込み)は多くの機能がありますが、調べていこうと思います。
1 ADconv1 コンバータ利用の第1歩
2 INT3 ポート信号による割り込み
3 キー入力割り込み これもポート信号による割り込み
1 ADconv1 コンバータ利用の第1歩
2015.06.18 pin20 p1_0にVR中点の電圧を入力して、それをAD変換し、PWMでpin10 p3_4に接続したLED(0で点灯)の明るさに変える回路です。
ハードウエアは、
p1_0にVRの中点(VRはVccとGNDに接続)
p3_4に-LED+1k-Vcc
と接続しています。
電圧が高くなるとデジタル変換値が大きくなり、パルスの幅が大きくなって、LEDは明るくなります。
ソフトウエアは以下のとおりです。
/***********************************************************************/
/* */
/* FILE :ADconvert01.c */
/* DATE :Wed, Jun 17, 2015 */
/* DESCRIPTION :main program file. */
/* CPU GROUP :M12A */
/* */
/* AD変換のテスト 変換値に合わせてLEDをPWM変調する */
/* AD AN0 and PWM p3_4 */
/* m12Aは10bitのAD変換を行う */
/* http://onechiplab.blogspot.jp/2013/02/r8c-m12a.html */
/* http://www.mcr.gr.jp/tech/r8cm12a/main005.html */
/* */
/* pin 20 p1_0 → VR中点(電圧値) */
/* pin 10 p3_4 → LED- PWM_output */
/* */
/* */
/* */
/***********************************************************************/
#include "sfr_r8m12a.h"
void main(void);
void main(void){
unsigned int i,n;
//Clock=20Mhz
prc0=1; //Protect off
hocoe=1;
{ char i; for(i=0;i<20;i++){} }
hscksel=1;
scksel=1;
prc0=0; //Protect on
pd3_4=1; //p3_4を出力に設定
//AD init
mstad=0; // AD on
admod=0B00000011; // 単発変換
adinsel=0B00000000; //AN0
// 10000001:AN7 10000000:AN4
// 01000001:AN3 01000000:AN2
// 00000001:AN1 00000000:AN0
// dat.reg. ad0=AN0 AN2 AN4 ad1=AN1 AN3 AN7
while(1){
adcon0=0b00000001; //Start AD (1=start 0→AD finish)
while(adcon0 & 1){} //wait AD finish ( adcon0=0 finish )
n=ad0;
n=n>>2; // 10bits→8bits
p3_4=1; //LED on
for(i=0; i<n; i++){};
p3_4=0; //LED off
for(i=n; i<255; i++){};
}//while(1)
}//********* end of main ***********************************
変換に際しては、
・変換を有効にすること: mstad=0; // AD on
・ポートを指定すること: adinsel=0B00000000; //AN0
・変換を開始すること: adcon0=0b00000001; //Start AD
・変換終了は adcon0=0 でわかる。
・変換値のレジスタはANポートによって ad0 または ad1になること
に注意が必要です。
VR中点の位置によってLEDの明るさが変わるのがわかります。しかし、面白い動作ではありません。
しかし、AD変換の書き方がわかりました。
2 INT3
RTCの時刻表示をするとき、適当にdelayで表示をすると正確な1秒(あるいは1分)ごとに更新されず同じ時刻が重複したり、時刻が飛んだりします。 RTCからは1秒の矩形波SQWが出ていますからこの信号の立ち上がりで割り込みをかけて処理すると正しく1秒に1回時刻が更新されます。
参考にしたプログラムの関係で ポートp3_3入力のINT3をi2c_uart.hのテストプログラムに使いました。その概要をここに書きます。
unsigned char flag_int3; //グローバル変数
void main(void){ //mainルーチンの中で
//Set INT port
pd3_3=0; //input
/* INT3割り込み設定 */
p33sel1 = 1; /* P3_3をINT3端子にする */
p33sel0 = 0;
int3en = 1; /* INT3入力許可ビット:許可 0=不許可 */
int3f1 = 0; /* INT3入力フィルタ選択ビット */
int3f0 = 1; /* 11=f32でサンプリング 01=f1サンプリング(フィルタあり */
int3sb = 0; /* INT3入力エッジ選択ビット */
int3sa = 1; /* 00=立ち下がりエッジで割込発生 01=立ち上がり 11=両方 */
ilvld1 = 1; /* 割り込み優先レベル設定ビット */
ilvld0 = 0; /* INT3はD1とD0に設定 10=レベル2 00=int禁止*/
// 割り込みがあったときの処理
if( flag_int3==1){//RTCから1秒の立ち上がりがあったとき
flag_int3=0;
-----処理---
}//if( flag_int3==1
}//--- end of main-------------------------------------------------------------
/* ---- INT3 割り込み処理 -------------------------------------------------- */
#pragma interrupt intINT3(vect=26)
void intINT3( void ){
flag_int3 = 1; //ここに割り込み時の処理を書く。
}
INT3はp3_3ポートだけですが、INT0〜INT2は複数のポートから選択できるので複雑になります。
ポートの選択です。
INT0
// P1_4端子のとき
p14sel2 = 0;
p14sel1 = 1;
p14sel0 = 1;
// P4_5端子のとき
p45sel1 = 0;
p45sel0 = 1;
INT1
// P1_5端子のとき
p15sel2 = 0;
p15sel1 = 1;
p15sel0 = 1;
// P1_7端子のとき
p17sel1 = 0;
p17sel0 = 1;
// P4_6端子のとき
p46sel2 = 0;
p46sel1 = 1;
p46sel0 = 1;
INT2
// P3_4端子のとき
p34sel1 = 1;
p34sel0 = 0;
// P4_7端子のとき
p47sel1 = 0;
p47sel0 = 1;
各INTのレジスタです。
INT3 INT2 INT1 INT0
int3en int2en int1en int0en /* 入力許可ビット:1=許可 0=不許可 */
int3f1 int2f1 int1f1 int0f1 /* INT3入力フィルタ選択ビット 00=フィルタなし */
int3f0 int2f0 int1f0 int0f0 /* 11=f32でサンプリング 01=f1サンプリング(フィルタあり */
int3sb int2sb int1sb int0sb /* 入力エッジ選択ビット */
int3sa int2sa int1sa int0sa /* 00=立ち下がりエッジで割込発生 01=立ち上がり 11=両方 */
ilvld1 ilvla5 ilvlc5 ilvle5 /* 割り込み優先レベル設定ビット */
ilvld0 ilvla4 ilvlc4 ilvle4 /* INT3はD1とD0に設定 10=レベル2 00=int禁止*/
割り込みベクタ
INT0 29
INT1 25
INT2 21
INT3 26
以上が頭のなかで整理できればポート入力のINTは使えるのかも。
3 キー入力割り込み これもポート信号による割り込み
2015.07.03 「キー入力割り込み」という割り込みがあります。ルネサスをはじめWEBを丹念に調べましたがR8C/M12Aの「キー入力割り込み」に関してはついに一つの事例も探し当てることができませんでした。キー入力割り込みが4つあります。関係レジスタはこれこれです。と説明がありますが、プログラムはありません。
試行錯誤のすえ、割り込みフラグが立つところまでは確認できました。しかし、vect=13 の割り込みルーチンに入ることはできませんでした。割り込みフラグが立つところまではたどり着きましたので、フラグをスキャンすればポートの立ち上がり、または立ち下がりの有無が確認できて関係の処理をすることができます。
例として、RTCの時刻を秒単位でTeraTermに送るとき正確に1秒ごとの時刻を送らなければ秒表示が跳んだり抜けたりします。それを避けるためにRTCから出る1Hzの立ち上がりで表示するために使いました。
キー入力割り込みについて次のことがわかりました。
1 割り込みキーは4つあります。 KI0、KI1、KI2、KI3 です。
2 使えるポートは、 KI0:p1_0、KI1:p1_1、KI2:p1_2とp3_5、KI3:p1_3とp4_2 です。
3 どのキーが関係しても割り込みフラグは1つ(1種)が立つだけです。どのポートかは判定できません。
4 KIのキーを設定するときは、全てをH、または全てをLにしなければなりません。Lになっていると立ち下がり
が検知できないし、Hのポートがあると立ち上がりは検知できません。
5 正常に設定されると、ポートのエッジに応じて割り込みフラグ IRKIビットが1になります。
6 このIRKIビットを読み、1であれば処理をして、このビットに0を書きます。0を書かないと1のまま続きます。
割り込み設定の例です。ポートp3_5をKI2として使っています。
asm("fclr i") //割り込み禁止。設定中に割り込みが入らないように。
// KI2 割り込み設定
p35sel1=1; //p3_5をKI入力にする。2ビットを"10"にする。
p35sel0=0; //上に同じ。"35"はポートによって変わる。
ki2en=1; //KI2を有効にする。enable。"2"はKI番号で変わる。
ki2pl=0; //立ち下がりエッジで。"1"なら立ち上がりエッジ。
pu3_5=1; //プルアップする。"0"プルアップなし。
ilvl65=1; //割り込み優先レジスタ。2ビットで、00:割り込み禁止
ilvl64=1; //01:レベル1 10:レベル2 11:レベル2
for(i=0;i<50;i++){asm("nop")} //割り込み許可までに少し時間を
asm("fset i") //割り込み許可
割り込みがあった時の処理の例です。(スキャンしないと使えないのですが)
//当然ループの中で(スキャンだから)
if( irki==1){//フラグが立っていれば
irki=0;
// 処理
}
本来だと次の割り込みルーチン(割り込み関数)に飛ばねばならないところですが。
#pragma interrupt intKI2(vect=13) //intKI2は関数の名前
void intKI2( void ){
//割り込み処理
}
調べるのにずいぶん時間がかかりましたが、あまり用途のない機能かもしれません。それで例もないのでしょう。INT割り込みが出来る状態では使わないでしょうね。あと、スリープから目覚める働きがあるようですが時期がきたら調べます。
この他の情報があればお教えいただきたいと思います。
工事中
1 めんにゅー 1 ほ そ く