SAR (SAR ADC Subsystem)

group group_sar

This driver configures and controls the SAR ADC subsystem block, which is a part of PASS hardware block.

The functions and other declarations used in this driver are in cy_sar.h. You can include cy_pdl.h to get access to all functions and declarations in the PDL.

This SAR ADC block is comprised of:

  • a 12-bit SAR converter (SARADC)

  • an embedded reference block (SARREF)

  • a mux (SARMUX) at the inputs of the converter

  • a sequence controller (SARSEQ) that enables multi-channel acquisition in a round robin fashion, without CPU intervention, to maximize scan rates.

Devices with PASS_v2 hardware block may contain multiple SAR ADC blocks.

../../../_images/sar_block_diagram.png

The high level features of the subsystem are:

  • maximum sample rate of 1 Msps (2 Msps for devices with PASS_v2 hardware block)

  • sixteen individually configurable channels (depends on device routing capabilities)

  • per channel selectable

    • single-ended or differential input mode

    • input from external pin (8 channels in single-ended mode or 4 channels in differential mode) or from internal signals (AMUXBUS, CTB, Die Temperature Sensor)

    • choose one of four programmable acquisition times

    • averaging and accumulation

  • scan can be triggered by firmware or hardware in single shot or continuous mode

  • hardware averaging from 2 to 256 samples

  • selectable voltage references

    • internal VDDA and VDDA/2 references

    • buffered 1.2 V bandgap reference from AREF

    • external reference from dedicated pin

  • interrupt generation

  • built-in FIFO buffer (PASS_v2 only)

  • ability to perform scans in Deep Sleep power mode (PASS_v2 only).

Usage

The high level steps to use this driver are:

  1. Initialization and Enable

  2. Triggering Conversions

  3. Handling Interrupts

  4. Retrieve Channel Results

  5. FIFO Usage

Initialization and Enable

To configure the SAR subsystem, call Cy_SAR_Init. Pass in a pointer to the SAR_Type structure for the base hardware register address and pass in the configuration structure, cy_stc_sar_config_t.

After initialization, call Cy_SAR_Enable to enable the hardware.

Here is guidance on how to set the data fields of the configuration structure:

uint32_t ctrl

This field specifies configurations that apply to all channels such as the Vref source or the negative terminal selection for all single-ended channels. Select a value from each of the following enums that begin with “cy_en_sar_ctrl_” and “OR” them together.

    #define CTRL                  (uint32_t)CY_SAR_VREF_PWR_100           /* Set reference voltage buffer to full power (100%) */\
                                | (uint32_t)CY_SAR_VREF_SEL_VDDA_DIV_2    /* Select internal VDDA/2 as the Vref. */\
                                | (uint32_t)CY_SAR_BYPASS_CAP_ENABLE      /* Enable Vref bypass capacitory. */\
                                | (uint32_t)CY_SAR_NEG_SEL_VREF           /* Use Vref as the negative terminal for all single-ended channels. */\
                                | (uint32_t)CY_SAR_CTRL_NEGVREF_HW        /* Enable hardware control of switch between Vref and negative terminal. */\
                                | (uint32_t)CY_SAR_CTRL_COMP_DLY_2P5      /* Set comparator latch delay to 2.5 ns delay for maximum conversion rates. */\
                                | (uint32_t)CY_SAR_COMP_PWR_100           /* Set comparator power to full power for maximum conversion rates. */\
                                | (uint32_t)CY_SAR_DEEPSLEEP_SARMUX_OFF   /* Disable SARMUX in Deep Sleep mode. */\
                                | (uint32_t)CY_SAR_SARSEQ_SWITCH_ENABLE   /* Enable the SARSEQ. */

uint32_t sampleCtrl

This field configures sampling details that apply to all channels. Select a value from each of the following enums that begin with “cy_en_sar_sample_” and “OR” them together.

    #define SAMPLE_CTRL           (uint32_t)CY_SAR_RIGHT_ALIGN                /* Right align result data to bits[11:0]. */\
                                | (uint32_t)CY_SAR_SINGLE_ENDED_UNSIGNED      /* Single ended channels are unsigned. */\
                                | (uint32_t)CY_SAR_DIFFERENTIAL_SIGNED        /* Differential channels are signed. */\
                                | (uint32_t)CY_SAR_AVG_CNT_2                  /* Set number of samples averaged to 2. */\
                                | (uint32_t)CY_SAR_AVG_MODE_SEQUENTIAL_FIXED  /* Averaging mode is sequential 12-bit fixed.*/\
                                | (uint32_t)CY_SAR_TRIGGER_MODE_FW_ONLY       /* Hardware trigger is disabled. */
    

uint32_t sampleTime01

This field configures the value for sample times 0 and 1 in ADC clock cycles.

The SAR has four programmable 10-bit aperture times that are configured using two data fields, uint32_t sampleTime01 and uint32_t sampleTime23. Ten bits allow for a range of 0 to 1023 cycles, however 0 and 1 are invalid. The minimum aperture time is 167 ns. With an 18 MHz ADC clock, this is equal to 3 cycles or a value of 4 in this field. The actual aperture time is one cycle less than the value stored in this field.

Use the shifts defined in cy_en_sar_sample_time_shift_t.

    #define SAMPLE_TIME01       (135 << CY_SAR_SAMPLE_TIME0_SHIFT)  /* Sample Time 0 set to 134 ADC clock cycles. */ \
                                | (4 << CY_SAR_SAMPLE_TIME1_SHIFT)  /* Sample Time 1 set to 3 ADC clock cycles. */

uint32_t sampleTime23

This field configures the value for sample times 2 and 3 in ADC clock cycles. Use the shifts defined in cy_en_sar_sample_time_shift_t.

    #define SAMPLE_TIME23       (4 << CY_SAR_SAMPLE_TIME2_SHIFT)    /* Sample Time 2 set to 3 ADC clock cycles. */ \
                                | (4 << CY_SAR_SAMPLE_TIME3_SHIFT)  /* Sample Time 3 set to 3 ADC clock cycles. */

uint32_t rangeThres

This field configures the upper and lower thresholds for the range interrupt. These thresholds apply on a global level for all channels with range detection enabled.

The SARSEQ supports range detection to allow for automatic detection of sample values compared to two programmable thresholds without CPU involvement. Range detection is done after averaging, alignment, and sign extension (if applicable). In other words the threshold values need to have the same data format as the result data. The values are interpreted as signed or unsigned according to each channel’s configuration.

Use the shifts defined in cy_en_sar_range_thres_shift_t.

The Cy_SAR_SetLowLimit and Cy_SAR_SetHighLimit provide run-time configurability of these thresholds.

    #define RANGE_THRES         (0x300uL  << CY_SAR_RANGE_LOW_SHIFT)     /* Lower limit of range detection is 0x300. */\
                                | (0xC00uL  << CY_SAR_RANGE_HIGH_SHIFT) /* Upper limit of range detection is 0xC00. */

cy_en_sar_range_detect_condition_t rangeCond

This field configures the condition (below, inside, outside, or above) that will trigger the range interrupt. Select a value from the cy_en_sar_range_detect_condition_t enum.

uint32_t chanEn

This field configures which channels will be scanned. Each bit corresponds to a channel. Bit 0 enables channel 0, bit 1 enables channel 1, bit 2 enables channel 2, and so on.

uint32_t chanConfig[16]

Each channel has its own channel configuration register. The channel configuration specifies which pin/signal is connected to that channel and how the channel is sampled.

Select a value from each of the following enums that begin with “cy_en_sar_chan_config_” and “OR” them together.

Some important considerations are:

  • The POS_PORT_ADDR and POS_PIN_ADDR bit fields are used by the SARSEQ to select the connection to the positive terminal (Vplus) of the ADC for each channel.

  • When the channel is an unpaired differential input (CY_SAR_CHAN_DIFFERENTIAL_UNPAIRED), the NEG_PORT_ADDR and NEG_PIN_ADDR are used by the SARSEQ to select the connection to the negative terminal (Vminus) of the ADC.

  • When the channel is a differential input pair (CY_SAR_CHAN_DIFFERENTIAL_PAIRED), the NEG_PORT_ADDR and NEG_PIN_ADDR are ignored. For differential input pairs, only the pin for the positive terminal needs to be specified and this pin must be even. For example, Pin 0 (positive terminal) and Pin 1 (negative terminal) are a pair. Pin 2 (positive terminal) and Pin 3 (negative terminal) are a pair.

If the SARSEQ is disabled (cy_en_sar_ctrl_sarseq_routing_switches_t) or it is not controlling any switches (uint32_t muxSwitchSqCtrl = 0), the port and pin addresses are ignored. This is possible when there is only one channel to scan.

    #define CHANNEL_0_CONFIG    CY_SAR_CHAN_SINGLE_ENDED        /* Channel 0 is a single ended channel. */ \
                                | CY_SAR_CHAN_SAMPLE_TIME_0     /* Aperature time is set by Sample Time 0. */\
                                | CY_SAR_POS_PORT_ADDR_SARMUX   /* Use the SARMUX dedicated port (see the device datasheet for the SARMUX port). */\
                                | CY_SAR_CHAN_POS_PIN_ADDR_2    /* Use Pin 2 of the SARMUX. */\
                                | CY_SAR_CHAN_AVG_DISABLE       /* Disable averaging. */
    
    #define CHANNEL_1_CONFIG    CY_SAR_CHAN_DIFFERENTIAL_PAIRED /* Channel 1 is a differential paired channel. */ \
                                | CY_SAR_CHAN_SAMPLE_TIME_1     /* Aperature time is set by Sample Time 1. */\
                                | CY_SAR_POS_PORT_ADDR_SARMUX   /* Use the SARMUX dedicated port (see the device datasheet for the SARMUX port). */\
                                | CY_SAR_CHAN_POS_PIN_ADDR_0    /* Positive terminal is connected to Pin 0 and negative terminal is connected to Pin 1 of the SARMUX. */\
                                | CY_SAR_CHAN_AVG_ENABLE        /* Enable averaging. */

    #define CHANNEL_CONFIG      {(uint32_t)CHANNEL_0_CONFIG, \
                                 (uint32_t)CHANNEL_1_CONFIG, \
                                 0U,0U,0U,0U,0U,0U,0U,0U,0U,0U,0U,0U,0U,0U} /* All other channels are unconfigured. */

uint32_t intrMask

This field configures which interrupt events (end of scan, overflow, or firmware collision) will be serviced by the firmware.

Select one or more values from the Interrupt Masks enum and “OR” them together.

    #define INTR_MASK           CY_SAR_INTR_EOS | CY_SAR_INTR_OVERFLOW /* Enable both EOS and overflow interrupt evnts. */

uint32_t satIntrMask

This field configures which channels will cause a saturation interrupt.

The SARSEQ has a saturation detect that is always applied to every conversion. This feature detects whether a channel’s sample value is equal to the minimum or maximum values. This allows the firmware to take action, for example, discard the result, when the SARADC saturates. The sample value is tested right after conversion, that is, before averaging. This means that it can happen that the interrupt is set while the averaged result in the data register is not equal to the minimum or maximum.

Each bit corresponds to a channel. A value of 0 disables saturation detection for all channels.

uint32_t rangeIntrMask

This field configures which channels will cause a range detection interrupt. Each bit corresponds to a channel. A value of 0 disables range detection for all channels.

uint32_t muxSwitch

This field is the firmware control of the SARMUX switches.

Use one or more values from the cy_en_sar_mux_switch_fw_ctrl_t enum and “OR” them together. If the SARSEQ is enabled, the SARMUX switches that will be used must also be closed using this firmware control.

    #define MUX_SWITCH          CY_SAR_MUX_FW_P2_VPLUS          /* Connect Pin 2 of the SARMUX to the positive terminal of the SARADC. */\
                                | CY_SAR_MUX_FW_P0_VPLUS        /* Connect Pin 0 of the SARMUX to the positive terminal of the SARADC. */\
                                | CY_SAR_MUX_FW_P1_VMINUS       /* Connect Pin 1 of the SARMUX to the negative terminal of the SARADC. */
Firmware control can be changed at run-time by calling Cy_SAR_SetAnalogSwitch with CY_SAR_MUX_SWITCH0 and the desired switch states.

uint32_t muxSwitchSqCtrl

This field enables or disables SARSEQ control of the SARMUX switches. To disable control of all switches, set this field to 0. To disable the SARSEQ all together, use CY_SAR_SARSEQ_SWITCH_DISABLE when configuring the uint32_t ctrl register.

Use one or more values from the cy_en_sar_mux_switch_sq_ctrl_t enum and “OR” them together.

    #define MUX_SWITCH_SQ_CTRL  CY_SAR_MUX_SQ_CTRL_P0           /* Enable sequencer control of Pins 0 of the SARMUX. */\
                                | CY_SAR_MUX_SQ_CTRL_P1         /* Enable sequencer control of Pins 1 of the SARMUX. */\
                                | CY_SAR_MUX_SQ_CTRL_P2         /* Enable sequencer control of Pins 2 of the SARMUX. */
SARSEQ control can be changed at run-time by calling Cy_SAR_SetSwitchSarSeqCtrl.

bool configRouting

If true, the uint32_t muxSwitch and uint32_t muxSwitchSqCtrl fields will be used. If false, the fields will be ignored.

uint32_t vrefMvValue

This field sets the value of the reference voltage in millivolts used. This value is used for converting counts to volts in the Cy_SAR_CountsTo_Volts, Cy_SAR_CountsTo_mVolts, and Cy_SAR_CountsTo_uVolts functions.

The rest of the cy_stc_sar_config_t fields starting from cy_stc_sar_config_t::clock affects SAR ADC configuration only for PASS_ver2. Refer to cy_stc_sar_config_t for details.

Triggering Conversions

The SAR subsystem has the following modes for triggering a conversion:

Mode

Description

Usage

Continuous

After completing a scan, the SARSEQ will immediately start the next scan. That is, the SARSEQ will always be BUSY. As a result all other triggers, firmware or hardware, are essentially ignored.

To enter this mode, call Cy_SAR_StartConvert with CY_SAR_START_CONVERT_CONTINUOUS. To stop continuous conversions, call Cy_SAR_StopConvert.

Firmware single shot

A single conversion of all enabled channels is triggered with a function call to Cy_SAR_StartConvert with CY_SAR_START_CONVERT_SINGLE_SHOT.

Firmware triggering is always available by calling Cy_SAR_StartConvert with CY_SAR_START_CONVERT_SINGLE_SHOT. To allow only firmware triggering, or disable hardware triggering, set up the cy_stc_sar_config_t config structure with CY_SAR_TRIGGER_MODE_FW_ONLY.

Hardware edge sensitive

A single conversion of all enabled channels is triggered on the rising edge of the hardware trigger signal.

To enable this mode, set up the cy_stc_sar_config_t config structure with CY_SAR_TRIGGER_MODE_FW_AND_HWEDGE.

Hardware level sensitive

Conversions are triggered continuously when the hardware trigger signal is high.

To enable this mode, set up the cy_stc_sar_config_t config structure with CY_SAR_TRIGGER_MODE_FW_AND_HWLEVEL.

If trigger occurs during a scan, a CY_SAR_INTR_FW_COLLISION interrupt occurs and the trigger is delayed until after end of scan.

The trigger mode can be changed during run time with Cy_SAR_SetConvertMode.

For the hardware trigger modes, use the TrigMux (Trigger Multiplexer) driver to route an internal or external signal to the SAR trigger input. When making the required Cy_TrigMux_Connect calls, use the pre-defined enum, TRIG6_OUT_PASS_TR_SAR_IN, for the SAR trigger input.

    /* Scenario: P0.0 is used to trigger the SAR conversions.
     * Configure and route P0.0 as the trigger input of the SAR. */
    
    /* Set drive mode of P0.0 to digital High-Z with the input buffer on.
     * Connect P0.0 to the HSIOM. */    
    Cy_GPIO_Pin_FastInit(GPIO_PRT0, 0UL, CY_GPIO_DM_HIGHZ, 0UL, P0_0_PERI_TR_IO_INPUT0);

    /* Connect the HSIOM to the SAR trigger input. */
#if (CY_IP_MXPERI_VERSION == 1U)
    (void)Cy_TrigMux_Connect(TRIG12_IN_PERI_TR_IO_INPUT0, TRIG12_OUT_TR_GROUP2_INPUT32, CY_TR_MUX_TR_INV_DISABLE, TRIGGER_TYPE_PERI_TR_IO_INPUT__LEVEL);
    (void)Cy_TrigMux_Connect(TRIG6_IN_TR_GROUP12_OUTPUT7, TRIG6_OUT_PASS_TR_SAR_IN, CY_TR_MUX_TR_INV_DISABLE, TRIGGER_TYPE_TR_GROUP_OUTPUT__LEVEL);
#else /* CY_IP_MXPERI_VERSION > 1 */
    (void)Cy_TrigMux_Connect(TRIG_IN_MUX_9_HSIOM_TR_OUT0, TRIG_OUT_MUX_9_PASS_TR_SAR_IN, CY_TR_MUX_TR_INV_DISABLE, TRIGGER_TYPE_PERI_TR_IO_INPUT__LEVEL);
#endif /* CY_IP_MXPERI_VERSION */

Handling Interrupts

The SAR can generate interrupts on these events:

  • End of scan (EOS): when scanning of all enabled channels complete.

  • Overflow: when the result register is updated before the previous result is read.

  • FW collision: when a new trigger is received while the SAR is still processing the previous trigger.

  • Saturation detection: when the channel result is equal to the minimum or maximum value.

  • Range detection: when the channel result meets the programmed upper or lower threshold values.

The SAR interrupt to the NVIC is raised any time the intersection (logic and) of the interrupt flags and the corresponding interrupt masks are non-zero.

Implement an interrupt routine and assign it to the SAR interrupt. Use the pre-defined enum, pass_interrupt_sar_IRQn, as the interrupt source for the SAR.

The following code snippet demonstrates how to implement a routine to handle the interrupt. The routine gets called when any one of the SAR interrupts are triggered. When servicing an interrupt, the user must clear the interrupt so that subsequent interrupts can be handled.


/* ISR function to handle all SAR interrupts. 
 * This same routine gets called when any of the enabled SAR interrupt sources
 * are enabled (EOS, overflow, FW collision, saturation detection, or range detection). */
void SAR_Interrupt(void)
{
    uint32_t intr_status = 0u;

    /* Read interrupt status register. */
    intr_status = Cy_SAR_GetInterruptStatus(SAR);

    /* Check what triggered the interrupt. */
    if ((intr_status & (uint32_t) CY_SAR_INTR_EOS) == (uint32_t) CY_SAR_INTR_EOS)
    {
        /* An end of scan occured, retrieve the ADC result and do something with it here. */
    }

    /* Check for the saturation detection status, if enabled. */

    /* Check for the range detection status, if enabled. */

    /* Clear the handled interrupt. */
    Cy_SAR_ClearInterrupt(SAR, intr_status);
}
The following code snippet demonstrates how to configure and enable the interrupt.

    /* Scenario: Configure and enable the SAR interrupt. */
                
    const cy_stc_sysint_t ADC_IRQ_cfg = {
        #if (CY_CPU_CORTEX_M0P)
            /* .intrSrc         = */ NvicMux7_IRQn,             /* CM0+ interrupt is NVIC #7 */
            /* .cm0pSrc         = */ pass_interrupt_sar_IRQn,   /* Source of NVIC #7 is the SAR interrupt */
            /* .intrPriority    = */ 3UL                        /* Interrupt priority is 3 */
        #else
            /* .intrSrc         = */ pass_interrupt_sar_IRQn,   /* Interrupt source is the SAR interrupt */
            /* .intrPriority    = */ 7UL                        /* Interrupt priority is 7 */
        #endif
    };
    
    /* Configure the interrupt with vector at SAR_Interrupt(). */
    (void)Cy_SysInt_Init(&ADC_IRQ_cfg, SAR_Interrupt);

    /* Enable the interrupt. */
    NVIC_EnableIRQ(ADC_IRQ_cfg.intrSrc);
    
Alternately, instead of handling the interrupts, the Cy_SAR_IsEndConversion function allows for firmware polling of the end of conversion status.

Retrieve Channel Results

Retrieve the ADC result by calling Cy_SAR_GetResult16 with the desired channel. To convert the result to a voltage, pass the ADC result to Cy_SAR_CountsTo_Volts, Cy_SAR_CountsTo_mVolts, or Cy_SAR_CountsTo_uVolts.

FIFO Usage

The PASS_ver2 SAR can operate in the system Deep Sleep power mode. To do so the SAR should be clocked by the Deep Sleep Clock, triggered by the Timer, and use the FIFO:

/* Scenario: Configure FIFO for SAR0 instance */

#define FIFO_DEPTH 64

const cy_stc_sar_fifo_config_t fifoConfig =
{
    .chanId = false, /* only one channel is used, no need for chan ID */
    .chainToNext = false, /* No FIFO chaining */
    .clrTrIntrOnRead = false, /* Interrupt is cleared by interrupt handler */
    .level = FIFO_DEPTH,
    .trOut = false /* Interrupt is used to get fifo data */
};

uint16_t sarResults[FIFO_DEPTH];

    
void FifoIsr(void)
{
    uint32_t intrMask = Cy_SAR_GetFifoInterruptStatus(SAR0);

    if (0UL != (CY_SAR_INTR_EOS & intrMask))
    {
        cy_stc_sar_fifo_read_t fifoRead;
        
        for (uint32_t i = 0; i < FIFO_DEPTH; i++)
        {
            Cy_SAR_FifoRead(SAR0, &fifoRead);
            sarResults[i] = fifoRead.value;
        }
    }

    Cy_SAR_ClearFifoInterrupt(SAR0, intrMask);
}
    
    /* Then, in the main function:
     * Suppose the simple SAR configuration itself is already constructed,
     * Deep Sleep Clock and Timer are initialized using Cy_SysAnalog_DeepSleepInit and enabled.
     */
    config.clock = CY_SAR_CLK_DEEPSLEEP;
    config.fifoCfgPtr = &fifoConfig;
    config.trTimer = true;
    (void) Cy_SAR_Init(SAR0, &config); /* Initialize SAR with FIFO */
    Cy_SAR_Enable(SAR0); /* FIFO is enabled with SAR if if fifoCfgPtr is not NULL */
    Cy_SAR_SetFifoInterruptMask(SAR0_HW, CY_SAR_INTR_FIFO_LEVEL);
    
    Cy_SysInt_SetVector(pass_interrupt_fifo_0_IRQn, FifoIsr);
    NVIC_EnableIRQ(pass_interrupt_fifo_0_IRQn);
    Cy_SAR_ClearFifoInterrupt(SAR0, CY_SAR_INTR_FIFO_LEVEL | CY_SAR_INTR_FIFO_OVERFLOW | CY_SAR_INTR_FIFO_UNDERFLOW);
    __enable_irq();
    
    while(true)
    {
        Cy_SysPm_CpuEnterDeepSleep(CY_SYSPM_WAIT_FOR_INTERRUPT);
    }

SAR Clock Configuration

The SAR requires a clock. Assign a clock to the SAR using the pre-defined enum, PCLK_PASS_CLOCK_SAR, to identify the SAR subsystem. Set the clock divider value to achieve the desired clock rate. The SAR can support a maximum frequency of 18 MHz.

For PASS_ver2 the maximum clock frequency is 36 MHz. Also, the SAR clock could be switched to the Deep Sleep Clock to operate in the system Deep Sleed power mode using cy_stc_sar_config_t::clock.

    /* Scenario: The PeriClk has been configured to output 50 MHz.
     * Use one of the PeriClk dividers with a divider value of 3 to get a 16.67 Mhz SAR clock. */
    
    /* Assign divider number 0 of the the 8-bit dividers to the SAR. */
    Cy_SysClk_PeriphAssignDivider(PCLK_PASS_CLOCK_SAR, CY_SYSCLK_DIV_8_BIT, 0u);

    /* Divide the PeriClk by 3, which is a input value of 2. */
    Cy_SysClk_PeriphSetDivider(CY_SYSCLK_DIV_8_BIT, 0u, 2u);

    /* Enable the divider. */
    Cy_SysClk_PeriphEnableDivider(CY_SYSCLK_DIV_8_BIT, 0u);

Scan Rate

The scan rate is dependent on the following:

  • ADC clock rate

  • Number of channels

  • Averaging

  • Resolution

  • Acquisition times

Acquisition Time

The acquisition time of a channel is based on which of the four global aperture times are selected for that channel. The selection is done during initialization per channel with uint32_t chanConfig[16]. The four global aperture times are also set during initialization with uint32_t sampleTime01 and uint32_t sampleTime23. Note that these global aperture times are in SAR clock cycles and the acquisition time is 1 less than that value in the register.

../../../_images/sar_acquisition_time_eqn.png

Channel Sample Time

The sample time for a channel is the time required to acquire the analog signal and convert it to a digital code.

../../../_images/sar_channel_sample_time_eqn.png

The SAR ADC is a 12-bit converter so Resolution = 12.

Total Scan Time

Channels using one of the sequential averaging modes (CY_SAR_AVG_MODE_SEQUENTIAL_ACCUM or CY_SAR_AVG_MODE_SEQUENTIAL_FIXED) are sampled multiple times per scan. The number of samples averaged are set during initialization with uint32_t sampleCtrl using one of the values from cy_en_sar_sample_ctrl_avg_cnt_t. Channels that are not averaged or use the CY_SAR_AVG_MODE_INTERLEAVED mode are only sampled once per scan.

The total scan time is the sum of each channel’s sample time multiplied by the samples per scan.

../../../_images/sar_scan_rate_eqn.png

where N is the total number of channels in the scan.

SARMUX and SARSEQ

The SARMUX is an analog programmable multiplexer. Its switches can be controlled by the SARSEQ or firmware. and the inputs can come from:

  • a dedicated port (can support 8 single-ended channels or 4 differential channels)

  • an internal die temperature (DieTemp) sensor

  • CTB output via SARBUS0/1 (if CTBs are available on the device)

  • AMUXBUSA/B

The following figure shows the SARMUX switches. See the device datasheet for the exact location of SARMUX pins.

../../../_images/sar_sarmux_switches.png

When using the SARSEQ, the following configurations must be performed:

  • enable SARSEQ control of required switches (see uint32_t muxSwitchSqCtrl)

  • close the required switches with firmware (see uint32_t muxSwitch)

  • configure the POS_PORT_ADDR and POS_PIN_ADDR, and if used, the NEG_PORT_ADDR and NEG_PIN_ADDR (see uint32_t chanConfig[16])

While firmware can control every switch in the SARMUX, not every switch can be controlled by the SARSEQ (green switches in the above figure). Additionally, switches outside of the SARMUX such as the AMUXBUSA/B switches or CTB switches will require separate function calls (see GPIO and CTB drivers). The SARSEQ can control three switches in the CTB driver (see Cy_CTB_EnableSarSeqCtrl). These switches need to be enabled for SARSEQ control if the CTB outputs are used as the SARMUX inputs.

The following table shows the required POS_PORT_ADDR and POS_PIN_ADDR settings for different input connections.

Input Connection Selection

POS_PORT_ADDR

POS_PIN_ADDR

SARMUX dedicated port

CY_SAR_POS_PORT_ADDR_SARMUX

CY_SAR_CHAN_POS_PIN_ADDR_0 through CY_SAR_CHAN_POS_PIN_ADDR_7

DieTemp sensor

CY_SAR_POS_PORT_ADDR_SARMUX_VIRT

CY_SAR_CHAN_POS_PIN_ADDR_0

AMUXBUSA

CY_SAR_POS_PORT_ADDR_SARMUX_VIRT

CY_SAR_CHAN_POS_PIN_ADDR_2

AMUXBUSB

CY_SAR_POS_PORT_ADDR_SARMUX_VIRT

CY_SAR_CHAN_POS_PIN_ADDR_3

CTB0 Opamp0 1x output

CY_SAR_POS_PORT_ADDR_CTB0

CY_SAR_CHAN_POS_PIN_ADDR_2

CTB0 Opamp1 1x output

CY_SAR_POS_PORT_ADDR_CTB0

CY_SAR_CHAN_POS_PIN_ADDR_3

Input from DieTemp sensor

When using the DieTemp sensor, always use single-ended mode. The temperature sensor can be routed to Vplus using the CY_SAR_MUX_FW_TEMP_VPLUS switch. Connecting this switch will also enable the sensor. Set the acquisition time to be at least 1 us to meet the settling time of the temperature sensor.

../../../_images/sar_sarmux_dietemp.png

    #define CHANNEL_EN          1u
    
    #define CHANNEL_0_CONFIG    ((uint32_t)CY_SAR_CHAN_SINGLE_ENDED           /* Single-ended channel. */\
                                | (uint32_t)CY_SAR_CHAN_SAMPLE_TIME_1         /* Use Sample Time 1 for 1 us acquisition time.*/ \
                                | (uint32_t)CY_SAR_POS_PORT_ADDR_SARMUX_VIRT  /* Set the Vplus port address to SARMUX_VIRT for the DieTemp. */\
                                | (uint32_t)CY_SAR_CHAN_POS_PIN_ADDR_0        /* Set the Vplus pin address to 0 for the DieTemp. */\
                                | (uint32_t)CY_SAR_CHAN_AVG_DISABLE)
    
    #define CHANNEL_CONFIG      {(uint32_t)CHANNEL_0_CONFIG \
                                ,0uL,0uL,0uL,0uL,0uL,0uL,0uL,0uL,0uL,0uL,0uL,0uL,0uL,0uL,0uL} /* Channels 1 through 15 are unconfigured. */
    
    #define MUX_SWITCH          ( CY_SAR_MUX_FW_TEMP_VPLUS      /* Close switch between Vplus and the DieTemp. This will also turn on the DieTemp sensor. */ \
                                | CY_SAR_MUX_FW_VSSA_VMINUS)    /* Close switch between Vminus and VSSA. */

    #define MUX_SWITCH_SQ_CTRL  0u  /* Disable SARSEQ since there is only one channel enabled. */
    
    /* If the DieTemp is scanned with other channels, enable SARSEQ with (CY_SAR_MUX_SQ_CTRL_TEMP | CY_SAR_MUX_SQ_CTRL_VSSA)
     * along with switches for other channels. */
    

Input from SARMUX port

The following figure and code snippet show how two GPIOs on the SARMUX dedicated port are connected to the SARADC as separate single-ended channels and as a differential-pair channel.

../../../_images/sar_sarmux_dedicated_port.png

    #define CHANNEL_EN          7u
    #define CHANNEL_0_CONFIG    ((uint32_t)CY_SAR_CHAN_SINGLE_ENDED       /* Single-ended channel. */\
                                | (uint32_t)CY_SAR_CHAN_SAMPLE_TIME_0     /* Use Sample Time 0 for 180 ns acquisition time. */ \
                                | (uint32_t)CY_SAR_POS_PORT_ADDR_SARMUX   /* Use dedicated SARMUX port. */\
                                | (uint32_t)CY_SAR_CHAN_POS_PIN_ADDR_0)   /* Use Pin 0. */

    #define CHANNEL_1_CONFIG    ((uint32_t)CY_SAR_CHAN_SINGLE_ENDED       /* Single-ended channel. */\
                                | (uint32_t)CY_SAR_CHAN_SAMPLE_TIME_1     /* Use Sample Time 1 for 1 us acquisition time. */ \
                                | (uint32_t)CY_SAR_POS_PORT_ADDR_SARMUX   /* Use dedicated SARMUX port. */ \
                                | (uint32_t)CY_SAR_CHAN_POS_PIN_ADDR_1)   /* Use Pin 1. */

    #define CHANNEL_2_CONFIG    ((uint32_t)CY_SAR_CHAN_DIFFERENTIAL_PAIRED    /* Differentia-paired channel. */\
                                | (uint32_t)CY_SAR_CHAN_SAMPLE_TIME_1         /* Use Sample Time 1 for 1 us acquisition time. */ \
                                | (uint32_t)CY_SAR_POS_PORT_ADDR_SARMUX       /* Use dedicated SARMUX port. */\
                                | (uint32_t)CY_SAR_CHAN_POS_PIN_ADDR_0)       /* Vplus connected to Pin 0 and Vminus connected to Pin 1. */
    
    #define CHANNEL_CONFIG      {(uint32_t)CHANNEL_0_CONFIG \
                                , (uint32_t)CHANNEL_1_CONFIG \
                                , (uint32_t)CHANNEL_2_CONFIG \
                                , 0uL,0uL,0uL,0uL,0uL,0uL,0uL,0uL,0uL,0uL,0uL,0uL,0uL} /* Channels 3 through 15 are unconfigured. */
    
    #define MUX_SWITCH          (CY_SAR_MUX_FW_P0_VPLUS         /* Close switch between Vplus and SARMUX Pin 0 for Channels 0 and 2. */ \
                                | CY_SAR_MUX_FW_P1_VPLUS        /* Close switch between Vplus and SARMUX Pin 1 for Channel 1. */ \
                                | CY_SAR_MUX_FW_P1_VMINUS       /* Close switch between Vmius and SARMUX Pin 1 for Channel 2. */ \
                                | CY_SAR_MUX_FW_VSSA_VMINUS)    /* Close switch between Vminus and VSSA for single-ended channels 0 and 1. */

    #define MUX_SWITCH_SQ_CTRL  (CY_SAR_MUX_SQ_CTRL_P0          /* Enable SARSEQ control of SARMUX Pin 0 switch. */ \
                                | CY_SAR_MUX_SQ_CTRL_P1         /* Enable SARSEQ control of SARMUX Pin 1. */  \
                                | CY_SAR_MUX_SQ_CTRL_VSSA)      /* Enable SARSEQ control of VSSA switch. */ 

Input from CTB output visa SARBUS0/1

The following figure and code snippet show how the two opamp outputs from the CTB are connected to the SARADC as separate single-ended channels and as a differential-pair channel. Note that separate function calls are needed to configure and enable the opamps, perform required analog routing, and enable SARSEQ control of the switches contained in the CTB.

../../../_images/sar_sarmux_ctb.png

    /* Check the device TRM for the CTB block presence */
    
    #define CHANNEL_EN          7u
    #define CHANNEL_0_CONFIG    ((uint32_t)CY_SAR_CHAN_SINGLE_ENDED           /* Single-ended channel. */\
                                | (uint32_t)CY_SAR_CHAN_SAMPLE_TIME_1         /* Use Sample Time 1 for 1 us acquisition time. */ \
                                | (uint32_t)CY_SAR_POS_PORT_ADDR_CTB0         /* Use CTB0 output. */\
                                | (uint32_t)CY_SAR_CHAN_POS_PIN_ADDR_2)       /* Use Pin address 2 for Opamp0 of CTB0. */
    
    #define CHANNEL_1_CONFIG    ((uint32_t)CY_SAR_CHAN_SINGLE_ENDED           /* Single-ended channel. */\
                                | (uint32_t)CY_SAR_CHAN_SAMPLE_TIME_1         /* Use Sample Time 1 for 1 us acquisition time. */ \
                                | (uint32_t)CY_SAR_POS_PORT_ADDR_CTB0         /* Use CTB0 output. */\
                                | (uint32_t)CY_SAR_CHAN_POS_PIN_ADDR_3)       /* Use Pin address 3 for Opamp1 of CTB0. */
    
    #define CHANNEL_2_CONFIG    ((uint32_t)CY_SAR_CHAN_DIFFERENTIAL_PAIRED    /* Differential paired channel. */\
                                | (uint32_t)CY_SAR_CHAN_SAMPLE_TIME_1         /* Use Sample Time 1 for 1 us acquisition time. */ \
                                | (uint32_t)CY_SAR_POS_PORT_ADDR_CTB0         /* Use CTB0 outputs. */\
                                | (uint32_t)CY_SAR_CHAN_POS_PIN_ADDR_2)       /* Use Opamp0 (pin address 2) for Vplus and Opamp1 (pin address 3) for Vminus. Note, differential paired input. */

    #define CHANNEL_CONFIG      {(uint32_t)CHANNEL_0_CONFIG \
                                ,(uint32_t)CHANNEL_1_CONFIG \
                                ,(uint32_t)CHANNEL_2_CONFIG \
                                ,0uL,0uL,0uL,0uL,0uL,0uL,0uL,0uL,0uL,0uL,0uL,0uL,0uL} /* Channels 3 through 15 are unconfigured. */
    
    #define MUX_SWITCH          (CY_SAR_MUX_FW_SARBUS0_VPLUS        /* Close switch between Vplus and SARBUS0 for Channels 0, 1, and 2. */ \
                                | CY_SAR_MUX_FW_SARBUS1_VMINUS      /* Close switch between Vminus and SARBUS1 for Channel 2. */ \
                                | CY_SAR_MUX_FW_VSSA_VMINUS)        /* Close switch between Vminus and VSSA for single-ended Channel 0. */

    #define MUX_SWITCH_SQ_CTRL  (CY_SAR_MUX_SQ_CTRL_SARBUS0         /* Enable SARSEQ control of SARBUS0 switch. */\
                                | CY_SAR_MUX_SQ_CTRL_SARBUS1        /* Enable SARSEQ control of SARBUS1 switch. */\
                                | CY_SAR_MUX_SQ_CTRL_VSSA)          /* Enable SARSEQ control of VSSA switch. */ 
    
    /* Configure both opamps in CTB for 1x mode. */
    (void) Cy_CTB_FastInit(CTBM0, &Cy_CTB_Fast_Opamp0_Opamp1x, &Cy_CTB_Fast_Opamp1_Opamp1x);
    
    /* Configure Opamp0 as a follower with Pin 0 of the CTB port as the input. */
    Cy_CTB_SetAnalogSwitch(CTBM0, CY_CTB_SWITCH_OA0_SW, CY_CTB_SW_OA0_NEG_OUT_MASK | CY_CTB_SW_OA0_POS_PIN0_MASK, CY_CTB_SWITCH_CLOSE);
    Cy_CTB_SetAnalogSwitch(CTBM0, CY_CTB_SWITCH_CTD_SW, CY_CTB_SW_CTD_CHOLD_OA0_POS_ISOLATE_MASK, CY_CTB_SWITCH_CLOSE);
    Cy_CTB_SetAnalogSwitch(CTBM0, CY_CTB_SWITCH_OA0_SW, CY_CTB_SW_OA0_OUT_SARBUS0_MASK, CY_CTB_SWITCH_CLOSE);
    
    /* Configure Opamp1 as a follower with Pin 7 of the CTB port as the input. */
    Cy_CTB_SetAnalogSwitch(CTBM0, CY_CTB_SWITCH_OA1_SW, CY_CTB_SW_OA1_NEG_OUT_MASK | CY_CTB_SW_OA1_POS_PIN7_MASK, CY_CTB_SWITCH_CLOSE);
    Cy_CTB_SetAnalogSwitch(CTBM0, CY_CTB_SWITCH_OA1_SW, CY_CTB_SW_OA1_OUT_SARBUS0_MASK | CY_CTB_SW_OA1_OUT_SARBUS1_MASK, CY_CTB_SWITCH_CLOSE);
    
    /* Enable SARSEQ control of switches inside CTB0. These are the only switches capable of SARSEQ control. */
    Cy_CTB_EnableSarSeqCtrl(CTBM0, CY_CTB_SW_SEQ_CTRL_D51_D52_D62_MASK);
    
    /* Enable the opamps. */
    Cy_CTB_Enable(CTBM0);
    

Input from other pins through AMUXBUSA/B

The following figure and code snippet show how two GPIOs on any port through the AMUXBUSA and AMUXBUSB are connected to the SARADC as separate single-ended channels and as a differential-pair channel. Note that separate function calls are needed to route the device pins to the SARMUX. The AMUXBUSes are separated into multiple segments and these segments are connected/disconnected using the AMUX_SPLIT_CTL registers in the HSIOM.

../../../_images/sar_sarmux_amuxbus.png

    #define CHANNEL_EN          7u
    #define CHANNEL_0_CONFIG    ((uint32_t)CY_SAR_CHAN_SINGLE_ENDED           /* Single-ended channel. */\
                                | (uint32_t)CY_SAR_CHAN_SAMPLE_TIME_1         /* Use Sample Time 1 for 1 us acquisition time. */ \
                                | (uint32_t)CY_SAR_POS_PORT_ADDR_SARMUX_VIRT  /* Set the Vplus port address to SARMUX_VIRT for the DieTemp. */\
                                | (uint32_t)CY_SAR_CHAN_POS_PIN_ADDR_2)       /* Set pin address to 2 for AMUXBUSA. */
    
    #define CHANNEL_1_CONFIG    ((uint32_t)CY_SAR_CHAN_SINGLE_ENDED           /* Single-ended channel. */\
                                | (uint32_t)CY_SAR_CHAN_SAMPLE_TIME_1         /* Use Sample Time 1 for 1 us acquisition time. */ \
                                | (uint32_t)CY_SAR_POS_PORT_ADDR_SARMUX_VIRT  /* Set the Vplus port address to SARMUX_VIRT for the DieTemp. */\
                                | (uint32_t)CY_SAR_CHAN_POS_PIN_ADDR_3)       /* Set pin address to 3 for AMUXBUSB. */
    
    #define CHANNEL_2_CONFIG    ((uint32_t)CY_SAR_CHAN_DIFFERENTIAL_PAIRED    /* Differential paired channel. */\
                                | (uint32_t)CY_SAR_CHAN_SAMPLE_TIME_1         /* Use Sample Time 1 for 1 us acquisition time. */ \
                                | (uint32_t)CY_SAR_POS_PORT_ADDR_SARMUX_VIRT  /* Set the Vplus port address to SARMUX_VIRT for the DieTemp. */\
                                | (uint32_t)CY_SAR_CHAN_POS_PIN_ADDR_2)       /* Use AMUXBUSA (pin address 2) for Vplus and AMXBUSB (pin address 3) for Vminus. Note, differential input pair. */
    
    #define CHANNEL_CONFIG      {(uint32_t)CHANNEL_0_CONFIG \
                                ,(uint32_t)CHANNEL_1_CONFIG \
                                ,(uint32_t)CHANNEL_2_CONFIG \
                                ,0uL,0uL,0uL,0uL,0uL,0uL,0uL,0uL,0uL,0uL,0uL,0uL,0uL} /* Channels 3 through 15 are unconfigured. */
    
    #define MUX_SWITCH          (CY_SAR_MUX_FW_AMUXBUSA_VPLUS       /* Close switch between Vplus and AMUXBUSA for Channels 0 and 2. */ \
                                | CY_SAR_MUX_FW_AMUXBUSB_VPLUS      /* Close switch between Vplus and AMUXBUSB for Channel 1. */\
                                | CY_SAR_MUX_FW_AMUXBUSB_VMINUS     /* Close switch between Vminus and AMUXMBUS for Channel 2. */ \
                                | CY_SAR_MUX_FW_VSSA_VMINUS)        /* Close switch between Vminus and VSSA for single-ended Channels 0 and 1. */

    #define MUX_SWITCH_SQ_CTRL  (CY_SAR_MUX_SQ_CTRL_AMUXBUSA        /* Enable SARSEQ control of AMUXBUSA switch. */ \
                                | CY_SAR_MUX_SQ_CTRL_AMUXBUSB       /* Enable SARSEQ control of AMUXBUSB switch. */  \
                                | CY_SAR_MUX_SQ_CTRL_VSSA)          /* Enable SARSEQ control of VSSA switch. */ 
    
    /* Configure pins */
    Cy_GPIO_SetHSIOM(GPIO_PRT9, 1u, P9_1_AMUXA);    /* Connect P9_1 to AMUXBUSA. */
    Cy_GPIO_SetHSIOM(GPIO_PRT9, 2u, P9_2_AMUXB);    /* Connect P9_2 to AMUXBUSB. */
    
    /* Set drive mode of P9_1 and P9_2 to analog high-z. */
    Cy_GPIO_SetDrivemode(GPIO_PRT9, 1u, CY_GPIO_DM_ANALOG);
    Cy_GPIO_SetDrivemode(GPIO_PRT9, 2u, CY_GPIO_DM_ANALOG);
    

To connect SARMUX to any other non-dedicated port, you may need to close additional HSIOM switches to route signals through AMUXBUS. For more detail, see the device TRM, AMUX splitting.

The following code snippet is an alternative pin configuration. To connect Port 1 to AMUXBUS, close the left and right switches of AMUX_SPLIT_CTL[1] and AMUX_SPLIT_CTL[6].

warning

This snippet shows how to configure pins for CY8C6347BZI-BLD53.

    /* Alternative pin configuration */
    Cy_GPIO_SetHSIOM(GPIO_PRT1, 2u, P1_2_AMUXA);    /* Connect P1_2 to AMUXBUSA. */
    Cy_GPIO_SetHSIOM(GPIO_PRT1, 4u, P1_4_AMUXB);    /* Connect P1_4 to AMUXBUSB. */
    
    /* Set drive mode of P1_2 and P1_4 to analog high-z. */
    Cy_GPIO_SetDrivemode(GPIO_PRT1, 2u, CY_GPIO_DM_ANALOG);
    Cy_GPIO_SetDrivemode(GPIO_PRT1, 4u, CY_GPIO_DM_ANALOG);
    
    /* To connect the SARMUX to Port 1 requires additional HSIOM switches, AMUX_SPLIT_CTL[1] and AMUX_SPLIT_CTL[6].
     * See the device TRM about AMUXBUS splitting. */
    HSIOM->AMUX_SPLIT_CTL[1] = HSIOM_AMUX_SPLIT_CTL_SWITCH_AA_SL_Msk \
                               | HSIOM_AMUX_SPLIT_CTL_SWITCH_AA_SR_Msk \
                               | HSIOM_AMUX_SPLIT_CTL_SWITCH_BB_SL_Msk \
                               | HSIOM_AMUX_SPLIT_CTL_SWITCH_BB_SR_Msk;
    
    HSIOM->AMUX_SPLIT_CTL[6] = HSIOM_AMUX_SPLIT_CTL_SWITCH_AA_SL_Msk \
                               | HSIOM_AMUX_SPLIT_CTL_SWITCH_AA_SR_Msk \
                               | HSIOM_AMUX_SPLIT_CTL_SWITCH_BB_SL_Msk \
                               | HSIOM_AMUX_SPLIT_CTL_SWITCH_BB_SR_Msk;
    

Low Power Support

This SAR driver provides a callback function to handle power mode transitions. The Cy_SAR_DeepSleepCallback function ensures that SAR conversions are stopped before Deep Sleep entry. Upon wakeup, the callback enables the hardware and continuous conversions, if previously enabled.

To trigger the callback execution, the callback must be registered before calling Cy_SysPm_CpuEnterDeepSleep. Refer to SysPm (System Power Management) driver for more information about power mode transitions and callback registration.

Recall that during configuration of the ctrl field, the SARMUX can be configured to remain enabled in Deep Sleep mode. All other blocks (SARADC, REFBUF, and SARSEQ) do not support Deep Sleep mode operation.

More Information

For more information on the SAR ADC subsystem, refer to the technical reference manual (TRM).

Changelog

Version

Changes

Reason for Change

2.0.1

Minor documentation updates.

Documentation enhancement.

2.0

Added the next PASS_ver2 features: Low Power features control Functions, FIFO buffer contlol Functions, and Common triggering Functions for multiple SAR instances.

New silicon support.

The Result Format check is added to the Cy_SAR_Init function when the interleaved averaging mode is used.

HW bug workaround.

Cy_SAR_Enable and Cy_SAR_Disable functions behavior is changed - now Cy_SAR_Disable checks the busy status before shutting down, and Cy_SAR_Enable doesn't.

Bug fixing.

Fixed/Documented MISRA 2012 violations.

MISRA 2012 compliance.

1.20.3

Minor documentation updates.

Documentation enhancement.

1.20.2

Code snippets update.

PDL infrastructure update, documentation enhancement.

1.20.1

Code snippets update.

PDL infrastructure update, documentation enhancement.

1.20

Flattened the organization of the driver source code into the single source directory and the single include directory.

Driver library directory-structure simplification.

Added register access layer. Use register access macros instead of direct register access using dereferenced pointers.

Makes register access device-independent, so that the PDL does not need to be recompiled for each supported part number.

1.10

Added workaround for parts with out of range CAP_TRIM in Init API.

Correct CAP_TRIM is necessary achieving specified SAR ADC linearity

Turn off the entire hardware block only if the SARMUX is not enabled for Deep Sleep operation.

Improvement of the Cy_SAR_DeepSleep flow

Updated "Low Power Support" section to describe registering the Deep Sleep callback. Added parenthesis around logical AND operation in Sleep API.

Documentation update and clarification

1.0

Initial version