マイクロマウス研修(槇原)

RX631でMPU-9250からデータを受信する – マイクロマウス研修(槇原)Part18

マイクロマウス研修(槇原)

はじめに

こんにちは、槇原です。前回からまただいぶ時間が空いてしまいましたが、もう少しマイコン関連の話を書きます。

今回のマウスで利用したIMUについて

今回はIMUとしては2023年現在生産中止になっていますが、よくIMUモジュールとして売られていたのでこちらを使いました。写真のマウスの基板の青いところがIMUモジュールです。

このICはSPIとI2Cのどちらかで通信することができますが、今回はSPI通信を使用します。

またMPU-9250のデータシートを見ると、SPIモードは3であることが分かります。そのためCPOLは1 CPHAは1となります。

以下では実際のRX631のレジスタの設定を行います。

制御レジスタ

SPCRレジスタで基本的なSPIの設定ができます。詳細はリファレンスマニュアルの38.2.1に記述があります。

今回はマスタモードでSPI動作をさせるため、MSTRビットを1にします。またSPIの機能を有効にするためSPEビットを1にします。

設定方法は以下の通りです。

	
	RSPI0.SPCR.BIT.SPMS=0;//SPI operation
	RSPI0.SPCR.BIT.TXMD=0;//full duplex
	RSPI0.SPCR.BIT.MODFEN=0;//disable mode fault
	RSPI0.SPCR.BIT.MSTR=1;//master mode
	RSPI0.SPCR.BIT.SPEIE=0;//disable interrupt request
	RSPI0.SPCR.BIT.SPTIE=0;//disable interrupt
	RSPI0.SPCR.BIT.SPE=1;//enable RSPI
	RSPI0.SPCR.BIT.SPRIE=0;//disable spi recive interrupt
	

ビットレートの設定

ビットレートはクロック周波数PCLK、SPBRレジスタの値n、BRDVのビットの値Nで決定されます。

ビットレート=f(PCLK)/(2*(n+1)*2^N)

MPU-9250の最大クロック周波数は1MHzなのでこれ以下の値にする必要があります。
今回のマウスではPCLKは48 MHzでn=3, N=3で0.75 MHzとしました。設定方法は以下の通りです。

SPBRレジスタ

	RSPI0.SPBR = 3;

SPCMD0レジスタBRDVビット

	RSPI0.SPCMD0.BIT.BRDV=3;

データ形式の設定

データ形式等の設定はSPDCRレジスタによって行います。

SPLW ビット

データレジスタ(SPDR)へのアクセス幅が指定できます。0のときワードアクセス(16bit)、1のときロングワードアクセス(32bit)ができます。今回はロングワードアクセスを利用します。32bitあるとIMUに投げるデータと受信データを1回のアクセスで完了させることができます

SPFCビット

フレーム数設定ビットSPDRレジスタ(送受信のデータを入れるレジスタ)のフレーム数を設定するビットです。今回はIMUからz軸のデータのみを取得するため16bit(z軸の各加速度の上位バイト、下位バイトの計16ビット)のみの通信をするため通信で必要なフレーム数は1フレーム(32bit)でOKです

	RSPI0.SPDCR.BIT.SPFC=0;//number of frame
	RSPI0.SPDCR.BIT.SPLW=1;//ward access for SPDR

コマンドレジスタ

コマンドレジスタはSPCMD0~SPCMD7という名前のレジスタで、ビットレートやSPIフォーマットなどをそれぞれ設定することができます。デフォルトはSPCMD0のみを参照して、シーケンス制御レジスタ(SPSCR)のシーケンス長設定レジスタの設定によって、コマンドレジスタの各設定を適応させることができます。今回は常に同じ設定を利用するため、SPCMD0だけを設定します。

SPCMDレジスタの内容はリファレンスマニュアルの38.2.14に記載があります。

SPIモードの設定

上で述べた通り今回はSPIモード3を使います。この設定にはSPCMD0レジスタのCPHA,CPOLビットを指定します。

	RSPI0.SPCMD0.BIT.CPHA=1; //SPI mode 3
	RSPI0.SPCMD0.BIT.CPOL=1; //SPI mode 3

SSLA(チップセレクトピン)はSSL0を使うため0に指定します。また、データ長は今回16bitにするので、SPBビットは0x0fにします。

	RSPI0.SPCMD0.BIT.SSLA=0; //SSL0
	RSPI0.SPCMD0.BIT.SPB=0x0f; //16bit
	RSPI0.SPCMD0.BIT.LSBF=0;//MSB first
	RSPI0.SPCMD0.BIT.SPNDEN=0;
	RSPI0.SPCMD0.BIT.SLNDEN=0;
	RSPI0.SPCMD0.BIT.SCKDEN=0;

IOの設定

SPI通信ではMISO, MOSI, CLK, CSの4本の線が用いられますが、今回はそれぞれP17, PC6, PC5, PC4に対応しています。
どのピンがSPIとして利用できるかはリファレンスマニュアルの表22.1に記載があります。

実際にSPIを使うためには端子機能選択ビットをSPIのピンに指定する必要があります。P17, PC6, PC5, PC4は表22.6と表22.29にPSELビットの値が記載されています。

	//MISO P17
	//MOSI PC6
	//CLK PC5
	//CS PC4
	PORT1.PDR.BIT.B7=IO_IN;
	PORTC.PDR.BIT.B6=IO_OUT;
	PORTC.PDR.BIT.B5=IO_OUT;
	PORTC.PDR.BIT.B4=IO_OUT;
	MPC.PWPR.BIT.B0WI=0;
	MPC.PWPR.BIT.PFSWE=1;
	MPC.P17PFS.BIT.PSEL=13;//MISOA
	MPC.PC6PFS.BIT.PSEL=13;//MOSIA
	MPC.PC5PFS.BIT.PSEL=13; //RSPCKA 
	MPC.PC4PFS.BIT.PSEL=13; //SSLA0 
	PC.PWPR.BYTE = 0x80; // Reprotect
	
	PORT1.PMR.BIT.B7=1;
	PORTC.PMR.BIT.B6=1;
	PORTC.PMR.BIT.B5=1;
	PORTC.PMR.BIT.B4=1;
	

コード例

InitIMU()関数は上で述べたSPIの設定を行う関数です。
WhoAmIIMU()関数はIMUのWHO_AM_Iを読むための関数でWHO_AM_Iのアドレスである0b01110101(0x75)とR/W(1/0)を表す最上位ビット0b10000000(0x80)のORを取った0b11110101(0xf5)を書き込みます。RSPI0.SPDR.LONGには最上位バイトに0xf5、その次にWHO_AM_Iのデータが書き込まれるので、16bit~24bitの部分を取り出しています。

void InitIMU(){
	SYSTEM.PRCR.WORD = 0xA502;
	MSTP(RSPI0) = 0;
	SYSTEM.PRCR.WORD = 0xA500;
	
	RSPI0.SPBR = 3;
	RSPI0.SPDCR.BIT.SPFC=0;//number of frame
	RSPI0.SPDCR.BIT.SPRDTD=0;//read rx buffer
	RSPI0.SPDCR.BIT.SPLW=1;//ward access for SPDR
	
	RSPI0.SPCKD.BIT.SCKDL=2; //SSLピンがLOWになってから信号開始までのサイクル 3RSPCK
	RSPI0.SSLND.BIT.SLNDL=1;//転送終了からSSLピンがHIGNに戻るまでのサイクル 2PSPCK
	RSPI0.SPND.BIT.SPNDL=2;//転送終了から次のアクセスまでのサイクル 3RSPCK+2PCLK
	
	RSPI0.SPCR2.BIT.SPPE=0;
	RSPI0.SPCR2.BIT.SPOE=0;
	RSPI0.SPCR2.BIT.SPIIE=0;
	RSPI0.SPCR2.BIT.PTE=0;
	
	RSPI0.SPCMD0.BIT.CPHA=1; //SPI mode 3
	RSPI0.SPCMD0.BIT.CPOL=1; //SPI mode 3
	
	RSPI0.SPCMD0.BIT.BRDV=3; //bit rate
	RSPI0.SPCMD0.BIT.SSLA=0; //SSL0
	RSPI0.SPCMD0.BIT.SPB=0x0f; //16bit
	RSPI0.SPCMD0.BIT.LSBF=0;//MSB first
	RSPI0.SPCMD0.BIT.SPNDEN=0;
	RSPI0.SPCMD0.BIT.SLNDEN=0;
	RSPI0.SPCMD0.BIT.SCKDEN=0;
	
	//MISO P17
	//MOSI PC6
	//CLK PC5
	//CS PC4
	PORT1.PDR.BIT.B7=IO_IN;
	PORTC.PDR.BIT.B6=IO_OUT;
	PORTC.PDR.BIT.B5=IO_OUT;
	PORTC.PDR.BIT.B4=IO_OUT;
	MPC.PWPR.BIT.B0WI=0;
	MPC.PWPR.BIT.PFSWE=1;
	MPC.P17PFS.BIT.PSEL=13;//MISOA
	MPC.PC6PFS.BIT.PSEL=13;//MOSIA
	MPC.PC5PFS.BIT.PSEL=13; //RSPCKA 
	MPC.PC4PFS.BIT.PSEL=13; //SSLA0 
	PC.PWPR.BYTE = 0x80; // Reprotect
	
	PORT1.PMR.BIT.B7=1;
	PORTC.PMR.BIT.B6=1;
	PORTC.PMR.BIT.B5=1;
	PORTC.PMR.BIT.B4=1;
	
	RSPI0.SPCR.BIT.SPMS=0;//SPI operation
	RSPI0.SPCR.BIT.TXMD=0;//full duplex
	RSPI0.SPCR.BIT.MODFEN=0;//disable mode fault
	RSPI0.SPCR.BIT.MSTR=1;//master mode
	RSPI0.SPCR.BIT.SPEIE=0;//disable interrupt request
	RSPI0.SPCR.BIT.SPTIE=0;//disable interrupt
	RSPI0.SPCR.BIT.SPE=1;//enable RSPI
	RSPI0.SPCR.BIT.SPRIE=0;//disable spi recive interrupt

}

unsigned long WhoAmIIMU(){
	RSPI0.SPCR.BIT.SPE=1; //enable RSPI
	RSPI0.SPDR.LONG=0xf5000000 & 0xFF000000;

	RSPI0.SPDCR.BIT.SPRDTD=0;//rx buffer
	return (RSPI0.SPDR.LONG); 
} 

/* 読み取り部分 
unsigned long imu=WhoAmIIMU(); 
imu=(imu>>16)&0xFF; 
*/

この際のSPIの波形は上のようになっています。MOSI(緑)の信号の最初の8bitはWHO_AM_Iレジスタです。MISO(オレンジ)の信号は16bit目からでWHO_AM_Iの中身(0x71)が出力されています。

今回まででマイコンのペリフェラルの話は終わりです。

タイトルとURLをコピーしました