ΔΣAD変換の制度や安定度,直線性を確認したいとΔΣAD変換ICを探した。
各メーカから,多々の製品が出ているが,いずれもプログラムが必要だったので,
いっそΔΣADを内臓してるRX21Aを使ってみることにした。
基板まで作るのは費用が掛かるので,CPUボードは市販品から選ぶことにした。
CPUボードはHSBRX21A(北斗電子製:@14,800+消費税)を用いることにした。
(3.3V電源アダプタ(@1,800+消費税)も同時に購入した)
http://www.hokutodenshi.co.jp/7/HSBRX21AF100.htm
![](https://blogimg.goo.ne.jp/user_image/13/15/73bc2d1d2a5eea13076012a366fdd896.jpg)
使ったことのないCPUのプログラムを作り始めるのは,とても大変だが北斗電子から
サンプルプログラムが用意されているので,それを理解するところから始めた。
1.サンプルプログラムによる起動とIOポート入出力
なんと言っても複雑難解なのは,クロックの多さ。
低消費電力や水晶振動子を使用しなくてもシステムが完成するよう便利なのだが
取っ付き辛い。
その部分は20MHz水晶を用いて,最大クロック周波数で動作可能なサンプル
プログラムとなっているため,そのまま使うことにした。
IOポートの入出力設定をし,LED出力,スイッチ状態入力の動作がわかる。
2.割り込み(CMT0による,1msec割込プログラムの作成)
(1)25MHz÷8÷3125=1000Hz
(2)CMT0初期化プログラム
/* CMT0の初期化 CMT0 イニシャライズ 1msec 割込TIMER */
void cmt_init(void)
{
SYSTEM.PRCR.WORD = 0xA502; /* protect off */
MSTP(CMT0) = 0; /* enable CMT0 */
SYSTEM.PRCR.WORD = 0xA500; /* protect on */
/* CMT0 interrupt is enable */
CMT0.CMCR.WORD = 0x0040; /* PCLK/8=25M/8=3.125MHz */
CMT0.CMCNT = 0; /* clear CMCNT */
CMT0.CMCOR = (3125-1); /* 1000Hz 1msec */
IR(CMT0,CMI0) = 0; /* 割込要求クリア */
IPR(CMT0, ) = 2; /* プライオリティ */
IEN(CMT0,CMI0) = 1; /* enable CMT interrupt */
CMT.CMSTR0.BIT.STR0 = 1; /* start CMT0 */
}
(3)割込み 割込みベクタ(vect.hで定義されているものをそのまま使用)
// CMT0 CMI0
#pragma interrupt (Excep_CMT0_CMI0(vect=28))
void Excep_CMT0_CMI0(void);
// 割込プログラム
void Excep_CMT0_CMI0(void)
{ count_1m++;
}
(4)mainの初期化時に下記組込み関数を実行しておくことを忘れずに。
setpsw_i(); /* ---- enable maskable interrupts ---- */
3.SCIの組込み
RS232C通信を用いることで,複雑なIO周辺回路やエニュレータを用いずに
変数の入出力が可能となる。
(1)ハードウエェア
秋月電子から,USB-RS232C変換ICとUSB-microを基板実装した
超小型USBシリアル変換モジュール(AE-FT234X:@600)が売られていたので
これを用い,簡単にハードが完成できる。
http://akizukidenshi.com/catalog/g/gM-08461/
![](https://blogimg.goo.ne.jp/user_image/08/42/2d09d764e36da9e9d037e60e48a44ed2.jpg)
(2)SCI6(P32:TxD6,P33:RxD6),115200,8bit,1stop,non
(3)初期化
void init_sci6(void)
{ /* ---- Initialization of SCI ---- */
DWORD wait_timer;
SYSTEM.PRCR.WORD = 0xA502;
MSTP(SCI6) = 0; /* The module stop state of SCI6 is canceled */
SYSTEM.PRCR.WORD = 0xA500; /* Enable write protection */
SCI6.SCR.BYTE = 0x00;
while (0x00 != (SCI6.SCR.BYTE & 0xF0))
{ /* Confirm that bit is actually 0 */
}
/* ---- Set the I/O port functions ---- */
PORT3.PODR.BIT.B2= 1;
/* Set port direction - TXDn is output port, RXDn is input port */
PORT3.PDR.BIT.B2 = 1;
PORT3.PDR.BIT.B3 = 0;
/* Set port mode - Use pin as general I/O port */
PORT3.PMR.BIT.B2 = 0;
PORT3.PMR.BIT.B3 = 0;
MPC.PWPR.BIT.B0WI = 0;
MPC.PWPR.BIT.PFSWE = 1;
MPC.P32PFS.BYTE = 0x0b;
MPC.P33PFS.BYTE = 0x0b;
MPC.PWPR.BIT.PFSWE = 0; /* Enable write protection */
MPC.PWPR.BIT.B0WI = 1;
/* Use pin as I/O port for peripheral functions */
PORT3.PMR.BIT.B2 = 1;
PORT3.PMR.BIT.B3 = 1; /* PFSと共に設定しないとペリフェラルにならない */
/* ---- Initialization of SCI ---- */
/* Select an On-chip baud rate generator to the clock source */
SCI6.SCR.BIT.CKE = 0;
SCI6.SMR.BYTE = 0x00; /* stop bit 1 */
/* BRR - Bit Rate Register (115200設定)*/
SCI6.BRR = 6; /* Bit Rate:{25MHz÷(64*0.5*115200)}-1 = 5.781 */
for(wait_timer=1 ; wait_timer /* Wait 1byte data send time */
/* ---- Initialization of SCI interrupt ---- */
IPR(SCI6, ) = 8;
IR(SCI6,RXI6) = 0; /* Interrupt request is cleared (Edge interrupt) */
IR(SCI6,ERI6) = 0;
IR(SCI6,TXI6) = 0;
IEN(SCI6,RXI6) = 1; /* enable SCI6 Rxi interrupt */
IEN(SCI6,ERI6) = 1; /* enable SCI6 ERi interrupt */
IEN(SCI6,TXI6) = 1; /* enable SCI6 Txi interrupt */
SCI6.SCR.BYTE = 0x50; /* RxI(ERI),RE,:受信割込許可 */
init_ring(); /* 送受信用リングバッファの初期化 */
}
(4)送受信の割込プログラムは省略
4.ΔΣADコンバータ
(1)バードウェアの制約
a) 差動入力回路は,GNDに対して±250mV(差動入力で±500mV)以下
b) シングル入力は±500mV以下
c) 内部にプルアップ抵抗がついているため,信号ラインのインピーダンス
の影響がでてしまう。
差動入力回路のインピーダンスを合わせること。
![](https://blogimg.goo.ne.jp/user_image/1f/3b/22d718edc79162c3f8cf0f50b1e916a3.jpg)
(2)動作説明
a) CMT1で81.92μsecのタイマーを作りイベント信号にする。
b) ELC(イベントリンクコントローラ)で上記イベント毎にΔΣADコンバータ起動
c) AD変換は7chほぼ同時に順次開始し,AD変換完了割込みを発生させることで
各チャンル毎にデータを取り込む。(Runesasのサンプルプログラム参照)
AD完了割込みを用いない場合は,81.92μsecを超える周期で,成行読込も可
d) バラツキにより10bit程度の安定度なので,フィルタを用い12bit相当のデータを得る。
e) イベント周期(81.92μsec)を変えると測定bit数が変わる
(3)初期化
void dsad_init(void)
{
volatile Uint16 loop;
SYSTEM.PRCR.WORD = 0xA502; /* protect off */
MSTP(DSAD) = 0; /* enable DSAD */
SYSTEM.PRCR.WORD = 0xA500; /* protect on */
DSAD.DSADRCR.BYTE = 0x40;
DSAD.DSADCR0.BYTE = 0x80;
DSAD.DSADCR1.BYTE = 0x80;
DSAD.DSADCR2.BYTE = 0x80;
DSAD.DSADCR3.BYTE = 0x80;
DSAD.DSADCR4.BYTE = 0x80;
DSAD.DSADCR5.BYTE = 0x80;
DSAD.DSADCR6.BYTE = 0x80;
DSAD.DSADGSR0.BYTE = 0x00;
DSAD.DSADGSR1.BYTE = 0x00;
DSAD.DSADGSR2.BYTE = 0x00;
DSAD.DSADGSR3.BYTE = 0x00;
DSAD.DSADGSR4.BYTE = 0x00;
DSAD.DSADGSR5.BYTE = 0x00;
DSAD.DSADGSR6.BYTE = 0x00;
for (loop = 0; loop < 50000; loop++)
{ /* wait to activate analog circuit */
}
DSAD.DSADRSTR.BYTE = 0x80;
while (DSAD.DSADRSTR.BIT.DSRST == 1)
{ /* Check that the DSRST bit is cleared. */
}
/* Enable the A/D conversion start by a trigger*/
DSAD.DSADCSR0.BYTE = 0x18;
DSAD.DSADCSR1.BYTE = 0x18;
DSAD.DSADCSR2.BYTE = 0x18;
DSAD.DSADCSR3.BYTE = 0x18;
DSAD.DSADCSR4.BYTE = 0x18;
DSAD.DSADCSR5.BYTE = 0x18;
DSAD.DSADCSR6.BYTE = 0x18;
/* AD変換完了割込でデータを格納する */
IPR(DSAD, DSADI0) = 1;
IPR(DSAD, DSADI1) = 1;
IPR(DSAD, DSADI2) = 1;
IPR(DSAD, DSADI3) = 1;
IPR(DSAD, DSADI4) = 1;
IPR(DSAD, DSADI5) = 1;
IPR(DSAD, DSADI6) = 1;
/* Interrupt Request Enable (IERm). */
IEN(DSAD, DSADI0) = 1;
IEN(DSAD, DSADI1) = 1;
IEN(DSAD, DSADI2) = 1;
IEN(DSAD, DSADI3) = 1;
IEN(DSAD, DSADI4) = 1;
IEN(DSAD, DSADI5) = 1;
IEN(DSAD, DSADI6) = 1;
}
/*------------------------------------------------------*/
void elc_init(void)
{
SYSTEM.PRCR.WORD = 0xA502; /* protect off */
MSTP(ELC) = 0; /* enable ELC */
SYSTEM.PRCR.WORD = 0xA500; /* protect on */
/* DSAD channel0 to 6 links to compare match of CMT1.
Then DSAD starts conversion every linked signal. */
ELC.ELSRB[0].BYTE = 0x1f; /* DSAD channel0 */
ELC.ELSRB[1].BYTE = 0x1f; /* DSAD channel1 */
ELC.ELSRB[2].BYTE = 0x1f; /* DSAD channel2 */
ELC.ELSRB[3].BYTE = 0x1f; /* DSAD channel3 */
ELC.ELSRB[4].BYTE = 0x1f; /* DSAD channel4 */
ELC.ELSRB[5].BYTE = 0x1f; /* DSAD channel5 */
ELC.ELSRB[6].BYTE = 0x1f; /* DSAD channel6 */
ELC.ELCR.BYTE = 0x80; /* ELC All Event Link Enable */
}
/*------------------------------------------------------*/
(4)ΔΣADコンバータの直線性誤差
市販DMMを基準として,直流電圧を測定し最大値と最小値を結ぶ
直線からの偏差を誤差としプロットした。
![](https://blogimg.goo.ne.jp/user_image/79/55/9b3dfcc723b77ed830be2f17e96351ed.jpg)
10mVを超える範囲で,±0.1%以内であり良好。
但し,毎回の測定値はバラツキがあり,デジタルフィルタを
入れないと安定した測定はできない。
2015.4.21 TMR3を用いてP13ポート(TMO3)に≒20kHzのPWM波形を出す。
ここでの備忘録は
(1)IOポート設定時のプロテクト解除と再設定
(2)汎用ポートをペリフェラルのIOポートにする初期化方法
/*------------------------------------------------------*/
void init_tmr3(void) /* TMR3 20kHz*/
{
/* ペリフェラルポートとして使うためのピンファンクションの初期化 */
SYSTEM.PRCR.WORD = 0xA502; /* protect off */
MSTP(TMR3) = 0; /* enable TMR3 */
SYSTEM.PRCR.WORD = 0xA500; /* protect on */
PORT1.PMR.BIT.B3 = 0x1; /* P13をペリフェラルIOに指定 */
MPC.PWPR.BIT.B0WI = 0; /* PWPR - Write-Protect Register */
MPC.PWPR.BIT.PFSWE = 1;
MPC.P13PFS.BIT.PSEL = 0x05; /* TMO3 指定 */
MPC.PWPR.BIT.PFSWE = 0; /* Enable write protection */
MPC.PWPR.BIT.B0WI = 1;
TMR3.TCNT = 0; /* CMT3 Count 0 */
TMR3.TCORA = 156-1; /* 25M/8/156=20kHz */
TMR3.TCORB = 78-1; /* Duty 50% 方形波 */
TMR3.TCR.BIT.CCLR = 0x01; /* TCORA clear */
TMR3.TCCR.BIT.CKS = 0x02; /* PCLK/8でカウント */
TMR3.TCCR.BIT.CSS = 0x01; /* PCLK/8でカウント */
TMR3.TCSR.BIT.OSA = 0x02; /* CMPA High Out */
TMR3.TCSR.BIT.OSB = 0x01; /* CMPB Low Out */
}
今はDATAFLASH(CPU内蔵FLASHをEEPROMとする)の使い方を学んでいます。