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.
======================================================================*/