はじめに
こんにちは、槇原です。前回からまただいぶ時間が空いてしまいましたが、もう少しマイコン関連の話を書きます。
今回のマウスで利用した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)が出力されています。
今回まででマイコンのペリフェラルの話は終わりです。