TI社のBLDCモータードライバDRV8301を コントロールするためのユーティリティのようなクラスです。 できるだけユーザーにわかりやすく レジスタの設定・読み取りなどを行います。 尚、データシートは必須の模様。

Dependents:   BLDC1Axis_DRV8301CTRL

Revision:
0:72d833823fd5
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DRV8301CTRL.cpp	Wed Aug 31 17:03:35 2016 +0000
@@ -0,0 +1,1011 @@
+#include "DRV8301CTRL.h"
+
+//ショートカット
+#define DRV8301_CS_ACTIVE cs->write(0)
+#define DRV8301_CS_INACTIVE cs->write(1)
+#define DRV8301_GATE_ACTIVE gate->write(1)
+#define DRV8301_GATE_INACTIVE gate->write(0)
+
+//コンストラクタ(オーバーロード +3) =================================
+/*
+ * シリアルとSPIのアドレス、CSとEN_GATEのピンネームを指定してインスタンスを生成
+ */
+drv8301ctrl::drv8301ctrl(Serial *serial, SPI *spi, PinName csel, PinName en_gate){
+    pc = serial;
+    si = spi;
+    cs = new DigitalOut(csel);
+    gate = new DigitalOut(en_gate);
+    hasSerial = !(pc == NULL);
+}
+
+//コンストラクタ(オーバーロード +3) =================================
+/*
+ * シリアルとSPIのアドレス、CSとEN_GATEのアドレスを指定してインスタンスを生成
+ */
+drv8301ctrl::drv8301ctrl(Serial *serial, SPI *spi, DigitalOut *csel, DigitalOut *en_gate){
+    pc = serial;
+    si = spi;
+    cs = csel;
+    gate = en_gate;
+    hasSerial = !(pc == NULL);
+}
+
+//コンストラクタ(オーバーロード +3) =================================
+/*
+ * SPIのアドレス、CSとEN_GATEのピンネームを指定してインスタンスを生成
+ * この場合、デバッグ(シリアルでのSPI通信内容の出力)は使用できない
+ */
+drv8301ctrl::drv8301ctrl(SPI *spi, PinName csel, PinName en_gate){
+    si = spi;
+    cs = new DigitalOut(csel);
+    gate = new DigitalOut(en_gate);
+    hasSerial = false;
+}
+
+//コンストラクタ(オーバーロード +3) =================================
+/*
+ * SPIのアドレス、CSとEN_GATEのアドレスを指定してインスタンスを生成
+ * この場合、デバッグ(シリアルでのSPI通信内容の出力)は使用できない
+ */
+drv8301ctrl::drv8301ctrl(SPI *spi, DigitalOut *csel, DigitalOut *en_gate){
+    si = spi;
+    cs = csel;
+    gate = en_gate;
+    hasSerial = false;
+}
+
+//デストラクタ  =================================================
+drv8301ctrl::~drv8301ctrl(){
+    delete pc;
+    delete si;
+    delete cs;
+    delete gate;
+}
+
+//private:SPIコマンド送信  ======================================
+/*
+ * SPIコマンドを送信し、DRV8301からの返答を受け取って返す
+ * DRV8301は16bitの命令を送信した際、次回送信時に前回の返答を返す
+ * つまり1回目でコマンドを送信し、2回目の空送信で返答を得る
+ *
+ * 引数debugを有効にした場合、SPIでのやりとりの内容をシリアルに出力する
+ * 引数debugはデフォルトでtrue
+ */
+int drv8301ctrl::spi_cmd(int val, bool debug){
+    DRV8301_CS_ACTIVE;
+    wait_us(1);
+
+    //送信
+    si->write(val);
+
+    wait_us(1);
+    DRV8301_CS_INACTIVE;
+
+    wait_us(1);
+
+    DRV8301_CS_ACTIVE;
+
+    //返答
+    int ret = si->write(0x0000);
+
+    if(debug && hasSerial){
+        pc->printf("CS ACTIVE\r\n\tSPI SEND >>>> values = 0x%08x\r\n\tRECEIVE  <<<< return = 0x%08x\r\nCS INACTIVE\r\n", val, ret);
+    }
+
+    wait_us(1);
+    DRV8301_CS_INACTIVE;
+    wait_us(1);
+
+    return ret;
+}
+
+//private:SPI関連の初期化とか  ====================================
+/*
+ * SPIインターフェースの初期化およびDRV8301への初期化コマンドの送信
+ *
+ * 引数reset_ifaceをfalseにすることでSPIインタフェースの初期化をスキップ
+ * すでに外部でSPIインターフェースを使用している等の場合はfalseを指定
+ * 引数reset_ifaceはデフォルトでtrue
+ *
+ */
+void drv8301ctrl::init(bool reset_iface){
+    //SPI初期化
+    if(reset_iface){
+        si->frequency(DRV8301CTRL_FREQ);
+        si->format(16, 1);
+    }
+
+    //EN_GATEの状態をリセット
+    gateReset();
+
+    //CS状態をセット
+    DRV8301_CS_INACTIVE;
+
+    //現在のレジスタ内容を出力
+    if(hasSerial){
+        pc->printf(
+            "1\tSTATUS 1   NOW : 0x%08x, STATUS 2   NOW : 0x%08x\r\n",
+            (spi_cmd(DRV8301REG_READMODE | DRV8301REG_STATUS1, false) & 0x07FF),
+            (spi_cmd(DRV8301REG_READMODE | DRV8301REG_STATUS2, false) & 0x07FF)
+        );
+        pc->printf(
+            "1\tREGISTER 1 NOW : 0x%08x, REGISTER 2 NOW : 0x%08x\r\n",
+            (spi_cmd(DRV8301REG_READMODE | DRV8301REG_CTRL1, false) & 0x07FF),
+            (spi_cmd(DRV8301REG_READMODE | DRV8301REG_CTRL2, false) & 0x07FF)
+        );
+    }
+
+    //初期設定
+    /*
+     * コントロールレジスタは、自分で格納用の値を作って列挙体の値を論理和でくっつけた後
+     * updateWriteValueやwriteCtrl(引数あり)で値を直接更新する方法と、
+     * クラスのメンバ変数が所持している値をメソッドで更新してから
+     * writeCtrl1(引数なし)で更新する方法などがある。
+     * 基本的にはクラスメソッドで値を更新して、writeCtrlを引数なしで呼ぶことが妥当。
+     *
+     * 下記の方法は前者。
+     */
+    unsigned short settingVal1 =
+        GATE_CURRENT_PEAKCURRENT_1_7A |
+        GATE_RESET_NORMAL |
+        PWM_MODE_PWMLINES_3 |
+        OCP_MODE_CURRENTLIMIT |
+        OC_ADJ_SET_ADJUST_0_358
+    ;
+
+    //上記をメソッド更新版で書いた場合
+    //setGATE_CURRENT(1.7f);
+    //setGATE_RESET(true);
+    //setPWM_MODE(false);
+    //setOCP_MODE(0x00);
+    //setOC_ADJ(0.358f);
+
+    //初期設定内容を書き込む
+    //メソッド更新のみで値を書き換えた場合は引数は不要
+    //writeCtrl1(); //メソッドで更新した場合 コントロールレジスタ1
+    //writeCtrl2(); //メソッドで更新した場合 コントロールレジスタ2
+    writeCtrl1(settingVal1); //コントロールレジスタ1
+
+    //現在のレジスタ内容を出力
+    if(hasSerial){
+        pc->printf(
+            "2\tSTATUS 1   NOW : 0x%08x, STATUS 2   NOW : 0x%08x\r\n",
+            (spi_cmd(DRV8301REG_READMODE | DRV8301REG_STATUS1, false) & 0x07FF),
+            (spi_cmd(DRV8301REG_READMODE | DRV8301REG_STATUS2, false) & 0x07FF)
+        );
+        pc->printf(
+            "2\tREGISTER 1 NOW : 0x%08x, REGISTER 2 NOW : 0x%08x\r\n",
+            (spi_cmd(DRV8301REG_READMODE | DRV8301REG_CTRL1, false) & 0x07FF),
+            (spi_cmd(DRV8301REG_READMODE | DRV8301REG_CTRL2, false) & 0x07FF)
+        );
+    }
+
+    unsigned short settingVal2 =
+        OCTW_MODE_REPORT_OT_OC_BOTH |
+        SHUNTGAIN_GAIN_40V_PER_V |
+        DC_CAL_CH1_ENABLE |
+        DC_CAL_CH2_ENABLE |
+        OC_TOFF_CYCLE_BY_CYCLE
+    ;
+
+    //上記をメソッド更新版で書いた場合
+    //setOCTW_MODE(0x00);
+    //setGAIN(2);
+    //setDC_CAL_CH1_Enabled(true);
+    //setDC_CAL_CH2_Enabled(true);
+    //setOC_TOFF_CycleByCycle(true);
+
+    //初期設定内容を書き込む
+    //メソッド更新のみで値を書き換えた場合は引数は不要
+    //writeCtrl1(); //メソッドで更新した場合 コントロールレジスタ1
+    //writeCtrl2(); //メソッドで更新した場合 コントロールレジスタ2
+    writeCtrl2(settingVal2); //コントロールレジスタ1
+
+    //デバイスIDを取得
+    devID = readDEVICE_ID();
+
+    //シリアル出力
+    if(hasSerial){
+        pc->printf("INITIALIZE BEGIN\r\n\tSPI Freq = %d[Hz], SPI Mode = 16, 1\r\n", (int)DRV8301CTRL_FREQ);
+        pc->printf("\tDEVICE ID = [%d]\r\n", (int)devID);
+    }
+
+    //現在のレジスタ内容を出力
+    if(hasSerial){
+        pc->printf(
+            "3\tSTATUS 1   NOW : 0x%08x, STATUS 2   NOW : 0x%08x\r\n",
+            (spi_cmd(DRV8301REG_READMODE | DRV8301REG_STATUS1, false) & 0x07FF),
+            (spi_cmd(DRV8301REG_READMODE | DRV8301REG_STATUS2, false) & 0x07FF)
+        );
+        pc->printf(
+            "3\tREGISTER 1 NOW : 0x%08x, REGISTER 2 NOW : 0x%08x\r\n",
+            (spi_cmd(DRV8301REG_READMODE | DRV8301REG_CTRL1, false) & 0x07FF),
+            (spi_cmd(DRV8301REG_READMODE | DRV8301REG_CTRL2, false) & 0x07FF)
+        );
+        pc->printf("\tINITIAL CTRL1 REG = 0x%08x\r\n\tINITIAL CTRL2 REG = 0x%08x\r\n", settingVal1, settingVal2);
+    }
+
+    //シリアル出力
+    if(hasSerial){
+        pc->printf("INITIALIZE END\r\n   ---===---===---   \r\n");
+    }
+
+    //待ち時間
+    wait_ms(5);
+}
+
+//ステータスレジスタ1の読み取り  ========================================
+/*
+ * DRV8301の現在の状態を読み取り、返す(ステータスレジスタ1)
+ *
+ * この情報で読み取れるものは、
+ * FAULT(何らかの異常), GVDD_UV(GVDD電圧下降), PVDD_UV(PVDD電圧下降),
+ * OTSD(温度上昇シャットダウン), OTW(温度上昇警告),
+ * FETHA_OC(A相FETハイサイド過電流), FETLA_OC(A相FETローサイド過電流),
+ * FETHB_OC(B相FETハイサイド過電流), FETLB_OC(B相FETローサイド過電流),
+ * FETHC_OC(B相FETハイサイド過電流), FETLC_OC(B相FETローサイド過電流)
+ *
+ * 異常がなければ0, 異常があれば1が設定される
+ */
+unsigned short drv8301ctrl::readStatus1(){
+    //SPIで値を読み取り、返す
+    return (unsigned short)(spi_cmd(DRV8301REG_READMODE | DRV8301REG_STATUS1) & 0x07FF);
+}
+
+//ステータスレジスタ2の読み取り  ========================================
+/*
+ * DRV8301の現在の状態を読み取り、返す(ステータスレジスタ2)
+ *
+ * この情報で読み取れるものは、
+ * GVDD_OV(GVDD過電圧)、DEVICE_ID(デバイスID)
+ *
+ * GVDD_OVは異常がなければ0, 異常があれば1が設定される
+ * デバイスIDは4bitの値で、通常は1(0x0001)を返す
+ */
+unsigned short drv8301ctrl::readStatus2(){
+    //SPIで値を読み取り、返す
+    return (unsigned short)(spi_cmd(DRV8301REG_READMODE | DRV8301REG_STATUS2) & 0x07FF);
+}
+
+//ステータスレジスタ:FAULTの読み取り  ===================================
+/*
+ * ステータスレジスタからFAULTの状態だけを切り取って返す
+ * 戻り値がtrueであればFAULT(何らかの異常)が発生している
+ */
+bool drv8301ctrl::readFault(){
+    return (((readStatus1() >> 10) & 0x0001) == 1);
+}
+
+//ステータスレジスタ:GVDD_UVの読み取り  =================================
+/*
+ * ステータスレジスタからGVDD_UVの状態だけを切り取って返す
+ * 戻り値がtrueであればGVDD_UV(GVDDの電圧下降)が発生している
+ */
+bool drv8301ctrl::readGVDD_UV(){
+    return (((readStatus1() >> 9) & 0x0001) == 1);
+}
+
+//ステータスレジスタ:PVDD_UVの読み取り  =================================
+/*
+ * ステータスレジスタからPVDD_UVの状態だけを切り取って返す
+ * 戻り値がtrueであればPVDD_UV(PVDDの電圧下降)が発生している
+ */
+bool drv8301ctrl::readPVDD_UV(){
+    return (((readStatus1() >> 8) & 0x0001) == 1);
+}
+
+//ステータスレジスタ:OTSDの読み取り  ====================================
+/*
+ * ステータスレジスタからOTSDの状態だけを切り取って返す
+ * 戻り値がtrueであればOTSD(温度上昇によるシャットダウン)が発生している
+ *
+ * 温度上昇によるシャットダウンは摂氏150度で設定される
+ */
+bool drv8301ctrl::readOTSD(){
+    return (((readStatus1() >> 7) & 0x0001) == 1);
+}
+
+//ステータスレジスタ:OTWの読み取り  =====================================
+/*
+ * ステータスレジスタからOTWの状態だけを切り取って返す
+ * 戻り値がtrueであればOTW(温度上昇による警告)が発生している
+ *
+ * 温度上昇による警告は摂氏130度で設定される
+ * この警告は摂氏115度になるまで発生し続ける
+ */
+bool drv8301ctrl::readOTW(){
+    return (((readStatus1() >> 6) & 0x0001) == 1);
+}
+
+//ステータスレジスタ:FETHA_OCの読み取り  ================================
+/*
+ * ステータスレジスタからFETHA_OCの状態だけを切り取って返す
+ * 戻り値がtrueであればFETHA_OC(A相FETハイサイド過電流)が発生している
+ */
+bool drv8301ctrl::readFETHA_OC(){
+    return (((readStatus1() >> 5) & 0x0001) == 1);
+}
+
+//ステータスレジスタ:FETLA_OCの読み取り  ================================
+/*
+ * ステータスレジスタからFETLA_OCの状態だけを切り取って返す
+ * 戻り値がtrueであればFETLA_OC(A相FETローサイド過電流)が発生している
+ */
+bool drv8301ctrl::readFETLA_OC(){
+    return (((readStatus1() >> 4) & 0x0001) == 1);
+}
+
+//ステータスレジスタ:FETHB_OCの読み取り  ================================
+/*
+ * ステータスレジスタからFETHB_OCの状態だけを切り取って返す
+ * 戻り値がtrueであればFETHB_OC(B相FETハイサイド過電流)が発生している
+ */
+bool drv8301ctrl::readFETHB_OC(){
+    return (((readStatus1() >> 3) & 0x0001) == 1);
+}
+
+//ステータスレジスタ:FETLB_OCの読み取り  ================================
+/*
+ * ステータスレジスタからFETLB_OCの状態だけを切り取って返す
+ * 戻り値がtrueであればFETLB_OC(B相FETローサイド過電流)が発生している
+ */
+bool drv8301ctrl::readFETLB_OC(){
+    return (((readStatus1() >> 2) & 0x0001) == 1);
+}
+
+//ステータスレジスタ:FETHC_OCの読み取り  ================================
+/*
+ * ステータスレジスタからFETHC_OCの状態だけを切り取って返す
+ * 戻り値がtrueであればFETHC_OC(C相FETハイサイド過電流)が発生している
+ */
+bool drv8301ctrl::readFETHC_OC(){
+    return (((readStatus1() >> 1) & 0x0001) == 1);
+}
+
+//ステータスレジスタ:FETLC_OCの読み取り  ================================
+/*
+ * ステータスレジスタからFETLC_OCの状態だけを切り取って返す
+ * 戻り値がtrueであればFETLC_OC(C相FETローサイド過電流)が発生している
+ */
+bool drv8301ctrl::readFETLC_OC(){
+    return ((readStatus1() & 0x0001) == 1);
+}
+
+//ステータスレジスタ:GVDD_OVの読み取り  =================================
+/*
+ * ステータスレジスタからGVDD_OVの状態だけを切り取って返す
+ * 戻り値がtrueであればGVDD_OV(GVDD過電圧)が発生している
+ */
+bool drv8301ctrl::readGVDD_OV(){
+    return (((readStatus2() >> 7) & 0x0001) == 1);
+}
+
+//ステータスレジスタ:Device IDの読み取り  ===============================
+/*
+ * ステータスレジスタからDevideIDの状態だけを切り取って返す
+ * 戻り値は4bitの値、0 - 15の中のいずれか
+ */
+unsigned char drv8301ctrl::readDEVICE_ID(){
+    return (unsigned char)(readStatus2() & 0x0F);
+}
+
+//コントロールレジスタ1の読み取り  =======================================
+/*
+ * DRV8301の現在の状態を読み取り、返す(コントロールレジスタ1)
+ * 読み取った情報は、内部の保存用変数に格納する
+ *
+ * この情報で読み取れるものは、
+ * GATE_CURRENT(FETゲートカレント設定), GATE_RESET(ゲートリセット監視),
+ * PWM_MODE(PWM信号送出方法), OCP_MODE(過電流監視モード),
+ * OC_ADJ_SET(過電流調整値)
+ *
+ * 設定値はデフォルトであればOC_ADJ_SET以外は0を返す
+ */
+unsigned short drv8301ctrl::readCtrl1(){
+    //取得した値を次回書き込み用変数に格納
+    writeValue1 = (unsigned short)(spi_cmd(DRV8301REG_READMODE | DRV8301REG_CTRL1) & 0x07FF);
+    return writeValue1;
+}
+
+//コントロールレジスタ2の読み取り  =======================================
+/*
+ * DRV8301の現在の状態を読み取り、返す(コントロールレジスタ2)
+ * 読み取った情報は、内部の保存用変数に格納する
+ *
+ * この情報で読み取れるものは、
+ * OCTW_MODE(過電流、温度上昇監視方法), GAIN(電流読み取り値増幅),
+ * DC_CAL_CH1(電流読み取り値オフセットch1),
+ * DC_CAL_CH2(電流読み取り値オフセットch2),
+ * OC_TOFF(過電流発生時オフタイム設定)
+ *
+ * 設定値はデフォルトであれば0を返す
+ */
+unsigned short drv8301ctrl::readCtrl2(){
+    //取得した値を次回書き込み用変数に格納
+    writeValue2 = (unsigned short)(spi_cmd(DRV8301REG_READMODE | DRV8301REG_CTRL2) & 0x07FF);
+    return writeValue2;
+}
+
+//コントロールレジスタ:GATE_CURRENTの読み取り  ===========================
+/*
+ * コントロールレジスタからGATE_CURRENTの状態だけを切り取って返す
+ *
+ * 戻り値の値は0 - 3の4種類
+ * Gate drive peak current 1.7 A = 0
+ * Gate drive peak current 0.7 A = 1
+ * Gate drive peak current 0.25 A = 2
+ * Reserved = 3
+ */
+unsigned char drv8301ctrl::readGATE_CURRENT(){
+    return (unsigned char)(readCtrl1() & 0x03);
+}
+
+//コントロールレジスタ:GATE_CURRENTの読み取り:実際の値で返す  ===================
+/*
+ * コントロールレジスタからGATE_CURRENTの状態だけを切り取って返す
+ *
+ * 戻り値の値は4種類
+ * Gate drive peak current 1.7 A = 1.7f
+ * Gate drive peak current 0.7 A = 0.7f
+ * Gate drive peak current 0.25 A = 0.25f
+ * Reserved = -1.0f
+ */
+float drv8301ctrl::readValGATE_CURRENT(){
+    float ret = 0.0f;
+    switch(readCtrl1() & 0x03){
+        case 0:
+            //1.7A
+            ret = 1.7f;
+            break;
+        case 1:
+            //0.7A
+            ret = 0.7f;
+            break;
+        case 2:
+            //0.25A
+            ret = 0.25f;
+            break;
+        default:
+            //reserved
+            ret = -1.0f;
+    }
+    return ret;
+}
+
+//コントロールレジスタ:GATE_RESETの読み取り  =============================
+/*
+ * コントロールレジスタからGATE_RESETの状態だけを切り取って返す
+ *
+ * 戻り値がtrueならNormal mode
+ * falseならReset gate driver latched faults (reverts to 0)
+ */
+bool drv8301ctrl::readGATE_RESETisNormal(){
+    //設定がNormalならtrue、そうでないならfalseを返す
+    return (((readCtrl1() >> 2) & 0x01) == 0);
+}
+
+//コントロールレジスタ:PWM_MODEの読み取り  ===============================
+/*
+ * コントロールレジスタからPWM_MODEの状態だけを切り取って返す
+ *
+ * 戻り値がtrueなら6線式PWMモード
+ * falseなら3線式PWMモード
+ */
+bool drv8301ctrl::readPWM_MODEis6PWM(){
+    //設定が6-PWM Modeならtrue、3-PWM Modeならfalseを返す
+    return (((readCtrl1() >> 3) & 0x01) == 0);
+}
+
+//コントロールレジスタ:OCP_MODEの読み取り  ===============================
+/*
+ * コントロールレジスタからOCP_MODEの状態だけを切り取って返す
+ *
+ * 戻り値の値は0 - 3の4種類
+ * Current limit = 0
+ * OC latch shut down = 1
+ * Report only = 2
+ * OC disabled = 3
+ */
+unsigned char drv8301ctrl::readOCP_MODE(){
+    return (unsigned char)((readCtrl1() >> 4) & 0x03);
+}
+
+//コントロールレジスタ:OC_ADJ_SETの読み取り  =============================
+/*
+ * コントロールレジスタからOC_ADJ_SETの状態だけを切り取って返す
+ *
+ * 戻り値の値は設定値の5bit(0 - 32)
+ */
+unsigned char drv8301ctrl::readOC_ADJ_SET(){
+    return (unsigned char)((readCtrl1() >> 6) & 0x1F);
+}
+
+//コントロールレジスタ:OC_ADJ_SETの読み取り:実際の値で返す  =====================
+/*
+ * コントロールレジスタからOC_ADJ_SETの状態だけを切り取って返す
+ *
+ * 戻り値の値は設定値の実際の値
+ */
+float drv8301ctrl::readValOC_ADJ_SET(){
+    float ret = 0.0f;
+    switch(readCtrl1() & 0x07C0){
+        case 0x0000: ret = 0.060; break;
+        case 0x0040: ret = 0.068; break;
+        case 0x0080: ret = 0.076; break;
+        case 0x00C0: ret = 0.086; break;
+        case 0x0100: ret = 0.097; break;
+        case 0x0140: ret = 0.109; break;
+        case 0x0180: ret = 0.123; break;
+        case 0x01C0: ret = 0.138; break;
+        case 0x0200: ret = 0.155; break;
+        case 0x0240: ret = 0.175; break;
+        case 0x0280: ret = 0.197; break;
+        case 0x02C0: ret = 0.222; break;
+        case 0x0300: ret = 0.250; break;
+        case 0x0340: ret = 0.282; break;
+        case 0x0380: ret = 0.317; break;
+        case 0x03C0: ret = 0.358; break;
+        case 0x0400: ret = 0.403; break;
+        case 0x0440: ret = 0.454; break;
+        case 0x0480: ret = 0.511; break;
+        case 0x04C0: ret = 0.576; break;
+        case 0x0500: ret = 0.648; break;
+        case 0x0540: ret = 0.730; break;
+        case 0x0580: ret = 0.822; break;
+        case 0x05C0: ret = 0.926; break;
+        case 0x0600: ret = 1.043; break;
+        case 0x0640: ret = 1.175; break;
+        case 0x0680: ret = 1.324; break;
+        case 0x06C0: ret = 1.491; break;
+        case 0x0700: ret = 1.679; break;
+        case 0x0740: ret = 1.892; break;
+        case 0x0780: ret = 2.131; break;
+        case 0x07C0: ret = 2.400; break;
+    }
+    return ret;
+}
+
+//コントロールレジスタ:OCTW_MODEの読み取り  ==============================
+/*
+ * コントロールレジスタからOCTW_MODEの状態だけを切り取って返す
+ *
+ * 戻り値の値は0 - 3の4種類
+ * Report both OT and OC at nOCTW pin = 0
+ * Report OT only = 1
+ * Report OC only = 2
+ * Report OC only (reserved) = 3
+ */
+unsigned char drv8301ctrl::readOCTW_MODE(){
+    return (unsigned char)(readCtrl2() & 0x03);
+}
+
+//コントロールレジスタ:GAINの読み取り  ===================================
+/*
+ * コントロールレジスタからGAINの状態だけを切り取って返す
+ *
+ * 戻り値の値は0 - 3の4種類
+ * Gain of shunt amplifier: 10 V/V = 0
+ * Gain of shunt amplifier: 20 V/V = 1
+ * Gain of shunt amplifier: 40 V/V = 2
+ * Gain of shunt amplifier: 80 V/V = 3
+ */
+unsigned char drv8301ctrl::readGAIN(){
+    return (unsigned char)((readCtrl2() >> 2) & 0x03);
+}
+
+//コントロールレジスタ:DC_CAL_CH1の読み取り  =============================
+/*
+ * コントロールレジスタからDC_CAL_CH1の状態だけを切り取って返す
+ *
+ * 戻り値がtrueならオフセット有効
+ * falseならオフセット無効
+ */
+bool drv8301ctrl::readDC_CAL_CH1isEnabled(){
+    //設定が有効(Enabled)ならtrue、そうでないならfalseを返す
+    return (((readCtrl2() >> 4) & 0x01) == 0);
+}
+
+//コントロールレジスタ:DC_CAL_CH2の読み取り  =============================
+/*
+ * コントロールレジスタからDC_CAL_CH2の状態だけを切り取って返す
+ *
+ * 戻り値がtrueならオフセット有効
+ * falseならオフセット無効
+ */
+bool drv8301ctrl::readDC_CAL_CH2isEnabled(){
+    //設定が有効(Enabled)ならtrue、そうでないならfalseを返す
+    return (((readCtrl2() >> 5) & 0x01) == 0);
+}
+
+//コントロールレジスタ:OC_TOFFの読み取り  ================================
+/*
+ * コントロールレジスタからOC_TOFFの状態だけを切り取って返す
+ *
+ * 戻り値がtrueならCycle by cycle
+ * falseならOff-time control
+ */
+bool drv8301ctrl::readOC_TOFFisCycleByCycle(){
+    //設定がCycle by Cycleならtrue、そうでないならfalseを返す
+    return (((readCtrl2() >> 6) & 0x01) == 0);
+}
+
+//コントロールレジスタ1への書き込み:valが0xffffならwriteValue1を使用する  =========
+/*
+ *  コントロールレジスタ1へ値を書き込む
+ *  引数valが指定されていれば、引数の中の値を書き込み
+ *  引数valが指定されていないか、もしくは引数valが0xffffであれば
+ *  内部に保存しているwriteValue1の中の値を書き込む
+ *
+ *  戻り値がtrueであれば書き込み成功
+ */
+bool drv8301ctrl::writeCtrl1(unsigned short val){
+    //シリアル出力
+    if(hasSerial){
+        pc->printf("CURRENT SETTING = 0x%08x\r\n", (spi_cmd(DRV8301REG_READMODE | DRV8301REG_CTRL1, false) & 0x07FF));
+        pc->printf(">>>>WRITE CTRL1 REGISTER\r\n\tval         = 0x%08x\r\n\twriteValue1 = 0x%08x\r\n", val, writeValue1);
+    }
+
+    //値の書き込み(先頭(MSB)に1がついていたら書き込み失敗)
+    unsigned short ret = spi_cmd(DRV8301REG_WRITEMODE | DRV8301REG_CTRL1 | ((val == 0xffff)? writeValue1 : val));
+
+    //値の書き込みが終わったら現在の値を取得して値をリセットする
+    resetWriteValue1();
+
+    //先頭ビットに1がついていなければ(32768未満であれば)書き込み成功(trueを返す)
+    return (ret < 32768);
+}
+
+//コントロールレジスタ2への書き込み:valが0xffffならwriteValue2を使用する  =========
+/*
+ *  コントロールレジスタ2へ値を書き込む
+ *  引数valが指定されていれば、引数の中の値を書き込み
+ *  引数valが指定されていないか、もしくは引数valが0xffffであれば
+ *  内部に保存しているwriteValue2の中の値を書き込む
+ *
+ *  戻り値がtrueであれば書き込み成功
+ */
+bool drv8301ctrl::writeCtrl2(unsigned short val){
+    //シリアル出力
+    if(hasSerial){
+        pc->printf("CURRENT SETTING = 0x%08x\r\n", (spi_cmd(DRV8301REG_READMODE | DRV8301REG_CTRL2, false) & 0x07FF));
+        pc->printf(">>>>WRITE CTRL2 REGISTER\r\n\tval         = 0x%08x\r\n\twriteValue2 = 0x%08x\r\n", val, writeValue2);
+    }
+
+    //値の書き込み(先頭(MSB)に1がついていたら書き込み失敗)
+    unsigned short ret = spi_cmd(DRV8301REG_WRITEMODE | DRV8301REG_CTRL2 | ((val == 0xffff)? writeValue2 : val));
+
+    //値の書き込みが終わったら現在の値を取得して値をリセットする
+    resetWriteValue2();
+
+    //先頭ビットに1がついていなければ(32768未満であれば)書き込み成功(trueを返す)
+    return (ret < 32768);
+}
+
+//コントロールレジスタ1に設定する内容を格納した変数をリセット  =========================
+void drv8301ctrl::resetWriteValue1(){
+    writeValue1 = (unsigned short)(spi_cmd(DRV8301REG_READMODE | DRV8301REG_CTRL1) & 0x07FF);
+}
+
+//コントロールレジスタ2に設定する内容を格納した変数をリセット  =========================
+void drv8301ctrl::resetWriteValue2(){
+    writeValue2 = (unsigned short)(spi_cmd(DRV8301REG_READMODE | DRV8301REG_CTRL2) & 0x07FF);
+}
+
+//コントロールレジスタ1に設定する内容を格納した変数を直接アップデート  =====================
+void drv8301ctrl::updateWriteValue1(unsigned short val){
+    writeValue1 = val;
+}
+
+//コントロールレジスタ2に設定する内容を格納した変数を直接アップデート  =====================
+void drv8301ctrl::updateWriteValue2(unsigned short val){
+    writeValue2 = val;
+}
+
+//コントロールレジスタ:GATE_CURRENTの書き込み  ===========================
+void drv8301ctrl::setGATE_CURRENT(unsigned char val){
+    //値は0x00,0x01,0x10,0x11の4種類。値が3(0x11)以上のものは0x00として扱う
+    if(val > 3) val = 0;
+
+    //writeValueの対象部分をゼロにして、論理和をとる
+    writeValue1 &= 0xFFFC;
+    writeValue1 |= val;
+
+    //シリアル出力
+    if(hasSerial){
+        pc->printf("Register1 temporary value changed, [GATE_CURRENT]\r\n\tval = 0x%08x, writeValue1 = 0x%08x\r\n", val, writeValue1);
+    }
+}
+
+//コントロールレジスタ:GATE_CURRENTの書き込み:実際の値に近いものを書き込む  ============
+void drv8301ctrl::setGATE_CURRENT(float realVal){
+    //値は0.0(reserved),0.25,0.7,1.7の4種類。値が1.7以上は1.7として扱う
+    realVal = (realVal < 0.0f) ? 0.0f : (realVal > 1.7f) ? 1.7f : realVal;
+
+    //writeValueの対象部分をゼロにする
+    writeValue1 &= 0xFFFC;
+
+    if(realVal < 0.25f){
+        writeValue1 |= GATE_CURRENT_PEAKCURRENT_RESERVED; //reserved
+    }else if(realVal < 0.7f){
+        writeValue1 |= GATE_CURRENT_PEAKCURRENT_0_25A; //0.25A
+    }else if(realVal < 1.7f){
+        writeValue1 |= GATE_CURRENT_PEAKCURRENT_0_7A; //0.7A
+    }else{
+        writeValue1 |= GATE_CURRENT_PEAKCURRENT_1_7A; //1.7A
+    }
+
+    //シリアル出力
+    if(hasSerial){
+        pc->printf("Register1 temporary value changed, [GATE_CURRENT]\r\n\tval = %01.2f, writeValue1 = 0x%08x\r\n", realVal, writeValue1);
+    }
+}
+
+//コントロールレジスタ:GATE_RESETの書き込み  =============================
+void drv8301ctrl::setGATE_RESET(bool isNormal){
+    //writeValueの対象部分をゼロにする
+    writeValue1 &= 0xFFFB;
+
+    writeValue1 |= isNormal ? GATE_RESET_NORMAL : GATE_RESET_RESETGATE_LATCHED_FAULT;
+
+    //シリアル出力
+    if(hasSerial){
+        pc->printf(
+            "Register1 temporary value changed, [GATE_RESET]\r\n\tisNormal = %s, writeValue1 = 0x%08x\r\n",
+            (isNormal ? "true" : "false"),
+            writeValue1
+        );
+    }
+}
+
+//コントロールレジスタ:PWM_MODEの書き込み  ===============================
+void drv8301ctrl::setPWM_MODE(bool is6PWM){
+    //writeValueの対象部分をゼロにする
+    writeValue1 &= 0xFFF7;
+
+    writeValue1 |= is6PWM ? PWM_MODE_PWMLINES_6 : PWM_MODE_PWMLINES_3;
+
+    //シリアル出力
+    if(hasSerial){
+        pc->printf(
+            "Register1 temporary value changed, [PWM_MODE]\r\n\tis6PWM = %s, writeValue1 = 0x%08x\r\n",
+            (is6PWM ? "true" : "false"),
+            writeValue1
+        );
+    }
+}
+
+//コントロールレジスタ:OCP_MODEの書き込み  ===============================
+void drv8301ctrl::setOCP_MODE(unsigned char val){
+    //値は0x00,0x01,0x10,0x11の4種類。値が3(0x11)以上のものは0x00として扱う
+    if(val > 3) val = 0;
+
+    //writeValueの対象部分をゼロにする
+    writeValue1 &= 0xFFCF;
+
+    switch(val){
+        case 0: writeValue1 |= OCP_MODE_CURRENTLIMIT; break;
+        case 1: writeValue1 |= OCP_MODE_OC_LATCH_SHUTDOWN; break;
+        case 2: writeValue1 |= OCP_MODE_REPORTONLY; break;
+        case 3: writeValue1 |= OCP_MODE_OC_DISABLE; break;
+    }
+
+    //シリアル出力
+    if(hasSerial){
+        pc->printf("Register1 temporary value changed, [GATE_CURRENT]\r\n\tval = 0x%08x, writeValue1 = 0x%08x\r\n", val, writeValue1);
+    }
+}
+
+//コントロールレジスタ:OC_ADJ_SETの書き込み  =============================
+void drv8301ctrl::setOC_ADJ(unsigned char val){
+    //値は0(0x00)から31(0x1f)まで。31以上は0として扱う
+    if(val > 31) val = 0;
+
+    //writeValueの対象部分をゼロにする
+    writeValue1 &= 0xF83F;
+
+    switch(val){
+        case 0: writeValue1 |= OC_ADJ_SET_ADJUST_0_060; break;
+        case 1: writeValue1 |= OC_ADJ_SET_ADJUST_0_068; break;
+        case 2: writeValue1 |= OC_ADJ_SET_ADJUST_0_076; break;
+        case 3: writeValue1 |= OC_ADJ_SET_ADJUST_0_086; break;
+        case 4: writeValue1 |= OC_ADJ_SET_ADJUST_0_097; break;
+        case 5: writeValue1 |= OC_ADJ_SET_ADJUST_0_109; break;
+        case 6: writeValue1 |= OC_ADJ_SET_ADJUST_0_123; break;
+        case 7: writeValue1 |= OC_ADJ_SET_ADJUST_0_138; break;
+        case 8: writeValue1 |= OC_ADJ_SET_ADJUST_0_155; break;
+        case 9: writeValue1 |= OC_ADJ_SET_ADJUST_0_175; break;
+        case 10: writeValue1 |= OC_ADJ_SET_ADJUST_0_197; break;
+        case 11: writeValue1 |= OC_ADJ_SET_ADJUST_0_222; break;
+        case 12: writeValue1 |= OC_ADJ_SET_ADJUST_0_250; break;
+        case 13: writeValue1 |= OC_ADJ_SET_ADJUST_0_282; break;
+        case 14: writeValue1 |= OC_ADJ_SET_ADJUST_0_317; break;
+        case 15: writeValue1 |= OC_ADJ_SET_ADJUST_0_358; break;
+        case 16: writeValue1 |= OC_ADJ_SET_ADJUST_0_403; break;
+        case 17: writeValue1 |= OC_ADJ_SET_ADJUST_0_454; break;
+        case 18: writeValue1 |= OC_ADJ_SET_ADJUST_0_511; break;
+        case 19: writeValue1 |= OC_ADJ_SET_ADJUST_0_576; break;
+        case 20: writeValue1 |= OC_ADJ_SET_ADJUST_0_648; break;
+        case 21: writeValue1 |= OC_ADJ_SET_ADJUST_0_730; break;
+        case 22: writeValue1 |= OC_ADJ_SET_ADJUST_0_822; break;
+        case 23: writeValue1 |= OC_ADJ_SET_ADJUST_0_926; break;
+        case 24: writeValue1 |= OC_ADJ_SET_ADJUST_1_043; break;
+        case 25: writeValue1 |= OC_ADJ_SET_ADJUST_1_175; break;
+        case 26: writeValue1 |= OC_ADJ_SET_ADJUST_1_324; break;
+        case 27: writeValue1 |= OC_ADJ_SET_ADJUST_1_491; break;
+        case 28: writeValue1 |= OC_ADJ_SET_ADJUST_1_679; break;
+        case 29: writeValue1 |= OC_ADJ_SET_ADJUST_1_892; break;
+        case 30: writeValue1 |= OC_ADJ_SET_ADJUST_2_131; break;
+        case 31: writeValue1 |= OC_ADJ_SET_ADJUST_2_400; break;
+    }
+
+    //シリアル出力
+    if(hasSerial){
+        pc->printf("Register1 temporary value changed, [OC_ADJ_SET]\r\n\tval = 0x%08x, writeValue1 = 0x%08x\r\n", val, writeValue1);
+    }
+}
+
+//コントロールレジスタ:OC_ADJ_SETの書き込み:実際の値に近いものを書き込む  ==============
+void drv8301ctrl::setOC_ADJ(float realVal){
+    //値は0.06から2.4まで。それ以上は0.06として扱う
+    realVal = (realVal < 0.06f) ? 0.06f : (realVal > 2.4f) ? 2.4f : realVal;
+
+    //writeValueの対象部分をゼロにする
+    writeValue1 &= 0xF83F;
+
+    //ifで振り分けていく・・・しかないのか・・・?
+    if(realVal < 0.068f) writeValue1 |= OC_ADJ_SET_ADJUST_0_060;
+    else if(realVal < 0.076f) writeValue1 |= OC_ADJ_SET_ADJUST_0_068;
+    else if(realVal < 0.086f) writeValue1 |= OC_ADJ_SET_ADJUST_0_076;
+    else if(realVal < 0.097f) writeValue1 |= OC_ADJ_SET_ADJUST_0_086;
+    else if(realVal < 0.109f) writeValue1 |= OC_ADJ_SET_ADJUST_0_097;
+    else if(realVal < 0.123f) writeValue1 |= OC_ADJ_SET_ADJUST_0_109;
+    else if(realVal < 0.138f) writeValue1 |= OC_ADJ_SET_ADJUST_0_123;
+    else if(realVal < 0.155f) writeValue1 |= OC_ADJ_SET_ADJUST_0_138;
+    else if(realVal < 0.175f) writeValue1 |= OC_ADJ_SET_ADJUST_0_155;
+    else if(realVal < 0.197f) writeValue1 |= OC_ADJ_SET_ADJUST_0_175;
+    else if(realVal < 0.222f) writeValue1 |= OC_ADJ_SET_ADJUST_0_197;
+    else if(realVal < 0.250f) writeValue1 |= OC_ADJ_SET_ADJUST_0_222;
+    else if(realVal < 0.282f) writeValue1 |= OC_ADJ_SET_ADJUST_0_250;
+    else if(realVal < 0.317f) writeValue1 |= OC_ADJ_SET_ADJUST_0_282;
+    else if(realVal < 0.358f) writeValue1 |= OC_ADJ_SET_ADJUST_0_317;
+    else if(realVal < 0.403f) writeValue1 |= OC_ADJ_SET_ADJUST_0_358;
+    else if(realVal < 0.454f) writeValue1 |= OC_ADJ_SET_ADJUST_0_403;
+    else if(realVal < 0.511f) writeValue1 |= OC_ADJ_SET_ADJUST_0_454;
+    else if(realVal < 0.576f) writeValue1 |= OC_ADJ_SET_ADJUST_0_511;
+    else if(realVal < 0.648f) writeValue1 |= OC_ADJ_SET_ADJUST_0_576;
+    else if(realVal < 0.730f) writeValue1 |= OC_ADJ_SET_ADJUST_0_648;
+    else if(realVal < 0.822f) writeValue1 |= OC_ADJ_SET_ADJUST_0_730;
+    else if(realVal < 0.926f) writeValue1 |= OC_ADJ_SET_ADJUST_0_822;
+    else if(realVal < 1.043f) writeValue1 |= OC_ADJ_SET_ADJUST_0_926;
+    else if(realVal < 1.175f) writeValue1 |= OC_ADJ_SET_ADJUST_1_043;
+    else if(realVal < 1.324f) writeValue1 |= OC_ADJ_SET_ADJUST_1_175;
+    else if(realVal < 1.491f) writeValue1 |= OC_ADJ_SET_ADJUST_1_324;
+    else if(realVal < 1.679f) writeValue1 |= OC_ADJ_SET_ADJUST_1_491;
+    else if(realVal < 1.892f) writeValue1 |= OC_ADJ_SET_ADJUST_1_679;
+    else if(realVal < 2.131f) writeValue1 |= OC_ADJ_SET_ADJUST_1_892;
+    else if(realVal < 2.400f) writeValue1 |= OC_ADJ_SET_ADJUST_2_131;
+    else writeValue1 |= OC_ADJ_SET_ADJUST_2_400;
+
+    //シリアル出力
+    if(hasSerial){
+        pc->printf("Register1 temporary value changed, [OC_ADJ_SET]\r\n\tval = %2.3f, writeValue1 = 0x%08x\r\n", realVal, writeValue1);
+    }
+}
+
+//コントロールレジスタ:OCTW_MODEの書き込み  ==============================
+void drv8301ctrl::setOCTW_MODE(unsigned char val){
+    //値は0x00,0x01,0x10,0x11の4種類。値が3(0x11)以上のものは0x00として扱う
+    if(val > 3) val = 0;
+
+    //writeValueの対象部分をゼロにする
+    writeValue2 &= 0xFFFC;
+
+    switch(val){
+        case 0: writeValue2 |= OCTW_MODE_REPORT_OT_OC_BOTH; break;
+        case 1: writeValue2 |= OCTW_MODE_REPORT_OVERTEMP_ONLY; break;
+        case 2: writeValue2 |= OCTW_MODE_REPORT_OVERCURRENT_ONLY; break;
+        case 3: writeValue2 |= OCTW_MODE_REPORT_RESERVED; break;
+    }
+
+    //シリアル出力
+    if(hasSerial){
+        pc->printf("Register2 temporary value changed, [OCTW_MODE]\r\n\tval = 0x%08x, writeValue1 = 0x%08x\r\n", val, writeValue2);
+    }
+}
+
+//コントロールレジスタ:GAINの書き込み  ===================================
+void drv8301ctrl::setGAIN(unsigned char val){
+    //値は0x00,0x01,0x10,0x11の4種類。値が3(0x11)以上のものは0x00として扱う
+    if(val > 3) val = 0;
+
+    //writeValueの対象部分をゼロにする
+    writeValue2 &= 0xFFF3;
+
+    switch(val){
+        case 0: writeValue2 |= SHUNTGAIN_GAIN_10V_PER_V; break;
+        case 1: writeValue2 |= SHUNTGAIN_GAIN_20V_PER_V; break;
+        case 2: writeValue2 |= SHUNTGAIN_GAIN_40V_PER_V; break;
+        case 3: writeValue2 |= SHUNTGAIN_GAIN_80V_PER_V; break;
+    }
+
+    //シリアル出力
+    if(hasSerial){
+        pc->printf("Register2 temporary value changed, [GAIN]\r\n\tval = 0x%08x, writeValue1 = 0x%08x\r\n", val, writeValue2);
+    }
+}
+
+//コントロールレジスタ:DC_CAL_CH1の書き込み  =============================
+void drv8301ctrl::setDC_CAL_CH1_Enabled(bool enable){
+    //writeValueの対象部分をゼロにする
+    writeValue2 &= 0xFFEF;
+
+    //引数がtrueならDC_CALを有効にする
+    writeValue2 |= enable ? DC_CAL_CH1_ENABLE : DC_CAL_CH1_DISABLE;
+
+    //シリアル出力
+    if(hasSerial){
+        pc->printf(
+            "Register2 temporary value changed, [DC_CAL_CH1]\r\n\tval = %s, writeValue1 = 0x%08x\r\n",
+            enable ? "true" : "false",
+            writeValue2
+        );
+    }
+}
+
+//コントロールレジスタ:DC_CAL_CH2の書き込み  =============================
+void drv8301ctrl::setDC_CAL_CH2_Enabled(bool enable){
+    //writeValueの対象部分をゼロにする
+    writeValue2 &= 0xFFDF;
+
+    //引数がtrueならDC_CALを有効にする
+    writeValue2 |= enable ? DC_CAL_CH1_ENABLE : DC_CAL_CH1_DISABLE;
+
+    //シリアル出力
+    if(hasSerial){
+        pc->printf(
+            "Register2 temporary value changed, [DC_CAL_CH2]\r\n\tval = %s, writeValue1 = 0x%08x\r\n",
+            enable ? "true" : "false",
+            writeValue2
+        );
+    }
+}
+
+//コントロールレジスタ:OC_TOFFの書き込み  ================================
+void drv8301ctrl::setOC_TOFF_CycleByCycle(bool enable){
+    //writeValueの対象部分をゼロにする
+    writeValue2 &= 0xFFBF;
+
+    //引数がtrueならOC_TOFFをCycleByCycleにする
+    writeValue2 |= enable ? OC_TOFF_CYCLE_BY_CYCLE : OC_TOFF_OFF_TIME_CONTROL;
+
+    //シリアル出力
+    if(hasSerial){
+        pc->printf(
+            "Register2 temporary value changed, [OC_TOFF]\r\n\tval = %s, writeValue1 = 0x%08x\r\n",
+            enable ? "true" : "false",
+            writeValue2
+        );
+    }
+}
+
+//EN_GATEを有効にする
+void drv8301ctrl::gateEnable(){
+    DRV8301_GATE_ACTIVE;
+    wait_us(20);
+}
+
+//EN_GATEを無効にする
+void drv8301ctrl::gateDisable(){
+    DRV8301_GATE_INACTIVE;
+    wait_us(20);
+}
+
+//状態をリセットする(ON-OFF-ON)
+void drv8301ctrl::gateReset(){
+    DRV8301_GATE_ACTIVE;
+    wait_us(15);
+    DRV8301_GATE_INACTIVE;
+    wait_us(15);
+    DRV8301_GATE_ACTIVE;
+    wait_us(15);
+}