ADC interrupt

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

ADC interrupt

Jump to solution
3,897 Views
irmantasbudrys
Contributor III

Hello,

I am using FRDM DEV BRD KEAZ128 and S32. I am writing a code where PIT gives interrupt every 1s and starts ADC conversion. But I am not waiting in while loop for COCO bit to set 1. I am enabling ADC interrupt and doing some simple math in main() in for(;;) loop. 

But the problem is that ADC interrupt does not show up. I know that PIT interrupts works. But I do not understand how to trigger  ADC (adc interrupt and start adc conversion) after PIT interrupt. Could you help me here?  

 my main loop:

int main(void)
{


init_UART();
ADC_Init(10,2); //ADC_init ( channel,mode)
Enable_ADC_Interrupt();
init_pit_0 ();
init_IRQs(); /* Initialize PIT interrupts */

for(;;){

if (ready_flag==1)
{
ADC_accumulator+= ADC_Result ; // read ADC value and add total
dec--; // update decimation counter
GPIOB_PTOR |= (1<<PTH1);
ready_flag=0;

if (dec==0)
{
dec=16; // reset counter
My_ADC_Result= ADC_accumulator>>2;// 14bit value
My_ADC_Result=My_ADC_Result * 5000; // ADC value times 5000mV
My_ADC_Result=My_ADC_Result>>14; // converts ADC value to mV
print_adc_value= My_ADC_Result; // writes ADC value to uint16_t variable for printf()

printf("\nADC= %d",print_adc_value ); // print to terminal ADC value in mV


ADC_accumulator=0;
My_ADC_Result=0;
print_adc_value =0;

}

}
}

return 0;

my PIT.C :

 

/* Initialize PIT to generate interrupt every... */
void init_pit_0 (void) {

SIM_SCGC |= SIM_SCGC_PIT_MASK; /* enable clock for PIT*/
PIT_MCR= 0x0; /* Turn on PIT module, Freeze disabled */
PIT_LDVAL0 |= 2400000 - 1; /*PIT0: Load value to count 24MHz bus clocks */
/* if bus clock 24MHz it is equal to 1s */
//PIT_LDVAL0 |= 750 - 1; /* for 32kHz sampling freq = 32.25us */

PIT_TCTRL0 |= PIT_TCTRL_TIE_MASK ; /* Enable interrupt */
PIT_TCTRL0 |= PIT_TCTRL_TEN_MASK; /* PIT0: Start timer */

}

/* Initialize PIT interrupts */
void init_IRQs (void) {

NVIC_ClearPendingIRQ(PIT_CH0_IRQn); /* Clear any Pending IRQ for PIT (#22) */
NVIC_EnableIRQ(PIT_CH0_IRQn); /* Set Enable IRQ for PIT */
NVIC_SetPriority(PIT_CH0_IRQn,0); /* Set Priority for PIT */

}

/* Initialize PIT interrupt handler */
void PIT_CH0_IRQHandler (void) {

PIT_TFLG0 |= PIT_TFLG_TIF_MASK ; /* Clear PIT0 clear flag/acknowledge */
//ADC_Result = ADC_R;
//ADC_Result= ADC_Read(10);
//ready_flag=1; //ready flag

}

my ADC.C 

void ADC_Init (uint8_t channel, uint8_t mode){

SIM_SCGC |=SIM_SCGC_ADC_MASK ; /* Enable bus clock for ADC */

ADC_SC3 |= ADC_SC3_ADICLK(0b00); /* Bus clock selected */

ADC_SC2 |= 0x00; /* Software Conversion trigger, disable compare function*/
ADC_SC1 = 0 ;
ADC_SC1|= ADC_SC1_AIEN_MASK; /*Conversion complete interrupt enabled */
ADC_SC1 &= ~ADC_SC1_ADCH_MASK; /* Clear any prior ADCH bits*/
ADC_APCTL1 |= ADC_APCTL1_ADPC(1<<channel); /* Channel selection */
ADC_SC3 = ADC_SC3_MODE(mode); /* Select 0-8bit,1-10bit,2-12 bit mode operation */
}

uint16_t ADC_Read(uint8_t channel)
{

ADC_SC1 |= ADC_SC1_ADCH(channel); /* Select channel to read */
while(!(ADC_SC1 & ADC_SC1_COCO_MASK)); /* Wait conversion to complete */
return ADC_R; /* Return ADC value */

}


/* Initialize ADC interrupts when conversion finished */
void Enable_ADC_Interrupt(void) {

NVIC_ClearPendingIRQ( ADC_IRQn ); /* Clear any Pending IRQ for ADC (#15) */
NVIC_EnableIRQ( ADC_IRQn ); /* Set Enable IRQ for ADC */
NVIC_SetPriority( ADC_IRQn ,0); /* Set Priority for ADC */

ADC_SC1 |=ADC_SC1_AIEN_MASK; /*Conversion complete interrupt enabled */
}

void ADC_IRQHandler (void) {
ADC_Result = ADC_Read(10);
ready_flag=1; //ready flag
}

0 Kudos
1 Solution
2,155 Views
Robin_Shen
NXP TechSupport
NXP TechSupport

Hi

That ADC_Read function seems to be used for polling mode of ADC.

The ADCH bits in ADC_SC1 register can be used to change ADC channel.

If you don't need to change ADC channel, the ADCH bits can be set in ADC_Init function.

If you need to change ADC channel, please refer the function below:

ADC_SetChannel.png

The PIT channel0 overflow will trigger ADC module start sample the signal of that channel.

So you can direct read the ADC_R in your ADC(Conversion Complete) interrupt function. See below:

void ADC_IRQHandler (void) {
   ADC_Result = ADC_R;
   ready_flag=1;
}

Best Regards,

Robin

View solution in original post

3 Replies
2,155 Views
Robin_Shen
NXP TechSupport
NXP TechSupport

Hi Irmantas Budrys,

Please read the "24.4.3 Hardware trigger" of KEA128RM.pdf. See below:

24.4.3 Hardware trigger.png

When hardware trigger is selected, a ADC conversion is initiated following the assertion of the ADHWT input.

ADTRG.png

And you need selects "PIT channel0 overflow" as the ADC hardware trigger source.

ADHWT SIM_SOPT0.png

Best Regards,

Robin

 

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
---------------------------------------------------------------------------------------------------------------------

2,155 Views
irmantasbudrys
Contributor III

Hello Robin,

Thank you for your answer, it is really helpful. But I think it answers only half of my question.

When ADC is triggered conversation takes around 4us. So instead waiting in while() loop (function ADC_Read() below) until conversation is completed I would like to do something useful in my  main()  function.

You explained me how to trigger ADC, but I still do not understand how to read ADC value after ADC interrupt occurred?

uint16_t ADC_Read(uint8_t channel)
{

ADC_SC1 |= ADC_SC1_ADCH(channel); /* Select channel to read */
while(!(ADC_SC1 & ADC_SC1_COCO_MASK)); /* Wait conversion to complete */
return ADC_R; /* Return ADC value */

}

Best Regards,

IB

2,156 Views
Robin_Shen
NXP TechSupport
NXP TechSupport

Hi

That ADC_Read function seems to be used for polling mode of ADC.

The ADCH bits in ADC_SC1 register can be used to change ADC channel.

If you don't need to change ADC channel, the ADCH bits can be set in ADC_Init function.

If you need to change ADC channel, please refer the function below:

ADC_SetChannel.png

The PIT channel0 overflow will trigger ADC module start sample the signal of that channel.

So you can direct read the ADC_R in your ADC(Conversion Complete) interrupt function. See below:

void ADC_IRQHandler (void) {
   ADC_Result = ADC_R;
   ready_flag=1;
}

Best Regards,

Robin