S32K144 2 ADC with PDB Trigger

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

S32K144 2 ADC with PDB Trigger

Jump to solution
802 Views
snow3847
Contributor II

Hi,

I am trying to sample 2 ADCs with 4 Channels each with 1 PDB module. i am trying to sample both ADCs continuously and send an interrupt on when the 4th Conversion is done (for each ADC) then write it to my terminal. I have multiple questions:

1. it samples only ADC0 one time and stops (ADC1 is not sampled at all and ADC0 is only sampled once). why?

2. The results are not written to my terminal. i programmed a print function in the ADC handler. why?

PS: i tried the continous mode for the pdb and the back to back mode for the pretriggers. 

void print(const char *sourceStr)
{
    uint32_t bytesRemaining;
 
    /* Send data via LPUART */
    LPUART_DRV_SendData(INST_LPUART_1, (uint8_t *) sourceStr, strlen(sourceStr));
   // LPUART_DRV_SendDataPolling(INST_LPUART_1, (uint8_t *) sourceStr, strlen(sourceStr));
    /* Wait for transmission to be successful */
    while (LPUART_DRV_GetTransmitStatus(INST_LPUART_1, &bytesRemaining)
            != STATUS_SUCCESS)
    {
    }
}
 
/* The IRQ handler uses the default IRQ handler weak symbol defined in startup (.S) file */
 
void PDB0_IRQHandler(void)
{
  /* Clear PDB instance Interrupt flag */
  PDB_DRV_ClearTimerIntFlag(INST_PDB_0);
 
  print("Timer restarting");
}
 
 
void ADC0_IRQHandler(void)
{
  /* Clear PDB instance Interrupt flag */
  PDB_DRV_ClearTimerIntFlag(INST_PDB_0);
 
  if(ADC_DRV_GetConvCompleteFlag(INST_ADC_CONFIG_1, 3)){
 
  ADC_DRV_GetChanResult(INST_ADC_CONFIG_1,0U, &res[0]);
  ADC_DRV_GetChanResult(INST_ADC_CONFIG_1,1U, &res[1]);
  ADC_DRV_GetChanResult(INST_ADC_CONFIG_1,2U, &res[2]);
  ADC_DRV_GetChanResult(INST_ADC_CONFIG_1,3U, &res[3]);
 
  adcConvDone = true;
  inc++;
 
  for(int i = 0; i<4 ; i++){
      print("ADC 0 results are :");
    uint16ToStr(&res[i], msg[i], 5);
    print(msg[i]);
  }
 
  }
  else counter++;
}
void ADC1_IRQHandler (void){
 
// /* Clear PDB instance Interrupt flag */
  PDB_DRV_ClearTimerIntFlag(INST_PDB_0);
 
if(ADC_DRV_GetConvCompleteFlag(INST_ADC_CONFIG_2, 3)){
 
  ADC_DRV_GetChanResult(INST_ADC_CONFIG_2,0U, &res1[0]);
  ADC_DRV_GetChanResult(INST_ADC_CONFIG_2,1U, &res1[1]);
  ADC_DRV_GetChanResult(INST_ADC_CONFIG_2,2U, &res1[2]);
  ADC_DRV_GetChanResult(INST_ADC_CONFIG_2,3U, &res1[3]);
 
  for(int j = 0; j<4 ; j++){
        print("ADC 1 results are :");
      uint16ToStr(&res1[j], msg1[j], 5);
      print(msg1[j]);
  }
  }
}
bool calculateIntValue(const pdb_timer_config_t * const pdbConfig, const uint32_t uSec, uint16_t * const intVal)
{
    /* Local variables used to store different parameters
     * such as frequency and prescalers
     */
    uint32_t    intVal_l            = 0;
    uint8_t     pdbPrescaler        = (1 << pdbConfig->clkPreDiv);
    uint8_t     pdbPrescalerMult    = 0;
    uint32_t    pdbFrequency;
 
    bool resultValid = false;
 
    /* Get the Prescaler Multiplier from the configuration structure */
    switch (pdbConfig->clkPreMultFactor)
    {
        case PDB_CLK_PREMULT_FACT_AS_1:
            pdbPrescalerMult    =   1U;
            break;
        case PDB_CLK_PREMULT_FACT_AS_10:
            pdbPrescalerMult    =   10U;
            break;
        case PDB_CLK_PREMULT_FACT_AS_20:
            pdbPrescalerMult    =   20U;
            break;
        case PDB_CLK_PREMULT_FACT_AS_40:
            pdbPrescalerMult    =   40U;
            break;
        default:
            /* Defaulting the multiplier to 1 to avoid dividing by 0*/
            pdbPrescalerMult    =   1U;
            break;
    }
 
    /* Get the frequency of the PDB clock source and scale it
     * so that the result will be in microseconds
     */
    CLOCK_SYS_GetFreq(CORE_CLK, &pdbFrequency);
    pdbFrequency /= 1000000;
 
    /* Calculate the interrupt value for the prescaler, multiplier, frequency
     * configured and time needed.
     */
    intVal_l = (pdbFrequency * uSec) / (pdbPrescaler * pdbPrescalerMult );
 
    /* Check if the value belongs to the interval */
    if((intVal_l == 0) || (intVal_l >= (1 << 16)))
    {
        resultValid = false;
        (*intVal) = 0U;
    }
    else
    {
        resultValid = true;
        (*intVal) = (uint16_t)intVal_l;
    }
 
    return resultValid;
}
 
//char msg[30];
uint16_t dutyCycle = 0U;
 
 
int main(void)
{
  status_t error;
 
  /* Configure clocks for PORT */
 
  CLOCK_SYS_Init(g_clockManConfigsArr, CLOCK_MANAGER_CONFIG_CNT,
  g_clockManCallbacksArr, CLOCK_MANAGER_CALLBACK_CNT);
  CLOCK_SYS_UpdateConfiguration(0U, CLOCK_MANAGER_POLICY_AGREEMENT);
 
  /* Set pins as GPIO */
  error = PINS_DRV_Init(NUM_OF_CONFIGURED_PINS0, g_pin_mux_InitConfigArr0);
  DEV_ASSERT(error == STATUS_SUCCESS);
 
  /* Set Output value LED_Green & LED_Red */
  PINS_DRV_SetPins(LED_Green_PORT, 1 << LED_Green_PIN);
//  //PINS_DRV_SetPins(LED_Red_PORT, 1 << LED_Red_PIN);

uint16_t pdbTimerVal;
char value[30];

if (LPUART_DRV_Init(INST_LPUART_1, &lpUartState0, &lpuart_0_InitConfig0)
!= STATUS_SUCCESS)
__asm("bkpt #255");

ftm_state_t ftmStateStruct;

/* Initialize FTM instance */
FTM_DRV_Init(INST_FLEXTIMER_PWM_1, &flexTimer_pwm_1_InitConfig, &ftmStateStruct);

/* Initialize FTM PWM */
FTM_DRV_InitPwm(INST_FLEXTIMER_PWM_1, &flexTimer_pwm_1_PwmConfig);

/*ADC0 and ADC1 Configuration*/
ADC_DRV_ConfigConverter(INST_ADC_CONFIG_1, &adc_config_1_ConvConfig0);
ADC_DRV_ConfigConverter(INST_ADC_CONFIG_2, &adc_config_2_ConvConfig0);

/*ADC0 and ADC1 Auto Calibration*/
ADC_DRV_AutoCalibration(INST_ADC_CONFIG_1);
ADC_DRV_AutoCalibration(INST_ADC_CONFIG_2);

/*PDB Configuration*/
PDB_DRV_Init(INST_PDB_0,&pdb_config_1_timerConfig0);

/*ADC0 Channel Configuration*/
ADC_DRV_ConfigChan(INST_ADC_CONFIG_1, 0U, &Current_Sense_3);
ADC_DRV_ConfigChan(INST_ADC_CONFIG_1, 1U, &Voltage_Sense_2);
ADC_DRV_ConfigChan(INST_ADC_CONFIG_1, 2U, &Voltage_Sense_3);
ADC_DRV_ConfigChan(INST_ADC_CONFIG_1, 3U, &Current_Sense_2);

/*ADC1 Channel Configuration*/
ADC_DRV_ConfigChan(INST_ADC_CONFIG_2, 0U, &Current_Sense_1);
ADC_DRV_ConfigChan(INST_ADC_CONFIG_2, 1U, &Current_Sense_4);
ADC_DRV_ConfigChan(INST_ADC_CONFIG_2, 2U, &Voltage_Sense_1);
ADC_DRV_ConfigChan(INST_ADC_CONFIG_2, 3U, &Voltage_Sense_4);

/*Check if the Interrupt value is ok*/
DEV_ASSERT(calculateIntValue(&pdb_config_1_timerConfig0, TIMEOUT_US, &pdbTimerVal) == true);

/*Pre-Trigger Configuration for ADC0 (CH0 of the PDB)*/

PDB_DRV_ConfigAdcPreTrigger(INST_PDB_0,0,&pdb_config_1_adc0TrigConfig0);
PDB_DRV_ConfigAdcPreTrigger(INST_PDB_0,0,&pdb_config_1_adc0TrigConfig1);
PDB_DRV_ConfigAdcPreTrigger(INST_PDB_0,0,&pdb_config_1_adc0TrigConfig2);
PDB_DRV_ConfigAdcPreTrigger(INST_PDB_0,0,&pdb_config_1_adc0TrigConfig3);

/*Pre-Trigger Configuration for ADC1 (CH1 of the PDB)*/

PDB_DRV_ConfigAdcPreTrigger(INST_PDB_0,1,&pdb_config_1_adc1TrigConfig0);
PDB_DRV_ConfigAdcPreTrigger(INST_PDB_0,1,&pdb_config_1_adc1TrigConfig1);
PDB_DRV_ConfigAdcPreTrigger(INST_PDB_0,1,&pdb_config_1_adc1TrigConfig2);
PDB_DRV_ConfigAdcPreTrigger(INST_PDB_0,1,&pdb_config_1_adc1TrigConfig3);

/*set the Modulus value*/

PDB_DRV_SetTimerModulusValue(INST_PDB_0, pdbTimerVal);

/*set Pre-Trigger Delays for PDB CH0*/

PDB_DRV_SetAdcPreTriggerDelayValue(INST_PDB_0, 0, 0, 400);
PDB_DRV_SetAdcPreTriggerDelayValue(INST_PDB_0, 0, 1, 800);
PDB_DRV_SetAdcPreTriggerDelayValue(INST_PDB_0, 0, 2, 1200);
PDB_DRV_SetAdcPreTriggerDelayValue(INST_PDB_0, 0, 3, 1400);

/*set Pre-Trigger Delays for PDB CH1*/

PDB_DRV_SetAdcPreTriggerDelayValue(INST_PDB_0, 1, 0, 400);
PDB_DRV_SetAdcPreTriggerDelayValue(INST_PDB_0, 1, 1, 800);
PDB_DRV_SetAdcPreTriggerDelayValue(INST_PDB_0, 1, 2, 1200);
PDB_DRV_SetAdcPreTriggerDelayValue(INST_PDB_0, 1, 3, 1400);

INT_SYS_EnableIRQ(PDB0_IRQn);

/*set the Interrupt value*/
PDB_DRV_SetValueForTimerInterrupt(INST_PDB_0, pdbTimerVal);

print("pdbTimerVal :");
uint16ToStr(&pdbTimerVal, value, 5);
print(value);


/*Load Values into the PDB*/
PDB_DRV_LoadValuesCmd(INST_PDB_0);

/*Enable the PDB*/
PDB_DRV_Enable(INST_PDB_0);

/*enable NVIC Interrupts for ADC0*/
INT_SYS_EnableIRQ(ADC0_IRQn);

/*enable NVIC Interrupts for ADC1*/
INT_SYS_EnableIRQ(ADC1_IRQn);


/* Trigger PDB timer */
PDB_DRV_SoftTriggerCmd(INST_PDB_0);

 

 

0 Kudos
Reply
1 Solution
780 Views
Senlent
NXP TechSupport
NXP TechSupport

Hi@snow3847

Senlent_0-1716964394322.png

Senlent_1-1716964422304.png

 

But in your code, One PDB instance to trigger two ADC instances.

Senlent_2-1716964725753.png

 

View solution in original post

0 Kudos
Reply
5 Replies
777 Views
snow3847
Contributor II

Hi,

Thank you for the response. Now i understand that PDB0 is for ADC0 and PDB1 is for ADC1 but i have a question : how do i synchronise them? i want the conversion on ADC0 and on ADC1 to start on the same time. if i understood correctly we should use TRGMUX and FTM. if so can you tell me to parametrise TRGMUX (in the pinout section and peripheral section of s32DS) because i barely found documentation on that.

i will attach what i did under my reply.

thank you .

0 Kudos
Reply
773 Views
Senlent
NXP TechSupport
NXP TechSupport

Hi@snow3847

For FTM,you can use FTM init as Trigger source.

For example:

Enable FTM init trigger:

Senlent_1-1716967522942.png

Senlent_2-1716967567114.png

 

Tags (1)
0 Kudos
Reply
770 Views
snow3847
Contributor II
do i need to map the TRGMUX also in the pinout section?
0 Kudos
Reply
767 Views
Senlent
NXP TechSupport
NXP TechSupport

Hi@snow3847

if you use FTM Init Trigger as PDB trigger source then you don't need to do it, because it is a internal signal.

0 Kudos
Reply
781 Views
Senlent
NXP TechSupport
NXP TechSupport

Hi@snow3847

Senlent_0-1716964394322.png

Senlent_1-1716964422304.png

 

But in your code, One PDB instance to trigger two ADC instances.

Senlent_2-1716964725753.png

 

0 Kudos
Reply