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.

DSP2812控制板输出的PWM频率很低

各位老师好,我使用的是DSP2812板子,设置的PWM频率为20KHz,但是控制板输出的频率100Hz都达不到,如果复位后,直接会没有PWM信号输出。

这是什么原因?麻烦各位老师指导,谢谢老师了!!

  • 您好,
    我建议您先跑下TI的例程。
  • 老师,您好,很高兴收到您的回复。
    我用的是BLDC3-1例程,现在出现的问题是捕获端口捕获不到霍尔信号状态,没办法进行换相。程序一直进行的是f281xhall3中启动电机寄存器Stallcount的递增,直到0xFFFF后进行换相。
    您能帮我看看问题出在哪吗?万分感谢您!!
    下面是我的主程序和f281xhall3源程序:
    #include "DSP281x_Device.h" // DSP281x Headerfile Include File
    #include "DSPMotor_Head.h"

    #include "IQmathLib.h"
    #include "BLDCMotor.h"
    #include "parameter.h"
    #include "DSP281x_GlobalPrototypes.h"
    #include <math.h>
    ///// 函数声明 ////////////////////////////////////////////////////////////
    interrupt void MainISR(void);

    ///// 全局变量声明
    float32 SpeedRef = 0.5; // Speed reference (pu),0.5*BaseSpeed
    float32 T = 0.001/ISR_FREQUENCY; // Samping period (sec), see parameter.h
    Uint32 VirtualTimer = 0;
    Uint16 ILoopFlag = FALSE;
    Uint16 SpeedLoopFlag = FALSE;
    int16 DFuncDesired = 0xFA00; // Desired duty cycle (Q15)=0.2

    _iq CurrentSet = _IQ(0.3);

    Uint16 IsrTicker = 0;
    Uint16 BackTicker = 0;

    int16 DlogCh1 = 0;
    int16 DlogCh2 = 0;
    int16 DlogCh3 = 0;
    int16 DlogCh4 = 0;

    // Instance PID regulator to regulate the DC-bus current and speed
    PIDREG3 pid1_idc = PIDREG3_DEFAULTS;
    PIDREG3 pid1_spd = PIDREG3_DEFAULTS;

    // Instance a PWM driver instance
    PWMGEN pwm1 = PWMGEN_DEFAULTS;

    // Create an instance of the ADC driver
    ADCVALS adc1 = ADCVALS_DEFAULTS;

    // Instance a Hall effect driver
    HALL3 hall1 = HALL3_DEFAULTS;

    // Instance a ramp controller to smoothly ramp the frequency
    RMPCNTL rc1 = RMPCNTL_DEFAULTS;//where is rm_cntl_calc??,rc1 function??

    // Instance a RAMP2 Module
    RMP2 rmp2 = RMP2_DEFAULTS;//where is rmp2_cntl_calc??,rmp2 function??

    // Instance a MOD6 Module
    MOD6CNT mod1 = MOD6CNT_DEFAULTS;//mod6cnt_calc function??

    // Instance a SPEED_PR Module
    SPEED_MEAS_CAP speed1 = SPEED_MEAS_CAP_DEFAULTS;//speed_prd_calc where??

    // Create an instance of DATALOG Module
    DLOG_4CH dlog = DLOG_4CH_DEFAULTS;

    ////////////////////////// 主程序 //////////////////////////////////////////////

    void main(void)
    {

    // Initialize System Control registers, PLL, WatchDog, Clocks to default state:
    // This function is found in the DSP281x_SysCtrl.c file.
    InitSysCtrl();

    // HISPCP prescale register settings, normally it will be set to default values
    EALLOW; // This is needed to write to EALLOW protected registers
    SysCtrlRegs.HISPCP.all = 0x0000; // SYSCLKOUT/1
    EDIS; // This is needed to disable write to EALLOW protected registers

    // Disable and clear all CPU interrupts:
    DINT;
    IER = 0x0000;
    IFR = 0x0000;

    // Initialize Pie Control Registers To Default State:
    // This function is found in the DSP281x_PieCtrl.c file.
    InitPieCtrl();

    // Initialize the PIE Vector Table To a Known State:
    // This function is found in DSP281x_PieVect.c.
    // This function populates the PIE vector table with pointers
    // to the shell ISR functions found in DSP281x_DefaultIsr.c.
    InitPieVectTable();

    //EvaRegs.EVAIMRC.bit.CAP1INT=1;
    EvaRegs.EVAIFRC.bit.CAP1INT=1;
    //EvaRegs.EVAIMRC.bit.CAP2INT=1;
    EvaRegs.EVAIFRC.bit.CAP2INT=1;
    //EvaRegs.EVAIMRC.bit.CAP3INT=1;
    EvaRegs.EVAIFRC.bit.CAP3INT=1;

    // User specific functions, Reassign vectors (optional), Enable Interrupts:

    // Initialize EVA Timer 1/2:
    // Setup Timer 1/2 Registers (EV A)
    EvaRegs.GPTCONA.all = 0;

    // Set the Period for the GP timer 2
    EvaRegs.T2PR = SYSTEM_FREQUENCY*1000000*T; // Perscaler X1 (T2), ISR period = T x 1

    // Clear the counter/compare Regs for GP timer 2
    EvaRegs.T2CNT = 0x0000;
    EvaRegs.T2CMPR = 0x0000;

    // Enable Period interrupt bits for GP timer 2
    EvaRegs.EVAIMRB.bit.T2PINT = 1;
    EvaRegs.EVAIFRB.bit.T2PINT = 1;

    // Count up, x1, internal clk, disable compare, use own period
    EvaRegs.T2CON.all = 0x1040;//已经使能计数

    // Reassign ISRs.
    // Reassign the PIE vector for T2PINT to point to a different
    // ISR then the shell routine found in DSP281x_DefaultIsr.c.
    // This is done if the user does not want to use the shell ISR routine
    // but instead wants to use their own ISR.

    EALLOW; // This is needed to write to EALLOW protected registers
    PieVectTable.T2PINT = &MainISR;//
    EDIS; // This is needed to disable write to EALLOW protected registers

    // Enable PIE group 3 interrupt 1 for T2PINT
    PieCtrlRegs.PIEIER3.all = M_INT1;

    // Enable CPU INT3 for T2PINT:
    IER |= M_INT3;

    // Initialize PWM module
    pwm1.PeriodMax = (SYSTEM_FREQUENCY/PWM_FREQUENCY)*1000; // Asymmetric PWM
    pwm1.DutyFunc = DFuncDesired; // DutyFunc = Q15
    pwm1.init(&pwm1);

    // Initialize DATALOG module
    dlog.iptr1 = &DlogCh1;
    dlog.iptr2 = &DlogCh2;
    dlog.iptr3 = &DlogCh3;
    dlog.iptr4 = &DlogCh4;
    dlog.trig_value = 0x01;
    dlog.size = 0x400;
    dlog.prescalar = 1;
    dlog.init(&dlog);

    // Initialize ADC module
    adc1.ChSelect = 0x6543; // for DMC1500 and eZdsp2812/eZdsp2808 boards
    adc1.init(&adc1);

    // Initialize the SPEED_PR module (150 MHz, N = 1 event period/rev)
    speed1.InputSelect = 0;
    speed1.BaseRpm = 120*(BASE_FREQ/P);//120*f/极数
    speed1.SpeedScaler = (Uint32)(ISR_FREQUENCY/(1*BASE_FREQ*0.001));

    // Initialize RMPCNTL module
    rc1.RampDelayMax = 20;//
    rc1.RampLowLimit = _IQ(0);
    rc1.RampHighLimit = _IQ(1);

    // Initialize Hall module
    hall1.DebounceAmount = 5;
    hall1.Revolutions = -10;
    hall1.init(&hall1);
    mod1.Counter = Counter;
    // Initialize RMP2 module
    rmp2.Out = (int32)DFuncDesired;
    rmp2.Ramp2Delay = 0x00000050;
    rmp2.Ramp2Max = 0x00007FFF;
    rmp2.Ramp2Min = 0x0000000F;

    // Initialize the PID_REG3 module for dc-bus current
    pid1_idc.Kp = _IQ(1);
    pid1_idc.Ki = _IQ(T/0.003);//Ki=Kp*T/Ti
    pid1_idc.Kd = _IQ(0/T);
    pid1_idc.Kc = _IQ(0.2);
    pid1_idc.OutMax = _IQ(0.99);
    pid1_idc.OutMin = _IQ(0);

    // Initialize the PID_REG3 module for speed
    pid1_spd.Kp = _IQ(1);
    pid1_spd.Ki = _IQ(T/0.1);
    pid1_spd.Kd = _IQ(0/T);
    pid1_spd.Kc = _IQ(0.2);
    pid1_spd.OutMax = _IQ(0.99);
    pid1_spd.OutMin = _IQ(0);

    // Enable global Interrupts and higher priority real-time debug events:
    EINT; // Enable Global interrupt INTM
    ERTM; // Enable Global realtime interrupt DBGM
    EvaRegs.T1CON.bit.TENABLE=1;//开始计数
    // IDLE loop. Just sit and loop forever:
    for(;;) BackTicker++;

    }

    interrupt void MainISR(void)//T2的周期中断
    {

    // Verifying the ISR
    IsrTicker++;

    // ------------------------------------------------------------------------------
    // Call the ADC04U_DRV read function.
    // ------------------------------------------------------------------------------
    adc1.read(&adc1);

    // ------------------------------------------------------------------------------
    // Connect inputs of the RMP module and call the Ramp control
    // calculation function.
    // ------------------------------------------------------------------------------
    rc1.TargetValue = _IQ(SpeedRef);
    rc1.calc(&rc1);

    // ------------------------------------------------------------------------------
    // Connect inputs of the HALL module and call the Hall sensor
    // read function.
    // ------------------------------------------------------------------------------
    hall1.HallMapPointer = (int16)mod1.Counter;
    hall1.read(&hall1);

    // ------------------------------------------------------------------------------
    // Connect inputs of the MOD6 module and call the Modulo 6 counter
    // calculation function.
    // ------------------------------------------------------------------------------
    mod1.TrigInput =(int32)hall1.CmtnTrigHall;
    mod1.Counter = (int32)hall1.HallMapPointer;
    mod1.calc(&mod1);

    // ------------------------------------------------------------------------------
    // Connect inputs of the RMP2 module and call the Ramp control 2
    // calculation function.
    // ------------------------------------------------------------------------------
    rmp2.DesiredInput = (int32)DFuncDesired;
    rmp2.calc(&rmp2);

    // ------------------------------------------------------------------------------
    // Connect inputs of the PID_REG3 module and call the PID speed controller
    // calculation function.
    // ------------------------------------------------------------------------------
    pid1_spd.Ref = rc1.SetpointValue;
    pid1_spd.Fdb = speed1.Speed;
    pid1_spd.calc(&pid1_spd);

    // ------------------------------------------------------------------------------
    // Set the speed closed loop flag once the speed is built up to a desired value.
    // ------------------------------------------------------------------------------
    if (rc1.EqualFlag == 0x7FFFFFFF)
    {
    SpeedLoopFlag = TRUE;
    rc1.RampDelayMax = 300;
    }

    // ------------------------------------------------------------------------------
    // Connect inputs of the PWM_DRV module and call the PWM signal generation
    // update function.
    // ------------------------------------------------------------------------------
    // Switch from fixed duty-cycle or controlled Speed duty-cycle by SpeedLoopFlag variable
    if (SpeedLoopFlag == FALSE)
    {
    pwm1.DutyFunc = (int16)rmp2.Out;
    }// fixed duty-cycle
    else
    {
    pwm1.DutyFunc = (int16)_IQtoIQ15(pid1_spd.Out);
    }// controlled Speed duty-cycle

    pwm1.CmtnPointer = (int16)mod1.Counter;
    pwm1.update(&pwm1);

    // ------------------------------------------------------------------------------
    // Connect inputs of the SPEED_PR module and call the speed calculation
    // function.
    // ------------------------------------------------------------------------------
    if ((mod1.Counter == 5)&&(hall1.CmtnTrigHall == 0x7FFF))
    {
    speed1.TimeStamp = VirtualTimer;
    speed1.calc(speed1);
    }

    // ------------------------------------------------------------------------------
    // Connect inputs of the DATALOG module
    // ------------------------------------------------------------------------------
    DlogCh1 = (int16)mod1.Counter;
    DlogCh2 = (int16)mod1.TrigInput;
    DlogCh3 = (int16)_IQtoIQ15(pid1_spd.Ref);
    DlogCh4 = (int16)_IQtoIQ15(pid1_spd.Fdb);

    // ------------------------------------------------------------------------------
    // Increase virtual timer and force 15 bit wrap around
    // ------------------------------------------------------------------------------
    VirtualTimer++;
    VirtualTimer &= 0x00007FFF;

    // ------------------------------------------------------------------------------
    // Call the DATALOG update function.
    // ------------------------------------------------------------------------------
    dlog.update(&dlog);

    // Enable more interrupts from this timer
    EvaRegs.EVAIMRB.bit.T2PINT = 1;

    // Note: To be safe, use a mask value to write to the entire
    // EVAIFRB register. Writing to one bit will cause a read-modify-write
    // operation that may have the result of writing 1's to clear
    // bits other then those intended.
    EvaRegs.EVAIFRB.all = BIT0;

    // Acknowledge interrupt to recieve more interrupts from PIE group 3
    PieCtrlRegs.PIEACK.all |= PIEACK_GROUP3;
    }


    //===========================================================================
    // No more.


    f281xhall3源程序:#include "DSP281x_Device.h"
    #include "DSP281x_Hall3.h"
    #include "DSP281x_GlobalPrototypes.h"
    Uint32 Counter;
    void F281X_EV1_HALL3_Init(HALL3 *p)
    {

    F281X_EV1_HALL3_Determine_State(p);
    p->HallGpioBuffer = p->HallGpio; // Init with current CAP/GPIO logic levels
    p->HallGpioAccepted = p->HallGpio; // Init with current CAP/GPIO logic levels

    EvaRegs.CAPCONA.all = HALL3_INIT_STATE; // Set up capture units, CAP1-3 using GP timer 2
    EvaRegs.CAPFIFOA.all = 0x1500; // Write "01" each CAPxFIFO for EV to believe that there is already an entry in the FIFO

    EALLOW; // Enable EALLOW
    GpioMuxRegs.GPAMUX.all |= 0x0700; // Set up the capture 1-3 pins to primary functions
    EDIS; // Disable EALLOW

    //修改部分,为了启动电机
    if(p->HallGpio == 1)//AC相导通
    {
    Counter = 1;
    }
    else if(p->HallGpio == 2)//BA相导通
    {
    Counter = 3;
    }
    else if(p->HallGpio == 3)//BC相导通
    {
    Counter = 2;
    }
    else if(p->HallGpio == 4)//CB相导通
    {
    Counter = 5;
    }
    else if(p->HallGpio == 5)//AB相导通
    {
    Counter = 0;
    }
    else//CA相导通
    {
    Counter = 4;
    }
    }


    void F281X_EV1_HALL3_Read(HALL3 *p)
    {

    p->CapFlag = EvaRegs.EVAIFRC.all; // Save capture flag register, convenient for Watch Window
    if (p->CapFlag==0) // NO_EDGE_DETECTED: No hall signal edges detected on CAP1-3 (bits 0-2)
    {
    p->CmtnTrigHall = 0; // Reset trigger, it only handshakes with calling program.
    if (p->EdgeDebounced==0) // If motor has not moved then debounce current position.
    {
    F281X_EV1_HALL3_Debounce(p);//如果是第七次调用Debounced后,则会直接给EdgeDebounced赋值为0x7FFF,那么CmtnTrigHall的值也就会发生跳变。
    p->CmtnTrigHall = p->EdgeDebounced; // Set Commutation trigger here
    }
    else
    { // If current position is debounced, find match in table
    F281X_EV1_HALL3_Next_State_Ptr(p); // and return pointer to current state. Ptr to be incremented
    // by MOD6CNT after RET.
    p->EdgeDebounced = 0; // Reset trigger
    }
    }
    else // EDGE_DETECTED: Any hall signal edges detected on CAP1-3
    {
    p->StallCount = 0xFFFF; // On new edge, reset stall counter
    EvaRegs.EVAIFRC.all = 0x0007; // Clear all CAP1-3 Int-flags
    F281X_EV1_HALL3_Determine_State(p); // Since motor has moved, determine state (read HallGpio)
    p->CapCounter += 1; // Increment running edge detection counter
    }
    }

    void F281X_EV1_HALL3_Determine_State(HALL3 *p)
    {
    EALLOW; // Enable EALLOW
    // Configure CAP1-3 as GPIO-inputs (GPIO8-GPIO10)
    GpioMuxRegs.GPAMUX.all &= 0xF8FF;

    // config GPIO8-GPIO10 as inputs
    GpioMuxRegs.GPADIR.bit.GPIOA8 = 0;
    GpioMuxRegs.GPADIR.bit.GPIOA9 = 0;
    GpioMuxRegs.GPADIR.bit.GPIOA10 = 0;
    EDIS; // Disable EALLOW

    p->HallGpio = GpioDataRegs.GPADAT.all&0x0700; // HallGpio.2-0 = GPIO10-GPIO8
    p->HallGpio = p->HallGpio>>8;

    EALLOW; // Enable EALLOW
    GpioMuxRegs.GPAMUX.all |= 0x0700; // Set up the CAP1-3 pins to primary functions
    EDIS; // Disable EALLOW

    }


    void F281X_EV1_HALL3_Debounce(HALL3 *p)
    {

    if (p->HallGpio == p->HallGpioAccepted) // GPIO_UNCHANGED: Current GPIO reading == debounced GPIO reading?
    {
    if (p->Revolutions <= 0) // Only create hall map during initial Revolutions
    F281X_EV1_HALL3_Create_Map(p);
    p->StallCount -= 1; // Decrement stall counter
    if (p->StallCount == 0)
    {
    p->EdgeDebounced = 0x7FFF; // If motor has stalled, then user trigger to commutate
    p->StallCount = 0xFFFF; // Reset counter to starting value
    }
    }
    else // GPIO_CHANGED: If not zero, then the motor has moved to a new position.
    {
    if (p->HallGpio == p->HallGpioBuffer) // Current GPIO reading == previous GPIO reading?
    {
    if (p->DebounceCount >= p->DebounceAmount) // If equal, is current GPIO reading debounced?
    {
    p->HallGpioAccepted = p->HallGpioBuffer; // Current GPIO reading is now debounced
    p->EdgeDebounced = 0x7FFF; // Edge/position debounced, trigger commutation

    p->DebounceCount = 0; // Reset debounce counter

    if (p->HallMapPointer==0)
    p->Revolutions += 1; // Increment on every rev (HallMapPointer = 0)
    }
    else // DEBOUNCE_MORE
    p->DebounceCount += 1; // Increment debounce counter
    }
    else // NEW_READING
    {
    p->HallGpioBuffer = p->HallGpio; // Save new reading and reset debounce counter
    p->DebounceCount = 0;
    }
    }
    }


    void F281X_EV1_HALL3_Next_State_Ptr(HALL3 *p)
    {
    int16 i, HallPointer;

    if (p->Revolutions>0) // Only run function after map has been created.
    {
    for (i=0;i<=5;i++) // Search for a match of current debounced GPIO position
    { // and the table entries.
    if (p->HallMap[i] == p->HallGpioAccepted) // Match_Found
    HallPointer = i;
    }
    p->HallMapPointer = HallPointer; // On match, save pointer position. Pointer will be incremented
    } // by 1 since MOD6CNT will receive a positive trigger
    } // and pointer as inputs.


    void F281X_EV1_HALL3_Create_Map(HALL3 *p)
    {
    p->HallMap[p->HallMapPointer] = p->HallGpioAccepted; // Save debounced GPIO to table.
    }

    这个程序太长有点繁琐,但是恳求老师百忙之中能解决学生的疑惑,在此万分感谢!