c2000 ePWM 微步驱动步进电机

/ 0评 / 0

测试时序:

展开:

更细的微步:

微步原理:

程序代码:

#include "DSP28x_Project.h"
#include "sfo_v6.h"

#define STEP_SIZE 0.1

int MEP_ScaleFactor;

volatile struct EPWM_REGS *ePWM[PWM_CH] =
    {&EPwm1Regs, &EPwm1Regs, &EPwm2Regs, &EPwm3Regs, &EPwm4Regs};

volatile int StepStatus;

volatile double StepData[4];

void PWM_Init()
{
    uint8_t i = 0;

    StepData[0] = 1.0f;
    StepData[1] = 0.0f;
    StepData[2] = 0.0f;
    StepData[3] = 0.0f;

    StepStatus = 0;

    EALLOW;

    GpioCtrlRegs.GPAPUD.bit.GPIO0 = 1;  // Disable pull-up on GPIO0 (EPWM1A)
    GpioCtrlRegs.GPAPUD.bit.GPIO2 = 1;  // Disable pull-up on GPIO2 (EPWM2A)
    GpioCtrlRegs.GPAPUD.bit.GPIO4 = 1;  // Disable pull-up on GPIO4 (EPWM3A)
    GpioCtrlRegs.GPAPUD.bit.GPIO6 = 1;  // Disable pull-up on GPIO6 (EPWM4A)
    GpioCtrlRegs.GPAMUX1.bit.GPIO0 = 1; // Configure GPIO0 as EPWM1A
    GpioCtrlRegs.GPAMUX1.bit.GPIO2 = 1; // Configure GPIO2 as EPWM2A
    GpioCtrlRegs.GPAMUX1.bit.GPIO4 = 1; // Configure GPIO4 as EPWM3A
    GpioCtrlRegs.GPAMUX1.bit.GPIO6 = 1; // Configure GPIO6 as EPWM4A

    while (SFO() != SFO_COMPLETE)
    {
    };

    SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 0;

    for (i = 1; i < 5; i++)
    {
        ePWM[i]->TBPRD = 6000;
        ePWM[i]->TBPHS.half.TBPHS = 0;
        ePWM[i]->TBCTR = 0;
        ePWM[i]->TBCTL.bit.CTRMODE = TB_COUNT_UP;
        if (i == 1)
        {
            ePWM[i]->TBCTL.bit.PHSEN = TB_DISABLE;
            ePWM[i]->TBCTL.bit.SYNCOSEL = TB_CTR_ZERO;
        }
        else
        {
            ePWM[i]->TBCTL.bit.PHSEN = TB_ENABLE;
            ePWM[i]->TBCTL.bit.SYNCOSEL = TB_SYNC_IN;
        }
        ePWM[i]->TBCTL.bit.HSPCLKDIV = TB_DIV1; // 2分频 设置时基时钟速率为系统时钟/2 = 60MHz / 2 = 30MHz
        ePWM[i]->TBCTL.bit.CLKDIV = TB_DIV1;    // 2分频,计算到TBPRD结束,1000就是30MHz=>30kHz

        ePWM[i]->CMPCTL.bit.SHDWAMODE = CC_SHADOW;   // 是否使用影子寄存器
        ePWM[i]->CMPCTL.bit.LOADAMODE = CC_CTR_ZERO; // 若使用影子寄存器,则加载条件模式选择.
        ePWM[i]->CMPA.half.CMPA = 0;                 // 0 ~ 65535

        ePWM[i]->AQCTLA.bit.CAU = AQ_CLEAR; // 递增计数时,发生比较寄存器A匹配时清除PWM1A输出
        ePWM[i]->AQCTLA.bit.ZRO = AQ_SET;   // 计数到0 PWM1A输出高电平

        ePWM[i]->HRCNFG.all = 0x0;
        ePWM[i]->HRCNFG.bit.EDGMODE = HR_FEP;
        ePWM[i]->HRCNFG.bit.CTLMODE = HR_CMP;
        ePWM[i]->HRCNFG.bit.HRLOAD = HR_CTR_ZERO;
        ePWM[i]->CMPA.half.CMPAHR = 0; // HRPWM部分 0 ~ 255
    }

    SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 1;

    EDIS;
}

void PWM_Set(uint8_t ch, double value)
{
    uint32_t val;

    val = value * 1536000.0f;

    EALLOW;

    ePWM[ch]->CMPA.half.CMPA = (val >> 8);
    ePWM[ch]->CMPA.half.CMPAHR = (val & 0xFF);

    EDIS;
}

void PWM_Step()
{
    if (StepStatus == 0)
    {
        StepData[0] = StepData[0] - STEP_SIZE;
        StepData[1] = 1.0f - StepData[0];
        if (StepData[1] >= 1.0f)
        {
            StepData[0] = 0.0f;
            StepData[1] = 1.0f;
            StepStatus = 1;
        }
    }
    else if (StepStatus == 1)
    {
        StepData[1] = StepData[1] - STEP_SIZE;
        StepData[2] = 1.0f - StepData[1];
        if (StepData[2] >= 1.0f)
        {
            StepData[1] = 0.0f;
            StepData[2] = 1.0f;
            StepStatus = 2;
        }
    }
    else if (StepStatus == 2)
    {
        StepData[2] = StepData[2] - STEP_SIZE;
        StepData[3] = 1.0f - StepData[2];
        if (StepData[3] >= 1.0f)
        {
            StepData[2] = 0.0f;
            StepData[3] = 1.0f;
            StepStatus = 3;
        }
    }
    else if (StepStatus == 3)
    {
        StepData[3] = StepData[3] - STEP_SIZE;
        StepData[0] = 1.0f - StepData[3];
        if (StepData[0] >= 1.0f)
        {
            StepData[3] = 0.0f;
            StepData[0] = 1.0f;
            StepStatus = 0;
        }
    }

    PWM_Set(1, StepData[0]);
    PWM_Set(2, StepData[1]);
    PWM_Set(3, StepData[2]);
    PWM_Set(4, StepData[3]);
}

void main(void)
{
#ifdef _FLASH
    memcpy(&RamfuncsRunStart, &RamfuncsLoadStart, (size_t)&RamfuncsLoadSize);
#endif

    InitSysCtrl();
    InitGpio();

    DINT;

    InitPieCtrl();

    IER = 0x0000;
    IFR = 0x0000;

    InitPieVectTable();

    PWM_Init();

    for (;;)
    {
        PWM_Step();
        while (SFO() != SFO_COMPLETE)
        {
        };
    }
}

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注