【S32K3 RTD LLD篇5】K344 ADC SW+HW trigger

时间:2024-10-04 07:00:47

【S32K3 RTD LLD篇5】K344 ADC SW+HW trigger

  • 一,文档简介
  • 二,ADC SW HW 触发
    • 2.1 软硬件平台
    • 2.2 SW+ADC 软件触发
    • 2.3 SW+BCTU+ADC 软件BCTU触发
    • 2.4 PIT+TRIGMUX+ADC 硬件PIT TRIGUMX触发
    • 2.5 EMIOS+BCTUHW+ADC硬件EMIOS BCTU触发
    • 2.6 EMIOS+BCTUHW LIST+ADC硬件EMIOS BCTU触发LIST采集

一,文档简介

S32K344的ADC是一款分辨率高达14位的SAR ADC,拥有丰富的软件以及硬件触发方式,支持多样的外部触发源,并且引入BCTU使得触发资源可以外联到多通道的EMIOS以及TRIGMUX,增加了更多的ADC触发源。本文主要讲解如下几种方式的ADC软硬件触发情况,并且配套给出代码。

在这里插入图片描述

图 1

主要分为5部分:
(1) SW+ADC: 软件触发,通过添加定时器PIT,定时调用软件触发ADC完成通道采样,并且通过UART printf打印出采集值。
(2) SW+BCTU+ADC: 软件触发, 通过添加定时器PIT,定时调用软件触发BTCU, 完成ADC通道采样,并且通过UART printf打印出采集值。
(3) PIT+TRIGMUX+ADC: 硬件触发, 通过TRIGMUX连接PIT到ADC,通过PIT硬件触发ADC通道采样,并且在采样转换完成后打印转换值。
(4) EMIOS+BCTUHW+ADC: 硬件触发,通过EMIOS定时触发BCTU完成对应ADC单通道采样,由于采样速率较高,所以只是定时打印BCTU采样值。
(5) EMIOS+BCTUHWLIST+ADC: 硬件触发,通过EMIOS定时触发BCTU完成ADC列表通道采样,由于采样速率较高,所以定时打印BCTU 采样到的列表通道值。

二,ADC SW HW 触发

2.1 软硬件平台

软件: RTD400 LLD,S32DS3.5
硬件:S32K3X4EVB-T172

2.2 SW+ADC 软件触发

实际上,原始的RTD400自带的ADC demo已经有了ADC 软件以及BCTU的软件触发,本文是在该功能的基础上添加了PIT定时软件触发,并且通过UART printf打印出来,让检查ADC的测试值通过串口打印变的更加方便。
本文软件触发ADC的框图结构如下:

在这里插入图片描述

图 2

S32K344EVB板载有一个电位器,接到了ADC1_S10, PTA11:
在这里插入图片描述

图 3

所以,本节软件触发主要用于采集ADC1_S10。 UART 打印端口使用的是板载仿真器自带的串口:LPUART6_RX PTA15, LPUART6_TX PTA16,波特率为115200.
对于本文软件触发demo,主要配置涉及如下模块:
(1)Pins:
在这里插入图片描述

图 4

ADC1_s10, PTA11是当前要测试板载电位器电压,可调。
PTA29:连接板载D13红灯,用于测试PIT定时器中断进入闪烁,作为PIT的呼吸灯使用。
PTA16: UART6_TX, 用于发送采集到的ADC值。
(2)clocks
用于配置系统时钟,需要关注UART6时钟源为40Mhz,ADC1时钟源为160Mhz,PIT0时钟源为40Mhz
(3)Peripherals
涉及外设模块Siul2_Port,Siul2_Dio, Pit, Lpuart_Uart, Adc_Sar_Ip, IntCtrl_Ip.
Siul2_Port: 添加4个引脚ADC PTA11 MSCR 11, RED LED PTA29 MSCR 29,UART6_RX PTA15 MSCR 15, UART6_RX PTA16 MSCR 16.
Siul2_Dio:添加模块主要是为了让相关的API函数进来,便于控制GPIO引脚。
Pit: 用于生成1S的定时,主要配置如下:
在这里插入图片描述

图 5

在这里插入图片描述

图6

Lpuart_Uart:
在这里插入图片描述

图7

Adc_Sar_Ip:
在这里插入图片描述

图8

在这里插入图片描述

图9

这里需要注意的是ADC calibration prescale,以及Adc prescaler vale,需要满足如下条件,这点可以在S32K3RM上找到:
在这里插入图片描述

图 10

由于ADC1的时钟源是160MHz, 所以配置校准分频为4分频,转换分频为2分频。
IntCtrl_Ip:
在这里插入图片描述

图 11

旨在打开PIT, LPUART6的中断,并且注册对应的handler.
CT配置完成,生成代码,下一步,移步main函数,添加代码如下:

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

 }
}

测试结果打印如下:
在这里插入图片描述

图 12

本节内容配套代码:S32K344_PIT_SW_ADC_RTD400.zip

2.3 SW+BCTU+ADC 软件BCTU触发

基于SW+ADC触发,添加BCTU,并且使用BCTU软件触发完成ADC采样。框图结构如下:
在这里插入图片描述

图 13

本节功能是使用BCTU软件触发ADC0采样,采样通道并没有真实的使用外部的引脚输入,而是采集ADC0 的bandgap的值。软件触发通过PIT 1S周期调用软件触发函数,完成后打印ADC采样转换值到UART。
CT工具中,主要修改点为peripherals, adc_sar_lp中添加ADC0,并且配置为BCTU触发。
在这里插入图片描述

图 14

在这里插入图片描述

图 15

这里可以看到,图14中 adc ctu mode为:trigger mode.
添加Bctu_Ip模块,并且配置如下:
在这里插入图片描述

图 16

对应选择的BCTU的通道为48,该通道对应内部的bandgap模块。
在这里插入图片描述

图 17

典型值是1.2V,所以参考电压为5V,对应的14位ADC的bandgap期望值为:
(2^14)*1.2/5=3932周围。
完成CT配置生成代码后,在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);
      }

    }
}

测结果如下:
在这里插入图片描述

图18

和典型期望值接近,说明已经成功运行。
配套代码:S32K344_PIT_TRIGMUX_BCTUSW_ADC_printf_RTD400.zip

2.4 PIT+TRIGMUX+ADC 硬件PIT TRIGUMX触发

本节为硬件触发,使用PIT结合TRIGMUX直接触发ADC1 通道34即ADC1_S10采样,触发结构框图如下:
在这里插入图片描述

图19

同样在之前代码的基础上,需要在CT的peripherals中额外添加模块Trgmux_Ip,其余配置不变。
在这里插入图片描述

图 20

这里选择了Trigmux的输入为PIT0_CH0, 输出为ADC1.
代码也简单很多,在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);
      }
    }

While(1)中,可以看到,已经没有软件触发的调用,直接判别ADC1转换完成的标志,然后打印数据,测试结果如下:
在这里插入图片描述

图 21

可以看到,随着外部电位器的改变,采样得到的ADC1_S10的值也在改变。
本节代码:S32K344_PIT_TRIGMUX_ADC_printf_RTD400.zip

2.5 EMIOS+BCTUHW+ADC硬件EMIOS BCTU触发

本节框图结构如下:

在这里插入图片描述

图 22

使用eMIOS0_CH0,生成10Khz的时钟,去触发BCTU完成ADC0_48通道,即bandgap的采样。
在CT工具中,添加Emios_Mcal_Ip,配置如下:
在这里插入图片描述

图 23

BCTU配置改成使能HW triggering,配置如下:

在这里插入图片描述

图24

Main代码相关代码如下:

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);

  }
}

由于采样率是按照10Khz的频率去触发,频率较快,这里打印还是按照1s打印,打印结果如下:

在这里插入图片描述

图 25

可以看到,得到的结果也是一个可以变动的bandgap值。
本节代码:S32K344_PIT_TRIGMUX_BCTUHW_EMIOS_ADC_printf_RTD400.zip

2.6 EMIOS+BCTUHW LIST+ADC硬件EMIOS BCTU触发LIST采集

本节和上面的EMIOS BCTU硬件触发类似,只是在BCTU中配置使用LIST的形式,可以一次触发转换多个通道。主要修改点为BCTU模块:

在这里插入图片描述

图 26

添加对应的main代码如下:

#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]);

      }
    }

测试结果如下:
在这里插入图片描述

图 27

可以看到,结果和采集的bandgap,VREFL,VREFH还是吻合的,说明代码功能正常运行。
本节代码:
S32K344_PIT_TRIGMUX_BCTUHWLIST_EMIOS_ADC_printf_RTD400.zip
代码链接:
https://community.nxp.com/t5/S32K-Knowledge-Base/RTD400-K344-ADC-SW-HW-trigger/ta-p/1966179