Dear All,
Could you kindly help me to understand how to create PWM from ADC counter that can produce from analog input according to SPRU791f.
1. Should I use ePWM_SOCB ?
2. I want to use I/O pins from 1A to 6A of EPWM output.
3. If I need zero-crossing and fire angle in then what to do with code?
Take a look in example, attached here.
//============================================================================================ // ����ó�� ���� //-------------------------------------------------------------------------------------------- #include "DSP28x_Project.h" // Device Headerfile and Examples Include File #define BUFFER_LENGTH 64 //============================================================================================ //============================================================================================ // �Լ� ���� //-------------------------------------------------------------------------------------------- interrupt void adc_isr(void); // ADC ���ͷ�Ʈ �Լ� ���� //============================================================================================ //============================================================================================ // �ý��ۿ��� ����� ���� ���� ���� //-------------------------------------------------------------------------------------------- Uint16 ADC_buffer[8][BUFFER_LENGTH]; Uint16 i,j; Uint16 Loop_cnt, ADC_cnt; Uint16 Bufferful_flag; //============================================================================================ void main(void) { //============================================================================================ // Step 1. ���� ���ͷ�Ʈ ��Ȱ��ȭ //-------------------------------------------------------------------------------------------- DINT; //============================================================================================ //============================================================================================ // Step 2. �ý��� ��Ʈ�� �ʱ�ȭ: //-------------------------------------------------------------------------------------------- InitSysCtrl(); EALLOW; SysCtrlRegs.HISPCP.bit.HSPCLK = 1; // HSPCLK = SYSCLKOUT/(HISPCP*2) EDIS; // HSPCLK = 150MHz/(1*2) = 75MHz //============================================================================================ //============================================================================================ // Step 3. ���ͷ�Ʈ �ʱ�ȭ: //-------------------------------------------------------------------------------------------- InitPieCtrl(); IER = 0x0000; IFR = 0x0000; InitPieVectTable(); // Vector Remapping EALLOW; PieVectTable.ADCINT = &adc_isr; EDIS; //============================================================================================ //============================================================================================ // Step 4. ADC �ʱ�ȭ //-------------------------------------------------------------------------------------------- InitAdc(); // ADC ���� AdcRegs.ADCTRL3.bit.ADCCLKPS = 3; // ADCCLK = HSPCLK/(ADCCLKPS*2)/(CPS+1) AdcRegs.ADCTRL1.bit.CPS = 1; // ADCCLK = 75MHz/(3*2)/(1+1) = 6.25MHz AdcRegs.ADCTRL1.bit.ACQ_PS = 3; // ����/Ȧ�� ����Ŭ = ACQ_PS + 1 = 4 (ADCCLK����) AdcRegs.ADCTRL1.bit.SEQ_CASC = 1; // ������ ��� ����: ���� ������ ��� (0:���� ���, 1:���� ���) AdcRegs.ADCTRL3.bit.SMODE_SEL = 0; // ���� ���ø� ��� AdcRegs.ADCMAXCONV.all = 7; // ADC ä�μ� ����: 8��(=MAX_CONV+1)ä���� ADC AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 0; // ADC ���� ����: 1��°�� ADCINA0 ä���� ADC AdcRegs.ADCCHSELSEQ1.bit.CONV01 = 1; // ADC ���� ����: 2��°�� ADCINA1 ä���� ADC AdcRegs.ADCCHSELSEQ1.bit.CONV02 = 2; // ADC ���� ����: 3��°�� ADCINA2 ä���� ADC AdcRegs.ADCCHSELSEQ1.bit.CONV03 = 3; // ADC ���� ����: 4��°�� ADCINA3 ä���� ADC AdcRegs.ADCCHSELSEQ2.bit.CONV04 = 8; // ADC ���� ����: 5��°�� ADCINB0 ä���� ADC AdcRegs.ADCCHSELSEQ2.bit.CONV05 = 9; // ADC ���� ����: 6��°�� ADCINB1 ä���� ADC AdcRegs.ADCCHSELSEQ2.bit.CONV06 = 10; // ADC ���� ����: 7��°�� ADCINB2 ä���� ADC AdcRegs.ADCCHSELSEQ2.bit.CONV07 = 11; // ADC ���� ����: 8��°�� ADCINB3 ä���� ADC AdcRegs.ADCTRL2.bit.EPWM_SOCB_SEQ = 1; // ePWM_SOCB�� ADC ������ �õ� AdcRegs.ADCTRL2.bit.INT_ENA_SEQ1 = 1; // ADC ������ �Ϸ�� ���ͷ�Ʈ �� ���� //ePWM_SOCB �̺�Ʈ Ʈ���� ���� EPwm3Regs.ETSEL.bit.SOCBEN = 1; // SOCB �̺�Ʈ Ʈ���� Enable EPwm3Regs.ETSEL.bit.SOCBSEL = 2; // SCCB Ʈ���� ���� : ī���� �ֱ� ��ġ �� EPwm3Regs.ETPS.bit.SOCBPRD = 1; // SOCB �̺�Ʈ ���� ���� : Ʈ���� ���� �ѹ� ���� EPwm3Regs.TBCTL.bit.CTRMODE = 0; // ī��Ʈ ��� ����: Up-conut ��� EPwm3Regs.TBCTL.bit.HSPCLKDIV = 1; // TBCLK = [SYSCLKOUT / ((HSPCLKDIV*2) * 2^(CLKDIV))] EPwm3Regs.TBCTL.bit.CLKDIV = 1; // TBCLK = [150MHz / (2*2)] = 37.5MHz EPwm3Regs.TBPRD = 1874; // TB�ֱ�= (TBPRD+1)/TBCLK = 1875/37.5MHz = 50us(20KHz) EPwm3Regs.TBCTR = 0x0000; // TB ī���� �ʱ�ȭ // PIE�� ADC ���ͷ�Ʈ Ȱ��ȭ PieCtrlRegs.PIEIER1.bit.INTx6 = 1; // PIE ���ͷ�Ʈ(ADCINT) Ȱ��ȭ IER |= M_INT1; // CPU ���ͷ�Ʈ(INT1) Ȱ��ȭ //============================================================================================ //============================================================================================ // Step 5. PWM �ʱ�ȭ //-------------------------------------------------------------------------------------------- InitEPwm1Gpio(); // Time-Base Submodule �ʱ�ȭ EPwm1Regs.TBCTL.bit.PRDLD = TB_IMMEDIATE; // TBRRD �� ��� �ݿ�(shadow�������� ��� ����) EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP; // Up-count mode: EPwm1Regs.TBCTL.bit.HSPCLKDIV = 1; // TBCLK = [SYSCLKOUT / ((HSPCLKDIV*2) * 2^(CLKDIV))] EPwm1Regs.TBCTL.bit.CLKDIV = 1; // TBCLK = [150MHz / (2*2)] = 37.5MHz EPwm1Regs.TBPRD = 37499; // TB �ֱ� = (TBPRD+1)/TBCLK = 37500/37.5MHz = 1ms(1KHz) EPwm1Regs.TBCTR = 0; // TB ī���� �ʱ�ȭ // Counter-Compare Submodule �ʱ�ȭ EPwm1Regs.CMPA.half.CMPA = 11249; // ��ƼA ������ ���� (30%) EPwm1Regs.CMPB = 26249; // ��ƼB ������ ���� (70%) EPwm1Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW; // �� �������Ϳ� Shadow �������� ��� EPwm1Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO; // ī���Ͱ� 0 �϶� Shadow �������Ϳ��� �� �������Ϳ� �� �� �ε� EPwm1Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW; // �� �������Ϳ� Shadow �������� ��� EPwm1Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO; // ī���Ͱ� 0 �϶� Shadow �������Ϳ��� �� �������Ϳ� �� �� �ε� // Action-qualifier �ʱ�ȭ EPwm1Regs.AQCTLA.bit.ZRO = AQ_SET; // ī���Ͱ� ������ �� High EPwm1Regs.AQCTLA.bit.CAU = AQ_CLEAR; // ī���Ͱ� ����� �� ���� ��ġ�ϸ� Low EPwm1Regs.AQCTLB.bit.ZRO = AQ_SET; // ī���Ͱ� ������ �� High EPwm1Regs.AQCTLB.bit.CBU = AQ_CLEAR; // ī���Ͱ� ����� �� ���� ��ġ�ϸ� Low //============================================================================================ //============================================================================================ // Step 6. Initialize Application Variables //-------------------------------------------------------------------------------------------- for(i=0;i<8;i++){ for(j=0;j<BUFFER_LENGTH;j++) ADC_buffer[i][j] = 0; } Loop_cnt = 0; ADC_cnt = 0; Bufferful_flag = 0; //============================================================================================ //============================================================================================ // ���� ���ͷ�Ʈ Ȱ��ȭ , ����Ÿ�� ����� ���ͷ�Ʈ Ȱ��ȭ: //-------------------------------------------------------------------------------------------- EINT; // Enable Global interrupt INTM ERTM; // Enable Global realtime interrupt DBGM //============================================================================================ //============================================================================================ // IDLE loop. Just sit and loop forever : //-------------------------------------------------------------------------------------------- for(;;) { if(Bufferful_flag==1){ Bufferful_flag = 0; } Loop_cnt++; } //============================================================================================ } //============================================================================================ // ���� �Լ� - �� //============================================================================================ //============================================================================================ // ���ͷ�Ʈ ���� ��ƾ ���� //-------------------------------------------------------------------------------------------- interrupt void adc_isr(void) { ADC_buffer[0][ADC_cnt] = AdcRegs.ADCRESULT0; ADC_buffer[1][ADC_cnt] = AdcRegs.ADCRESULT1; ADC_buffer[2][ADC_cnt] = AdcRegs.ADCRESULT2; ADC_buffer[3][ADC_cnt] = AdcRegs.ADCRESULT3; ADC_buffer[4][ADC_cnt] = AdcRegs.ADCRESULT4; ADC_buffer[5][ADC_cnt] = AdcRegs.ADCRESULT5; ADC_buffer[6][ADC_cnt] = AdcRegs.ADCRESULT6; ADC_buffer[7][ADC_cnt] = AdcRegs.ADCRESULT7; // ADC �Է� ������ ������ ���� ���� ī���� ADC_cnt==BUFFER_LENGTH-1 ? ADC_cnt=0,Bufferful_flag=1 : ADC_cnt++; // Reinitialize for next ADC sequence AdcRegs.ADCTRL2.bit.RST_SEQ1 = 1; // Reset SEQ1 AdcRegs.ADCST.bit.INT_SEQ1_CLR = 1; // Clear INT SEQ1 bit PieCtrlRegs.PIEACK.all = PIEACK_GROUP1; // Acknowledge interrupt to PIE } //============================================================================================
/*====================================================================== File name : EPWM01_1Ch_PWM_Asymmetric_Single_Edge_Control.c Originator : Digital Control Systems Group SyncWorks Target : TMS320F28335 Version : 1.00 ======================================================================*/ /*====================================================================== History : 2011-07-29, Version 1.00 ======================================================================*/ #include "DSP28x_Project.h" /* Device Headerfile and Examples Include File */ #define SYSTEM_CLOCK 150E6 /* 150MHz */ #define TBCLK 150E6 /* 150MHz */ #define PWM_CARRIER 20E3 /* 20kHz */ #define PWM_DUTY_RATIO 2E-1 /* 0.2, 20% */ #define UFEC 0 /* Up-Count, Falling Edge Control */ #define UREC 0 /* Up-Count, Rising Edge Control */ #define DFEC 0 /* Down-Count, Falling Edge Control */ #define DREC 1 /* Down-Count, Rising Edge Control */ /* Prototype statements for functions found within this Example */ void InitEPwm4Module(void); /* Global variables used in this Example */ Uint16 BackTicker; float32 PwmCarrierFrequency; float32 PwmDutyRatio; void main(void) { /*----------------------------------------------------------------------------- Step 1 Disable Global Interrupt & Interrupt Flag Clear -----------------------------------------------------------------------------*/ DINT; IER = 0x0000; IFR = 0x0000; /*----------------------------------------------------------------------------- Step 2 2.1 InitSysCtrl() 2.1.1 Disables the watchdog 2.1.2 Set the PLLCR for proper SYSCLKOUT frequency 2.1.3 Set the pre-scaler for the high and low frequency peripheral clocks 2.1.4 Enable the clocks to the peripherals 2.2 Initialize GPIO MUX -----------------------------------------------------------------------------*/ InitSysCtrl(); EALLOW; GpioCtrlRegs.GPAPUD.bit.GPIO6 = 0; /* Enable pull-up on GPIO6 (EPWM4A) */ GpioCtrlRegs.GPAMUX1.bit.GPIO6 = 1; /* Configure GPIO6 as EPWM4A */ EDIS; /*----------------------------------------------------------------------------- Step 3 3.1 Initialize Peripheral Interrupt Expansion circuit -----------------------------------------------------------------------------*/ /* Not required for this example */ /*----------------------------------------------------------------------------- Step 4 4.1 Pie Vector Table Re-allocation -----------------------------------------------------------------------------*/ /* Not required for this example */ /*----------------------------------------------------------------------------- Step 5 5.1 Interrupt Service routine re-mapping and Interrupt vector enable -----------------------------------------------------------------------------*/ /* Not required for this example */ /*----------------------------------------------------------------------------- Step 6 6.1 Initialize Periphrals for User Application -----------------------------------------------------------------------------*/ /* Initialize EPWM4 Module */ InitEPwm4Module(); /*----------------------------------------------------------------------------- Step 7 7.1 Initialize S/W modules and Variables -----------------------------------------------------------------------------*/ BackTicker = 0; PwmCarrierFrequency = PWM_CARRIER; PwmDutyRatio = PWM_DUTY_RATIO; /*----------------------------------------------------------------------------- Step 8 8.1 Enable Global realtime interrupt DBGM 8.2 Enable Global Interrupt -----------------------------------------------------------------------------*/ ERTM; /* Enable Global realtime interrupt DBGM */ EINT; /* Enable Global interrupt INTM */ /*----------------------------------------------------------------------------- Step 9 9.1 Idle Loop -----------------------------------------------------------------------------*/ /* IDLE loop. Just sit and loop forever: */ for(;;) { BackTicker++; #if(UFEC) EPwm4Regs.TBPRD = (TBCLK / PwmCarrierFrequency) - 1; EPwm4Regs.CMPA.half.CMPA = (EPwm4Regs.TBPRD + 1) * PwmDutyRatio; #endif #if(UREC) EPwm4Regs.TBPRD = (TBCLK / PwmCarrierFrequency) - 1; EPwm4Regs.CMPA.half.CMPA = EPwm4Regs.TBPRD - ((EPwm4Regs.TBPRD + 1) * PwmDutyRatio); #endif #if(DFEC) EPwm4Regs.TBPRD = (TBCLK / PwmCarrierFrequency) - 1; EPwm4Regs.CMPA.half.CMPA = EPwm4Regs.TBPRD - ((EPwm4Regs.TBPRD + 1) * PwmDutyRatio); #endif #if(DREC) EPwm4Regs.TBPRD = (TBCLK / PwmCarrierFrequency) - 1; EPwm4Regs.CMPA.half.CMPA = (EPwm4Regs.TBPRD + 1) * PwmDutyRatio; #endif } } /*----------------------------------------------------------------------------- Step 10 10.1 Local Interrupt Service Routines & Functions -----------------------------------------------------------------------------*/ void InitEPwm4Module(void) { /* Setup Counter Mode and Clock */ #if(UFEC) EPwm4Regs.TBCTL.bit.CTRMODE = 0; /* Count Up (Asymmetric) */ #endif #if(UREC) EPwm4Regs.TBCTL.bit.CTRMODE = 0; /* Count Up (Asymmetric) */ #endif #if(DFEC) EPwm4Regs.TBCTL.bit.CTRMODE = 1; /* Count Down (Asymmetric) */ #endif #if(DREC) EPwm4Regs.TBCTL.bit.CTRMODE = 1; /* Count Down (Asymmetric) */ #endif EPwm4Regs.TBCTL.bit.HSPCLKDIV = 0; /* TBCLK = SYSCLKOUT / (HSPCLKDIV * CLKDIV) = 150MHz */ EPwm4Regs.TBCTL.bit.CLKDIV = 0; /* Setup Phase */ EPwm4Regs.TBPHS.half.TBPHS = 0; /* Phase is 0 */ EPwm4Regs.TBCTL.bit.PHSEN = 0; /* Disable phase loading */ /* Setup Period (Carrier Frequency) */ EPwm4Regs.TBPRD = (TBCLK/PWM_CARRIER)-1; /* Set Timer Period, (150MHz/20KHz)-1 = 7,499 (0x1D4B) */ EPwm4Regs.TBCTR = 0; /* Clear Counter */ /* Set Compare Value */ #if(UFEC) /* Set Compare A Value to 20% */ EPwm4Regs.CMPA.half.CMPA = (Uint16)((EPwm4Regs.TBPRD + 1) * PWM_DUTY_RATIO); #endif #if(UREC) /* Set Compare A Value to 20% */ EPwm4Regs.CMPA.half.CMPA = (Uint16)(EPwm4Regs.TBPRD - ((EPwm4Regs.TBPRD + 1) * PWM_DUTY_RATIO)); #endif #if(DFEC) /* Set Compare A Value to 20% */ EPwm4Regs.CMPA.half.CMPA = (Uint16)(EPwm4Regs.TBPRD - ((EPwm4Regs.TBPRD + 1) * PWM_DUTY_RATIO)); #endif #if(DREC) /* Set Compare A Value to 20% */ EPwm4Regs.CMPA.half.CMPA = (Uint16)((EPwm4Regs.TBPRD + 1) * PWM_DUTY_RATIO); #endif /* Setup shadowing */ EPwm4Regs.TBCTL.bit.PRDLD = 0; /* Period Register is loaded from its shadow when CNTR=Zero */ EPwm4Regs.CMPCTL.bit.SHDWAMODE = 0; /* Compare A Register is loaded from its shadow when CNTR=Zero */ EPwm4Regs.CMPCTL.bit.LOADAMODE = 0; /* Set actions */ #if(UFEC) EPwm4Regs.AQCTLA.bit.ZRO = 2; /* Set EPWM4A on CNTR=Zero */ EPwm4Regs.AQCTLA.bit.CAU = 1; /* Clear EPWM4A on CNTR=CMPA, Up-Count */ #endif #if(UREC) EPwm4Regs.AQCTLA.bit.CAU = 2; /* Set EPWM4A on CNTR=CMPA, Up-Count */ EPwm4Regs.AQCTLA.bit.PRD = 1; /* Clear EPWM4A on CNTR=PRD */ #endif #if(DFEC) EPwm4Regs.AQCTLA.bit.PRD = 2; /* Set EPWM4A on CNTR=PRD */ EPwm4Regs.AQCTLA.bit.CAD = 1; /* Clear EPWM4A on CNTR=CMPA, Down-Count */ #endif #if(DREC) EPwm4Regs.AQCTLA.bit.CAD = 2; /* Set EPWM4A on CNTR=CMPA, Down-Count */ EPwm4Regs.AQCTLA.bit.ZRO = 1; /* Clear EPWM4A on CNTR=Zero */ #endif } /*====================================================================== End of file. ======================================================================*/