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
}
解決済! 解決策の投稿を見る。
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:
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
Hi Irmantas Budrys,
Please read the "24.4.3 Hardware trigger" of KEA128RM.pdf. See below:
When hardware trigger is selected, a ADC conversion is initiated following the assertion of the ADHWT input.
And you need selects "PIT channel0 overflow" as the ADC hardware trigger source.
Best Regards,
Robin
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
---------------------------------------------------------------------------------------------------------------------
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
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:
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