[RTD400 LLD]K344 ADC SW+HW trigger

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

[RTD400 LLD]K344 ADC SW+HW trigger

[RTD400 LLD]K344 ADC SW+HW trigger

1. Abstract

The S32K344 ADC is a SAR ADC with a resolution which can up to 14 bits. It has a variety of software and hardware triggering methods, supports various external trigger sources, and introduces BCTU so that the trigger resources can be externally connected to multi-channel EMIOS and TRIGMUX, adding more ADC trigger sources. This article mainly explains the following ADC software and hardware triggering methods, and provides supporting codes.  

1.png 

Fig 1

It is mainly divided into 5 parts:

(1) SW+ADC: software trigger, by adding timer PIT, the software trigger ADC is called regularly to complete channel sampling, and the collected value is printed out through UART printf.

(2) SW+BCTU+ADC: software trigger, by adding timer PIT, the software trigger BTCU is called regularly to complete ADC channel sampling, and the collected value is printed out through UART printf.

(3) PIT+TRIGMUX+ADC: hardware trigger, connect PIT to ADC through TRIGMUX, trigger ADC channel sampling through PIT hardware, and print the conversion value after the sampling conversion is completed.

(4) EMIOS+BCTUHW+ADC: hardware trigger, through EMIOS timing trigger BCTU to complete the corresponding ADC single channel sampling, due to the high sampling rate, only the BCTU sampling value is printed regularly.

(5) EMIOS+BCTUHWLIST+ADC: hardware trigger, through EMIOS timing trigger BCTU to complete ADC list channel sampling, due to the high sampling rate, the list channel value sampled by BCTU is printed regularly.

2. ADC SW HW Trigger

2.1 Hardware and software platform

SW: RTD400 LLD,S32DS3.5

HW:S32K3X4EVB-T172

2.2 SW+ADC software trigger

    In fact, the original ADC demo of RTD400 already has ADC software and BCTU software trigger. This article adds PIT timing software trigger based on this function, and prints it out through UART printf, making it more convenient to check the ADC test value through serial port printing.

The block diagram structure of the software triggering ADC in this article is as follows:

   2.png

Fig 2

     The S32K344EVB board has a potentiometer connected to ADC1_S10, PTA11:

 3.png

Fig 3

Therefore, the software trigger in this section is mainly used to collect ADC1_S10. The UART printing port uses the serial port of the onboard emulator: LPUART6_RX PTA15, LPUART6_TX PTA16, with a baud rate of 115200.

For the software trigger demo in this article, the main configuration involves the following modules:

(1)Pins:

 4.png

Fig 4

ADC1_s10: PTA11 is the voltage of the onboard potentiometer to be tested, which is adjustable.

PTA29: Connect the onboard D13 red light to test the PIT timer interrupt and enter the flashing state, used as the breathing light of the PIT.

PTA16: UART6_TX, used to send the collected ADC value.

(2)clocks

Used to configure the system clock. You need to pay attention to the UART6 clock source of 40Mhz, the ADC1 clock source of 160Mhz, and the PIT0 clock source of 40Mhz

(3)Peripherals

Involved peripheral modules Siul2_Port,Siul2_Dio, Pit, Lpuart_Uart, Adc_Sar_Ip, IntCtrl_Ip.

Siul2_Port: Add 4 pins ADC PTA11 MSCR 11, RED LED PTA29 MSCR 29, UART6_RX PTA15 MSCR 15, UART6_RX PTA16 MSCR 16.

Siul2_Dio: Add the module mainly to allow related API functions to come in, so as to control GPIO pins.

Pit: Used to generate 1S timing, the main configuration is as follows:

 5.png

Fig 5                                                            

6.png

Fig 6

Lpuart_Uart:

7.png

Fig 7

Adc_Sar_Ip:

 8.png

Fig 8

9.png                                                                       

Fig 9

It should be noted here that ADC calibration prescale and Adc prescaler vale need to meet the following conditions, which can be found on S32K3RM:

 10.png

Fig 10

Since the clock source of ADC1 is 160MHz, the calibration division is configured as 4 and the conversion division is configured as 2.

IntCtrl_Ip:

 11.png

Fig 11

The purpose is to open the interrupt of PIT and LPUART6, and register the corresponding handler.

CT configuration is completed, and the code is generated. Next, move to the main function and add the following code:

void AdcEndOfChainNotif1(void)
{
    notif_triggered1 = TRUE;
    data1 = Adc_Sar_Ip_GetConvData(ADCHWUNIT_1_BOARD_INITPERIPHERALS_INSTANCE, 34);
    /* Checks the measured ADC data conversion */
   // while (ADC_TOLERANCE(data, ADC_BANDGAP));
}
void Pit0ch0Notification(void)
{
    toggleLed = 1U;
    Siul2_Dio_Ip_TogglePins(LED_Q172_PORT, (1<<LED_Q172_PIN));
}
int main(void)
{
    StatusType status;
    uint8 Index;
    Clock_Ip_StatusType clockStatus;

    /* Initialize and configure drivers */
    clockStatus = Clock_Ip_Init(&Clock_Ip_aClockConfig[0]);
    while (clockStatus != CLOCK_IP_SUCCESS)
    {
        clockStatus = Clock_Ip_Init(&Clock_Ip_aClockConfig[0]);
    }
    Siul2_Port_Ip_Init(NUM_OF_CONFIGURED_PINS_PortContainer_0_BOARD_InitPeripherals, g_pin_mux_InitConfigArr_PortContainer_0_BOARD_InitPeripherals);


    /* set PIT 0 interrupt */
    IntCtrl_Ip_Init(&IntCtrlConfig_0);
IntCtrl_Ip_EnableIrq(PIT0_IRQn);

    status = (StatusType) Adc_Sar_Ip_Init(ADCHWUNIT_1_BOARD_INITPERIPHERALS_INSTANCE, &AdcHwUnit_1_BOARD_InitPeripherals);
    while (status != E_OK);

IntCtrl_Ip_InstallHandler(ADC1_IRQn, Adc_Sar_1_Isr, NULL_PTR);

IntCtrl_Ip_EnableIrq(ADC1_IRQn);

    for(Index = 0; Index <= 5; Index++)
    {
        status = (StatusType) Adc_Sar_Ip_DoCalibration(ADCHWUNIT_1_BOARD_INITPERIPHERALS_INSTANCE);
        if(status == E_OK)
        {
            break;
        }
}

    Adc_Sar_Ip_EnableNotifications(ADCHWUNIT_1_BOARD_INITPERIPHERALS_INSTANCE, ADC_SAR_IP_NOTIF_FLAG_NORMAL_ENDCHAIN | ADC_SAR_IP_NOTIF_FLAG_INJECTED_ENDCHAIN);

    /* Initialize PIT instance 0 - Channel 0 */
    Pit_Ip_Init(PIT_INST_0, &PIT_0_InitConfig_PB_BOARD_InitPeripherals);
    /* Initialize channel 0 */
    Pit_Ip_InitChannel(PIT_INST_0, PIT_0_CH_0);
    /* Enable channel interrupt PIT_0 - CH_0 */
    Pit_Ip_EnableChannelInterrupt(PIT_INST_0, CH_0);
    /* Start channel CH_0 */
    Pit_Ip_StartChannel(PIT_INST_0, CH_0, PIT_PERIOD);

    Lpuart_Uart_Ip_Init(UART_LPUART_INTERNAL_CHANNEL, &Lpuart_Uart_Ip_xHwConfigPB_6_BOARD_INITPERIPHERALS);
    printf("S32K344 PIT TRIGMUX ADC demo RTD400.\r\n");
    while(1)
    {
#if 1
      if( toggleLed == 1)
      {
    	  toggleLed = 0;
        /* Start a SW triggered normal conversion on ADC_SAR */

        Adc_Sar_Ip_StartConversion(ADCHWUNIT_1_BOARD_INITPERIPHERALS_INSTANCE, ADC_SAR_IP_CONV_CHAIN_NORMAL);

        /* Wait for the notification to be triggered and read the data */
        while (notif_triggered1 != TRUE);
        notif_triggered1 = FALSE;
        printf("ADC1_s10 ch34 data = %d .\r\n", data1);
      }
#endif

 }
}

The test results are printed as follows:

 12.png

Fig 12

This section content supporting code: S32K344_PIT_SW_ADC_RTD400.zip

 

2.3 SW+BCTU+ADC Software trigger BCTU

Based on SW+ADC trigger, add BCTU, and use BCTU software trigger to complete ADC sampling. The block diagram structure is as follows:

 13.png

Fig 13

This section uses BCTU software to trigger ADC0 sampling. The sampling channel does not actually use external pin input, but collects the bandgap value of ADC0. The software trigger calls the software trigger function through the PIT 1S cycle, and prints the ADC sampling conversion value to UART after completion.

In the CT tool, the main modification points are peripherals, adding ADC0 in adc_sar_lp, and configuring it as BCTU trigger.

 14.png

Fig 14                                                      

15.png

 Fig 15

Here we can see that in Figure 14, the adc ctu mode is: trigger mode.

Add the Bctu_Ip module and configure it as follows:

 16.png

Fig 16

The corresponding selected BCTU channel is 48, which corresponds to the internal bandgap module.

 17.png

Fig 17

The typical value is 1.2V, so the reference voltage is 5V, and the corresponding 14-bit ADC bandgap expected value is:

(2^14)*1.2/5=3932 around.

After completing the CT configuration code generation, add the following code in main.c:

void AdcEndOfChainNotif(void)
{
    notif_triggered = TRUE;
    data = Adc_Sar_Ip_GetConvData(ADCHWUNIT_0_BOARD_INITPERIPHERALS_INSTANCE, ADC_SAR_USED_CH);
}
void Pit0ch0Notification(void)
{
    toggleLed = 1U;
    Siul2_Dio_Ip_TogglePins(LED_Q172_PORT, (1<<LED_Q172_PIN));
}

void BctuWatermarkNotif(void)
{
    uint8 idx;
    notif_triggered = TRUE;
    for (idx = 0u; idx < BCTU_FIFO_WATERMARK; idx++)
    {
    	data_bctu = Bctu_Ip_GetFifoData(BCTUHWUNIT_0_BOARD_INITPERIPHERALS_INSTANCE, BCTU_USED_FIFO_IDX);
    }
}

int main(void)
{
    StatusType status;
    uint8 Index;
    Clock_Ip_StatusType clockStatus;

    /* Initialize and configure drivers */
    clockStatus = Clock_Ip_Init(&Clock_Ip_aClockConfig[0]);
    while (clockStatus != CLOCK_IP_SUCCESS)
    {
        clockStatus = Clock_Ip_Init(&Clock_Ip_aClockConfig[0]);
    }
    Siul2_Port_Ip_Init(NUM_OF_CONFIGURED_PINS_PortContainer_0_BOARD_InitPeripherals, g_pin_mux_InitConfigArr_PortContainer_0_BOARD_InitPeripherals);

    Bctu_Ip_Init(BCTUHWUNIT_0_BOARD_INITPERIPHERALS_INSTANCE, &BctuHwUnit_0_BOARD_INITPERIPHERALS);

    status = (StatusType) Adc_Sar_Ip_Init(ADCHWUNIT_0_BOARD_INITPERIPHERALS_INSTANCE, &AdcHwUnit_0_BOARD_InitPeripherals);
while (status != E_OK);

    /* set PIT 0 interrupt */
    IntCtrl_Ip_Init(&IntCtrlConfig_0);
    IntCtrl_Ip_EnableIrq(PIT0_IRQn);
    /* Install and enable interrupt handlers */
    IntCtrl_Ip_InstallHandler(ADC0_IRQn, Adc_Sar_0_Isr, NULL_PTR);
    IntCtrl_Ip_InstallHandler(BCTU_IRQn, Bctu_0_Isr, NULL_PTR);

    IntCtrl_Ip_EnableIrq(ADC0_IRQn);
    IntCtrl_Ip_EnableIrq(BCTU_IRQn);

    /* Call Calibration function multiple times, to mitigate instability of board source */
    for(Index = 0; Index <= 5; Index++)
    {
        status = (StatusType) Adc_Sar_Ip_DoCalibration(ADCHWUNIT_0_BOARD_INITPERIPHERALS_INSTANCE);
        if(status == E_OK)
        {
            break;
        }
}

    Adc_Sar_Ip_EnableNotifications(ADCHWUNIT_0_BOARD_INITPERIPHERALS_INSTANCE, ADC_SAR_IP_NOTIF_FLAG_NORMAL_ENDCHAIN | ADC_SAR_IP_NOTIF_FLAG_INJECTED_ENDCHAIN);
    /* Start a SW triggered conversion on BCTU using a single trigger */
    Bctu_Ip_SetGlobalTriggerEn(BCTUHWUNIT_0_BOARD_INITPERIPHERALS_INSTANCE, TRUE);
Bctu_Ip_EnableNotifications(BCTUHWUNIT_0_BOARD_INITPERIPHERALS_INSTANCE, BCTU_IP_NOTIF_FIFO1);

    /* Initialize PIT instance 0 - Channel 0 */
    Pit_Ip_Init(PIT_INST_0, &PIT_0_InitConfig_PB_BOARD_InitPeripherals);
    /* Initialize channel 0 */
    Pit_Ip_InitChannel(PIT_INST_0, PIT_0_CH_0);
    /* Enable channel interrupt PIT_0 - CH_0 */
    Pit_Ip_EnableChannelInterrupt(PIT_INST_0, CH_0);
    /* Start channel CH_0 */
    Pit_Ip_StartChannel(PIT_INST_0, CH_0, PIT_PERIOD);

    Trgmux_Ip_Init(&Trgmux_Ip_xTrgmuxInitPB);//
    Lpuart_Uart_Ip_Init(UART_LPUART_INTERNAL_CHANNEL, &Lpuart_Uart_Ip_xHwConfigPB_6_BOARD_INITPERIPHERALS);


    printf("S32K344 PIT TRIGMUX ADC demo RTD400.\r\n");

    while(1)
    {
      if( toggleLed == 1)
      {
    	  toggleLed = 0;
    	  Bctu_Ip_SwTriggerConversion(BCTUHWUNIT_0_BOARD_INITPERIPHERALS_INSTANCE, BCTU_USED_SINGLE_TRIG_IDX);
    	  while (notif_triggered != TRUE);
    	  notif_triggered = FALSE;
    	  printf("ADC0_bandgap ch48 data_bctu = %d .\r\n", data_bctu);
      }

    }
}

Test result:

18.png

Fig 18

It is close to the typical expected value, indicating that it has been successfully run.

Used demo code:S32K344_PIT_TRIGMUX_BCTUSW_ADC_printf_RTD400.zip

 

2.4 PIT+TRIGMUX+ADC hardware PIT TRIGUMX trigger

This section is about hardware triggering. PIT is used in combination with TRIGMUX to directly trigger ADC1 channel 34, i.e. ADC1_S10 sampling. The trigger structure diagram is as follows:

 19.png

Fig 19

Also based on the previous code, you need to add an additional module Trgmux_Ip in the CT peripherals, and the rest of the configuration remains unchanged.

 20.png

Fig 20

Here, the input of Trigmux is selected as PIT0_CH0 and the output is ADC1.

The code is also much simpler. Add the following code in main:

Trgmux_Ip_Init(&Trgmux_Ip_xTrgmuxInitPB);//
    while(1)
    {
      if(notif_triggered1 == TRUE)
      {
    	  notif_triggered1 = FALSE;
    	  printf("ADC1_s10 ch34 data = %d .\r\n", data1);
      }
    }

In While(1), we can see that there is no software-triggered call. We can directly check the ADC1 conversion completion flag and then print the data. The test results are as follows:

21.png

Fig 21

It can be seen that as the external potentiometer changes, the sampled value of ADC1_S10 also changes.

Used demo:S32K344_PIT_TRIGMUX_ADC_printf_RTD400.zip

 

2.5 EMIOS+BCTUHW+ADC hardware EMIOS BCTU trigger

The block diagram structure of this section is as follows:

 22.png

Fig 22

Use eMIOS0_CH0 to generate a 10Khz clock to trigger BCTU to complete the sampling of ADC0_48 channel, that is, bandgap.

In the CT tool, add Emios_Mcal_Ip and configure it as follows:    

 23.png

Fig 23

Change the BCTU configuration to enable HW triggering. The configuration is as follows:

 24.png

Fig 24

Main code related codes are as follows:

Emios_Mcl_Ip_Init(EMIOS_INST0, &Emios_Mcl_Ip_0_Config_BOARD_INITPERIPHERALS);
    while(1)
    {
      if( toggleLed == 1)
      {
    	  toggleLed = 0;
    	  printf("ADC0_bandgap ch48 data_bctu = %d .\r\n", data_bctu);

      }
    }

Since the sampling rate is triggered at a frequency of 10Khz, the frequency is relatively fast, so the printing here is still based on 1s. The printing results are as follows:

 25.png

Fig 25

As you can see, the result is also a variable bandgap value.

Used demo:S32K344_PIT_TRIGMUX_BCTUHW_EMIOS_ADC_printf_RTD400.zip

 

2.6 EMIOS+BCTUHW LIST+ADC hardware EMIOS BCTU trigger LIST

This section is similar to the EMIOS BCTU hardware trigger above, except that the BCTU is configured in the form of LIST, which can trigger the conversion of multiple channels at once. The main modifications are in the BCTU module:

 26.png

Fig 26

Add the corresponding main code as follows:

#define BCTU_FIFO_WATERMARK             3U
void BctuWatermarkNotif(void)
{
    uint8 idx;
    notif_triggered = TRUE;
    for (idx = 0u; idx < BCTU_FIFO_WATERMARK; idx++)
    {
    	data_bctu[idx] = Bctu_Ip_GetFifoData(BCTUHWUNIT_0_BOARD_INITPERIPHERALS_INSTANCE, BCTU_USED_FIFO_IDX);
    }
}
    while(1)
    {
      if( toggleLed == 1)
      {
    	  toggleLed = 0;
    	  printf("ADC0_bandgap    ch48 data_bctu = %d .\r\n", data_bctu[0]);
    	  printf("ADC0_vrefl       ch54 data_bctu = %d .\r\n", data_bctu[1]);
    	  printf("ADC0_vrefh       ch55 data_bctu = %d .\r\n", data_bctu[2]);

      }
    }

Test result is:

27.png

Fig 27

It can be seen that the results are consistent with the collected bandgap, VREFL, and VREFH, indicating that the code function is running normally.

Code in this section:S32K344_PIT_TRIGMUX_BCTUHWLIST_EMIOS_ADC_printf_RTD400.zip

 

Attachments
No ratings
Version history
Last update:
‎10-06-2024 03:37 AM
Updated by: