自作CPU #16 RIIC設定

ブートローダであるRX220にアドレスバスとかクロックとかリセットとか一部のレジスタ等をつなげまくったのでほとんどのピンを使った。しかしRAMへのデータ線はRXには繋がっていない。64ピンを使ったがピン数が足らないのでIOエクスパンダを使った。 MCP23017というやつこのIOエクスパンダはI2Cで通信する仕様でこのためにRX220のRIICという機能を使った。送信はスムーズに行えた。

IOエクスパンダに出力Hを設定したときの波形

f:id:Hamakita:20180130150239j:plain

しかしながら受信で手間取った。受信関数については公式のサンプルプログラムを参考に作りました。だけど少し手直しが必要でRIIC0.ICMR3.BIT.ACKBT=1を書く前にRIIC0.ICMR3.BIT.ACKWP=1を実行する必要があったみたいです。これに気付くのにずいぶん時間が掛かってしまった。

追記 どうやら公式資料ではRIICの初期化でRIIC0.ICMR3.BIT.ACKWP=1を実行していたみたいです。

サンプルプログラム

https://elearning.renesas.com/pluginfile.php/355/mod_folder/content/0/RX_MCU_Japanese/RX63N_RIIC.pdf

RIIC初期化関数

void RIICinit(void){
    SYSTEM.PRCR.WORD = 0xA502;	//プロテクト解除
    MSTP(RIIC0) = 0;				//RIIC起動
    SYSTEM.PRCR.WORD = 0xA500;	//プロテクト
    //IOポート設定
    MPC.PWPR.BIT.B0WI = 0;      //プロテクト解除
    MPC.PWPR.BIT.PFSWE = 1;		//プロテクト解除
    MPC.P16PFS.BIT.PSEL = 0x0F; //P16/SCL
    MPC.P17PFS.BIT.PSEL = 0x0F; //P17/SDA
    MPC.PWPR.BIT.PFSWE = 0;     //プロテクト
    MPC.PWPR.BIT.B0WI = 1;		//プロテクト
    PORT1.PMR.BIT.B6 = 1;       //P16/周辺
    PORT1.PMR.BIT.B7 = 1;       //P17/周辺

    do{    RIIC0.ICCR1.BIT.ICE=0;
    }while(RIIC0.ICCR1.BIT.ICE!=0);
    RIIC0.ICCR1.BIT.IICRST=1;
    RIIC0.ICCR1.BIT.ICE=1;
    RIIC0.ICSER.BYTE =0x00;
    RIIC0.ICMR1.BIT.CKS=0x03;//PCLK/8で動作
    RIIC0.ICBRH.BIT.BRH=0x02;//通信速度の設定
    RIIC0.ICBRL.BIT.BRL=0x03;
    //RIIC0.ICMR2.BYTE = 0x00;//保留
    //RIIC0.ICMR3.BYTE = 0x00;
    //RIIC0.ICFER.BYTE = 0x00;
    RIIC0.ICFER.BYTE = 0x00;//割り込み設定
    RIIC0.ICCR1.BIT.IICRST=0;//内部リセット解除
}

マスター受信関数

int MasterRead(_UBYTE Sad,int clen,_UBYTE *cdata,int rlen,_UBYTE *rdata){
	int RE=-1;
	int ccnt=0;
	int rcnt=0;
	_UBYTE send;
	volatile _UBYTE dummy;
	while(RIIC0.ICCR2.BIT.BBSY!=0);
	RIIC0.ICCR2.BIT.ST=1;
	if(0<clen){
		while(RIIC0.ICSR2.BIT.NACKF==0){
			if(RIIC0.ICSR2.BIT.TDRE==0){
				continue;
			}
			if(ccnt==0){
				send=Sad&0xFE;
			}
			else{
				send=cdata[ccnt-1];
			}
			RIIC0.ICDRT=send;
			if(ccnt==clen){
				while(RIIC0.ICSR2.BIT.TEND!=1);
				RE=0;
				break;
			}
			ccnt++;
		}
		RIIC0.ICCR2.BIT.RS=1;
		while(RIIC0.ICCR2.BIT.RS!=0);
	}
	while(RIIC0.ICSR2.BIT.TDRE!=1);
	RIIC0.ICDRT=Sad|0x01;
	while(RIIC0.ICSR2.BIT.RDRF!=1);
	///
	if(RIIC0.ICSR2.BIT.NACKF==0){//0ならスレーブが認識されている
		if(rlen == 1){
			RIIC0.ICMR3.BIT.ACKWP=1;//ACKBTへのプロテクト解除
			RIIC0.ICMR3.BIT.ACKBT=1;//NACKを送信する
		}
		else if(rlen==2){
			RIIC0.ICMR3.BIT.WAIT=1;
		}
		dummy = RIIC0.ICDRR;
		while(rcnt<rlen-1){
			while(RIIC0.ICSR2.BIT.RDRF!=1);
			if(rcnt+1==rlen-2){
				RIIC0.ICMR3.BIT.WAIT=1;
			}
			else if(rcnt+1==rlen-1){
				RIIC0.ICMR3.BIT.ACKWP=1;//ACKBTへのプロテクト解除
				RIIC0.ICMR3.BIT.ACKBT=1;//NACKを送信する
			}
			rdata[rcnt]=RIIC0.ICDRR;
			rcnt++;
		}
		while(RIIC0.ICSR2.BIT.RDRF!=1);
		RIIC0.ICSR2.BIT.STOP=0;
		RIIC0.ICCR2.BIT.SP=1;
		rdata[rcnt]=RIIC0.ICDRR;
		RIIC0.ICMR3.BIT.WAIT=0;
	}
	else{
		RE=-1;
		RIIC0.ICSR2.BIT.STOP=0;
		RIIC0.ICCR2.BIT.SP=1;
		dummy=RIIC0.ICDRR;
	}
	while(RIIC0.ICSR2.BIT.STOP!=1);
	RIIC0.ICSR2.BIT.NACKF=0;
	RIIC0.ICSR2.BIT.STOP=0;
	return RE;

}