Microprocessor/DSP (TMS320F28x) TR28335 모듈 PWM 사용하
  • 728x90
    반응형

     

     

    PWM

     

    (Pulse Width Modulation) 펄스 폭 변조


     

     

    Enhanced PWM Module

    SyncWorks TR28335 LAB1_A.c

    /*============================================================================================
        헤더파일 선언 및 선행처리 지시구문 정의
    ============================================================================================*/
    #include "DSP28x_Project.h"        /* Device Headerfile and Examples Include File */
    
    #define    BUFF    1024            /* 0x400 */
    
    
    /*============================================================================================
        예제에서 사용되는 함수들 선언
    ============================================================================================*/
    void InitLEDGpio(void);
    void LEDIndicator(Uint16 Duty, Uint16 Period);
    void InitEPwm6Module(void);
    interrupt void AdcIsr(void);
    
    
    /*============================================================================================
        예제에서 사용되는 전역 변수들 선언
    ============================================================================================*/
    Uint16    BackTicker;
    Uint16    IsrTicker;
    Uint16    AdcResultBuffer[BUFF];
    Uint32    BufferPointer;
    
    
    /*============================================================================================
        메인 함수 - 시작
    ============================================================================================*/
    void main(void)
    {
        Uint16    i;
    
    /*============================================================================================
        단계 1. 전역 인터럽트 비-활성화 및 인터럽트 플래그 초기화
    ============================================================================================*/
        DINT;
        IER = 0x0000;
        IFR = 0x0000;
    
    /*============================================================================================
        단계 2. 시스템 컨트롤 초기화 (DSP2833x_SysCtrl.c 파일 참조)
    ============================================================================================*/
        InitSysCtrl();
        
    
    /*============================================================================================
        단계 3. 범용 입출력 포트(GPIO) 초기화
    ============================================================================================*/
        /* for PWM Outputs */
        EALLOW;
        GpioCtrlRegs.GPAPUD.bit.GPIO10 = 0;        /* Enable pull-up on GPIO10 (EPWM6A) */
        GpioCtrlRegs.GPAMUX1.bit.GPIO10 = 1;    /* Configure GPIO10 as EPWM6A */
        EDIS;
        
        /* for LED control */
        InitLEDGpio();
    
    /*============================================================================================
        단계 4. 인터럽트 초기화 (DSP2833x_PieCtrl.c / DSP2833x_PieVect.c 파일 참조)
    ============================================================================================*/
        InitPieCtrl();
        InitPieVectTable();
    
        /* 인터럽트 벡터 재-연결 (Interrupt Vector Re-mapping) */      
        EALLOW;
        PieVectTable.ADCINT = &AdcIsr;
        EDIS;
    
        /* ADC 인터럽트 벡터 Enable */
        PieCtrlRegs.PIEIER1.bit.INTx6 = 1;    /* PIE 인터럽트 (ADC_INT) : Enable */
        IER |= M_INT1;                        /* CPU 인터럽트 (INT1) : Enable */
        
    
    /*============================================================================================
        단계 5. EPWM 모듈 6번과 ADC 모듈 초기화
    ============================================================================================*/
        /* Initialize EPWM6 Module */
        InitEPwm6Module();
    
        /* Initialize ADC Module */
        InitAdc();
    
        /* Configuration ADC module */
        AdcRegs.ADCTRL3.bit.ADCCLKPS = 15;        /* HSPCLK/[30*(CPS + 1)] */
        AdcRegs.ADCTRL1.bit.CPS = 0;            /* Prescaled CLK by ADCCLKPS / 1 */
                                                /* ADC clock = 75MHz/[30*(0 + 1)] = 2.5MHz */
        AdcRegs.ADCMAXCONV.all = 0;                /* 1 single conv's */
    
        AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 2;    /* Conv. Channel select (ADCINA2)  */
    
        AdcRegs.ADCTRL1.bit.ACQ_PS = 15;        /* Acq. window size : 16 ADCCLK */
        AdcRegs.ADCTRL3.bit.SMODE_SEL = 0;        /* Setup sequential sampling mode */
        AdcRegs.ADCTRL1.bit.SEQ_CASC = 1;        /* Setup cascaded sequencer mode */
        AdcRegs.ADCTRL2.bit.EPWM_SOCA_SEQ1 = 1;    /* Enable SOCA from ePWM to start SEQ1 */
        AdcRegs.ADCTRL2.bit.INT_ENA_SEQ1 = 1;    /* Enable SEQ1 interrupt (every EOS) */
    
        /* Set up Event Trigger(SOC) with CNT_zero enable for Time-base of EPWM1 */
        EPwm1Regs.ETSEL.bit.SOCAEN = 1;            /* Enable SOC on A group */
        EPwm1Regs.ETSEL.bit.SOCASEL = 2;        /* Select SOC from CNTR=PRD */
        EPwm1Regs.ETPS.bit.SOCAPRD = 1;            /* Generate pulse on 1st event */
        EPwm1Regs.TBCTL.bit.CLKDIV = 0;
        EPwm1Regs.TBCTL.bit.HSPCLKDIV = 5;
        EPwm1Regs.TBPRD = 299;                    /* Set period : 50kHz @ 15MHz TBCLK */
        EPwm1Regs.TBCTL.bit.CTRMODE = 0;        /* count up and start */
    
    /*============================================================================================
        단계 6. 변수 초기화
    ============================================================================================*/
        BackTicker = 0;
        IsrTicker = 0;
        
        for(i=0 ; i<BUFF ; i++)
        {
            AdcResultBuffer[i] = 0;
        }
    
        BufferPointer = 0;
    
    /*============================================================================================
        단계 7. 전역 인터럽트 및 리얼타임 디버깅 인터럽트 활성화
    ============================================================================================*/
        ERTM;    /* Enable Global realtime interrupt DBGM */
        EINT;   /* Enable Global interrupt INTM */
    
    /*============================================================================================
        단계 8. 유휴대기 루프 (Idle-loop)
    ============================================================================================*/
        for(;;)
        {
            BackTicker++;
            LEDIndicator(EPwm6Regs.CMPA.half.CMPA, EPwm6Regs.TBPRD);
        }
    }
    /*============================================================================================
        메인 함수 - 끝
    ============================================================================================*/
    
    
    /*============================================================================================
        함수 정의
    ============================================================================================*/
    interrupt void AdcIsr(void)
    {
        IsrTicker++;
    
        AdcResultBuffer[BufferPointer++] = AdcRegs.ADCRESULT0 >>4;
    
        if(BufferPointer == BUFF)
        {
            asm(" NOP");
            BufferPointer = 0;
        }
    
        /* 다음 ADC 시퀀스를 위한 초기화 과정 */
        AdcRegs.ADCTRL2.bit.RST_SEQ1 = 1;
        AdcRegs.ADCST.bit.INT_SEQ1_CLR = 1;
        PieCtrlRegs.PIEACK.bit.ACK1 = 1;
    }
    
    
    void InitEPwm6Module(void)
    {
        /* Setup Counter Mode and Clock */
        EPwm6Regs.TBCTL.bit.CTRMODE = 0;     /* Count Up (Asymmetric) */
        EPwm6Regs.TBCTL.bit.HSPCLKDIV = ?;    /* TBCTL 레지스터의 HSPCLKDIV 비트와 CLKDIV 비트 설정을 통해 Time-Base Clock을 설정합니다. */
        EPwm6Regs.TBCTL.bit.CLKDIV = ?;
    
        /* Setup Phase */
        EPwm6Regs.TBPHS.half.TBPHS = 0;        /* Phase is 0 */
        EPwm6Regs.TBCTL.bit.PHSEN = 0;         /* Disable phase loading */
    
        /* Setup Period (Carrier Frequency) */
        EPwm6Regs.TBPRD = ?;                 /* PWM의 Carrier Freq.가 1kHz가 되도록 TBPRD 레지스터 값을 설정합니다.  */
        EPwm6Regs.TBCTR = 0;                 /* Clear Counter */
    
        /* Set Compare Value */
        EPwm6Regs.CMPA.half.CMPA = ?;         /* PWM의 Duty-ratio가 25%가 되도록 CMPA 레지스터 값을 설정합니다. */
            
        /* Setup shadowing */
        EPwm6Regs.TBCTL.bit.PRDLD = 0;         /* Period Register is loaded from its shadow when CNTR=Zero */
        EPwm6Regs.CMPCTL.bit.SHDWAMODE = 0;    /* Compare A Register is loaded from its shadow when CNTR=Zero */
        EPwm6Regs.CMPCTL.bit.LOADAMODE = 0;
    
        /* Set actions */
        EPwm6Regs.AQCTLA.bit.ZRO = ?;         /* 타이머 카운터가 0(Zero)과 일치할 때, PWM 핀의 상태를 Low에서 High로 변경하도록 설정합니다. */
        EPwm6Regs.AQCTLA.bit.CAU = ?;         /* 타이머 카운터가 상승계수 중 CMPA 레지스터 값과 일치할 때, PWM 핀의 상태를 High에서 Low로 변경하도록 설정합니다. */
    
        /* Set Dead-time (Bypass) */
        EPwm6Regs.DBCTL.bit.OUT_MODE = 0;     /* Dead-band generation is bypassed for both output signals */
        
        /* Set chopping (Bypass) */
        EPwm6Regs.PCCTL.bit.CHPEN = 0;         /* Disable(Bypass) PWM Chopping Function */
        
        /* Set Trip Action (Disable, Not used) */
    
        
        /* Set Interrupts (Not used) */
    
    
    }
    
    
    void InitLEDGpio(void)
    {
        EALLOW;
        GpioCtrlRegs.GPAMUX1.bit.GPIO0 = 0;    /* GPIO0 ~ GPIO5, GPIO 기능으로 설정 */
        GpioCtrlRegs.GPAMUX1.bit.GPIO1 = 0;
        GpioCtrlRegs.GPAMUX1.bit.GPIO2 = 0;
        GpioCtrlRegs.GPAMUX1.bit.GPIO3 = 0;
        GpioCtrlRegs.GPAMUX1.bit.GPIO4 = 0;
        GpioCtrlRegs.GPAMUX1.bit.GPIO5 = 0;
        GpioCtrlRegs.GPADIR.bit.GPIO0 = 1;    /* GPI00 ~ GPIO5, 출력으로 설정 */
        GpioCtrlRegs.GPADIR.bit.GPIO1 = 1;
        GpioCtrlRegs.GPADIR.bit.GPIO2 = 1;
        GpioCtrlRegs.GPADIR.bit.GPIO3 = 1;
        GpioCtrlRegs.GPADIR.bit.GPIO4 = 1;
        GpioCtrlRegs.GPADIR.bit.GPIO5 = 1;
        EDIS;
    
        GpioDataRegs.GPACLEAR.bit.GPIO0 = 1;
        GpioDataRegs.GPACLEAR.bit.GPIO1 = 1;
        GpioDataRegs.GPACLEAR.bit.GPIO2 = 1;
        GpioDataRegs.GPACLEAR.bit.GPIO3 = 1;
        GpioDataRegs.GPACLEAR.bit.GPIO4 = 1;
        GpioDataRegs.GPACLEAR.bit.GPIO5 = 1;
    }
    
    
    void LEDIndicator(Uint16 Duty, Uint16 Period)
    {
        Uint16    LEDPointer;
    
        LEDPointer = 6 * (1-((float32)Duty/Period));
    
        GpioDataRegs.GPADAT.all = 0x0000003F & (0x0000003F<<LEDPointer);
    }
    
    
    /*============================================================================================
        끝 - 예제 코드 종료
    ============================================================================================*/

     

    LAB1_A.c 파일의 162 ~ 201번 라인에 예제에서 사용되는 Enchanced PWM Module 6번 모듈을 초기화 하는 함수 InitEPwm6Module()가 작성되어 있다. 이 함수의 일부 코드들은 미완성된 체로 남아있다. 해당 레지터들의 설정을 완성해본다.

     

    • 타이머 클럭을 설정한다.
      • 예제에서 Core의 클럭속도는 150MHz로 초기화 되어 있다. 가장 먼저 구현하고자 하는 PWM Carrier Frequency에 적합한 타이머 클럭을 설정해야 한다. TBCTL 레지스터의 CLKDIV, HSPCLKDIV 비트 설정을 통해 타이머 클럭을 분주할 수 있다.
    • PWM Carrier Frequency가 1kHz (1,000Hz) 가 되도록 주기 레지스터(TBPRD) 값 설정
    • PWM Duty-ratio가 25%가 되도록 비교 레지스터(CMPA) 값 설정
    • 타이머 카운터가 0(Zero)과 일치할 때, PWM 핀 상태를 Low에서 High로 변경(AQCTLA)
    • 타이머 카운터가 상승계수 중, 비교 레지스터(CMPA) 값과 일치할 때, PWM 핀 상태를 High에서 Low로 변경(AQCTLA)

     

    Enhanced PWM Module의 User's Guide :

    sprug04a(ePWM).pdf
    다운로드

     

    User's Guide에 4절 Registers 편을 참고하여 미완성 코드들을 설정한다.

     

     

     

    728x90
    반응형
상단으로