ADC scan on l series Kinetis

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

ADC scan on l series Kinetis

788 Views
christianlees
Contributor III

I'attempting to get ADC channel scanning to work on a MKL17Z256.  There are examples of how to do it on a K series but not for the L series which has a different DMA controller.

I'm assuming it is possible in the same way using 2 DMA channels,  one loading the ADC channel and the other copying the data out.

Following is what I have but it is not working.  I'm not sure if I have the channel linking configured correctly

static void DMA_Callback_0(dma_handle_t *handle, void *userData)
{
uint32_t flags = DMA_GetChannelStatusFlags(DMA0, 0);
PRINTF("Flag 0: %u\r\n", flags);
DMA_ClearChannelStatusFlags(DMA0, 0, kDMA_TransactionsDoneFlag);


static void DMA_Callback_1(dma_handle_t *handle, void *userData)
{
uint32_t flags = DMA_GetChannelStatusFlags(DMA0, 1);
PRINTF("Flag 1: %u\r\n", flags);
if(flags & kDMA_TransactionsDoneFlag)
{

DMA_SubmitTransfer(&g_DMA_Handle_0, &transferConfig_0, kDMA_EnableInterrupt);
DMA_StartTransfer(&g_DMA_Handle_0);

DMA_SubmitTransfer(&g_DMA_Handle_1, &transferConfig_1, kDMA_EnableInterrupt);
DMA_StartTransfer(&g_DMA_Handle_1);

PRINTF("!");
DMA_ClearChannelStatusFlags(DMA0, 1, kDMA_TransactionsDoneFlag);
}

}

void adc_init()
{
//EnableIRQ(ADC0_IRQn);

adc16_config_t adc16ConfigStruct;
adc16_channel_config_t adc16ChannelConfigStruct;
/*
* adc16ConfigStruct.referenceVoltageSource = kADC16_ReferenceVoltageSourceVref;
* adc16ConfigStruct.clockSource = kADC16_ClockSourceAsynchronousClock;
* adc16ConfigStruct.enableAsynchronousClock = true;
* adc16ConfigStruct.clockDivider = kADC16_ClockDivider8;
* adc16ConfigStruct.resolution = kADC16_ResolutionSE12Bit;
* adc16ConfigStruct.longSampleMode = kADC16_LongSampleDisabled;
* adc16ConfigStruct.enableHighSpeed = false;
* adc16ConfigStruct.enableLowPower = false;
* adc16ConfigStruct.enableContinuousConversion = false;
*/
ADC16_GetDefaultConfig(&adc16ConfigStruct);
adc16ConfigStruct.resolution = kADC16_Resolution16Bit;
adc16ConfigStruct.enableContinuousConversion = true;
adc16ConfigStruct.clockSource = kADC16_ClockSourceAlt1;

adc16ConfigStruct.longSampleMode = kADC16_LongSampleCycle24;
adc16ConfigStruct.enableLowPower = true;

ADC16_Init( ADC0, &adc16ConfigStruct);

ADC16_DoAutoCalibration( ADC0 );

ADC16_EnableHardwareTrigger( ADC0, true);
ADC16_EnableDMA( ADC0, true);

adc16ChannelConfigStruct.channelNumber = g_ADC_mux[6];
adc16ChannelConfigStruct.enableInterruptOnConversionCompleted = true; /* Enable the interrupt. */
adc16ChannelConfigStruct.enableDifferentialConversion = false;
ADC16_SetChannelConfig( ADC0, 0, &adc16ChannelConfigStruct);

/* Configure SIM for ADC hw trigger source selection */
SIM->SOPT7 |= 0x8EU; // LPTMR, 1kHz
}

void dma_init()
{
/****************************************
* DMA Config
****************************************/

/* Configure DMAMUX */
DMAMUX_Init(DMAMUX0);

DMAMUX_SetSource(DMAMUX0, DMAChannel_0, 60); /* Channel 0 Source 60: DMA always enabled */
DMAMUX_EnableChannel(DMAMUX0, DMAChannel_0);

DMAMUX_SetSource(DMAMUX0, DMAChannel_1, 40); /* Channel 1 Source 40: ADC COCO trigger */
DMAMUX_EnableChannel(DMAMUX0, DMAChannel_1);

DMA_Init(DMA0);
DMA_CreateHandle(&g_DMA_Handle_0, DMA0, 0);
DMA_SetCallback(&g_DMA_Handle_0, DMA_Callback_0, NULL);

DMA_CreateHandle(&g_DMA_Handle_1, DMA0, 1);
DMA_SetCallback(&g_DMA_Handle_1, DMA_Callback_1, NULL);

DMA_PrepareTransfer(&transferConfig_0,
&g_ADC_mux[0], /* Source Address (ADC channels array) */
1, /* Source width (1 bytes) */
(uint32_t*)(ADC0->SC1),/* Destination Address (ADC_SC1A_ADCH)*/
1, /* Destination width (1 bytes) */
//sizeof(uint8_t), /* Bytes to transfer each minor loop (1 bytes) */
7, /* Total of bytes to transfer (3*1 bytes) */
kDMA_MemoryToPeripheral);/* From ADC channels array to ADCH register */

DMA_PrepareTransfer(&transferConfig_1,
(uint32_t*) (ADC0->R), /* Source Address (ADC0_RA) */
2, /* Source width (2 bytes) */
g_ADC0_resultBuffer, /* Destination Address (Internal buffer)*/
2, /* Destination width (2 bytes) */
//sizeof(uint16_t), /* Bytes to transfer each minor loop (2 bytes) */
B_SIZE * 2, /* Total of bytes to transfer (12*2 bytes) */
kDMA_PeripheralToMemory); /* From ADC to Memory */

DMA_SubmitTransfer(&g_DMA_Handle_0, &transferConfig_0, kDMA_EnableInterrupt);
DMA_SubmitTransfer(&g_DMA_Handle_1, &transferConfig_1, kDMA_EnableInterrupt);


link1.channel1 = 0;
link1.channel2 = 0;
link1.linkType = kDMA_ChannelLinkChannel1;
DMA_SetChannelLinkConfig(DMA0, 1, &link1);

DMA_StartTransfer(&g_DMA_Handle_1);

}

void adc_dma_init()
{

dma_init();
adc_init();
}

Labels (1)
1 Reply

533 Views
jorge_a_vazquez
NXP Employee
NXP Employee

Hi

Please consider that as long as this module doesn't have the minor loop, you will be able to only measure one time the ADC channels, this is if you have 3 channels listed in the g_ADC_mux, then only 3 ADC scan can be performed. Following code implement this with  uint8_t g_ADC_mux[CHANNELS] ={ VREFL_CH, VREFH_CH, CHANNEL_12  }; and B_SIZE= 3

     /****************************************
     * DMA Config
     ****************************************/

     dma_transfer_config_t transferConfig_0;
    dma_transfer_config_t transferConfig_1;

    DMAMUX_Init(DMAMUX0);
    DMAMUX_SetSource(DMAMUX0, DMA_CHANNEL0, DMA_SOURCE0);
    DMAMUX_SetSource(DMAMUX0, DMA_CHANNEL1, DMA_SOURCE1);
    DMAMUX_EnableChannel(DMAMUX0, DMA_CHANNEL0);
    DMAMUX_EnableChannel(DMAMUX0, DMA_CHANNEL1);
    /* Configure DMA one shot transfer */
    DMA_Init(DMA0);
    DMA_CreateHandle(&g_DMA_Handle0, DMA0, DMA_CHANNEL0);
    DMA_CreateHandle(&g_DMA_Handle1, DMA0, DMA_CHANNEL1);

    DMA_SetCallback(&g_DMA_Handle0, DMA_Callback0, NULL);
    DMA_SetCallback(&g_DMA_Handle1, DMA_Callback1, NULL);

    DMA_PrepareTransfer(&transferConfig_1,
                             (uint32_t*) (ADC0->R),
                              sizeof(uint16_t),
                              g_ADC0_resultBuffer,
                              sizeof(g_ADC0_resultBuffer[0]), /* Destination width (2 bytes) */
                              B_SIZE * 2,
                              kDMA_PeripheralToMemory);

    DMA_SubmitTransfer(&g_DMA_Handle1, &transferConfig_1, kDMA_EnableInterrupt);


    DMA_PrepareTransfer(&transferConfig_0,
                             &g_ADC_mux[0],
                              sizeof(g_ADC_mux[0]),
                              (uint32_t*)(ADC0->SC1),
                              sizeof(uint8_t),
                              CHANNELS,
                              kDMA_MemoryToPeripheral);

    DMA_SubmitTransfer(&g_DMA_Handle0, &transferConfig_0, kDMA_EnableInterrupt);

    dma_channel_link_config_t configlink;
    configlink.channel1 = DMA_CHANNEL0;
    configlink.channel2 = DMA_CHANNEL1;
    configlink.linkType = kDMA_ChannelLinkChannel1;

    DMA_SetChannelLinkConfig(DMA0, DMA_CHANNEL1, &configlink);

    DMA_StartTransfer(&g_DMA_Handle1);

Hope this helps, please let me know if you have any question about this.

Best regards

Jorge Alcala