各位老师好,我使用的是DSP2812板子,设置的PWM频率为20KHz,但是控制板输出的频率100Hz都达不到,如果复位后,直接会没有PWM信号输出。
这是什么原因?麻烦各位老师指导,谢谢老师了!!
Seven Han:您好,
我建议您先跑下TI的例程。
各位老师好,我使用的是DSP2812板子,设置的PWM频率为20KHz,但是控制板输出的频率100Hz都达不到,如果复位后,直接会没有PWM信号输出。
这是什么原因?麻烦各位老师指导,谢谢老师了!!
user5213609:
回复 Seven Han:
老师,您好,很高兴收到您的回复。
我用的是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 ModuleMOD6CNT 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 valuesEALLOW;// This is needed to write to EALLOW protected registersSysCtrlRegs.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 2EvaRegs.T2PR = SYSTEM_FREQUENCY*1000000*T;// Perscaler X1 (T2), ISR period = T x 1// Clear the counter/compare Regs for GP timer 2EvaRegs.T2CNT = 0x0000;EvaRegs.T2CMPR = 0x0000;
// Enable Period interrupt bits for GP timer 2EvaRegs.EVAIMRB.bit.T2PINT = 1;EvaRegs.EVAIFRB.bit.T2PINT = 1;
// Count up, x1, internal clk, disable compare, use own periodEvaRegs.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 registersPieVectTable.T2PINT = &MainISR;//EDIS;// This is needed to disable write to EALLOW protected registers
// Enable PIE group 3 interrupt 1 for T2PINTPieCtrlRegs.PIEIER3.all = M_INT1;
// Enable CPU INT3 for T2PINT:IER |= M_INT3;
// Initialize PWM modulepwm1.PeriodMax = (SYSTEM_FREQUENCY/PWM_FREQUENCY)*1000;// Asymmetric PWMpwm1.DutyFunc = DFuncDesired;// DutyFunc = Q15pwm1.init(&pwm1);
// Initialize DATALOG moduledlog.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 moduleadc1.ChSelect = 0x6543;// for DMC1500 and eZdsp2812/eZdsp2808 boardsadc1.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 modulerc1.RampDelayMax = 20;//rc1.RampLowLimit = _IQ(0);rc1.RampHighLimit = _IQ(1);
// Initialize Hall modulehall1.DebounceAmount = 5;hall1.Revolutions = -10;hall1.init(&hall1);mod1.Counter = Counter;
// Initialize RMP2 modulermp2.Out = (int32)DFuncDesired;rmp2.Ramp2Delay = 0x00000050;rmp2.Ramp2Max = 0x00007FFF;rmp2.Ramp2Min = 0x0000000F;
// Initialize the PID_REG3 module for dc-bus currentpid1_idc.Kp = _IQ(1);pid1_idc.Ki = _IQ(T/0.003);//Ki=Kp*T/Tipid1_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 speedpid1_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 INTMERTM; // Enable Global realtime interrupt DBGMEvaRegs.T1CON.bit.TENABLE=1;//开始计数
// IDLE loop. Just sit and loop forever: for(;;) BackTicker++;
}
interrupt void MainISR(void)//T2的周期中断
{
// Verifying the ISRIsrTicker++;
// ——————————————————————————
//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 variableif (SpeedLoopFlag == FALSE){pwm1.DutyFunc = (int16)rmp2.Out;}// fixed duty-cycleelse{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 timerEvaRegs.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 3PieCtrlRegs.PIEACK.all |= PIEACK_GROUP3;
}
//===========================================================================
// No more.
f281xhall3源程序:#include "DSP281x_Device.h"
#include "DSP281x_Hall3.h"
#include "DSP281x_GlobalPrototypes.h"Uint32 Counter;
voidF281X_EV1_HALL3_Init(HALL3 *p)
{
F281X_EV1_HALL3_Determine_State(p);p->HallGpioBuffer = p->HallGpio;// Init with current CAP/GPIO logic levelsp->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 2EvaRegs.CAPFIFOA.all = 0x1500;// Write "01" each CAPxFIFO for EV to believe that there is already an entry in the FIFO
EALLOW;// Enable EALLOWGpioMuxRegs.GPAMUX.all |= 0x0700;// Set up the capture 1-3 pins to primary functionsEDIS;// 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 Windowif (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 tableF281X_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 counterEvaRegs.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 inputsGpioMuxRegs.GPADIR.bit.GPIOA8 = 0;GpioMuxRegs.GPADIR.bit.GPIOA9 = 0;GpioMuxRegs.GPADIR.bit.GPIOA10 = 0;EDIS;// Disable EALLOWp->HallGpio = GpioDataRegs.GPADAT.all&0x0700;// HallGpio.2-0 = GPIO10-GPIO8 p->HallGpio = p->HallGpio>>8;
EALLOW;// Enable EALLOWGpioMuxRegs.GPAMUX.all |= 0x0700;// Set up the CAP1-3 pins to primary functionsEDIS;// 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 RevolutionsF281X_EV1_HALL3_Create_Map(p);p->StallCount -= 1;// Decrement stall counterif (p->StallCount == 0){p->EdgeDebounced = 0x7FFF;// If motor has stalled, then user trigger to commutatep->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 debouncedp->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_MOREp->DebounceCount += 1;// Increment debounce counter}else// NEW_READING{p->HallGpioBuffer = p->HallGpio;// Save new reading and reset debounce counterp->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_FoundHallPointer = 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.
}
这个程序太长有点繁琐,但是恳求老师百忙之中能解决学生的疑惑,在此万分感谢!