This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

DRV8316REVM: Example for Custom PWM Control with TMS320F280025C and DRV8135EVM

Part Number: DRV8316REVM
Other Parts Discussed in Thread: TMS320F280025C,

Tool/software:

Dear TI Experts,

While I am awaiting your response on my previous post, I wanted to ask if there is an example or guidance available for using the TMS320F280025C LaunchPad in combination with the DRV8135EVM driver to send custom PWM signals. My goal is to achieve a steady low RPM in my BLDC motor.

Any pointers or resources on implementing this would be greatly appreciated.

Thank you for your time and support!

Best regards,

  • Hello Shahar,

    Any firmware examples we have can be located on the EVM webpage:

    Regards,

    Yara

  • Thanks for the quick response!

    After trying several examples to activate the PWM, I still can't get the motor to run. Could you provide an example or guidance on running a BLDC motor using just PWM signals with the DRV8316REVM?

    For reference, I was able to make the motor work as expected on an Arduino by using a basic PWM signal.

  • Hi Shahar,

    I'm not sure I understand.

    What code was used on the Arduino if you don't mind sharing that? It might help me track down maybe similar code we have that I can share.

    Regards,

    Yara

  • Thank you, Yara!

    Here’s the link to the Arduino code and explanation:

    Arduino Code and Explanation 

    Many thanks!

  • Hi Shahar,

    This is what I could find, I think it'll help push you in the right direction:

    //#############################################################################
    //
    // FILE:   DRV8316_Sensored.c
    //
    // TITLE:  FSK Transmitter using PWM mode on the AFE031
    //
    
    //! \addtogroup cpu01_example_list
    //! <h1> FSK Transmitter using PWM mode on the AFE031 </h1>
    //!
    //! This example sets up the F280049C Launchpad with the DRV8316REVM.
    //!
    //! \b External \b Connections \n
    //!  - Remove JP1, JP2, and JP3 headers on F280049C Launchpad
    //!  - Connect the DRV8316REVM boosterpack to the upper F280049C
    //!    Launchpad pins
    //!  - Supply VM power via upper right most jumpers
    //!
    //! \b Watch \b Variables \n
    //!  - pwmDutyCycle
    //!  -
    //!  -
    //!
    //
    //###########################################################################
    // $TI Release: F28004x Support Library v1.08.00.00 $
    // $Release Date: Mon Dec 23 17:24:05 IST 2019 $
    // $Copyright:
    // Copyright (C) 2019 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.
    // $
    //###########################################################################
    
    //
    // Included Files
    //
    #include "F28x_Project.h"     // Device Header file and Examples Include File
    #include "SFO_V8.h"
    
    //
    // Defines
    //
    #define PWM_PERIOD   2500
    //2500 for 20kHz
    //1000 for 50kHz
    
    //#define PWM_6x_MODE 1
    #define PWM_3x_MODE 1
    
    // Period register
    #ifdef PWM_6x_MODE
    #define DEAD_TIME      0// results in a deadtime of 500ns @20kHz
    #endif
    #define nFAULT GpioDataRegs.GPBDAT.bit.GPIO35
    #define nSLEEP 37
    #define HALLA 58
    #define HALLB 30
    #define HALLC 0
    #define DRVOFF 39
    
    #ifdef PWM_3x_MODE
    #define INLA 11
    #define INLB 9
    #define INLC 5
    #endif
    
    //
    // Typedef
    //
    typedef struct
    {
        volatile struct EPWM_REGS *EPwmRegHandle;
    } EPWM_INFO;
    
    //
    // Globals
    //
    float pwmDutyCycle;
    int pwmTrip;
    int current_duty_cycle;
    int rampCounter;
    int accelDelay;
    int hall_state;
    int hall_read;
    EPWM_INFO epwm6_info;
    EPWM_INFO epwm5_info;
    EPWM_INFO epwm3_info;
    
    bool OutputEnable = 1;
    bool FaultLED = 0;
    bool FAULT_BIT = 0;
    bool resetFault = 0;
    Uint16 FaultCounter = 0;
    Uint16 FaultLimit = 10;
    
    bool spiWrite = false;
    bool spiRead = false;
    bool spiReadAll = false;
    bool clear_fault = false;
    Uint16 spi_addr = 0;
    Uint16 spi_data = 0;
    
    
    //Global Status Regs
    struct drv8316regs{
        Uint16 IC_STAT;
        Uint16 STAT1;
        Uint16 STAT2;
        Uint16 CTRL1;
        Uint16 CTRL2;
        Uint16 CTRL3;
        Uint16 CTRL4;
        Uint16 CTRL5;
        Uint16 CTRL6;
        Uint16 CTRL10;
    } drv8316regs;
    
    Uint16 spiData;
    
    //
    // Function Prototypes
    //
    void DRV_InitGpio(void);
    void DRV_InitGpioInput(void);
    void DRV_InitGpioOutput(void);
    void Config_evm_spi(void);
    Uint16 spi_xmit(Uint16 spiFrame);
    Uint16 spi_write(Uint16 addr, Uint16 data);
    Uint16 spi_read(Uint16 addr);
    void EPWM_Init(void);
    void error (void);
    #ifdef PWM_3x_MODE
    void Set_HS0_LS1(EPWM_INFO *epwm_info, char phase);
    void Set_HS0_LS0(EPWM_INFO *epwm_info, char phase);
    void Set_PWM(EPWM_INFO *epwm_info, char phase, int duty_cycle);
    #endif
    #ifdef PWM_6x_MODE
    void Set_HS0_LS1(EPWM_INFO *epwm_info);
    void Set_HS0_LS0(EPWM_INFO *epwm_info);
    void Set_PWM(EPWM_INFO *epwm_info, int duty_cycle);
    #endif
    
    void clearFault(void);
    void disableCRC(void);
    void unlockSPI(void);
    void resetDRV(void);
    void readStatusRegisters(void);
    void readAllRegisters(void);
    
    void main(void)
    {
        //
        // Initialize System Control:
        // PLL, WatchDog, enable Peripheral Clocks
        //
        InitSysCtrl();
    
        //
        // Initialize GPIO:
        // These GPIOs control LEDs, AFE GPIOS.
        //
        InitGpio();
        DRV_InitGpioInput();
        DRV_InitGpioOutput();
    
        //
        // Initialize SPI
        //
        Config_evm_spi();
    
        //
        // Initialize PIE vector table:
        //
        //DINT;
    
        //
        // Initialize PIE control registers to their default state:
        //
        //InitPieCtrl();
    
        // Disable and clear all CPU interrupts
        IER = 0x0000;
        IFR = 0x0000;
    
        //
        // Initialize the PIE vector table with pointers to the shell Interrupt
        // Service Routines (ISR).
        // This will populate the entire table, even if the interrupt
        // is not used in this example.  This is useful for debug purposes.
        //
        //InitPieVectTable();
    
        //
        // Interrupts that are used in this example are re-mapped to
        // ISR functions found within this file.
        //
        //EALLOW;
        //PieVectTable.EPWM2_INT = &epwm3_isr;
        //EDIS;
    
        //
        //initialize the ePWM
        //
    
        EALLOW;
        CpuSysRegs.PCLKCR0.bit.TBCLKSYNC = 0;
        EDIS;
    
        EPWM_Init();
    
        EALLOW;
        CpuSysRegs.PCLKCR0.bit.TBCLKSYNC = 1;
        EDIS;
    
    
        //Initialize and Setup DRV
        resetDRV();
        GPIO_WritePin(59,0);    //set MCU LED low to turn on
        GPIO_WritePin(39,0);    //set DRVOFF low to enable device
    
    //    int i;
    //    for(i=0;i<30000;i++)
    //    {
    //        if (GpioDataRegs.GPBDAT.bit.GPIO35 == 1) //Once nFAULT goes low, device has completed power-up sequence
    //        {
    //            break;
    //        }
    //    }
        readAllRegisters();
    
        spi_write(0x03,0x03); //unlock SPI registers
    #ifdef PWM_3x_MODE
        spi_write(0x04,0x1C); //SLEW = 200V/us, PWM_MODE = 3x mode
    #endif
    
        //Testing
        //spi_write(0x0C, 0x19); //enable DLYCMP, DLY_TARGET = 2us
        //spi_write(0x07, 0x03); //set gain to 0.75V/A
        //spi_write(0x07, 0x04); //enable AAR, ILIM_RECIR = brake, gain = 0.15V/A
        //spi_write(0x07, 0x02); //enable ASR, ILIM_RECIR = brake, gain = 0.15V/A
        //spi_write(0x05, 0x00); //enable PWM_100_DUTY_SEL at 20kHz
        //spi_write(0x04, 0x02); //Enable 6x PWM w/ current limit
    
        clearFault(); //Clear faults command
    
        //Read All SPI Registers
        readAllRegisters();
    
        //Align
        /*
        Set_PWM(&epwm6_info, current_duty_cycle);
        Set_HS0_LS1(&epwm3_info);
        Set_HS0_LS1(&epwm3_info);
        for(i=0;i<30000;i++)
            {
    
            }
        */
    
        //Commutation Code and Settings
    
        pwmDutyCycle = 20.0;
        rampCounter = 0;
        pwmTrip = 0;
        accelDelay = 50;
    
        while(1)
        {
    
            if(nFAULT == 0)
            {
    //            FaultCounter++;
    //
    //            if(FaultCounter >= FaultLimit)
    //            {
    //                FaultCounter = 0;
    //                FaultLED = 1; //Fault has occurred
    //
    //                readStatusRegisters();
    //
    //                resetDRV();
    //                unlockSPI();
    //                clearFault();
    //
    //                readAllRegisters();
                //}
            }
    
            rampCounter++;
    
            if(rampCounter == accelDelay)
             {
               if(pwmTrip < (PWM_PERIOD * (pwmDutyCycle/100)))
               {
                   pwmTrip = pwmTrip + 1;
               }
               else if(pwmTrip > (PWM_PERIOD * (pwmDutyCycle/100)))
               {
                   pwmTrip = pwmTrip - 1;
               }
               rampCounter = 0;
             }
    
            current_duty_cycle = PWM_PERIOD - pwmTrip;
    
            //Check Hall Sensors
            //hall_read = ((GpioDataRegs.GPBDAT.bit.GPIO58 << 2) | (GpioDataRegs.GPADAT.bit.GPIO30 << 1) | (GpioDataRegs.GPADAT.bit.GPIO0 << 0));	//Rev 1
            hall_read = ((GpioDataRegs.GPBDAT.bit.GPIO58 << 2) | (GpioDataRegs.GPADAT.bit.GPIO30 << 1) | (GpioDataRegs.GPBDAT.bit.GPIO40 << 0));	//Rev 2
    		hall_state = (hall_read^0xF)&0x7;
            if (hall_state)
            {
    #ifdef PWM_6x_MODE
                switch(hall_state)
                {
                case 1:
                    //B-C
                    Set_HS0_LS0(&epwm6_info);
                    Set_PWM(&epwm5_info, current_duty_cycle);
                    Set_HS0_LS1(&epwm3_info);
                    break;
                case 2:
                    //A-C
                    Set_PWM(&epwm6_info, current_duty_cycle);
                    Set_HS0_LS1(&epwm5_info);
                    Set_HS0_LS0(&epwm3_info);
                    break;
                case 3:
                    //A-B
                    Set_PWM(&epwm6_info, current_duty_cycle);
                    Set_HS0_LS0(&epwm5_info);
                    Set_HS0_LS1(&epwm3_info);
                    break;
                case 4:
                    //C-B
                    Set_HS0_LS1(&epwm6_info);
                    Set_HS0_LS0(&epwm5_info);
                    Set_PWM(&epwm3_info, current_duty_cycle);
                    break;
                case 5:
                    //C-A
                    Set_HS0_LS1(&epwm6_info);
                    Set_PWM(&epwm5_info, current_duty_cycle);
                    Set_HS0_LS0(&epwm3_info);
                    break;
                case 6:
                    //B-A
                    Set_HS0_LS0(&epwm6_info);
                    Set_HS0_LS1(&epwm5_info);
                    Set_PWM(&epwm3_info, current_duty_cycle);
                    break;
                } //end of switch
    #endif
    
    #ifdef PWM_3x_MODE
                switch(hall_state)
                {
                case 1:
                    //B-C
                    Set_HS0_LS0(&epwm6_info, 'A');
                    Set_PWM(&epwm5_info, 'B', current_duty_cycle);
                    Set_HS0_LS1(&epwm3_info, 'C');
                    break;
                case 2:
                    //A-C
                    Set_PWM(&epwm6_info, 'A', current_duty_cycle);
                    Set_HS0_LS1(&epwm5_info, 'B');
                    Set_HS0_LS0(&epwm3_info, 'C');
                    break;
                case 3:
                    //A-B
                    Set_PWM(&epwm6_info, 'A', current_duty_cycle);
                    Set_HS0_LS0(&epwm5_info, 'B');
                    Set_HS0_LS1(&epwm3_info, 'C');
                    break;
                case 4:
                    //C-B
                    Set_HS0_LS1(&epwm6_info, 'A');
                    Set_HS0_LS0(&epwm5_info, 'B');
                    Set_PWM(&epwm3_info, 'C', current_duty_cycle);
                    break;
                case 5:
                    //C-A
                    Set_HS0_LS1(&epwm6_info, 'A');
                    Set_PWM(&epwm5_info, 'B', current_duty_cycle);
                    Set_HS0_LS0(&epwm3_info, 'C');
                    break;
                case 6:
                    //B-A
                    Set_HS0_LS0(&epwm6_info, 'A');
                    Set_HS0_LS1(&epwm5_info, 'B');
                    Set_PWM(&epwm3_info, 'C', current_duty_cycle);
                    break;
                } //end of switch
    #endif
            } //end of if
    
    
            //real time SPI reads and writes
            if (spiWrite)
            {
                spi_write(spi_addr,spi_data);
                spiWrite = false;
            }
    
            if (spiRead)
            {
                spi_data = spi_read(spi_addr);
                spiRead = false;
            }
    
            if (spiReadAll)
            {
                readAllRegisters();
                spiReadAll = false;
            }
    
            if (clear_fault)
            {
                clearFault();
                clear_fault = false;
            }
    
        } //end of while
    }
    
    //
    // DRV_InitGpio - Initialize the GPIOs on launchpad and boosterpack
    //
    void DRV_InitGpioInput()
    {
        EALLOW; // below registers are "protected", allow access.
        // GPIO DRV Hall A
        GPIO_SetupPinMux(58, GPIO_MUX_CPU1, 0);
        GPIO_SetupPinOptions(58, GPIO_INPUT, 0);
    
        // GPIO DRV Hall B
        GPIO_SetupPinMux(30, GPIO_MUX_CPU1, 0);
        GPIO_SetupPinOptions(30, GPIO_INPUT, 0);
    
        // GPIO DRV Hall C (Rev 1)
        //GPIO_SetupPinMux(0, GPIO_MUX_CPU1, 0);
        //GPIO_SetupPinOptions(0, GPIO_INPUT, 0);
    	
    	// GPIO DRV Hall C (Rev 2)
        GPIO_SetupPinMux(40, GPIO_MUX_CPU1, 0);
        GPIO_SetupPinOptions(40, GPIO_INPUT, 0);
    
        // nFAULT
        GPIO_SetupPinMux(35, GPIO_MUX_CPU1, 0);
        GPIO_SetupPinOptions(35, GPIO_INPUT, GPIO_PULLUP);
    
        EDIS;
        // Disable register access
    }
    
    void DRV_InitGpioOutput()
    {
        EALLOW;
    
        //INHA DRV
        GpioCtrlRegs.GPADIR.bit.GPIO10 = 1;
        GpioCtrlRegs.GPAPUD.bit.GPIO10 = 1;    // Disable pull-up on GPIO10 (EPWM6A)
        GpioCtrlRegs.GPAMUX1.bit.GPIO10 = 1;   // Configure GPIO10 as EPWM6A
        //INHB DRV
        GpioCtrlRegs.GPADIR.bit.GPIO8 = 1;
        GpioCtrlRegs.GPAPUD.bit.GPIO8 = 1;
        GpioCtrlRegs.GPAMUX1.bit.GPIO8 = 1;
        //INHC DRV
        GpioCtrlRegs.GPADIR.bit.GPIO4 = 1;
        GpioCtrlRegs.GPAPUD.bit.GPIO4 = 1;
        GpioCtrlRegs.GPAMUX1.bit.GPIO4 = 1;
    
    #ifdef PWM_6x_MODE
        //INLA DRV
        GpioCtrlRegs.GPADIR.bit.GPIO11 = 1;
        GpioCtrlRegs.GPAPUD.bit.GPIO11 = 1;    //...
        GpioCtrlRegs.GPAMUX1.bit.GPIO11 = 1;
        //INLB DRV
        GpioCtrlRegs.GPADIR.bit.GPIO9 = 1;
        GpioCtrlRegs.GPAPUD.bit.GPIO9 = 1;
        GpioCtrlRegs.GPAMUX1.bit.GPIO9 = 1;
        //INLC DRV
        GpioCtrlRegs.GPADIR.bit.GPIO5 = 1;
        GpioCtrlRegs.GPAPUD.bit.GPIO5 = 1;
        GpioCtrlRegs.GPAMUX1.bit.GPIO5 = 1;
    #endif
    #ifdef PWM_3x_MODE
        //INLA
        GPIO_SetupPinMux(INLA, GPIO_MUX_CPU1, 0);
        GPIO_SetupPinOptions(INLA, GPIO_OUTPUT, GPIO_PUSHPULL);
        GPIO_WritePin(INLA,0);
    
        //INLB
        GPIO_SetupPinMux(INLB, GPIO_MUX_CPU1, 0);
        GPIO_SetupPinOptions(INLB, GPIO_OUTPUT, GPIO_PUSHPULL);
        GPIO_WritePin(INLB,0);
    
        //INLC
        GPIO_SetupPinMux(INLC, GPIO_MUX_CPU1, 0);
        GPIO_SetupPinOptions(INLC, GPIO_OUTPUT, GPIO_PUSHPULL);
        GPIO_WritePin(INLC,0);
    #endif
    
        //MCU LED
        GPIO_SetupPinMux(59, GPIO_MUX_CPU1, 0);
        GPIO_SetupPinOptions(59, GPIO_OUTPUT, GPIO_PUSHPULL);
    
        //nSLEEP
        GPIO_SetupPinMux(37, GPIO_MUX_CPU1, 0);
        GPIO_SetupPinOptions(37, GPIO_OUTPUT, GPIO_PUSHPULL);
        GPIO_WritePin(37,1);
    
        //DRVOFF
        GPIO_SetupPinMux(39, GPIO_MUX_CPU1, 0);
        GPIO_SetupPinOptions(39, GPIO_OUTPUT, GPIO_PUSHPULL);
    
        EDIS;
    }
    
    #ifdef PWM_3x_MODE
    void EPWM_Init()
    {
        //
        // enable PWM6, PWM5 and PWM3
        //
        CpuSysRegs.PCLKCR2.bit.EPWM6=1;
        CpuSysRegs.PCLKCR2.bit.EPWM5=1;
        CpuSysRegs.PCLKCR2.bit.EPWM3=1;
        //
        // Setup TBCLK
        //
        EPwm6Regs.TBPRD = PWM_PERIOD;                // Set timer period 16000 TBCLKs
        EPwm6Regs.TBPHS.bit.TBPHS = 0x0000;          // Phase is 0
        EPwm6Regs.TBCTR = 0x0000;                    // Clear counter
        EPwm5Regs.TBPRD = PWM_PERIOD;                // Set timer period 16000 TBCLKs
        EPwm5Regs.TBPHS.bit.TBPHS = 0x0000;          // Phase is 0
        EPwm5Regs.TBCTR = 0x0000;                    // Clear counter
        EPwm3Regs.TBPRD = PWM_PERIOD;                // Set timer period 16000 TBCLKs
        EPwm3Regs.TBPHS.bit.TBPHS = 0x0000;          // Phase is 0
        EPwm3Regs.TBCTR = 0x0000;                    // Clear counter
    
        //
        // Setup counter mode
        //
        EPwm6Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN;    // Count up/down
        EPwm6Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1;      // Clock ratio to SYSCLKOUT
        EPwm6Regs.TBCTL.bit.CLKDIV = TB_DIV1;
        EPwm5Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN;    // Count up/down
        EPwm5Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1;      // Clock ratio to SYSCLKOUT
        EPwm5Regs.TBCTL.bit.CLKDIV = TB_DIV1;
        EPwm3Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN;    // Count up/down
        EPwm3Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1;      // Clock ratio to SYSCLKOUT
        EPwm3Regs.TBCTL.bit.CLKDIV = TB_DIV1;
    
        //
        // Setup shadowing
        //
        EPwm6Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;
        EPwm6Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;
        EPwm6Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO; // Load on Zero
        EPwm6Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;
        EPwm5Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;
        EPwm5Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;
        EPwm5Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO; // Load on Zero
        EPwm5Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;
        EPwm3Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;
        EPwm3Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;
        EPwm3Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO; // Load on Zero
        EPwm3Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;
    
        EPwm6Regs.AQCTLA.bit.CAU = AQ_SET; // set actions for EPWM6A
        EPwm6Regs.AQCTLA.bit.CAD = AQ_CLEAR;
        EPwm6Regs.DBCTL.bit.OUT_MODE = DB_DISABLE; // enable Dead-band module
    
        EPwm5Regs.AQCTLA.bit.CAU = AQ_SET; // set actions for EPWM1A
        EPwm5Regs.AQCTLA.bit.CAD = AQ_CLEAR;
        EPwm5Regs.DBCTL.bit.OUT_MODE = DB_DISABLE; // enable Dead-band module
    
        EPwm3Regs.AQCTLA.bit.CAU = AQ_SET; // set actions for EPWM1A
        EPwm3Regs.AQCTLA.bit.CAD = AQ_CLEAR;
        EPwm3Regs.DBCTL.bit.OUT_MODE = DB_DISABLE; // enable Dead-band module
    
    
        //
        //Disable Interrupt
        //
        EPwm6Regs.ETSEL.bit.INTEN = 0;                // disable INT
        EPwm5Regs.ETSEL.bit.INTEN = 0;                // disable INT
        EPwm3Regs.ETSEL.bit.INTEN = 0;                // disable INT
    
    
        //Set Handles
        epwm6_info.EPwmRegHandle = &EPwm6Regs;
        epwm5_info.EPwmRegHandle = &EPwm5Regs;
        epwm3_info.EPwmRegHandle = &EPwm3Regs;
    
        //Set Initial Compare values to be counter + 1 so that low side gates turn on and stay on to charge HS bootstrap
        EPwm6Regs.CMPA.bit.CMPA = PWM_PERIOD + 1;
        EPwm5Regs.CMPA.bit.CMPA = PWM_PERIOD + 1;
        EPwm3Regs.CMPA.bit.CMPA = PWM_PERIOD + 1;
    }
    void Set_HS0_LS1(EPWM_INFO *epwm_info, char phase)
    {
        epwm_info->EPwmRegHandle->CMPA.bit.CMPA = (PWM_PERIOD + 1); // Set so PWM counter never trips, keeping high side off
        switch(phase)
        {
        case 'A':
            GPIO_WritePin(INLA,1);
            break;
        case 'B':
            GPIO_WritePin(INLB,1);
            break;
        case 'C':
            GPIO_WritePin(INLC,1);
            break;
        }
    
    }
    
    void Set_HS0_LS0(EPWM_INFO *epwm_info, char phase)
    {
        epwm_info->EPwmRegHandle->CMPA.bit.CMPA = (PWM_PERIOD + 1); // Set so PWM counter never trips, keeping high side off
        switch(phase)
        {
        case 'A':
            GPIO_WritePin(INLA,0);
            break;
        case 'B':
            GPIO_WritePin(INLB,0);
            break;
        case 'C':
            GPIO_WritePin(INLC,0);
            break;
        }
    }
    
    void Set_PWM(EPWM_INFO *epwm_info, char phase, int duty_cycle)
    {
        epwm_info->EPwmRegHandle->CMPA.bit.CMPA = duty_cycle;
        switch(phase)
        {
        case 'A':
            GPIO_WritePin(INLA,1);
            break;
        case 'B':
            GPIO_WritePin(INLB,1);
            break;
        case 'C':
            GPIO_WritePin(INLC,1);
            break;
        }
    }
    #endif
    #ifdef PWM_6x_MODE
    void EPWM_Init()
    {
        //
        // enable PWM6, PWM5 and PWM3
        //
        CpuSysRegs.PCLKCR2.bit.EPWM6=1;
        CpuSysRegs.PCLKCR2.bit.EPWM5=1;
        CpuSysRegs.PCLKCR2.bit.EPWM3=1;
        //
        // Setup TBCLK
        //
        EPwm6Regs.TBPRD = PWM_PERIOD;                // Set timer period 16000 TBCLKs
        EPwm6Regs.TBPHS.bit.TBPHS = 0x0000;          // Phase is 0
        EPwm6Regs.TBCTR = 0x0000;                    // Clear counter
        EPwm5Regs.TBPRD = PWM_PERIOD;                // Set timer period 16000 TBCLKs
        EPwm5Regs.TBPHS.bit.TBPHS = 0x0000;          // Phase is 0
        EPwm5Regs.TBCTR = 0x0000;                    // Clear counter
        EPwm3Regs.TBPRD = PWM_PERIOD;                // Set timer period 16000 TBCLKs
        EPwm3Regs.TBPHS.bit.TBPHS = 0x0000;          // Phase is 0
        EPwm3Regs.TBCTR = 0x0000;                    // Clear counter
    
        //
        // Setup counter mode
        //
        EPwm6Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN;    // Count up/down
        EPwm6Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1;      // Clock ratio to SYSCLKOUT
        EPwm6Regs.TBCTL.bit.CLKDIV = TB_DIV1;
        EPwm5Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN;    // Count up/down
        EPwm5Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1;      // Clock ratio to SYSCLKOUT
        EPwm5Regs.TBCTL.bit.CLKDIV = TB_DIV1;
        EPwm3Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN;    // Count up/down
        EPwm3Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1;      // Clock ratio to SYSCLKOUT
        EPwm3Regs.TBCTL.bit.CLKDIV = TB_DIV1;
    
        //
        // Setup shadowing
        //
        EPwm6Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;
        EPwm6Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;
        EPwm6Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO; // Load on Zero
        EPwm6Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;
        EPwm5Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;
        EPwm5Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;
        EPwm5Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO; // Load on Zero
        EPwm5Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;
        EPwm3Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;
        EPwm3Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;
        EPwm3Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO; // Load on Zero
        EPwm3Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;
    
        EPwm6Regs.AQCTLA.bit.CAU = AQ_SET; // set actions for EPWM1A
        EPwm6Regs.AQCTLA.bit.CAD = AQ_CLEAR;
        EPwm6Regs.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE; // enable Dead-band module
        EPwm6Regs.DBCTL.bit.POLSEL = DB_ACTV_HIC; // Active Hi complementary
        EPwm6Regs.DBFED.bit.DBFED = DEAD_TIME;
        EPwm6Regs.DBRED.bit.DBRED = DEAD_TIME;
        EPwm5Regs.AQCTLA.bit.CAU = AQ_SET; // set actions for EPWM1A
        EPwm5Regs.AQCTLA.bit.CAD = AQ_CLEAR;
        EPwm5Regs.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE; // enable Dead-band module
        EPwm5Regs.DBCTL.bit.POLSEL = DB_ACTV_HIC; // Active Hi complementary
        EPwm5Regs.DBFED.bit.DBFED = DEAD_TIME;
        EPwm5Regs.DBRED.bit.DBRED = DEAD_TIME;
        EPwm3Regs.AQCTLA.bit.CAU = AQ_SET; // set actions for EPWM1A
        EPwm3Regs.AQCTLA.bit.CAD = AQ_CLEAR;
        EPwm3Regs.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE; // enable Dead-band module
        EPwm3Regs.DBCTL.bit.POLSEL = DB_ACTV_HIC; // Active Hi complementary
        EPwm3Regs.DBFED.bit.DBFED = DEAD_TIME;
        EPwm3Regs.DBRED.bit.DBRED = DEAD_TIME;
    
        //
        //Disable Interrupt
        //
        EPwm6Regs.ETSEL.bit.INTEN = 0;                // disable INT
        EPwm5Regs.ETSEL.bit.INTEN = 0;                // disable INT
        EPwm3Regs.ETSEL.bit.INTEN = 0;                // disable INT
    
    
        //Set Handles
        epwm6_info.EPwmRegHandle = &EPwm6Regs;
        epwm5_info.EPwmRegHandle = &EPwm5Regs;
        epwm3_info.EPwmRegHandle = &EPwm3Regs;
    
        //Set Initial Compare values to be counter + 1 so that low side gates turn on and stay on to charge HS bootstrap
        EPwm6Regs.CMPA.bit.CMPA = PWM_PERIOD + 1;
        EPwm5Regs.CMPA.bit.CMPA = PWM_PERIOD + 1;
        EPwm3Regs.CMPA.bit.CMPA = PWM_PERIOD + 1;
    }
    void Set_HS0_LS1(EPWM_INFO *epwm_info)
    {
        epwm_info->EPwmRegHandle->DBCTL.bit.POLSEL = DB_ACTV_HIC;    //set to keep low side on
        epwm_info->EPwmRegHandle->CMPA.bit.CMPA = (PWM_PERIOD + 1); // Set so PWM counter never trips, keeping high side off
    }
    
    void Set_HS0_LS0(EPWM_INFO *epwm_info)
    {
        epwm_info->EPwmRegHandle->DBCTL.bit.POLSEL = DB_ACTV_HI;     //Set to keep low side off
        epwm_info->EPwmRegHandle->CMPA.bit.CMPA = (PWM_PERIOD + 1); // Set so PWM counter never trips, keeping high side off
    }
    
    void Set_PWM(EPWM_INFO *epwm_info, int duty_cycle)
    {
        epwm_info->EPwmRegHandle->DBCTL.bit.POLSEL = DB_ACTV_HIC;
        epwm_info->EPwmRegHandle->CMPA.bit.CMPA = duty_cycle;
    }
    #endif
    
    void Config_evm_spi(void)
    {
        //Pin Config
        EALLOW;
        // SPI_MOSI
        GPIO_SetupPinOptions(16, GPIO_INPUT, GPIO_ASYNC | GPIO_PULLUP);
        // SPI_MISO
        GPIO_SetupPinOptions(17, GPIO_INPUT, GPIO_ASYNC | GPIO_PULLUP);
        // SPI_CS
        GPIO_SetupPinOptions(56, GPIO_INPUT, GPIO_ASYNC | GPIO_PULLUP);
        // SPI_CLK
        GPIO_SetupPinOptions(57, GPIO_INPUT, GPIO_ASYNC | GPIO_PULLUP);
    
        GPIO_SetupPinMux(16, GPIO_MUX_CPU1, 1);
        GPIO_SetupPinMux(17, GPIO_MUX_CPU1, 1);
        GPIO_SetupPinMux(56, GPIO_MUX_CPU1, 1);
        GPIO_SetupPinMux(57, GPIO_MUX_CPU1, 1);
        EDIS;
    
        EALLOW;
        ClkCfgRegs.LOSPCP.all = 0;
        EDIS;
    
        // Initialize SPI FIFO registers
        SpiaRegs.SPIFFTX.all=0xE040;
        SpiaRegs.SPIFFRX.all=0x2044;
        SpiaRegs.SPIFFCT.all=0x0;
    
        //SPI Settings
        SpiaRegs.SPICCR.bit.SPISWRESET = 0;     //SPI Reset On
        SpiaRegs.SPICCR.bit.CLKPOLARITY = 0;    //SCLK Active High
        SpiaRegs.SPICCR.bit.SPICHAR = 0xF;      //16-bit SPI char
        SpiaRegs.SPICCR.bit.SPILBK = 0;
    
        SpiaRegs.SPICTL.bit.OVERRUNINTENA = 0;  //No overrun interrupt
        SpiaRegs.SPICTL.bit.CLK_PHASE = 0;      //Phase 0
        SpiaRegs.SPICTL.bit.MASTER_SLAVE = 1;   //Master mode
        SpiaRegs.SPICTL.bit.TALK = 1;           //nSCS enabled
        SpiaRegs.SPICTL.bit.SPIINTENA = 0;      //TX/RX Interrupt Disabled
    
        SpiaRegs.SPIBRR.bit.SPI_BIT_RATE = ((25000000 / 1000000) - 1);              //Set baud rate to 1MHz
        SpiaRegs.SPIPRI.bit.FREE = 1;           //Set so breakpoints don't disturb transmission
        SpiaRegs.SPICCR.bit.SPISWRESET = 1;   //Exit SPI reset
    
    }
    
    Uint16 spi_xmit(Uint16 spiFrame)
    {
        SpiaRegs.SPITXBUF=spiFrame;
    
        //Wait for RX flag to indicate SPI frame completion
        while(SpiaRegs.SPIFFRX.bit.RXFFST != 1)
        {
        }
    
        return SpiaRegs.SPIRXBUF;
    }
    
    Uint16 spi_read(Uint16 addr)
    {
        Uint16 commandword = 0;
        uint16_t p_addr = addr;
        uint16_t p_data = 0;
    
        uint16_t calc = ((p_addr << 9) & 0x7E00) | (p_data & 0x00FF);
        uint16_t parity = 0;
        while(calc)
        {
           parity ^= (calc & 1);
           calc >>= 1;
        }
    
        commandword = (0x8000 | (addr << 9) | (parity << 8));
        return spi_xmit(commandword);
    }
    
    Uint16 spi_write(Uint16 addr, Uint16 data)
    {
        Uint16 commandword = 0;
        uint16_t p_addr = addr;
        uint16_t p_data = data;
    
        uint16_t calc = ((p_addr << 9) & 0x7E00) | (p_data & 0x00FF);
        uint16_t parity = 0;
        while(calc)
        {
           parity ^= (calc & 1);
           calc >>= 1;
        }
    
        commandword = ((addr << 9) | (parity << 8) | data);
        return spi_xmit(commandword);
    }
    
    
    
    void clearFault(void){
        Uint16 temp = spi_read(0x04);
        temp |= 0x01;
        spi_write(0x04, temp);
    }
    
    void resetDRV(void){    //set nSLEEP low for 100us
        GPIO_WritePin(nSLEEP,0);
        int i;
        for(i=0;i<10000;i++);
        GPIO_WritePin(nSLEEP,1);
    }
    
    void unlockSPI(void){
        spi_write(0x03, 0x03); //unlock SPI
    }
    
    void readAllRegisters(void){
        drv8316regs.IC_STAT = spi_read(0x00) & 0xFF;
        drv8316regs.STAT1 = spi_read(0x01) & 0xFF;
        drv8316regs.STAT2 = spi_read(0x02) & 0xFF;
        drv8316regs.CTRL1 = spi_read(0x03) & 0xFF;
        drv8316regs.CTRL2 = spi_read(0x04) & 0xFF;
        drv8316regs.CTRL3 = spi_read(0x05) & 0xFF;
        drv8316regs.CTRL4 = spi_read(0x06) & 0xFF;
        drv8316regs.CTRL5 = spi_read(0x07) & 0xFF;
        drv8316regs.CTRL6 = spi_read(0x08) & 0xFF;
        drv8316regs.CTRL10 = spi_read(0x0C) & 0xFF;
    }
    
    void readStatusRegisters(void){
        drv8316regs.IC_STAT = spi_read(0x00) & 0xFF;
        drv8316regs.STAT1 = spi_read(0x01) & 0xFF;
        drv8316regs.STAT2 = spi_read(0x02) & 0xFF;
    }
    
    //
    // error - Halt debugger when called
    //
    void error(void)
    {
        ESTOP0;         // Stop here and handle error
    }
    
    
    //
    // End of file
    //
    
    

    //#############################################################################
    //
    // FILE:   DRV8316_Sensored.c
    //
    // TITLE:  FSK Transmitter using PWM mode on the AFE031
    //
    
    //! \addtogroup cpu01_example_list
    //! <h1> FSK Transmitter using PWM mode on the AFE031 </h1>
    //!
    //! This example sets up the F280049C Launchpad with the DRV8316REVM.
    //!
    //! \b External \b Connections \n
    //!  - Remove JP1, JP2, and JP3 headers on F280049C Launchpad
    //!  - Connect the DRV8316REVM boosterpack to the upper F280049C
    //!    Launchpad pins
    //!  - Supply VM power via upper right most jumpers
    //!
    //! \b Watch \b Variables \n
    //!  - pwmDutyCycle
    //!  -
    //!  -
    //!
    //
    //###########################################################################
    // $TI Release: F28004x Support Library v1.08.00.00 $
    // $Release Date: Mon Dec 23 17:24:05 IST 2019 $
    // $Copyright:
    // Copyright (C) 2019 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.
    // $
    //###########################################################################
    
    //
    // Included Files
    //
    #include "F28x_Project.h"     // Device Header file and Examples Include File
    #include "SFO_V8.h"
    
    //
    // Defines
    //
    #define PWM_PERIOD   2500
    //2500 for 20kHz
    //1000 for 50kHz
    
    // Period register
    #define DEAD_TIME      0// results in a deadtime of 500ns @20kHz
    #define nFAULT GpioDataRegs.GPBDAT.bit.GPIO35
    #define nSLEEP 37
    #define HALLA 58
    #define HALLB 30
    #define HALLC 0
    #define DRVOFF 39
    
    //
    // Typedef
    //
    typedef struct
    {
        volatile struct EPWM_REGS *EPwmRegHandle;
    } EPWM_INFO;
    
    //
    // Globals
    //
    float pwmDutyCycle;
    int pwmTrip;
    int current_duty_cycle;
    int rampCounter;
    int accelDelay;
    int hall_state;
    int hall_read;
    EPWM_INFO epwm6_info;
    EPWM_INFO epwm5_info;
    EPWM_INFO epwm3_info;
    
    bool OutputEnable = 1;
    bool FaultLED = 0;
    bool FAULT_BIT = 0;
    bool resetFault = 0;
    Uint16 FaultCounter = 0;
    Uint16 FaultLimit = 10;
    
    bool spiWrite = false;
    bool spiRead = false;
    bool spiReadAll = false;
    bool clear_fault = false;
    Uint16 spi_addr = 0;
    Uint16 spi_data = 0;
    
    
    //Global Status Regs
    struct drv8316regs{
        Uint16 IC_STAT;
        Uint16 STAT1;
        Uint16 STAT2;
        Uint16 CTRL1;
        Uint16 CTRL2;
        Uint16 CTRL3;
        Uint16 CTRL4;
        Uint16 CTRL5;
        Uint16 CTRL6;
        Uint16 CTRL10;
    } drv8316regs;
    
    //
    // Function Prototypes
    //
    void DRV_InitGpio(void);
    void DRV_InitGpioInput(void);
    void DRV_InitGpioOutput(void);
    void Config_evm_spi(void);
    Uint16 spi_xmit(Uint16 spiFrame);
    Uint16 spi_write(Uint16 addr, Uint16 data);
    Uint16 spi_read(Uint16 addr);
    void EPWM_Init(void);
    void error (void);
    void Set_HS0_LS1(EPWM_INFO *epwm_info);
    void Set_HS0_LS0(EPWM_INFO *epwm_info);
    void Set_PWM(EPWM_INFO *epwm_info, int duty_cycle);
    
    void clearFault(void);
    void unlockSPI(void);
    void resetDRV(void);
    void readStatusRegisters(void);
    void readAllRegisters(void);
    
    void main(void)
    {
        //
        // Initialize System Control:
        // PLL, WatchDog, enable Peripheral Clocks
        //
        InitSysCtrl();
    
        //
        // Initialize GPIO:
        // These GPIOs control LEDs, AFE GPIOS.
        //
        InitGpio();
        DRV_InitGpioInput();
        DRV_InitGpioOutput();
    
        //
        // Initialize SPI
        //
        Config_evm_spi();
        readAllRegisters();
    
        //
        // Initialize PIE vector table:
        //
        //DINT;
    
        //
        // Initialize PIE control registers to their default state:
        //
        //InitPieCtrl();
    
        // Disable and clear all CPU interrupts
        IER = 0x0000;
        IFR = 0x0000;
    
        //
        // Initialize the PIE vector table with pointers to the shell Interrupt
        // Service Routines (ISR).
        // This will populate the entire table, even if the interrupt
        // is not used in this example.  This is useful for debug purposes.
        //
        //InitPieVectTable();
    
        //
        // Interrupts that are used in this example are re-mapped to
        // ISR functions found within this file.
        //
        //EALLOW;
        //PieVectTable.EPWM2_INT = &epwm3_isr;
        //EDIS;
    
        //
        //initialize the ePWM
        //
    
        EALLOW;
        CpuSysRegs.PCLKCR0.bit.TBCLKSYNC = 0;
        EDIS;
    
        EPWM_Init();
    
        EALLOW;
        CpuSysRegs.PCLKCR0.bit.TBCLKSYNC = 1;
        EDIS;
    
    
        //Initialize and Setup DRV
        resetDRV();
        GPIO_WritePin(59,0);    //set MCU LED low to turn on
        GPIO_WritePin(39,0);    //set DRVOFF low to enable device
    
    //    int i;
    //    for(i=0;i<30000;i++)
    //    {
    //        if (GpioDataRegs.GPBDAT.bit.GPIO35 == 1) //Once nFAULT goes low, device has completed power-up sequence
    //        {
    //            break;
    //        }
    //    }
        spi_write(0x03,0x03); //unlock SPI registers
        clearFault(); //Clear faults command
    
        //Read All SPI Registers
        readAllRegisters();
    
        //Commutation Code and Settings
        pwmDutyCycle = 20.0;
        rampCounter = 0;
        pwmTrip = 0;
        accelDelay = 50;
    
        while(1)
        {
    
            if(nFAULT == 0)
            {
    //            FaultCounter++;
    //
    //            if(FaultCounter >= FaultLimit)
    //            {
    //                FaultCounter = 0;
    //                FaultLED = 1; //Fault has occurred
    //
    //                readStatusRegisters();
    //
    //                resetDRV();
    //                unlockSPI();
    //                clearFault();
    //
    //                readAllRegisters();
                //}
            }
    
            rampCounter++;
    
            if(rampCounter == accelDelay)
             {
               if(pwmTrip < (PWM_PERIOD * (pwmDutyCycle/100)))
               {
                   pwmTrip = pwmTrip + 1;
               }
               else if(pwmTrip > (PWM_PERIOD * (pwmDutyCycle/100)))
               {
                   pwmTrip = pwmTrip - 1;
               }
               rampCounter = 0;
             }
    
            current_duty_cycle = PWM_PERIOD - pwmTrip;
    
            //Check Hall Sensors
            /*
            //hall_read = ((GpioDataRegs.GPBDAT.bit.GPIO58 << 2) | (GpioDataRegs.GPADAT.bit.GPIO30 << 1) | (GpioDataRegs.GPADAT.bit.GPIO0 << 0));	//Rev 1
            hall_read = ((GpioDataRegs.GPBDAT.bit.GPIO58 << 2) | (GpioDataRegs.GPADAT.bit.GPIO30 << 1) | (GpioDataRegs.GPBDAT.bit.GPIO40 << 0));	//Rev 2
            hall_state = (hall_read^0xF)&0x7;
            if (hall_state)
            {
                switch(hall_state)
                {
                case 1:
                    //B-C
                    Set_HS0_LS0(&epwm6_info);
                    Set_PWM(&epwm5_info, current_duty_cycle);
                    Set_HS0_LS1(&epwm3_info);
                    break;
                case 2:
                    //A-C
                    Set_PWM(&epwm6_info, current_duty_cycle);
                    Set_HS0_LS1(&epwm5_info);
                    Set_HS0_LS0(&epwm3_info);
                    break;
                case 3:
                    //A-B
                    Set_PWM(&epwm6_info, current_duty_cycle);
                    Set_HS0_LS0(&epwm5_info);
                    Set_HS0_LS1(&epwm3_info);
                    break;
                case 4:
                    //C-B
                    Set_HS0_LS1(&epwm6_info);
                    Set_HS0_LS0(&epwm5_info);
                    Set_PWM(&epwm3_info, current_duty_cycle);
                    break;
                case 5:
                    //C-A
                    Set_HS0_LS1(&epwm6_info);
                    Set_PWM(&epwm5_info, current_duty_cycle);
                    Set_HS0_LS0(&epwm3_info);
                    break;
                case 6:
                    //B-A
                    Set_HS0_LS0(&epwm6_info);
                    Set_HS0_LS1(&epwm5_info);
                    Set_PWM(&epwm3_info, current_duty_cycle);
                    break;
                } //end of switch
            } //end of if
    */
    
            //real time SPI reads and writes
            if (spiWrite)
            {
                spi_write(spi_addr,spi_data);
                spiWrite = false;
            }
    
            if (spiRead)
            {
                spi_data = spi_read(spi_addr);
                spiRead = false;
            }
    
            if (spiReadAll)
            {
                readAllRegisters();
                spiReadAll = false;
            }
    
            if (clear_fault)
            {
                clearFault();
                clear_fault = false;
            }
    
        } //end of while
    }
    
    //
    // DRV_InitGpio - Initialize the GPIOs on launchpad and boosterpack
    //
    void DRV_InitGpioInput()
    {
        EALLOW; // below registers are "protected", allow access.
        // GPIO DRV Hall A
        GPIO_SetupPinMux(58, GPIO_MUX_CPU1, 0);
        GPIO_SetupPinOptions(58, GPIO_INPUT, 0);
    
        // GPIO DRV Hall B
        GPIO_SetupPinMux(30, GPIO_MUX_CPU1, 0);
        GPIO_SetupPinOptions(30, GPIO_INPUT, 0);
    
        // GPIO DRV Hall C (Rev 1)
        //GPIO_SetupPinMux(0, GPIO_MUX_CPU1, 0);
        //GPIO_SetupPinOptions(0, GPIO_INPUT, 0);
    	
    	// GPIO DRV Hall C (Rev 2)
        GPIO_SetupPinMux(40, GPIO_MUX_CPU1, 0);
        GPIO_SetupPinOptions(40, GPIO_INPUT, 0);
    
        // nFAULT
        GPIO_SetupPinMux(35, GPIO_MUX_CPU1, 0);
        GPIO_SetupPinOptions(35, GPIO_INPUT, GPIO_PULLUP);
    
        EDIS;
        // Disable register access
    }
    
    void DRV_InitGpioOutput()
    {
        EALLOW;
    
        //INHA DRV
        GpioCtrlRegs.GPADIR.bit.GPIO10 = 1;
        GpioCtrlRegs.GPAPUD.bit.GPIO10 = 1;    // Disable pull-up on GPIO10 (EPWM6A)
        GpioCtrlRegs.GPAMUX1.bit.GPIO10 = 1;   // Configure GPIO10 as EPWM6A
        //INLA DRV
        GpioCtrlRegs.GPADIR.bit.GPIO11 = 1;
        GpioCtrlRegs.GPAPUD.bit.GPIO11 = 1;    //...
        GpioCtrlRegs.GPAMUX1.bit.GPIO11 = 1;
        //INHB DRV
        GpioCtrlRegs.GPADIR.bit.GPIO8 = 1;
        GpioCtrlRegs.GPAPUD.bit.GPIO8 = 1;
        GpioCtrlRegs.GPAMUX1.bit.GPIO8 = 1;
        //INLB DRV
        GpioCtrlRegs.GPADIR.bit.GPIO9 = 1;
        GpioCtrlRegs.GPAPUD.bit.GPIO9 = 1;
        GpioCtrlRegs.GPAMUX1.bit.GPIO9 = 1;
        //INHC DRV
        GpioCtrlRegs.GPADIR.bit.GPIO4 = 1;
        GpioCtrlRegs.GPAPUD.bit.GPIO4 = 1;
        GpioCtrlRegs.GPAMUX1.bit.GPIO4 = 1;
        //INLC DRV
        GpioCtrlRegs.GPADIR.bit.GPIO5 = 1;
        GpioCtrlRegs.GPAPUD.bit.GPIO5 = 1;
        GpioCtrlRegs.GPAMUX1.bit.GPIO5 = 1;
    
        //MCU LED
        GPIO_SetupPinMux(59, GPIO_MUX_CPU1, 0);
        GPIO_SetupPinOptions(59, GPIO_OUTPUT, GPIO_PUSHPULL);
    
        //nSLEEP
        GPIO_SetupPinMux(37, GPIO_MUX_CPU1, 0);
        GPIO_SetupPinOptions(37, GPIO_OUTPUT, GPIO_PUSHPULL);
        GPIO_WritePin(37,1);
    
        //DRVOFF
        GPIO_SetupPinMux(39, GPIO_MUX_CPU1, 0);
        GPIO_SetupPinOptions(39, GPIO_OUTPUT, GPIO_PUSHPULL);
    
        //nSCS
        GPIO_SetupPinMux(13, GPIO_MUX_CPU1, 0);
        GPIO_SetupPinOptions(13,GPIO_OUTPUT, GPIO_PUSHPULL);
        GPIO_WritePin(13,1);
    
        EDIS;
    }
    
    //
    // EPWM_Init - Initialize EPWM configuration
    //
    void EPWM_Init()
    {
        //
        // enable PWM6, PWM5 and PWM3
        //
        CpuSysRegs.PCLKCR2.bit.EPWM6=1;
        CpuSysRegs.PCLKCR2.bit.EPWM5=1;
        CpuSysRegs.PCLKCR2.bit.EPWM3=1;
        //
        // Setup TBCLK
        //
        EPwm6Regs.TBPRD = PWM_PERIOD;                // Set timer period 16000 TBCLKs
        EPwm6Regs.TBPHS.bit.TBPHS = 0x0000;          // Phase is 0
        EPwm6Regs.TBCTR = 0x0000;                    // Clear counter
        EPwm5Regs.TBPRD = PWM_PERIOD;                // Set timer period 16000 TBCLKs
        EPwm5Regs.TBPHS.bit.TBPHS = 0x0000;          // Phase is 0
        EPwm5Regs.TBCTR = 0x0000;                    // Clear counter
        EPwm3Regs.TBPRD = PWM_PERIOD;                // Set timer period 16000 TBCLKs
        EPwm3Regs.TBPHS.bit.TBPHS = 0x0000;          // Phase is 0
        EPwm3Regs.TBCTR = 0x0000;                    // Clear counter
    
        //
        // Setup counter mode
        //
        EPwm6Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN;    // Count up/down
        EPwm6Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1;      // Clock ratio to SYSCLKOUT
        EPwm6Regs.TBCTL.bit.CLKDIV = TB_DIV1;
        EPwm5Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN;    // Count up/down
        EPwm5Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1;      // Clock ratio to SYSCLKOUT
        EPwm5Regs.TBCTL.bit.CLKDIV = TB_DIV1;
        EPwm3Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN;    // Count up/down
        EPwm3Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1;      // Clock ratio to SYSCLKOUT
        EPwm3Regs.TBCTL.bit.CLKDIV = TB_DIV1;
    
        //
        // Setup shadowing
        //
        EPwm6Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;
        EPwm6Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;
        EPwm6Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO; // Load on Zero
        EPwm6Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;
        EPwm5Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;
        EPwm5Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;
        EPwm5Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO; // Load on Zero
        EPwm5Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;
        EPwm3Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;
        EPwm3Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;
        EPwm3Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO; // Load on Zero
        EPwm3Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;
    
        EPwm6Regs.AQCTLA.bit.CAU = AQ_SET; // set actions for EPWM1A
        EPwm6Regs.AQCTLA.bit.CAD = AQ_CLEAR;
        EPwm6Regs.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE; // enable Dead-band module
        EPwm6Regs.DBCTL.bit.POLSEL = DB_ACTV_HIC; // Active Hi complementary
        EPwm6Regs.DBFED.bit.DBFED = DEAD_TIME;
        EPwm6Regs.DBRED.bit.DBRED = DEAD_TIME;
        EPwm5Regs.AQCTLA.bit.CAU = AQ_SET; // set actions for EPWM1A
        EPwm5Regs.AQCTLA.bit.CAD = AQ_CLEAR;
        EPwm5Regs.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE; // enable Dead-band module
        EPwm5Regs.DBCTL.bit.POLSEL = DB_ACTV_HIC; // Active Hi complementary
        EPwm5Regs.DBFED.bit.DBFED = DEAD_TIME;
        EPwm5Regs.DBRED.bit.DBRED = DEAD_TIME;
        EPwm3Regs.AQCTLA.bit.CAU = AQ_SET; // set actions for EPWM1A
        EPwm3Regs.AQCTLA.bit.CAD = AQ_CLEAR;
        EPwm3Regs.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE; // enable Dead-band module
        EPwm3Regs.DBCTL.bit.POLSEL = DB_ACTV_HIC; // Active Hi complementary
        EPwm3Regs.DBFED.bit.DBFED = DEAD_TIME;
        EPwm3Regs.DBRED.bit.DBRED = DEAD_TIME;
    
        //
        //Disable Interrupt
        //
        EPwm6Regs.ETSEL.bit.INTEN = 0;                // disable INT
        EPwm5Regs.ETSEL.bit.INTEN = 0;                // disable INT
        EPwm3Regs.ETSEL.bit.INTEN = 0;                // disable INT
    
    
        //Set Handles
        epwm6_info.EPwmRegHandle = &EPwm6Regs;
        epwm5_info.EPwmRegHandle = &EPwm5Regs;
        epwm3_info.EPwmRegHandle = &EPwm3Regs;
    
        //Set Initial Compare values to be counter + 1 so that low side gates turn on and stay on to charge HS bootstrap
        EPwm6Regs.CMPA.bit.CMPA = PWM_PERIOD + 1;
        EPwm5Regs.CMPA.bit.CMPA = PWM_PERIOD + 1;
        EPwm3Regs.CMPA.bit.CMPA = PWM_PERIOD + 1;
    }
    void Set_HS0_LS1(EPWM_INFO *epwm_info)
    {
        epwm_info->EPwmRegHandle->DBCTL.bit.POLSEL = DB_ACTV_HIC;    //set to keep low side on
        epwm_info->EPwmRegHandle->CMPA.bit.CMPA = (PWM_PERIOD + 1); // Set so PWM counter never trips, keeping high side off
    }
    
    void Set_HS0_LS0(EPWM_INFO *epwm_info)
    {
        epwm_info->EPwmRegHandle->DBCTL.bit.POLSEL = DB_ACTV_HI;     //Set to keep low side off
        epwm_info->EPwmRegHandle->CMPA.bit.CMPA = (PWM_PERIOD + 1); // Set so PWM counter never trips, keeping high side off
    }
    
    void Set_PWM(EPWM_INFO *epwm_info, int duty_cycle)
    {
        epwm_info->EPwmRegHandle->DBCTL.bit.POLSEL = DB_ACTV_HIC;
        epwm_info->EPwmRegHandle->CMPA.bit.CMPA = duty_cycle;
    }
    
    void Config_evm_spi(void)
    {
        //Pin Config
        EALLOW;
        // SPI_MOSI
        GPIO_SetupPinOptions(16, GPIO_INPUT, GPIO_ASYNC | GPIO_PULLUP);
        // SPI_MISO
        GPIO_SetupPinOptions(17, GPIO_INPUT, GPIO_ASYNC | GPIO_PULLUP);
        // SPI_CLK
        GPIO_SetupPinOptions(56, GPIO_INPUT, GPIO_ASYNC | GPIO_PULLUP);
        // SPI_CS
        GPIO_SetupPinOptions(57, GPIO_INPUT, GPIO_ASYNC | GPIO_PULLUP);
    
        GPIO_SetupPinMux(16, GPIO_MUX_CPU1, 1);
        GPIO_SetupPinMux(17, GPIO_MUX_CPU1, 1);
        GPIO_SetupPinMux(56, GPIO_MUX_CPU1, 1);
        GPIO_SetupPinMux(57, GPIO_MUX_CPU1, 1);
        EDIS;
    
        EALLOW;
        ClkCfgRegs.LOSPCP.all = 0;
        EDIS;
    
        // Initialize SPI FIFO registers
        SpiaRegs.SPIFFTX.all=0xE040;
        SpiaRegs.SPIFFRX.all=0x2044;
        SpiaRegs.SPIFFCT.all=0x0;
    
        //SPI Settings
        SpiaRegs.SPICCR.bit.SPISWRESET = 0;     //SPI Reset On
        SpiaRegs.SPICCR.bit.CLKPOLARITY = 0;    //SCLK Active High
        SpiaRegs.SPICCR.bit.SPICHAR = 0xF;      //16-bit SPI char
        SpiaRegs.SPICCR.bit.SPILBK = 0;
    
        SpiaRegs.SPICTL.bit.OVERRUNINTENA = 0;  //No overrun interrupt
        SpiaRegs.SPICTL.bit.CLK_PHASE = 0;      //Phase 0
        SpiaRegs.SPICTL.bit.MASTER_SLAVE = 1;   //Master mode
        SpiaRegs.SPICTL.bit.TALK = 1;           //nSCS enabled
        SpiaRegs.SPICTL.bit.SPIINTENA = 0;      //TX/RX Interrupt Disabled
    
        SpiaRegs.SPIBRR.bit.SPI_BIT_RATE = ((25000000 / 1000000) - 1);              //Set baud rate to 1MHz
        SpiaRegs.SPIPRI.bit.FREE = 1;           //Set so breakpoints don't disturb transmission
        SpiaRegs.SPICCR.bit.SPISWRESET = 1;   //Exit SPI reset
    
    }
    
    Uint16 spi_xmit(Uint16 spiFrame)
    {
        SpiaRegs.SPITXBUF=spiFrame;
    
        //Wait for RX flag to indicate SPI frame completion
        while(SpiaRegs.SPIFFRX.bit.RXFFST != 1)
        {
        }
    
        return SpiaRegs.SPIRXBUF;
    }
    
    Uint16 spi_read(Uint16 addr)
    {
        Uint16 commandword = 0;
        uint16_t p_addr = addr;
        uint16_t p_data = 0;
    
        uint16_t calc = ((p_addr << 9) & 0x7E00) | (p_data & 0x00FF);
        uint16_t parity = 0;
        while(calc)
        {
           parity ^= (calc & 1);
           calc >>= 1;
        }
    
        commandword = (0x8000 | (addr << 9) | (parity << 8));
        return spi_xmit(commandword);
    }
    
    Uint16 spi_write(Uint16 addr, Uint16 data)
    {
        Uint16 commandword = 0;
        uint16_t p_addr = addr;
        uint16_t p_data = data;
    
        uint16_t calc = ((p_addr << 9) & 0x7E00) | (p_data & 0x00FF);
        uint16_t parity = 0;
        while(calc)
        {
           parity ^= (calc & 1);
           calc >>= 1;
        }
    
        commandword = ((addr << 9) | (parity << 8) | data);
        return spi_xmit(commandword);
    }
    
    void clearFault(void){
        Uint16 temp = spi_read(0x04);
        temp |= 0x01;
        spi_write(0x04, temp);
    }
    
    void resetDRV(void){    //set nSLEEP low for 100us
        GPIO_WritePin(nSLEEP,0);
        int i;
        for(i=0;i<10000;i++);
        GPIO_WritePin(nSLEEP,1);
    }
    
    void unlockSPI(void){
        spi_write(0x03, 0x03); //unlock SPI
    }
    
    void readAllRegisters(void){
        drv8316regs.IC_STAT = spi_read(0x00) & 0xFF;
        drv8316regs.STAT1 = spi_read(0x01) & 0xFF;
        drv8316regs.STAT2 = spi_read(0x02) & 0xFF;
        drv8316regs.CTRL1 = spi_read(0x03) & 0xFF;
        drv8316regs.CTRL2 = spi_read(0x04) & 0xFF;
        drv8316regs.CTRL3 = spi_read(0x05) & 0xFF;
        drv8316regs.CTRL4 = spi_read(0x06) & 0xFF;
        drv8316regs.CTRL5 = spi_read(0x07) & 0xFF;
        drv8316regs.CTRL6 = spi_read(0x08) & 0xFF;
        drv8316regs.CTRL10 = spi_read(0x0C) & 0xFF;
    }
    
    void readStatusRegisters(void){
        drv8316regs.IC_STAT = spi_read(0x00) & 0xFF;
        drv8316regs.STAT1 = spi_read(0x01) & 0xFF;
        drv8316regs.STAT2 = spi_read(0x02) & 0xFF;
    }
    
    //
    // error - Halt debugger when called
    //
    void error(void)
    {
        ESTOP0;         // Stop here and handle error
    }
    
    
    //
    // End of file
    //
    
    

    Regards,

    Yara

  • Hi Yara,

    Thank you for the quick response!

    I noticed that the code you provided includes a method called:

    void unlockSPI(void);

    I couldn’t find any explanation of this method or its functionality in the datasheet. Could you please clarify what this method does and provide more details about its purpose?, I cant read/write register until i unlock the register?

    Looking forward to your response!

    Best regards,

  • Hi Shahar,

    I’m not entirely sure if the registers by default are locked upon power up. I think this function in CCS is unlocking the registers just in case the device by default starts with them locked. Have you been able to successfully communicate with the device via SPI?

    Regards,

    Yara

  • Hi, I am encountering an issue with SPI communication while writing to the DRV8316R.

    I have implemented the following function for the SPI write operation:

    void DRV8316R_writeRegister(uint32_t spiBase, uint8_t address, uint8_t data)
    {
    uint16_t command = 0;

    // Construct the write command
    command |= (address << 9); // Address (bits 14-9)
    command |= (0 << 15); // Write bit (B15 = 0)
    command |= (data & 0xFF); // Data (bits 7-0)
    command |= DRV8316R_calculateParity(command) << 8; // Parity bit (B8)

    // Assert CS low
    // GPIO_writePin(g_csPin, 0);

    // Write the command to SPI
    SPI_writeDataBlockingNonFIFO(spiBase, command);

    // Wait for the SPI transaction to complete
    DEVICE_DELAY_US(1);

    // De-assert CS high
    // GPIO_writePin(g_csPin, 1);

    // Delay to meet nSCS high time requirement
    DEVICE_DELAY_US(1);
    }


    The problem arises as I receive the value 96 both before and after executing the write operation, suggesting that the write may not be taking effect. I suspect the issue might be related to the SPI configuration in the syscfg.

    Here is what I have verified so far:

    1. SPI settings are configured to Mode 0: polarity 0, phase 0 (data is sampled on the rising edge).
    2. Parity bit calculation is performed before adding it to the command.
    3. Delays are included to meet the timing requirements for the DRV8316R.

    Could the problem stem from a mismatch in the syscfg SPI settings or timing constraints that I might have overlooked? Additionally, is there a recommended debugging approach for verifying SPI transactions with the DRV8316R?

    Any insights or suggestions you could provide would be greatly appreciated.

    Thank you for your time and assistance!

    worth to mention i already try the external pull down on the SDO as mentioned here 

  • Hi Shahar,

    Typically for SPI debug I always think it’s helpful to look at your SPI communications with a logic analyzer if you have one. I also recommend to see if you can simply read all the registers after power up and see if the registers line up with the default values in the datasheet. If you’re not able to read back the default values then I’d say right off the bat there could be something wrong with how SPI is configured or how you’re reading the registers.

    if you could probe your SPI lines with some sort of analyzer that’d be super helpful, nSCS, SCLK, SDI, and SDO.

    You mentioned you tried an external pull down for SDO? SDO requires an external pull up.

    Regards,

    Yara

  • Hi,

    I have already tried using pull-up resistors and verified the signals with a scope. On the scope, both the read and write operations appear to function as expected, with the signals aligning correctly.

    However, despite this, the SPI write operation still does not take effect, and the values remain unchanged. I’ve also double-checked all the default values, and they are correct as per the documentation.

    Do you have any suggestions or insights into what might be causing this issue?

    Thank you!

  • Hi Shahar,

    I'm not sure where the issue lies. It could be with your SPI configuration or your write function? Seems like your read function is working since you mentioned you were able to read back the default values of every register correct? Are you able to provide screenshots of your successful read transactions and unsuccessful write transactions?

    You mentioned you are using one of our GUIs? But I can see you're using you're own code? Can you clarify which GUI you are using as there are multiple for this EVM? Have you tried any of the GUIs we have on dev.ti.com?

    Regards,

    Yara