1. 37引脚VREF/ILIM在不同的PWM模式下功能不同,手册中有写:
“PWM模式1和模式3中的VREF:电流感应放大器电源输入和参考。在VREF和AGND引脚之间连接一个X5R或X7R、0.1µF、6.3V陶瓷电容器。
PWM模式2和模式4中的ILIM:设置逐周期电流限制中使用的相电流阈值。”
PWM模式是通过spi配置DRV8316_ADDRESS_CONTROL_2实现的,我使用的是模式一,6pwm输入,不带电流限制。在模式一,我需要给VREF提供参考电压,我提供的是3.3V,如果没有这个参考电压,采集到的三相电流基准AD值就是150左右,而不是2048左右的基准。
2. 22引脚nFAULT需要硬件上拉,仅用MCU引脚配置内部上拉是不行的,手册有写:
“故障指示灯。故障状态下的逻辑拉低;漏极开路输出需要1.8 V至5.0 V的外部上拉电阻器。如果使用外部电源上拉nFAULT,请确保在通电时将其拉至>2.2 V,否则设备将进入测试模式。”
我实测只用MCU内部引脚上拉后,还是和spi接口通信不上,硬件加上拉就可以通信上了,我的理解是上电时到MCU真正运行到配置这个引脚这段时间,这个引脚的电平未必是在2.2V以上,还有就是我的程序有boot,上电先运行boot再运行app,我一般不会在boot里配置这种外设引脚,所以中间的时间就更长了。
3. nSLEEP引脚和DEVOFF引脚上电后前者拉高,后者拉低就行。
4. SPI的SDO引脚是个开漏脚,最好硬件上拉,我这边硬件不上拉的情况下MCU读数据会失败(全零和全一?)。
二,软件
(1)SPI要配成模式1或模式3,时钟不要高于5M。我的配置如下:
/* spi4 init start.*/ /* spi1,4 APB2 PCLK2(150M) DIV32 4.57M DIV16 9.41M spi2,3 APB1 PCLK1(75 M) mode CPOL CPHA mode0 0 0 mode1 0 1 # mode2 1 0 mode3 1 1 */ spi_set_nss_gpio(&DRV_SPI4, GPIO_SPI4_CS0); gpio_set_pin(GPIO_SPI4_CS0); spi_init(&DRV_SPI4); spi_spi4_config(&DRV_SPI4); (void)spi_set_baud(&DRV_SPI4, SPI_BAUDRATE_DIV32); (void)spi_set_fformat(&DRV_SPI4, SPI_FRAMEFORMAT_MSB); (void)spi_set_fsize(&DRV_SPI4, SPI_FRAMESIZE_16); (void)spi_set_cpha(&DRV_SPI4, SPI_CPHA_1); (void)spi_set_cpol(&DRV_SPI4, SPI_CPOL_0); spi_start(&DRV_SPI4); /* spi4 init end.*/
2. 寄存器配置(不方便截图,配合手册看)
2.1 Control Register 1:向该寄存器写入0x03解锁,写入此值后允许修改所有寄存器,在配置其他寄存器时要先完成这步操作,配置完所有寄存器后可以向该寄存器写入0x06锁定。
//! \brief Enumeration for the high side gate drive peak source current; //! gate currents not consistent with DS //! typedef enum { DRV8316_REG_LOCK_0 = 0, //!< No effect unless locked or unlocked DRV8316_REG_LOCK_1 = 1, //!< No effect unless locked or unlocked DRV8316_REG_LOCK_2 = 2, //!< No effect unless locked or unlocked DRV8316_REG_LOCK_3 = 3, //!< Write 011b to this register to unlock all registers DRV8316_REG_LOCK_4 = 4, //!< No effect unless locked or unlocked DRV8316_REG_LOCK_5 = 5, //!< No effect unless locked or unlocked DRV8316_REG_LOCK_6 = 6, //!< Write 110b to lock the settings by ignoring further register DRV8316_REG_LOCK_7 = 7 //!< No effect unless locked or unlocked } DRV8316_CTRL01_RegLock_e;
2.2 Control Register 2:
bit5 决定SDO引脚是开漏模式还是推挽模式,无关紧要我这里选择推挽。
//! \brief Enumeration for the SDO Mode Setting //! typedef enum { DRV8316_SDOMODE_OPEN_DRAIN = 0, //!< SDO IO in Open Drain Mode DRV8316_SDOMODE_PUSH_PULL = 1 //!< SDO IO in Push Pull Mode } DRV8316_CTRL02_SDOMode_e;
bit4 和 bit3 决定压摆率可选项,用于控制功率MOSFET的开关速度,直接影响EMI(电磁干扰)和开关损耗,这里开到最大200V/us,即这两个bit写0x03。
这里有请deepseek介绍下压摆率:
“定义:电压变化速率(dV/dt),单位 V/μs,反映MOSFET从开到关(或反之)的切换速度。
影响:高压摆率 → 开关损耗低、效率高,但EMI噪声大;低压摆率 → EMI小,但开关损耗增加(导致发热)。”
//! \brief Enumeration for the slew rate //! typedef enum { DRV8316_SLEW_25V = 0, //!< Slew rate is 25 V/uS DRV8316_SLEW_50V = 1, //!< Slew rate is 50 V/uS DRV8316_SLEW_150V = 2, //!< Slew rate is 150 V/uS DRV8316_SLEW_200V = 3 //!< Slew rate is 200 V/uS } DRV8316_CTRL02_SlewRate_e;
bit2 和 bit1 决定PWM模式,这里使用六PWM,不带电流限制的模式,即这两个bit写0x00。
//! \brief Enumeration for the driver PWM mode //! typedef enum { DRV8316_PWMMODE_6_N = 0, //!< PWM_MODE = 6 inputs DRV8316_PWMMODE_6_LC = 1, //!< PWM_MODE = 6 inputs with current limit DRV8316_PWMMODE_3_N = 2, //!< PWM_MODE = 3 inputs DRV8316_PWMMODE_3_LC = 3, //!< PWM_MODE = 3 inputs with current limit } DRV8316_CTRL02_PWMMode_e;
bit0 写1用来清除故障,清除后该bit值归零。
2.3 Control Register 3:
bit4 决定在100% PWM占空比时的工作频率选项,直接影响功率器件的开关损耗和系统噪声,这里使用20khz,该位写0。
//! \brief Enumeration for the Freqency of PWM at 100% Duty Cycle //! typedef enum { DRV8316_PWM_100_DUTY_SEL_20KHz = 0, //!< 20KHz DRV8316_PWM_100_DUTY_SEL_40KHz = 1 //!< 40KHz } DRV8316_CTRL03_DUTYSEL_e;
bit3 决定在过压阈值,这里使用34V作为过压阈值,该位写0。
//! \brief Enumeration for the Overvoltage Level Setting //! typedef enum { DRV8316_OVPSEL_32V = 0, //!< VM overvoltage level is 32-V DRV8316_OVPSEL_20V = 1 //!< VM overvoltage level is 20-V } DRV8316_CTRL03_OVPSEL_e;
bit2 决定是否开启过压保护,选择开启,该位写1。bit1 决定是否使用nFAULT引脚上报spi故障,选择开启,该位写0。bit0 决定是否使用nFAULT引脚上报过温警告,选择开启,该位写1。
2.4 Control Register 4:
bit7 写1紧急关断电机驱动器的功率输出,将三相桥臂置于高阻态(Hi-Z),这里写入0。
bit6 写0禁用PWM周期同步清除OCP,OCP触发后需手动干预(如复位、写寄存器)才能恢复输出;写1启用PWM周期同步清除OCP,OCP状态会在PWM输入信号的下一个周期开始时自动清除,尝试恢复输出。
bit5 和 bit4 决定设定 过流保护(OCP) 触发前的信号去抖时间(消抖时间),如下:
//! \brief Enumeration for the OCP Deglitch Time Settings //! typedef enum { DRV8316_OCP_DEG_0p2us = 0, //!< OCP deglitch time is 0.2 us DRV8316_OCP_DEG_0p6us = 1, //!< OCP deglitch time is 0.6 us DRV8316_OCP_DEG_1p1us = 2, //!< OCP deglitch time is 1.1 us DRV8316_OCP_DEG_1p6us = 3 //!< OCP deglitch time is 1.6 us } DRV8316_CTRL04_OCPDEGE_e;
bit3 设定 过流保护(OCP)触发后,系统自动尝试恢复输出的等待时间,如下:
//! \brief Enumeration for the OCP Retry Time Settings //! typedef enum { DRV8316_OCP_RETRY_5ms = 0, //!< OCP retry time is 5 ms DRV8316_OCP_RETRY_500ms = 1 //!< OCP retry time is 500 ms } DRV8316_CTRL04_OCPRETRY_e;
bit2 决定过流保护阈值,写入0时16A相电流过流,写入1时24A过流,这里写0。
bit1 和 bit0 决定OCP(过电流保护)故障选项配置,如下:
0h = 过电流触发锁定故障(需手动复位)
1h = 过电流触发自动重试故障(系统自动恢复)
2h = 过电流仅报告但不采取任何措施
3h = 过电流不报告也不采取任何措施
2.5 Control Register 5:
bit6 决定在电流限制或故障状态时的电流续流路径选择,写0FET续流(制动模式),写1二极管续流(滑行模式),这里写0。
选择制动模式(0h)当:需要快速减速(如伺服急停);系统有足够散热能力;允许更高功耗。
选择滑行模式(1h)当:优先考虑系统安全(如过热保护);允许电机自由滑行(如风扇停机);减少功率器件应力。
bit3 决定主动异步整流功能的开关状态,写0AAR禁用,仅通过MOSFET体二极管续流;写1AAR启用,主动控制MOSFET同步整流,这里写0。
bit2 决定主动同步整流功能的开关状态,是优化续流阶段能效的先进技术,与异步整流(AAR)形成互补方案,写0ASR禁用,写1ASR启用,这里写0。
bit1和bit0决定运放系数,写入的值对应的运放系数如下:这里写入0x00。
//! \brief Enumeration for the Current Sense Amplifier's Gain Settings //! typedef enum { DRV8316_CSA_GAIN_0p15VpA = 0, //!< CSA gain is 0.15 V/A DRV8316_CSA_GAIN_0p30VpA = 1, //!< CSA gain is 0.30 V/A DRV8316_CSA_GAIN_0p60VpA = 2, //!< CSA gain is 0.60 V/A DRV8316_CSA_GAIN_1p20VpA = 3, //!< CSA gain is 1.20 V/A } DRV8316_CTRL05_CSAGain_e;
2.6 Control Register 6:
bit 4 用于控制 Buck电源转换器(DC-DC降压电路) 的上下电时序,写0启用Buck电源时序控制(默认正常模式);写1Buck转换器不受时序管理直接工作。
bit3 写入0时 = Buck regulator current limit is set to 600 mA,写1则是150mA,
bit2 和 bit1 决定buck voltage,如下:
//! \brief Enumeration for the Buck Voltage Selection //! typedef enum { DRV8316_BUCK_SEL_3p3V = 0, //!< Buck voltage is 3.3 V DRV8316_BUCK_SEL_5p0V = 1, //!< Buck voltage is 5.0 V DRV8316_BUCK_SEL_4p0V = 2, //!< Buck voltage is 4.0 V DRV8316_BUCK_SEL_5p7V = 3, //!< Buck voltage is 5.7 V } DRV8316_CTRL06_BUCKSEL_e;
bit0 写0 buck regular 失能,写1使能,这里写1。
2.7 Control Register 10:驱动延迟补偿,未使用,全写0。
2.8 代码参考(借鉴TI官方代码):
drv8316.h
//############################################################################# // $Copyright: // Copyright (C) 2017-2023 Texas Instruments Incorporated - http://www.ti.com/ // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // $ //############################################################################# //! \file libraries/drvic/drv8316/include/drv8316s.h //! \brief Contains public interface to various functions related //! to the DRV8316 object //! #ifndef DRV8316S_H #define DRV8316S_H //***************************************************************************** // // If building with a C++ compiler, make all of the definitions in this header // have a C binding. // //***************************************************************************** #ifdef __cplusplus extern "C" { #endif //***************************************************************************** // //! \defgroup DRVIC DRV8316 //! @{ // //***************************************************************************** // the includes #include <math.h> #include <stdint.h> #include <stdbool.h> // ************************************************************************** // modules // ************************************************************************** // solutions // ************************************************************************** // the defines //! \brief Defines the address mask //! #define DRV8316_ADDR_MASK (0x7E00) //! \brief Defines the data mask //! #define DRV8316_DATA_MASK (0x00FF) //! \brief Defines the R/W mask //! #define DRV8316_RW_MASK (0x8000) // // STATUS00 // //! \brief Defines the R/W mask //! #define DRV8316_FAULT_TYPE_MASK (0x00FF) //! \brief Defines the register address //! #define statReg00_addr 0x00 #define statReg01_addr 0x01 #define statReg02_addr 0x02 #define ctrlReg01_addr 0x03 #define ctrlReg02_addr 0x04 #define ctrlReg03_addr 0x05 #define ctrlReg04_addr 0x06 #define ctrlReg05_addr 0x07 #define ctrlReg06_addr 0x08 #define ctrlReg10_addr 0x0C // // STATUS00 // #define DRV8316_STAT00_FAULT_BITS (1 << 0) #define DRV8316_STAT00_OT_BITS (1 << 1) #define DRV8316_STAT00_OVP_BITS (1 << 2) #define DRV8316_STAT00_NPOR_BITS (1 << 3) #define DRV8316_STAT00_OCP_BITS (1 << 4) #define DRV8316_STAT00_SPI_FLT_BITS (1 << 5) #define DRV8316_STAT00_BK_FLT_BITS (1 << 6) #define DRV8316_STAT00_RESERVED_BITS (1 << 7) // // STATUS01 // #define DRV8316_STAT01_OCP_LA_BITS (1 << 0) #define DRV8316_STAT01_OCP_HA_BITS (1 << 1) #define DRV8316_STAT01_OCP_LB_BITS (1 << 2) #define DRV8316_STAT01_OCP_HB_BITS (1 << 3) #define DRV8316_STAT01_OCP_LC_BITS (1 << 4) #define DRV8316_STAT01_OCP_HC_BITS (1 << 5) #define DRV8316_STAT01_OTS_BITS (1 << 6) #define DRV8316_STAT01_OTW_BITS (1 << 7) // // STATUS02 // #define DRV8316_STAT02_SPI_ADDR_FLT_BITS (1 << 0) #define DRV8316_STAT02_SPI_SCLK_FLT_BITS (1 << 1) #define DRV8316_STAT02_SPI_PARITY_BITS (1 << 2) #define DRV8316_STAT02_VCP_UV_BITS (1 << 3) #define DRV8316_STAT02_BUCK_UV_BITS (1 << 4) #define DRV8316_STAT02_BUCK_OCP_BITS (1 << 5) #define DRV8316_STAT02_OTP_ERR_BITS (1 << 6) #define DRV8316_STAT02_RESERVED_BITS (1 << 7) // // CTRL03 // #define DRV8316_CTRL03_REG_LOCK_BITS (7 << 0) #define DRV8316_CTRL03_RESERVED1_BITS (1 << 3) #define DRV8316_CTRL03_RESERVED2_BITS (1 << 4) #define DRV8316_CTRL03_RESERVED3_BITS (1 << 5) #define DRV8316_CTRL03_RESERVED4_BITS (1 << 6) #define DRV8316_CTRL03_RESERVED5_BITS (1 << 7) // // CTRL04 // #define DRV8316_CTRL04_CLR_FLT_BITS (1 << 0) #define DRV8316_CTRL04_PWM_MODE_BITS (3 << 1) #define DRV8316_CTRL04_SLEW_BITS (3 << 3) #define DRV8316_CTRL04_RESERVED1_BITS (1 << 5) #define DRV8316_CTRL04_RESERVED2_BITS (1 << 6) #define DRV8316_CTRL04_RESERVED3_BITS (1 << 7) // // CTRL05 // #define DRV8316_CTRL05_OTW_REP_BITS (1 << 0) #define DRV8316_CTRL05_SPI_FLT_REP_BITS (1 << 1) #define DRV8316_CTRL05_OVP_EN_BITS (1 << 2) #define DRV8316_CTRL05_OVP_SEL_BITS (1 << 3) #define DRV8316_CTRL05_RESERVED1_BITS (1 << 4) #define DRV8316_CTRL05_RESERVED2_BITS (1 << 5) #define DRV8316_CTRL05_RESERVED3_BITS (1 << 6) #define DRV8316_CTRL05_RESERVED4_BITS (1 << 7) // // CTRL06 // #define DRV8316_CTRL06_OCP_MODE_BITS (3 << 0) #define DRV8316_CTRL06_OCP_LVL_BITS (1 << 2) #define DRV8316_CTRL06_OCP_RETRY_BITS (1 << 3) #define DRV8316_CTRL06_OCP_DEG_BITS (3 << 4) #define DRV8316_CTRL06_OCP_CBC_BITS (1 << 6) #define DRV8316_CTRL06_RESERVED_BITS (1 << 7) // // CTRL07 // #define DRV8316_CTRL07_CSA_GAIN_BITS (3 << 0) #define DRV8316_CTRL07_EN_ASR_BITS (1 << 2) #define DRV8316_CTRL07_EN_AAR_BITS (1 << 3) #define DRV8316_CTRL07_AD_COMP_TH_HS_BITS (1 << 4) #define DRV8316_CTRL07_AD_COMP_TH_LS_BITS (1 << 5) #define DRV8316_CTRL07_ILIM_RECIR_BITS (1 << 6) #define DRV8316_CTRL07_BEMF_TH_BITS (1 << 7) // // CTRL08 // #define DRV8316_CTRL08_BUCK_DIS_BITS (1 << 0) #define DRV8316_CTRL08_BUCK_SEL_BITS (3 << 1) #define DRV8316_CTRL08_BUCK_CL_BITS (1 << 3) #define DRV8316_CTRL08_BUCK_PS_DIS_BITS (1 << 4) #define DRV8316_CTRL08_BUCK_SR_BITS (1 << 5) #define DRV8316_CTRL08_RESERVED1_BITS (1 << 6) #define DRV8316_CTRL08_RESERVED2_BITS (1 << 7) // ************************************************************************** // the typedefs //------------------------------------------------------------------------------ //! \brief Enumeration for the R/W modes //! typedef enum { DRV8316_CTRLMODE_WRITE = (0 << 15), //!< Write Mode DRV8316_CTRLMODE_READ = (1 << 15) //!< Read Mode } DRV8316_CtrlMode_e; //! \brief Enumeration for the register addresses //! typedef enum { DRV8316_ADDRESS_STATUS_0 = (0x0 << 9), //!< Status Register 0 DRV8316_ADDRESS_STATUS_1 = (0x1 << 9), //!< Status Register 1 DRV8316_ADDRESS_STATUS_2 = (0x2 << 9), //!< Status Register 2 DRV8316_ADDRESS_CONTROL_1 = (0x3 << 9), //!< Control Register 1 DRV8316_ADDRESS_CONTROL_2 = (0x4 << 9), //!< Control Register 2 DRV8316_ADDRESS_CONTROL_3 = (0x5 << 9), //!< Control Register 3 DRV8316_ADDRESS_CONTROL_4 = (0x6 << 9), //!< Control Register 4 DRV8316_ADDRESS_CONTROL_5 = (0x7 << 9), //!< Control Register 5 DRV8316_ADDRESS_CONTROL_6 = (0x8 << 9), //!< Control Register 6 DRV8316_ADDRESS_CONTROL_10 = (0xC << 9) //!< Control Register 10 } DRV8316_Address_e; //! \brief Enumeration for the Status 0 register, faults //! typedef enum { DRV8316_FAULT = (1 << 0), //!< Device Fault DRV8316_OT = (1 << 1), //!< Overtemperature Fault DRV8316_OVP = (1 << 2), //!< Supply Overvoltage Protection DRV8316_NPOR = (1 << 3), //!< Supply Power On Reset DRV8316_OCP = (1 << 4), //!< Over Current Protection DRV8316_SPI_FLT = (1 << 5), //!< SPI Fault DRV8316_BK_FLT = (1 << 6) //!< Buck Fault } DRV8316_STATUS00_e; //! \brief Enumeration for the Status 1 register, faults //! typedef enum { DRV8316_OCP_LA = (1 << 0), //!< Overcurrent Status on Low-side switch of OUTA DRV8316_OCP_HA = (1 << 1), //!< Overcurrent Status on High-side switch of OUTA DRV8316_OCP_LB = (1 << 2), //!< Overcurrent Status on Low-side switch of OUTB DRV8316_OCP_HB = (1 << 3), //!< Overcurrent Status on High-side switch of OUTB DRV8316_OCL_LC = (1 << 4), //!< Overcurrent Status on Low-side switch of OUTC DRV8316_OCP_HC = (1 << 5), //!< Overcurrent Status on High-side switch of OUTC DRV8316_OTS = (1 << 6), //!< Overtemperature Shutdown Status DRV8316_OTW = (1 << 7) //!< Overtemperature Warning Status } DRV8316_STATUS01_e; //! \brief Enumeration for the Status 1 register, faults //! typedef enum { DRV8316_SPI_ADDR_FLT = (1 << 0), //!< SPI Address Error DRV8316_SPI_SCLK_FLT = (1 << 1), //!< SPI Clock Framing Error DRV8316_SPI_PARITY = (1 << 2), //!< SPI Parity Error DRV8316_VCP_UV = (1 << 3), //!< Charge Pump Undervoltage Status DRV8316_BUCK_UV = (1 << 4), //!< Buck Regulator Undervoltage Staus DRV8316_BUCK_OCP = (1 << 5), //!< Buck Regulator Overcurrent Staus DRV8316_OTP_ERR = (1 << 6), //!< One Time Programmabilty Error DRV8316_RESERVED = (1 << 7) //!< Reserved } DRV8316_STATUS02_e; //! \brief Enumeration for the high side gate drive peak source current; //! gate currents not consistent with DS //! typedef enum { DRV8316_REG_LOCK_0 = 0, //!< No effect unless locked or unlocked DRV8316_REG_LOCK_1 = 1, //!< No effect unless locked or unlocked DRV8316_REG_LOCK_2 = 2, //!< No effect unless locked or unlocked DRV8316_REG_LOCK_3 = 3, //!< Write 011b to this register to unlock all registers DRV8316_REG_LOCK_4 = 4, //!< No effect unless locked or unlocked DRV8316_REG_LOCK_5 = 5, //!< No effect unless locked or unlocked DRV8316_REG_LOCK_6 = 6, //!< Write 110b to lock the settings by ignoring further register DRV8316_REG_LOCK_7 = 7 //!< No effect unless locked or unlocked } DRV8316_CTRL01_RegLock_e; //! \brief Enumeration for the driver PWM mode //! typedef enum { DRV8316_PWMMODE_6_N = 0, //!< PWM_MODE = 6 inputs DRV8316_PWMMODE_6_LC = 1, //!< PWM_MODE = 6 inputs with current limit DRV8316_PWMMODE_3_N = 2, //!< PWM_MODE = 3 inputs DRV8316_PWMMODE_3_LC = 3, //!< PWM_MODE = 3 inputs with current limit } DRV8316_CTRL02_PWMMode_e; //! \brief Enumeration for the slew rate //! typedef enum { DRV8316_SLEW_25V = 0, //!< Slew rate is 25 V/uS DRV8316_SLEW_50V = 1, //!< Slew rate is 50 V/uS DRV8316_SLEW_150V = 2, //!< Slew rate is 150 V/uS DRV8316_SLEW_200V = 3 //!< Slew rate is 200 V/uS } DRV8316_CTRL02_SlewRate_e; //! \brief Enumeration for the SDO Mode Setting //! typedef enum { DRV8316_SDOMODE_OPEN_DRAIN = 0, //!< SDO IO in Open Drain Mode DRV8316_SDOMODE_PUSH_PULL = 1 //!< SDO IO in Push Pull Mode } DRV8316_CTRL02_SDOMode_e; //! \brief Enumeration for the Overvoltage Level Setting //! typedef enum { DRV8316_OVPSEL_32V = 0, //!< VM overvoltage level is 32-V DRV8316_OVPSEL_20V = 1 //!< VM overvoltage level is 20-V } DRV8316_CTRL03_OVPSEL_e; //! \brief Enumeration for the Freqency of PWM at 100% Duty Cycle //! typedef enum { DRV8316_PWM_100_DUTY_SEL_20KHz = 0, //!< 20KHz DRV8316_PWM_100_DUTY_SEL_40KHz = 1 //!< 40KHz } DRV8316_CTRL03_DUTYSEL_e; //! \brief Enumeration for the OCP Fault Options //! typedef enum { DRV8316_OCP_MODE_LATCH = 0, //!< Overcurrent causes a latched fault DRV8316_OCP_MODE_RETRY = 1, //!< Overcurrent causes an automatic retrying fault DRV8316_OCP_MODE_REPORT = 2, //!< Overcurrent is report only but no action is taken DRV8316_OCP_MODE_NO = 3 //!< Overcurrent is not reported and no action is taken } DRV8316_CTRL04_OCPMODE_e; //! \brief Enumeration for the Overcurrent Level Setting //! typedef enum { DRV8316_OCP_LVL_16A = 0, //!< 16A DRV8316_OCP_LVL_24A = 1 //!< 24A } DRV8316_CTRL04_OCPLVL_e; //! \brief Enumeration for the OCP Retry Time Settings //! typedef enum { DRV8316_OCP_RETRY_5ms = 0, //!< OCP retry time is 5 ms DRV8316_OCP_RETRY_500ms = 1 //!< OCP retry time is 500 ms } DRV8316_CTRL04_OCPRETRY_e; //! \brief Enumeration for the OCP Deglitch Time Settings //! typedef enum { DRV8316_OCP_DEG_0p2us = 0, //!< OCP deglitch time is 0.2 渭s DRV8316_OCP_DEG_0p6us = 1, //!< OCP deglitch time is 0.6 渭s DRV8316_OCP_DEG_1p1us = 2, //!< OCP deglitch time is 1.1 渭s DRV8316_OCP_DEG_1p6us = 3 //!< OCP deglitch time is 1.6 渭s } DRV8316_CTRL04_OCPDEGE_e; //! \brief Enumeration for the Current Sense Amplifier's Gain Settings //! typedef enum { DRV8316_CSA_GAIN_0p15VpA = 0, //!< CSA gain is 0.15 V/A DRV8316_CSA_GAIN_0p30VpA = 1, //!< CSA gain is 0.30 V/A DRV8316_CSA_GAIN_0p60VpA = 2, //!< CSA gain is 0.60 V/A DRV8316_CSA_GAIN_1p20VpA = 3, //!< CSA gain is 1.20 V/A } DRV8316_CTRL05_CSAGain_e; //! \brief Enumeration for the Current Limit Recirculation Settings //! typedef enum { DRV8316_ILIM_RECIR_Brake = 0, //!< Current recirculation through FETs (Brake Mode) DRV8316_ILIM_RECIR_Coast = 1 //!< Current recirculation through diodes (Coast Mode) } DRV8316_CTRL05_ILIMRECIR_e; //! \brief Enumeration for the Buck Voltage Selection //! typedef enum { DRV8316_BUCK_SEL_3p3V = 0, //!< Buck voltage is 3.3 V DRV8316_BUCK_SEL_5p0V = 1, //!< Buck voltage is 5.0 V DRV8316_BUCK_SEL_4p0V = 2, //!< Buck voltage is 4.0 V DRV8316_BUCK_SEL_5p7V = 3, //!< Buck voltage is 5.7 V } DRV8316_CTRL06_BUCKSEL_e; //! \brief Enumeration for the Current Limit Recirculation Settings //! typedef enum { DRV8316_BUCK_CL_600mA = 0, //!< Buck regulator current limit is set to 600 mA DRV8316_BUCK_CL_150mA = 1 //!< Buck regulator current limit is set to 150 mA } DRV8316_CTRL06_BUCKCL_e; //! \brief Enumeration for the Delay Target for Driver Delay Compensation //! typedef enum { DRV8316_DLY_TARGET_0p0us = 0x0, //!< Delay is 0 us DRV8316_DLY_TARGET_0p4us = 0x1, //!< Delay is 0.4 us DRV8316_DLY_TARGET_0p6us = 0x2, //!< Delay is 0.6 us DRV8316_DLY_TARGET_0p8us = 0x3, //!< Delay is 0.8 us DRV8316_DLY_TARGET_1p0us = 0x4, //!< Delay is 1.0 us DRV8316_DLY_TARGET_1p2us = 0x5, //!< Delay is 1.2 us DRV8316_DLY_TARGET_1p4us = 0x6, //!< Delay is 1.4 us DRV8316_DLY_TARGET_1p6us = 0x7, //!< Delay is 1.6 us DRV8316_DLY_TARGET_1p8us = 0x8, //!< Delay is 1.8 us DRV8316_DLY_TARGET_2p0us = 0x9, //!< Delay is 2.0 us DRV8316_DLY_TARGET_2p2us = 0xA, //!< Delay is 2.2 us DRV8316_DLY_TARGET_2p4us = 0xB, //!< Delay is 2.4 us DRV8316_DLY_TARGET_2p6us = 0xC, //!< Delay is 2.6 us DRV8316_DLY_TARGET_2p8us = 0xD, //!< Delay is 2.8 us DRV8316_DLY_TARGET_3p0us = 0xE, //!< Delay is 3.0 us DRV8316_DLY_TARGET_3p2us = 0xF //!< Delay is 3.2 us } DRV8316_CTRL10_DLYTARGET_e; //------------------------------------------------------------------------------ //! \brief Object for the DRV8316 STATUS00 register //! struct DRV8316_STAT00_BITS { // bits description bool FAULT:1; // Bits 0 bool OT:1; // Bits 1 bool OVP:1; // Bits 2 bool NPOR:1; // Bits 3 bool OCP:1; // Bits 4 bool SPI_FLT:1; // Bits 5 bool BK_FLT:1; // Bits 6 bool rsvd1:1; // Bits 7 }; union DRV8316_STAT00_REG { uint16_t all; struct DRV8316_STAT00_BITS bit; }; //! \brief Object for the DRV8316 STATUS01 register //! struct DRV8316_STAT01_BITS { // bits description bool OCP_LA:1; // Bits 0 bool OCP_HA:1; // Bits 1 bool OCP_LB:1; // Bits 2 bool OCP_HB:1; // Bits 3 bool OCL_LC:1; // Bits 4 bool OCP_HC:1; // Bits 5 bool OTS:1; // Bits 6 bool OTW:1; // Bits 7 }; union DRV8316_STAT01_REG { uint16_t all; struct DRV8316_STAT01_BITS bit; }; //! \brief Object for the DRV8316 STATUS02 register //! struct DRV8316_STAT02_BITS { // bits description bool SPI_ADDR_FLT:1; // Bits 0 bool SPI_SCLK_FLT:1; // Bits 1 bool SPI_PARITY:1; // Bits 2 bool VCP_UV:1; // Bits 3 bool BUCK_UV:1; // Bits 4 bool BUCK_OCP:1; // Bits 5 bool OTP_ERR:1; // Bits 6 uint16_t rsvd2:5; // Bits 7 Reserved }; union DRV8316_STAT02_REG { uint16_t all; struct DRV8316_STAT02_BITS bit; }; //! \brief Object for the DRV8316 CTRL01 register //! struct DRV8316_CTRL01_BITS { // bits description DRV8316_CTRL01_RegLock_e REG_LOCK:3; // Bits 2:0 uint16_t rsvd1:5; // 7:3 Reserved }; union DRV8316_CTRL01_REG { uint16_t all; struct DRV8316_CTRL01_BITS bit; }; //! \brief Object for the DRV8316 CTRL03 register //! struct DRV8316_CTRL02_BITS { // bits description bool CLR_FLT:1; // Bits 0 DRV8316_CTRL02_PWMMode_e PWM_MODE:2; // Bits 2-1 DRV8316_CTRL02_SlewRate_e SLEW:2; // Bits 4-3 DRV8316_CTRL02_SDOMode_e SDO_MODE:1; // Bits 5 uint16_t rsvd1:2; // 7:6 Reserved }; union DRV8316_CTRL02_REG { uint16_t all; struct DRV8316_CTRL02_BITS bit; }; //! \brief Object for the DRV8316 CTRL03 register //! struct DRV8316_CTRL03_BITS { // bits description bool OTW_REP:1; // Bits 0 bool SPI_FLT_REP:1; // Bits 1 bool OVP_EN:1; // Bits 2 DRV8316_CTRL03_OVPSEL_e OVP_SEL:1; // Bits 3 DRV8316_CTRL03_DUTYSEL_e PWM_100_DUTY_SEL:1; // Bits 4 uint16_t rsvd1:3; // 7:5 Reserved }; union DRV8316_CTRL03_REG { uint16_t all; struct DRV8316_CTRL03_BITS bit; }; //! \brief Object for the DRV8316 CTRL04 register //! struct DRV8316_CTRL04_BITS { // bits description DRV8316_CTRL04_OCPMODE_e OCP_MODE:2; // Bits 1-0 DRV8316_CTRL04_OCPLVL_e OCP_LVL:1; // Bits 2 DRV8316_CTRL04_OCPRETRY_e OCP_RETRY:1; // Bits 3 DRV8316_CTRL04_OCPDEGE_e OCP_DEG:2; // Bits 5-4 bool OCP_CBC:1; // Bits 6 bool DRV_OFF:1; // Bits 7 }; union DRV8316_CTRL04_REG { uint16_t all; struct DRV8316_CTRL04_BITS bit; }; //! \brief Object for the DRV8316 CTRL05 register //! struct DRV8316_CTRL05_BITS { // bits description DRV8316_CTRL05_CSAGain_e CSA_GAIN:2; // Bits 1-0 bool EN_ASR:1; // Bits 2 bool EN_AAR:1; // Bits 3 uint16_t rsvd1:1; // Bits 4 Reserved uint16_t rsvd2:1; // Bits 5 Reserved DRV8316_CTRL05_ILIMRECIR_e ILIM_RECIR:1; // Bits 6 uint16_t rsvd3:1; // Bits 7 Reserved }; union DRV8316_CTRL05_REG { uint16_t all; struct DRV8316_CTRL05_BITS bit; }; //! \brief Object for the DRV8316 CTRL06 register //! struct DRV8316_CTRL06_BITS { // bits description bool BUCK_DIS:1; // Bits 0 DRV8316_CTRL06_BUCKSEL_e BUCK_SEL:2; // Bits 2-1 DRV8316_CTRL06_BUCKCL_e BUCK_CL:1; // Bits 3 bool BUCK_PS_DIS:1; // Bits 4 uint16_t rsvd1:3; // Bits 7:5 Reserved }; union DRV8316_CTRL06_REG { uint16_t all; struct DRV8316_CTRL06_BITS bit; }; //! \brief Object for the DRV8316 CTRL10 register //! struct DRV8316_CTRL10_BITS { // bits description DRV8316_CTRL10_DLYTARGET_e DLY_TARGET:4; // Bits 3-0 bool DLYCMP_EN:1; // Bits 4 uint16_t rsvd1:3; // Bits 7:5 Reserved }; union DRV8316_CTRL10_REG { uint16_t all; struct DRV8316_CTRL10_BITS bit; }; //! \brief Object for the DRV8316 registers and commands //! typedef struct _DRV8316_VARS_t_ { union DRV8316_STAT00_REG statReg00; union DRV8316_STAT01_REG statReg01; union DRV8316_STAT02_REG statReg02; union DRV8316_CTRL01_REG ctrlReg01; union DRV8316_CTRL02_REG ctrlReg02; union DRV8316_CTRL03_REG ctrlReg03; union DRV8316_CTRL04_REG ctrlReg04; union DRV8316_CTRL05_REG ctrlReg05; union DRV8316_CTRL06_REG ctrlReg06; union DRV8316_CTRL10_REG ctrlReg10; bool writeCmd; bool readCmd; bool manWriteCmd; bool manReadCmd; uint16_t manWriteAddr; uint16_t manReadAddr; uint16_t manWriteData; uint16_t manReadData; }DRV8316_VARS_t; //! \brief Defines the DRV8316_VARS_t handle //! typedef struct _DRV8316_VARS_t_ *DRV8316VARS_Handle; // ************************************************************************** // the globals // ************************************************************************** // the function prototypes //! \brief Initializes the DRV8316 object //! \param[in] pMemory A pointer to the memory for the DRV8316 object //! \param[in] numBytes The number of bytes allocated for the DRV8316 //! object, bytes //! \return The DRV8316 object handle extern void DRV8316_init(); void DRV_getFaults(); extern volatile DRV8316_VARS_t drv8316Vars; //! \brief Builds the control word //! \param[in] ctrlMode The control mode //! \param[in] regName The register name //! \param[in] data The data //! \return The control word static inline uint16_t DRV8316_buildCtrlWord(const DRV8316_CtrlMode_e ctrlMode, const DRV8316_Address_e regAddr, const uint16_t data) { uint16_t p_addr = regAddr; uint16_t p_data = data; uint16_t p_mode = ctrlMode; uint16_t calc = (p_mode & 0x8000) | (p_addr & 0x7E00) | (p_data & 0x00FF); uint16_t parity = 0; while(calc) { parity ^= (calc & 1); calc >>= 1; } parity <<= 8; uint16_t ctrlWord = ctrlMode | regAddr | parity | (data & DRV8316_DATA_MASK); return(ctrlWord); } // end of DRV8316_buildCtrlWord() function //! \brief Reads data from the DRV8316 register //! \param[in] handle The DRV8316 handle //! \param[in] regAddr The register address //! \return The data value uint16_t DRV8316_readSPI(const DRV8316_Address_e regAddr); //! \brief Writes data to the DRV8316 register //! \param[in] handle The DRV8316 handle //! \param[in] regAddr The register name //! \param[in] data The data value void DRV8316_writeSPI(const DRV8316_Address_e regAddr, const uint16_t data); #if 0 //! \brief Initialize the interface to all 8320 SPI variables //! \param[in] handle The DRV8316 handle void DRV8316_setupSPI(DRV8316_VARS_t *drv8316Vars); //! \brief Read from the DRV8316 SPI registers //! \param[in] handle The DRV8316 handle //! \param[in] drv8316Vars The (DRV8316_VARS_t) structure that contains //! all DRV8316 Status/Control register options void DRV8316_readData(DRV8316_VARS_t *drv8316Vars); //! \brief Write to the DRV8316 SPI registers //! \param[in] handle The DRV8316 handle //! \param[in] drv8316Vars The (DRV8316_VARS_t) structure that contains //! all DRV8316 Status/Control register options void DRV8316_writeData(DRV8316_VARS_t *drv8316Vars); #endif //***************************************************************************** // // Close the Doxygen group. //! @} // //***************************************************************************** //***************************************************************************** // // Mark the end of the C bindings section for C++ compilers. // //***************************************************************************** #ifdef __cplusplus } #endif #endif // end of DRV8316S_H definition
drv8316.c
//############################################################################# // $Copyright: // Copyright (C) 2017-2023 Texas Instruments Incorporated - http://www.ti.com/ // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // $ //############################################################################# //! \file libraries/drvic/drv8316/source/drv8316s.c //! \brief Contains the various functions related to the DRV8316 object //! // ************************************************************************** // the includes #include "drv8316.h" #include "bsp_spi.h" // ************************************************************************** // drivers // ************************************************************************** // modules // ************************************************************************** // platforms // ************************************************************************** // the defines // ************************************************************************** // the globals bool DRV_BK_FLT = false; // Buck regulator fault condition is detected bool DRV_SPI_FLT = false; // SPI Fault condition is detected bool DRV_OCP_FLT = false; // Overcurrent condition is detected bool DRV_NPOR_FLT = false; // No power-on-reset condition is detected on VM bool DRV_OVP_FLT = false; // Overvoltage condition is detected on VM bool DRV_OT_FLT = false; // Overtemperature warning / shutdown is detected bool DRV_FAULT_FLT = false; // Fault condition is detected volatile DRV8316_VARS_t drv8316Vars = {0}; // ************************************************************************** // the function prototypes //! \brief Enables the DRV8316 //! \param[in] handle The DRV8316 handle static bool DRV8316_enable(void); void DRV8316_init() { DRV8316_SLEEP_DISABLE(); //pull higt DELAY_MS(10); DRV8316_ENABLE(); //pull low DELAY_MS(10); DRV_FAULT_FLT = DRV8316_enable(); if(true == DRV_FAULT_FLT) { //xxx } /*waitting for config successfully */ DELAY_MS(20); } // end of DRV8316_init() function static bool DRV8316_enable(void) { bool drvEnableFault = false; volatile uint16_t enableWaitTimeOut = 0; // Make sure the FAULT bit is not set during startup while(((DRV8316_readSPI(DRV8316_ADDRESS_STATUS_0) & DRV8316_STAT00_FAULT_BITS) != 0) && (enableWaitTimeOut < 1000)) { if(++enableWaitTimeOut > 999) { drvEnableFault = true; return drvEnableFault; } } // Write (011) unlock all registers, Write (110b) lock all registers DRV8316_writeSPI(DRV8316_ADDRESS_CONTROL_1, 0b011); // Write(1 11 00 1) SDO PP, slew rate is 200 V/μs, 6pwm, clear Fault DRV8316_writeSPI(DRV8316_ADDRESS_CONTROL_2, 0b111001); // Write(0 0 1 0 1b) 100%PWM frequence is 20KHz, VM overvoltage level is 34V, // enable Overvoltage protection, enable SPI fault, enable Over temperature fault DRV8316_writeSPI(DRV8316_ADDRESS_CONTROL_3, 0b00101); // Write(0 1 00 0 0 00b) Driver OFF No Action, OCP clearing in PWM input cycle change is enabled, // OCP Deglitch Time is 0.2us, OCP Retry Time is 5ms, 16A Overcurrent, Overcurrent causes a latched fault DRV8316_writeSPI(DRV8316_ADDRESS_CONTROL_4, 0b01000000); // Write (0 xx 0 0 00b) Current recirculation through FETs, AAR mode is disabled, // ASR mode is disabled, CSA gain is 0.15 V/A DRV8316_writeSPI(DRV8316_ADDRESS_CONTROL_5, 0b0000000); // Write(0 0 01 0b) buck power sequence enable, Buck regulator current limit 600mA // buck voltage 5V, buck regulator enable DRV8316_writeSPI(DRV8316_ADDRESS_CONTROL_6, 0b00010); // Write(0 000b) disable Driver Delay Compensation, Delay Target for Driver Delay Compensation is 0us DRV8316_writeSPI(DRV8316_ADDRESS_CONTROL_10, 0b0000); if((uint16_t)0b011 != DRV8316_readSPI(DRV8316_ADDRESS_CONTROL_1)) { drvEnableFault = true; } if((uint16_t)0b111000 != DRV8316_readSPI(DRV8316_ADDRESS_CONTROL_2)) { drvEnableFault = true; } if((uint16_t)0b00101 != DRV8316_readSPI(DRV8316_ADDRESS_CONTROL_3)) { drvEnableFault = true; } if((uint16_t)0b01000000 != DRV8316_readSPI(DRV8316_ADDRESS_CONTROL_4)) { drvEnableFault = true; } if((uint16_t)0b0000000 != DRV8316_readSPI(DRV8316_ADDRESS_CONTROL_5)) { drvEnableFault = true; } if((uint16_t)0b00010 != DRV8316_readSPI(DRV8316_ADDRESS_CONTROL_6)) { drvEnableFault = true; } if((uint16_t)0b0000 != DRV8316_readSPI(DRV8316_ADDRESS_CONTROL_10)) { drvEnableFault = true; } return drvEnableFault; } // end of DRV8316_enable() function void DRV_getFaults() { // if(IS_DRV_FAULT()) // { DRV_FAULT_FLT = true; drv8316Vars.statReg00.all = DRV8316_readSPI(DRV8316_ADDRESS_STATUS_0); drv8316Vars.statReg01.all = DRV8316_readSPI(DRV8316_ADDRESS_STATUS_1); drv8316Vars.statReg02.all = DRV8316_readSPI(DRV8316_ADDRESS_STATUS_2); drv8316Vars.ctrlReg01.all = DRV8316_readSPI(DRV8316_ADDRESS_CONTROL_1); drv8316Vars.ctrlReg02.all = DRV8316_readSPI(DRV8316_ADDRESS_CONTROL_2); drv8316Vars.ctrlReg03.all = DRV8316_readSPI(DRV8316_ADDRESS_CONTROL_3); drv8316Vars.ctrlReg04.all = DRV8316_readSPI(DRV8316_ADDRESS_CONTROL_4); drv8316Vars.ctrlReg05.all = DRV8316_readSPI(DRV8316_ADDRESS_CONTROL_5); drv8316Vars.ctrlReg06.all = DRV8316_readSPI(DRV8316_ADDRESS_CONTROL_6); drv8316Vars.ctrlReg10.all = DRV8316_readSPI(DRV8316_ADDRESS_CONTROL_10); // } // else // { // DRV_FAULT_FLT = false; // } } uint16_t DRV8316_readSPI(const DRV8316_Address_e regAddr) { uint16_t readWord = 0; uint16_t ctrlWord = 0; const uint16_t data = 0; // build the control word ctrlWord = (uint16_t)DRV8316_buildCtrlWord(DRV8316_CTRLMODE_READ, regAddr, data); DRV_SPI_NSS_ENABLE(); // write the command spiExchange(&DRV_SPI_DEV, (uint8_t *)(&ctrlWord), (uint8_t *)(&readWord), 1); DRV_SPI_NSS_DISABLE(); return(readWord & DRV8316_DATA_MASK); } // end of DRV8316_readSPI() function void DRV8316_writeSPI(const DRV8316_Address_e regAddr, const uint16_t data) { uint16_t ctrlWord; uint16_t readWord; // build the control word ctrlWord = (uint16_t)DRV8316_buildCtrlWord(DRV8316_CTRLMODE_WRITE, regAddr, data); DRV_SPI_NSS_ENABLE(); // write the command spiExchange(&DRV_SPI_DEV, (uint8_t *)(&ctrlWord), (uint8_t *)(&readWord), 1); DRV_SPI_NSS_DISABLE(); return; } // end of DRV8316_writeSPI() function #if 0 void DRV8316_setupSPI(DRV8316_VARS_t *drv8316Vars) { volatile DRV8316_Address_e drvRegAddr; uint16_t drvDataNew; // Set Default Values // Manual Read/Write drv8316Vars->manReadAddr = 0; drv8316Vars->manReadData = 0; drv8316Vars->manReadCmd = false; drv8316Vars->manWriteAddr = 0; drv8316Vars->manWriteData = 0; drv8316Vars->manWriteCmd = false; // Read/Write drv8316Vars->readCmd = false; drv8316Vars->writeCmd = false; // Read registers for default values // Read Status Register 0 drvRegAddr = DRV8316_ADDRESS_STATUS_0; drvDataNew = DRV8316_readSPI(drvRegAddr); drv8316Vars->statReg00.all = drvDataNew; // Read Status Register 1 drvRegAddr = DRV8316_ADDRESS_STATUS_1; drvDataNew = DRV8316_readSPI(drvRegAddr); drv8316Vars->statReg01.all = drvDataNew; // Read Status Register 2 drvRegAddr = DRV8316_ADDRESS_STATUS_2; drvDataNew = DRV8316_readSPI(drvRegAddr); drv8316Vars->statReg02.all = drvDataNew; // Read Control Register 1 drvRegAddr = DRV8316_ADDRESS_CONTROL_1; drvDataNew = DRV8316_readSPI(drvRegAddr); drv8316Vars->ctrlReg01.all = drvDataNew; // Read Control Register 2 drvRegAddr = DRV8316_ADDRESS_CONTROL_2; drvDataNew = DRV8316_readSPI(drvRegAddr); drv8316Vars->ctrlReg02.all = drvDataNew; // Read Control Register 3 drvRegAddr = DRV8316_ADDRESS_CONTROL_3; drvDataNew = DRV8316_readSPI(drvRegAddr); drv8316Vars->ctrlReg02.all = drvDataNew; // Read Control Register 4 drvRegAddr = DRV8316_ADDRESS_CONTROL_4; drvDataNew = DRV8316_readSPI(drvRegAddr); drv8316Vars->ctrlReg04.all = drvDataNew; // Read Control Register 5 drvRegAddr = DRV8316_ADDRESS_CONTROL_5; drvDataNew = DRV8316_readSPI(drvRegAddr); drv8316Vars->ctrlReg05.all = drvDataNew; // Read Control Register 6 drvRegAddr = DRV8316_ADDRESS_CONTROL_6; drvDataNew = DRV8316_readSPI(drvRegAddr); drv8316Vars->ctrlReg06.all = drvDataNew; // Read Control Register 10 drvRegAddr = DRV8316_ADDRESS_CONTROL_10; drvDataNew = DRV8316_readSPI(drvRegAddr); drv8316Vars->ctrlReg10.all = drvDataNew; return; } // end of DRV8316_setupSPI() function void DRV8316_readData(DRV8316_VARS_t *drv8316Vars) { DRV8316_Address_e drvRegAddr; uint16_t drvDataNew; if(drv8316Vars->readCmd) { // Read registers for default values // Read Status Register 0 drvRegAddr = DRV8316_ADDRESS_STATUS_0; drvDataNew = DRV8316_readSPI(drvRegAddr); drv8316Vars->statReg00.all = drvDataNew; // Read Status Register 1 drvRegAddr = DRV8316_ADDRESS_STATUS_1; drvDataNew = DRV8316_readSPI(drvRegAddr); drv8316Vars->statReg01.all = drvDataNew; // Read Status Register 2 drvRegAddr = DRV8316_ADDRESS_STATUS_2; drvDataNew = DRV8316_readSPI(drvRegAddr); drv8316Vars->statReg02.all = drvDataNew; // Read Control Register 1 drvRegAddr = DRV8316_ADDRESS_CONTROL_1; drvDataNew = DRV8316_readSPI(drvRegAddr); drv8316Vars->ctrlReg01.all = drvDataNew; // Read Control Register 2 drvRegAddr = DRV8316_ADDRESS_CONTROL_2; drvDataNew = DRV8316_readSPI(drvRegAddr); drv8316Vars->ctrlReg02.all = drvDataNew; // Read Control Register 3 drvRegAddr = DRV8316_ADDRESS_CONTROL_3; drvDataNew = DRV8316_readSPI(drvRegAddr); drv8316Vars->ctrlReg03.all = drvDataNew; // Read Control Register 4 drvRegAddr = DRV8316_ADDRESS_CONTROL_4; drvDataNew = DRV8316_readSPI(drvRegAddr); drv8316Vars->ctrlReg04.all = drvDataNew; // Read Control Register 5 drvRegAddr = DRV8316_ADDRESS_CONTROL_5; drvDataNew = DRV8316_readSPI(drvRegAddr); drv8316Vars->ctrlReg05.all = drvDataNew; // Read Control Register 6 drvRegAddr = DRV8316_ADDRESS_CONTROL_6; drvDataNew = DRV8316_readSPI(drvRegAddr); drv8316Vars->ctrlReg06.all = drvDataNew; // Read Control Register 10 drvRegAddr = DRV8316_ADDRESS_CONTROL_10; drvDataNew = DRV8316_readSPI(drvRegAddr); drv8316Vars->ctrlReg10.all = drvDataNew; drv8316Vars->readCmd = false; } // Manual read from the DRV8316 if(drv8316Vars->manReadCmd) { // Custom Read drvRegAddr = (DRV8316_Address_e)(drv8316Vars->manReadAddr << 11); drvDataNew = DRV8316_readSPI(drvRegAddr); drv8316Vars->manReadData = drvDataNew; drv8316Vars->manReadCmd = false; } return; } // end of DRV8316_readData() function void DRV8316_writeData(DRV8316_VARS_t *drv8316Vars) { DRV8316_Address_e drvRegAddr; uint16_t drvDataNew; if(drv8316Vars->writeCmd) { // Write Control Register 1 drvRegAddr = DRV8316_ADDRESS_CONTROL_1; drvDataNew = drv8316Vars->ctrlReg01.all & DRV8316_DATA_MASK; DRV8316_writeSPI(drvRegAddr, drvDataNew); // Write Control Register 2 drvRegAddr = DRV8316_ADDRESS_CONTROL_2; drvDataNew = drv8316Vars->ctrlReg02.all & DRV8316_DATA_MASK; DRV8316_writeSPI(drvRegAddr, drvDataNew); // Write Control Register 3 drvRegAddr = DRV8316_ADDRESS_CONTROL_3; drvDataNew = drv8316Vars->ctrlReg03.all & DRV8316_DATA_MASK; DRV8316_writeSPI(drvRegAddr, drvDataNew); // Write Control Register 4 drvRegAddr = DRV8316_ADDRESS_CONTROL_4; drvDataNew = drv8316Vars->ctrlReg04.all & DRV8316_DATA_MASK; DRV8316_writeSPI(drvRegAddr, drvDataNew); // Write Control Register 5 drvRegAddr = DRV8316_ADDRESS_CONTROL_5; drvDataNew = drv8316Vars->ctrlReg05.all & DRV8316_DATA_MASK; DRV8316_writeSPI(drvRegAddr, drvDataNew); // Write Control Register 6 drvRegAddr = DRV8316_ADDRESS_CONTROL_6; drvDataNew = drv8316Vars->ctrlReg06.all & DRV8316_DATA_MASK; DRV8316_writeSPI(drvRegAddr, drvDataNew); // Write Control Register 10 drvRegAddr = DRV8316_ADDRESS_CONTROL_10; drvDataNew = drv8316Vars->ctrlReg10.all & DRV8316_DATA_MASK; DRV8316_writeSPI(drvRegAddr, drvDataNew); drv8316Vars->writeCmd = false; } // Manual write to the DRV8316 if(drv8316Vars->manWriteCmd) { // Custom Write drvRegAddr = (DRV8316_Address_e)(drv8316Vars->manWriteAddr << 11); drvDataNew = drv8316Vars->manWriteData; DRV8316_writeSPI(drvRegAddr, drvDataNew); drv8316Vars->manWriteCmd = false; } return; } // end of DRV8316_writeData() function #endif
以下是有几种模式不太理解,AI的解答,可以略作参考。
枚举解析:DRV8316 PWM 100%占空比频率选择
这个枚举定义了DRV8316电机驱动芯片在100% PWM占空比时的工作频率选项,直接影响功率器件的开关损耗和系统噪声。
1. 枚举项说明
| 枚举值 | 物理意义 | 技术特点 |
|---|---|---|
DRV8316_PWM_100_DUTY_SEL_20KHz |
PWM频率=20kHz | • 较低的开关损耗 • 适合对噪声不敏感的应用 • 可能产生可闻噪声(人耳可听范围) |
DRV8316_PWM_100_DUTY_SEL_40KHz |
PWM频率=40kHz | • 更高的开关频率 • 减少电机电流纹波 • 适合需要静音的场景 • 增加约30%开关损耗 |
2. 硬件实现原理
-
控制路径:
通过配置DRV8316的CTRL03寄存器的特定位(通常为1个控制位)选择频率模式。 -
电路影响:
graph LR A[PWM发生器] -->|频率选择| B[栅极驱动器] B --> C[MOSFET开关速度] C --> D[开关损耗/EMI权衡]
3. 选型决策树
graph TD A[应用需求] --> B{需要超静音?} B -->|是| C[选择40kHz] B -->|否| D{系统散热条件好?} D -->|是| C D -->|否| E[选择20kHz]
4. 配置代码示例
// 安全配置函数(带错误检查) DRV8316_StatusTypeDef DRV8316_SetPwmFullDutyFreq(DRV8316_CTRL03_DUTYSEL_e freq) { if (freq > DRV8316_PWM_100_DUTY_SEL_40KHz) { return DRV8316_INVALID_PARAM; } // 先解锁寄存器(假设有锁定机制) DRV8316_UnlockRegisters(); // 保留其他位,仅修改频率选择位 uint8_t ctrl03 = DRV8316_ReadRegister(CTRL03_REG); ctrl03 = (ctrl03 & 0xFE) | (freq & 0x01); // 假设位0控制频率 DRV8316_WriteRegister(CTRL03_REG, ctrl03); // 重新锁定寄存器 DRV8316_LockRegisters(); return DRV8316_OK; }
5. 实测参数对比
| 参数 | 20kHz模式 | 40kHz模式 |
|---|---|---|
| 开关损耗 | 100% (基准) | ~130% |
| 电流纹波(100mA负载) | ±5mA | ±2mA |
| 可闻噪声 | 明显嗡嗡声 | 基本不可闻 |
| 适合场景 | 工业设备/风扇 | 医疗设备/消费电子 |
6. 进阶调试技巧
-
示波器观测:
-
检查GHx/GLx引脚波形,确认实际开关频率
-
测量上升/下降时间(应<100ns)
-
-
热成像分析:
-
比较不同频率下的MOSFET温升
-
建议在最大负载下测试
-
-
EMI测试:
-
40kHz可能将噪声推到更高频段(更易滤波)
-
7. 常见问题解决方案
Q1: 选择40kHz时驱动芯片过热
• 检查栅极电阻是否过小(建议值2-10Ω)
• 确认散热设计足够
Q2: 20kHz模式下电机有啸叫声
• 尝试调整PWM频率到18kHz或22kHz(避开人耳敏感频段)
• 或在软件中动态切换频率(低速用40kHz,高速用20kHz)
总结
该枚举为开发者提供了关键的PWM频率选择灵活性,实际应用中需根据:
-
声学要求
-
散热能力
-
效率需求
进行权衡选择。建议通过实测验证最终配置。
Current Limit Recirculation Settings 功能解析
这个配置选项定义了电机驱动芯片(如DRV8316)在电流限制或故障状态时的电流续流路径选择,直接影响系统的制动特性和安全行为。
1. 工作模式对比
| 模式值 | 路径选择 | 物理特性 | 典型应用场景 |
|---|---|---|---|
0h |
FET续流(制动模式) | • 电流通过MOSFET体二极管或主动导通 • 产生电气制动扭矩 • 发热集中在功率管 |
需要快速停车的场合 |
1h |
二极管续流(滑行模式) | • 电流仅通过体二极管 • 无主动制动 • 系统自由滑行 • 发热更分散 |
低功耗需求或故障保护场景 |
2. 硬件实现原理
graph LR A[电流限制触发] --> B{模式选择} B -->|0h| C[主动MOSFET导通] B -->|1h| D[仅体二极管通路] C --> E[快速能量消耗] D --> F[缓慢自然衰减]
3. 配置建议
选择制动模式(0h)当:
-
需要快速减速(如伺服急停)
-
系统有足够散热能力
-
允许更高功耗
选择滑行模式(1h)当:
-
优先考虑系统安全(如过热保护)
-
允许电机自由滑行(如风扇停机)
-
减少功率器件应力
4. 寄存器配置示例
// 设置续流模式(假设控制位在CTRL04寄存器的bit3) void DRV8316_SetRecircMode(uint8_t mode) { uint8_t reg_val = DRV8316_ReadRegister(CTRL04_REG); // 清除并设置模式位 reg_val &= ~(1 << 3); // 清除bit3 reg_val |= (mode & 0x01) << 3; // 设置新模式 DRV8316_WriteRegister(CTRL04_REG, reg_val); }
5. 动态特性对比
| 参数 | FET续流模式 | 二极管续流模式 |
|---|---|---|
| 制动时间(1000rpm) | 50ms | >500ms |
| 峰值回馈电流 | 可达额定电流150% | <额定电流30% |
| 芯片温升ΔT | +25°C | +10°C |
| 总线电压泵升 | 显著 | 轻微 |
6. 安全注意事项
-
总线电压监控:
FET续流时可能产生高压回馈,需确保母线电容和OVP电路足够。 -
热管理:
制动模式下建议监测MOSFET结温,特别是:P_{diss} = I^2 \times R_{DS(on)} -
模式切换时序:
从制动模式切换到滑行模式时,需等待电流完全衰减(通常3~5个PWM周期)。
7. 故障排查指南
现象:制动模式下发烫严重
✓ 检查MOSFET的R<sub>DS(on)</sub>是否正常
✓ 验证散热器接触热阻
现象:滑行模式停车过慢
✓ 确认机械系统无额外阻力
✓ 检查二极管正向压降特性
总结
该配置位提供了关键的能量管理策略选择:
-
制动模式 → 更高性能,更大损耗
-
滑行模式 → 更安全,更低功耗
实际选择应基于:
-
系统安全要求等级
-
动态响应需求
-
热设计余量
建议通过示波器观测相电流衰减曲线(如下图)验证模式效果:
FET模式电流衰减:|------ 二极管模式衰减:|~~~~~~~~
Active Asynchronous Rectification (AAR) 功能解析
这个配置位控制电机驱动芯片(如DRV8316)的主动异步整流功能的开关状态,是优化续流阶段能效的关键技术。
1. 功能模式对比
| 模式值 | 工作状态 | 技术特性 | 能效影响 |
|---|---|---|---|
0h |
AAR禁用 | • 仅通过MOSFET体二极管续流 • 续流压降约0.7V • 简单可靠但损耗大 |
效率降低2-5% |
1h |
AAR启用 | • 主动控制MOSFET同步整流 • 续流压降=I×R<sub>DS(on)</sub> • 需精确时序控制 |
提升效率3-8% |
2. 硬件工作原理
graph TB A[PWM关断阶段] --> B{AAR使能?} B -->|0h| C[体二极管导通] B -->|1h| D[MOSFET主动导通] C --> E[高续流损耗] D --> F[低导通损耗]
电压降对比:
-
体二极管:
V_f ≈ 0.7V -
AAR模式:
V_drop = I_load × R_DS(on)(如10A×5mΩ=50mV)
3. 配置建议
启用AAR(1h)当:
-
系统对效率敏感(如电池供电设备)
-
工作电流较大(>5A)
-
驱动芯片支持精确的死区时间控制
禁用AAR(0h)当:
-
需要最高可靠性(避免误导通风险)
-
超高频开关(>100kHz)导致控制困难
-
调试阶段排查问题
4. 寄存器配置示例
// 设置AAR模式(假设控制位在CTRL05寄存器的bit4) void DRV8316_SetAARMode(bool enable) { uint8_t reg_val = DRV8316_ReadRegister(CTRL05_REG); reg_val &= ~(1 << 4); // 清除bit4 reg_val |= (enable & 0x01) << 4; // 设置新状态 DRV8316_WriteRegister(CTRL05_REG, reg_val); // AAR需要额外5us稳定时间(参照芯片手册) delayMicroseconds(5); }
5. 能效实测数据
| 条件 | AAR禁用 | AAR启用 | 提升幅度 |
|---|---|---|---|
| 10A负载续流损耗 | 7W | 0.5W | 85%↓ |
| 系统整体效率@20kHz | 92% | 95% | +3% |
| 芯片温升ΔT | +40°C | +28°C | 12°C↓ |
6. 关键注意事项
-
死区时间协调:
-
AAR要求死区时间 < MOSFET开关延迟时间
-
推荐值:
t_{dead} = \max(t_{d(off)} - t_{d(on)}) + 20ns
-
-
电流检测延迟:
-
启用AAR时需确保电流采样在PWM关断前完成
-
典型窗口:PWM周期最后10%时间
-
-
故障保护:
-
必须配置短路保护(如DESAT检测)
-
AAR异常可能导致直通短路
-
7. 调试技巧
示波器观测要点:
-
比较GHx/GLx信号与相电压(确认无重叠)
-
测量续流阶段V<sub>DS</sub>压降:
-
AAR启用时应≈I×R<sub>DS(on)</sub>
-
禁用时应≈0.7V
-
热成像分析:
-
AAR启用后MOSFET温度分布应更均匀
总结
AAR功能通过将续流路径从二极管切换到MOSFET,显著降低导通损耗:
-
推荐配置:多数应用应启用(1h),除非有特殊可靠性要求
-
验证步骤:
-
确认死区时间配置安全
-
测量效率提升效果
-
监控关键节点温度
-
📌 设计权衡:AAR在提升效率的同时会增加系统复杂性,建议在原型阶段充分验证时序可靠性。
Active Synchronous Rectification (ASR) 功能解析
此配置位控制电机驱动芯片(如DRV8316)的主动同步整流功能开关状态,是优化续流阶段能效的先进技术,与异步整流(AAR)形成互补方案。
1. 核心模式对比
| 模式值 | 工作状态 | 技术特性 | 适用场景 |
|---|---|---|---|
0h |
ASR禁用 | • 依赖体二极管或AAR续流 • 系统兼容性最佳 |
高干扰环境/调试阶段 |
1h |
ASR启用 | • 通过PWM同步控制MOSFET续流 • 需要精确的电流过零检测 • 可实现负电流续流 |
超高效率需求场景 |
2. 技术实现原理
graph LR A[电流换向阶段] --> B{ASR使能?} B -->|0h| C[传统续流模式] B -->|1h| D[实时电流极性检测] D --> E[同步PWM控制] E --> F[反向MOSFET主动导通]
关键优势:
-
相比AAR可降低额外50%的续流损耗
-
支持双向电流续流(电机发电工况)
3. 配置决策树
graph TD A[应用需求] --> B{需要超高效能?} B -->|是| C{系统支持电流检测?} C -->|是| D[启用ASR] C -->|否| E[启用AAR] B -->|否| F[禁用ASR]
4. 寄存器配置规范
// 安全配置流程(含状态验证) DRV8316_StatusTypeDef DRV8316_EnableASR(bool enable) { // 步骤1:检查电流检测是否就绪 if (enable && !DRV8316_CurrentSenseReady()) { return DRV8316_SENSOR_ERROR; } // 步骤2:修改配置(假设控制位在CTRL06_REG的bit5) uint8_t ctrl06 = DRV8316_ReadRegister(CTRL06_REG); ctrl06 = (ctrl06 & ~(1<<5)) | ((enable?1:0)<<5); DRV8316_WriteRegister(CTRL06_REG, ctrl06); // 步骤3:等待模式切换稳定(典型50us) delayMicroseconds(50); return DRV8316_OK; }
5. 性能对比数据
| 指标 | ASR禁用 | ASR启用 | 提升幅度 |
|---|---|---|---|
| 续流损耗@20A | 14W | 3W | 78%↓ |
| 系统效率@48V/10A | 94% | 97% | +3% |
| 动态响应延迟 | - | 增加2μs | - |
6. 关键注意事项
-
电流检测要求:
-
必须配置高带宽电流传感器(>500kHz)
-
推荐使用差分采样放大器
-
-
时序约束:
t_ASR_on < t_deadtime - 100ns // 必须满足
-
故障防护:
-
需使能DESAT保护
-
建议添加硬件看门狗监测ASR状态
-
7. 调试方法
示波器观测点:
-
相电流过零检测信号
-
互补PWM信号的死区重叠
-
MOSFET管压降波形:
正常ASR波形:
PWM_H: |¯¯|____|¯¯|____ PWM_L: |__|¯¯¯¯|__|¯¯¯¯ V_DS: ‾‾‾\____/‾‾‾\___
异常情况处理:
-
直通风险:立即禁用ASR并检查死区时间
-
续流失败:校准电流检测偏移量
总结
ASR技术通过实时电流追踪实现最优续流控制:
-
推荐场景:
-
48V以上高电压系统
-
精密伺服驱动
-
能量回馈应用
-
-
禁用场景:
-
低成本无电流检测设计
-
超高频开关(>150kHz)
-
⚠️ 实施建议:建议先通过AAR模式验证系统稳定性,再逐步启用ASR功能。效率提升与系统复杂度需要谨慎权衡。
浙公网安备 33010602011771号