Hi,
I am reading an ADC connected to a DMA at 20Khz at input A, triggered by PIT. However I need to read other 03 ADCs at 100Hz.
Is not possible to squeeze these 03 adc readings in between DMA interrupts because the 20KHz ADC start to miss some bytes. Input B is only hardware triggered and I am not able to get readings from those other 03 ADCs from a simple timer.
Does anyone have a sample code with a similar solution?
Thank you so much,
John
Hi
I check in all the samples code that we have but we do not have such example code. I'm really sorry.
Have a good day.
Hi
This solution is integrated in the uTasker Kinetis project as described at https://community.nxp.com/thread/446206
For example, the following sets TPM1 channels 0 and 1 to perform 20kHz sampling with one fixed input (ADC0-SE8) saving to a RAM buffer (sADC_buffer) by DMA. A PIT interrupt is then used to sample the B input
PWM_INTERRUPT_SETUP pwm_setup; // pwm configuration parameters
PIT_SETUP pit_setup; // PIT interrupt configuration parameters
ADC_SETUP adc_setup; // interrupt configuration parameters
adc_setup.int_type = ADC_INTERRUPT; // identifier when configuring
adc_setup.dma_int_priority = 3; // priority of DMA interrupt the user wants to set
adc_setup.dma_int_handler = 0; // no interrupt so that free-running circular buffer is used (when ADC_FULL_BUFFER_DMA_AUTO_REPEAT is not defined)
adc_setup.ucDmaTriggerSource = DMAMUX0_CHCFG_SOURCE_TPM1_OVERFLOW; // trigger DMA TPM overflows
adc_setup.ucDmaChannel = 2; // DMA channel 2 used
adc_setup.int_adc_mode = (ulCalibrate | ADC_FULL_BUFFER_DMA | ADC_HALF_BUFFER_DMA | ADC_SELECT_INPUTS_A | ADC_CLOCK_BUS_DIV_2 | ADC_CLOCK_DIVIDE_8 | ADC_SAMPLE_ACTIVATE_LONG | ADC_CONFIGURE_ADC | ADC_REFERENCE_VREF | ADC_CONFIGURE_CHANNEL | ADC_SINGLE_ENDED_INPUT | ADC_SINGLE_SHOT_MODE | ADC_12_BIT_MODE | ADC_HW_TRIGGERED); // hardware triggering (DMA to buffer)
adc_setup.int_adc_mode |= ADC_FULL_BUFFER_DMA_AUTO_REPEAT; // automated DMA (using interrupt) restart when not using modulo repetitions
adc_setup.pga_gain = PGA_GAIN_OFF; // PGA gain can be specified for certain inputs
adc_setup.int_adc_controller = 0; // ADC controller 0
adc_setup.int_adc_int_type = (ADC_SINGLE_SHOT_TRIGGER_INT); // interrupt type
adc_setup.int_adc_offset = 0; // no offset
adc_setup.int_adc_bit = ADC_SE8_SINGLE; // input A to sample
adc_setup.ptrADC_Buffer = sADC_buffer; // ADC sample buffer to be used
adc_setup.ulADC_buffer_length = sizeof(sADC_buffer); // physical length of the buffer
adc_setup.dma_int_handler = 0; // no user DMA interrupt call-back
adc_setup.int_adc_sample = (ADC_SAMPLE_LONG_PLUS_12 | ADC_SAMPLE_AVERAGING_8); // additional sampling clocks and hardware averaging
adc_setup.int_adc_bit_b = ADC_TEMP_SENSOR; // input B is only valid when using HW triggered mode
adc_setup.int_adc_result = 0; // no result is requested
fnConfigureInterrupt((void *)&adc_setup); // configure ADC
pwm_setup.int_type = PWM_INTERRUPT;
pwm_setup.pwm_mode = (PWM_SYS_CLK | PWM_PRESCALER_16 | PWM_CENTER_ALIGNED | PWM_DMA_PERIOD_ENABLE | PWM_NO_OUTPUT); // clock PWM timer from the system clock with /16 pre-scaler (don't use an output)
pwm_setup.int_handler = 0; // no user interrupt call-back on PWM cycle
pwm_setup.pwm_frequency = PWM_FREQUENCY(20000, 16); // generate 20kHz on PWM output (/16 pre-scaler)
pwm_setup.pwm_value = _PWM_PERCENT(1, pwm_setup.pwm_frequency); // 1% PWM (high/low)
pwm_setup.pwm_reference = (_TIMER_1 | 0); // timer module 1, channel 0 (triggers ADC0 input A)
fnConfigureInterrupt((void *)&pwm_setup);
pwm_setup.pwm_value = _PWM_PERCENT(99, pwm_setup.pwm_frequency); // 99% PWM (high/low)
pwm_setup.pwm_reference = (_TIMER_1 | 1); // timer module 1, channel 1 (triggers ADC0 input B)
fnConfigureInterrupt((void *)&pwm_setup);
pit_setup.int_type = PIT_INTERRUPT;
pit_setup.mode = PIT_PERIODIC;
pit_setup.ucPIT = 0; // use PIT0
pit_setup.int_handler = slow_sample;
pit_setup.int_priority = PIT0_INTERRUPT_PRIORITY;
pit_setup.count_delay = PIT_MS_DELAY(5); // 5ms period
fnConfigureInterrupt((void *)&pit_setup); // configure PIT
The PIT interrupt can cycle through 4 x B inputs using (eg. of ADC0-SE4, ADC0-SE12 ADC0-Differential, temperature sensor sequence)
#define MUX_INPUT_COUNT 4
static const unsigned long ulNextMuxInput[MUX_INPUT_COUNT] = {
ADC_SE4_SINGLE, ADC_SE12_SINGLE, (ADC_D3_DIFF | ADC_SC1A_DIFF), ADC_TEMP_SENSOR
};
static unsigned short usLastSample[MUX_INPUT_COUNT];
static void slow_sample(void) // PIT interrupt called periodically to collect result and set next mux input
{
static int InputMuxSelect = 0;
usLastSample[InputMuxSelect] = ADC0_RB; // read the result of the previous B input sample
if (++InputMuxSelect >= MUX_INPUT_COUNT) { // cycle though inputs
InputMuxSelect = 0; // set back to the first input
}
ADC0_SC1B = ulNextMuxInput[InputMuxSelect]; // set next B input to be sampled
}
Regards
Mark
Professional support for Kinetis: http://www.utasker.com/index.html
Remote desktop one-on-one coaching: http://www.utasker.com/services.html
Getting started to expert videos: https://www.youtube.com/results?search_query=utasker+shorts