This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
Tool/software: Code Composer Studio
If I want to set sample rate as 4kHz,what the TPBRD value should be? what mapping relationship between the sampling frequency and the TPBRD?
Please refer to Figure 15-6 in the TRM for this device (spruhm8h) to see the relationship between TBPRD and frequency. Presumably you are triggering the ADC from a PWM module. Note that the sampling frequency will depend on the clock frequency you have chosen for the PWM module (typically 100 MHz on this device) and whether you are using symmetrical or up-/dn-counting for the time-base. All this is explained in section 15.4.3 of the TRM, which you can find here:
Regards,
Richard
I think you will find it useful to follow the recording of the 1-day workshop on this device, here:
Section 1.6 in particular covers how to configure the PWM module.
To determine which count mode is active, you can inspect the CTRMODE field (bits 0-1) in the TBCTL register for the relevant PWM module. You can view this register in a CCS registers window. The logic is:
00: Up-count mode
01: Down-count mode
10: Up-down count mode
The settings which determine clock frequency and ADC triggering are all in chapter 15 of the TRM I linked in my last post.
Hope this helps.
Regards,
Richard
Tianyi,
You're welcome! The author of the example configured the PWM to generate SOCs for the ADC when there is a CMPA match and the timer timer is counting up. This is done in the line:
EPwm1Regs.ETSEL.bit.SOCASEL = 4; // Select SOC on up-count
He chose to set the CMPA value at half the period value:
EPwm1Regs.CMPA.bit.CMPA = 0x0800; // Set compare A value to 2048 counts
EPwm1Regs.TBPRD = 0x1000; // Set period to 4096 counts
I don't think there was any special reason for that choice. Since neither TBPRD not CMPA are modified afterwards, the sample rate remains fixed.
The program does not modify the TBCLK so the default of /1 is taken inside the PWM module. However, there is a pre-scalar outside the module which is set by the PERCLKDIVSEL register (see Figure 15-5 in the TRM). The default setting for that is /2, so the TB is being clocked at half the system clock - i.e. 100 MHz.
Regards,
Richard
Thank you for your reply,
and I will up load the program, can you help me to check the sample rate is 5254 or not? All I changed is the value of TBPRD and CMPA.And I ensure that my sine wawe is right(3V,2kHz).
In addition, You mean that ADC input pins are default analogue inputs and I need not to change it?
thanks and best,
Tianyi
//########################################################################### // FILE: adc_soc_epwm_cpu01.c // TITLE: ADC triggering via epwm for F2837xS. // //! \addtogroup cpu01_example_list //! <h1> ADC ePWM Triggering (adc_soc_epwm)</h1> //! //! This example sets up the ePWM to periodically trigger the ADC. //! //! After the program runs, the memory will contain:\n //! - \b AdcaResults \b: A sequence of analog-to-digital conversion samples from //! pin A0. The time between samples is determined based on the period //! of the ePWM timer. // //########################################################################### // $TI Release: F2837xS Support Library v190 $ // $Release Date: Mon Feb 1 16:59:09 CST 2016 $ // $Copyright: Copyright (C) 2014-2016 Texas Instruments Incorporated - // http://www.ti.com/ ALL RIGHTS RESERVED $ //########################################################################### #include "F28x_Project.h" // Device Headerfile and Examples Include File void ConfigureADC(void); void ConfigureEPWM(void); void SetupADCEpwm(Uint16 channel); interrupt void adca1_isr(void); //buffer for storing conversion results #define RESULTS_BUFFER_SIZE 512 int16 AdcaResults[RESULTS_BUFFER_SIZE]; Uint16 resultsIndex; volatile Uint16 bufferFull; void main(void) { // Step 1. Initialize System Control: // PLL, WatchDog, enable Peripheral Clocks // This example function is found in the F2837xS_SysCtrl.c file. InitSysCtrl(); // Step 2. Initialize GPIO: // This example function is found in the F2837xS_Gpio.c file and // illustrates how to set the GPIO to it's default state. InitGpio(); // Skipped for this example // Step 3. Clear all interrupts and initialize PIE vector table: // Disable CPU interrupts DINT; // Initialize the PIE control registers to their default state. // The default state is all PIE interrupts disabled and flags // are cleared. // This function is found in the F2837xS_PieCtrl.c file. InitPieCtrl(); // Disable CPU interrupts and clear all CPU interrupt flags: IER = 0x0000; IFR = 0x0000; // Initialize the PIE vector table with pointers to the shell Interrupt // Service Routines (ISR). // This will populate the entire table, even if the interrupt // is not used in this example. This is useful for debug purposes. // The shell ISR routines are found in F2837xS_DefaultIsr.c. // This function is found in F2837xS_PieVect.c. InitPieVectTable(); //Map ISR functions EALLOW; PieVectTable.ADCA1_INT = &adca1_isr; //function for ADCA interrupt 1 EDIS; //Configure the ADC and power it up ConfigureADC(); //Configure the ePWM ConfigureEPWM(); //Setup the ADC for ePWM triggered conversions on channel 0 SetupADCEpwm(0); //Enable global Interrupts and higher priority real-time debug events: IER |= M_INT1; //Enable group 1 interrupts EINT; // Enable Global interrupt INTM ERTM; // Enable Global realtime interrupt DBGM //Initialize results buffer for(resultsIndex = 0; resultsIndex < RESULTS_BUFFER_SIZE; resultsIndex++) { AdcaResults[resultsIndex] = 0; } resultsIndex = 0; bufferFull = 0; //enable PIE interrupt PieCtrlRegs.PIEIER1.bit.INTx1 = 1; //sync ePWM EALLOW; CpuSysRegs.PCLKCR0.bit.TBCLKSYNC = 1; //take conversions indefinitely in loop do { //start ePWM EPwm1Regs.ETSEL.bit.SOCAEN = 1; //enable SOCA EPwm1Regs.TBCTL.bit.CTRMODE = 0; //unfreeze, and enter up count mode //wait while ePWM causes ADC conversions, which then cause interrupts, //which fill the results buffer, eventually setting the bufferFull //flag while(!bufferFull); bufferFull = 0; //clear the buffer full flag //stop ePWM EPwm1Regs.ETSEL.bit.SOCAEN = 0; //disable SOCA EPwm1Regs.TBCTL.bit.CTRMODE = 3; //freeze counter //at this point, AdcaResults[] contains a sequence of conversions //from the selected channel //software breakpoint, hit run again to get updated conversions //asm(" ESTOP0"); }while(1); } //Write ADC configurations and power up the ADC for both ADC A and ADC B void ConfigureADC(void) { EALLOW; //write configurations AdcaRegs.ADCCTL2.bit.PRESCALE = 6; //set ADCCLK divider to /4 AdcSetMode(ADC_ADCA, ADC_RESOLUTION_12BIT, ADC_SIGNALMODE_SINGLE); //Set pulse positions to late AdcaRegs.ADCCTL1.bit.INTPULSEPOS = 1; //power up the ADC AdcaRegs.ADCCTL1.bit.ADCPWDNZ = 1; //delay for 1ms to allow ADC time to power up DELAY_US(1000); EDIS; } void ConfigureEPWM(void) { EALLOW; // Assumes ePWM clock is already enabled EPwm1Regs.ETSEL.bit.SOCAEN = 0; // Disable SOC on A group EPwm1Regs.ETSEL.bit.SOCASEL = 4; // Select SOC on up-count EPwm1Regs.ETPS.bit.SOCAPRD = 1; // Generate pulse on 1st event EPwm1Regs.CMPA.bit.CMPA = 0x4A59; // Set compare A value to 2048 counts EPwm1Regs.TBPRD = 0x94B1; // Set period to 4096 counts EPwm1Regs.TBCTL.bit.CTRMODE = 3; // freeze counter EDIS; } void SetupADCEpwm(Uint16 channel) { Uint16 acqps; //determine minimum acquisition window (in SYSCLKS) based on resolution if(ADC_RESOLUTION_12BIT == AdcaRegs.ADCCTL2.bit.RESOLUTION){ acqps = 14; //75ns } else { //resolution is 16-bit acqps = 63; //320ns } //Select the channels to convert and end of conversion flag EALLOW; AdcaRegs.ADCSOC0CTL.bit.CHSEL = channel; //SOC0 will convert pin A0 AdcaRegs.ADCSOC0CTL.bit.ACQPS = acqps; //sample window is 100 SYSCLK cycles AdcaRegs.ADCSOC0CTL.bit.TRIGSEL = 5; //trigger on ePWM1 SOCA/C AdcaRegs.ADCINTSEL1N2.bit.INT1SEL = 0; //end of SOC0 will set INT1 flag AdcaRegs.ADCINTSEL1N2.bit.INT1E = 1; //enable INT1 flag AdcaRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; //make sure INT1 flag is cleared } interrupt void adca1_isr(void) { AdcaResults[resultsIndex++] = AdcaResultRegs.ADCRESULT0; if(RESULTS_BUFFER_SIZE <= resultsIndex) { resultsIndex = 0; bufferFull = 1; } AdcaRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; //clear INT1 flag PieCtrlRegs.PIEACK.all = PIEACK_GROUP1; }
Hi Tianyi,
I think your SOC rate is half what you are aiming for: you are actually sampling a 2 kHz sine wave at 2.627 kHz.
The TBCLK is 100 MHz, and you have set the TBPRD to 0x94B1 = 38,065, which is twice what it should be. TBPRD is what determines the frequency, not CMPA. You need to change TBPRD to 0x4A58 = 19,032 and set CMPA to a value smaller than that, say 0x252C = 9,516. Then I think it will work.
EPwm1Regs.CMPA.bit.CMPA = 0x252C;
EPwm1Regs.TBPRD = 0x4A58;
You cannot change the function of the analogue pins. They are not GPIOs.
Regards,
Richard
Hi Richard,
I have set the CMPA and TBPRD as your command.
EPwm1Regs.CMPA.bit.CMPA = 0x252C;
EPwm1Regs.TBPRD = 0x4A58;
And sampled both in Differential-signal and single-signal mode, The sampled data and it' correspding matlab figure and fft frequency will be upload, I doubt that my data is not correspd to 2kHz sine wave at the 5254 sample rate. Could you help me analysis whether my data is right or not and why? It seems like that the fft frequency is not 2kHz.
best and thanks,
Tianyi