TI社のBLDCモータードライバDRV8301を コントロールするためのユーティリティのようなクラスです。 できるだけユーザーにわかりやすく レジスタの設定・読み取りなどを行います。 尚、データシートは必須の模様。
Dependents: BLDC1Axis_DRV8301CTRL
Diff: DRV8301CTRL.cpp
- 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); +}