CAT2 Peripheral Driver Library
SAR (SAR ADC)

This driver configures and controls the SAR ADC subsystem block. More...

Modules

 Macros
 
 Functions
 
 Data Structures
 
 Enumerated Types
 

Detailed Description

This driver configures and controls the SAR ADC subsystem 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 subsystem is comprised of:

sar_block_diagram.png

The high level features of the subsystem are:

Configuration Considerations

As an example, following SAR configuration will be used:

The high level steps to use SAR driver are:

Configuration structure

To configure the SAR subsystem, call Cy_SAR_Init. This function requires two pointers: a pointer to the SAR_Type structure for the base hardware register address and pointer to the configuration structure cy_stc_sar_config_t.

Configuration structure cy_stc_sar_config_t includes two substructures: cy_stc_sar_config_t::channelConfig and cy_stc_sar_config_t::routingConfig.

cy_stc_sar_channel_config_t is used to configure individual channels. Here is an example of SAR channels configuration for our use case:

{
/* .addr */ CY_SAR_ADDR_SARMUX_0, /* Use Pin 0 of the SARMUX */
/* .differential */ false, /* Single ended */
/* .resolution */ CY_SAR_MAX_RES, /* 12-bit */
/* .avgEn */ false, /* Disable averaging */
/* .sampleTimeSel */ 0UL, /* Aperture time is set by Sample Time 0 */
/* .rangeIntrEn */ false, /* Disable range interrupt */
/* .satIntEn */ false, /* Disable saturation interrupt */
#if defined (CY_IP_M0S8PASS4A_SAR_VERSION) && (4U <= CY_IP_M0S8PASS4A_SAR_VERSION)
/* .neg_addr */ CY_SAR_NEG_ADDR_SARMUX_7, /* Pin 7 of the SARMUX */
/* .negAddrEn */ false, /* Disable negative address */
/* .diagVplusSource */ false, /* Disable source current for Vplus */
/* .diagVplusSink */ false, /* Disable sink current for Vplus */
/* .diagVminusSoure */ false, /* Disable source current for Vminus */
/* .diagVminusSink */ false /* Disable sink current for Vminus */
#endif
};
{
/* .addr */ CY_SAR_ADDR_SARMUX_1, /* Use Pin 1 of the SARMUX */
/* .differential */ false, /* Single ended */
/* .resolution */ CY_SAR_MAX_RES, /* 12-bit */
/* .avgEn */ false, /* Disable averaging */
/* .sampleTimeSel */ 0UL, /* Aperture time is set by Sample Time 0 */
/* .rangeIntrEn */ false, /* Disable range interrupt */
/* .satIntEn */ false, /* Disable saturation interrupt */
#if defined (CY_IP_M0S8PASS4A_SAR_VERSION) && (4U <= CY_IP_M0S8PASS4A_SAR_VERSION)
/* .neg_addr */ CY_SAR_NEG_ADDR_SARMUX_7, /* Pin 7 of the SARMUX */
/* .negAddrEn */ false, /* Disable negative address */
/* .diagVplusSource */ false, /* Disable source current for Vplus */
/* .diagVplusSink */ false, /* Disable sink current for Vplus */
/* .diagVminusSoure */ false, /* Disable source current for Vminus */
/* .diagVminusSink */ false /* Disable sink current for Vminus */
#endif
};
cy_stc_sar_channel_config_t channelDiffCfg =
{
/* .addr */ CY_SAR_ADDR_SARMUX_0, /* Positive terminal is connected to Pin 0 and negative terminal is connected to Pin 1 of the SARMUX */
/* .differential */ true, /* Differential */
/* .resolution */ CY_SAR_MAX_RES, /* 12-bit */
/* .avgEn */ false, /* Disable averaging */
/* .sampleTimeSel */ 0UL, /* Aperture time is set by Sample Time 0 */
/* .rangeIntrEn */ false, /* Disable range interrupt */
/* .satIntEn */ false, /* Disable saturation interrupt */
#if defined (CY_IP_M0S8PASS4A_SAR_VERSION) && (4U <= CY_IP_M0S8PASS4A_SAR_VERSION)
/* .neg_addr */ CY_SAR_NEG_ADDR_SARMUX_7, /* Pin 7 of the SARMUX */
/* .negAddrEn */ false, /* Disable negative address */
/* .diagVplusSource */ false, /* Disable source current for Vplus */
/* .diagVplusSink */ false, /* Disable sink current for Vplus */
/* .diagVminusSoure */ false, /* Disable source current for Vminus */
/* .diagVminusSink */ false /* Disable sink current for Vminus */
#endif
};

cy_stc_sar_routing_config_t is used to define SARMUX configuration. Use one or more values from the SARMUX Switch Control Register Masks and "OR" them together. Firmware control can be changed at run-time by calling Cy_SAR_SetAnalogSwitch the desired switch states SARSEQ control can be changed at run-time by calling Cy_SAR_SetSwitchSarSeqCtrl.

{
/* .muxSwitch */ CY_SAR_MUX_FW_P0_VPLUS | /* Connect Pin 0 of the SARMUX to the positive terminal of the SARADC for the first single-ended channel */
CY_SAR_MUX_FW_P1_VPLUS | /* Connect Pin 1 of the SARMUX to the positive terminal of the SARADC for the second single-ended channel */
CY_SAR_MUX_FW_P1_VMINUS | /* Connect Pin 1 of the SARMUX to the negative terminal of the SARADC for the differential channel */
CY_SAR_MUX_FW_VSSA_VMINUS, /* Connect VSSA of the SARMUX to the negative terminal of the SARADC for the single-ended channels */
/* .muxSwitchHwCtrl */ CY_SAR_MUX_HW_CTRL_P0 | /* Enable sequencer control of Pins 0 of the SARMUX */
CY_SAR_MUX_HW_CTRL_P1 | /* Enable sequencer control of Pins 1 of the SARMUX */
CY_SAR_MUX_HW_CTRL_VSSA, /* Enable sequencer control of VSSA switch. */
/* .muxSwitch2 */ 0U,
/* .muxSwitchHwCtrl2*/ 0U
};

Firmware control also can be changed at run-time by calling Cy_SAR_SetDiagSwitch the desired switch states SARSEQ control can be changed at run-time by calling Cy_SAR_SetDiagHwCtrl for the DIAGMUX/EXPMUX

cy_stc_sar_routing_config_t routingConfigDiag =
{
/* .muxSwitch */ CY_SAR_MUX_FW_P0_VPLUS | /* Connect Pin 0 of the SARMUX to the positive terminal of the SARADC for the first single-ended channel */
CY_SAR_MUX_FW_P1_VPLUS | /* Connect Pin 1 of the SARMUX to the positive terminal of the SARADC for the second single-ended channel */
CY_SAR_MUX_FW_P1_VMINUS | /* Connect Pin 1 of the SARMUX to the negative terminal of the SARADC for the differential channel */
CY_SAR_MUX_FW_VSSA_VMINUS, /* Connect VSSA of the SARMUX to the negative terminal of the SARADC for the single-ended channels */
/* .muxSwitchHwCtrl */ CY_SAR_MUX_HW_CTRL_P0 | /* Enable sequencer control of Pins 0 of the SARMUX */
CY_SAR_MUX_HW_CTRL_P1 | /* Enable sequencer control of Pins 1 of the SARMUX */
CY_SAR_MUX_HW_CTRL_VSSA, /* Enable sequencer control of VSSA switch. */
/* .muxSwitch2 */ CY_SAR_DIAGMUX_FW_VD0_VPLUS | /* Connect Line 0 of the DIAGMUX to the positive terminal of the SARADC for the first single-ended channel */
CY_SAR_DIAGMUX_FW_VD1_VPLUS | /* Connect Line 1 of the DIAGMUX to the positive terminal of the SARADC for the second single-ended channel */
CY_SAR_DIAGMUX_FW_VG1_VMINUS | /* Connect Line 1 of the DIAGMUX to the negative terminal of the SARADC for the differential channel */
CY_SAR_MUX_FW_VSSA_VMINUS, /* Connect VSSA of the SARMUX to the negative terminal of the SARADC for the single-ended channels */
/* .muxSwitchHwCtrl2*/ CY_SAR_DIAGMUX_HW_CTRL_V0 | /* Enable sequencer control of Line 0 of the DIAGMUX */
CY_SAR_DIAGMUX_HW_CTRL_V1 | /* Enable sequencer control of Line 1 of the DIAGMUX */
CY_SAR_MUX_HW_CTRL_VSSA /* Enable sequencer control of VSSA switch. */
};

In order to complete SAR configuration structure, all remaining fields of cy_stc_sar_config_t should be filled:

{
/* .vrefSel */ CY_SAR_VREF_SEL_VDDA, /* Select internal VDDA as the Vref */
/* .vrefBypCapEn */ false, /* Disable Vref bypass capacitor */
/* .negSel */ CY_SAR_NEG_SEL_VSSA_KELVIN, /* Use Vref as the negative terminal for all single-ended channels */
/* .negVref */ CY_SAR_NEGVREF_HW, /* Enable hardware control of switch between Vref and negative terminal */
/* .boostPump */ true, /* Enable boost pump */
/* .power */ CY_SAR_NORMAL_PWR, /* Normal power level */
/* .sarMuxDsEn */ false, /* Disable SARMUX in Deep Sleep mode */
/* .switchDisable */ false, /* Enable the SARSEQ */
/* .subResolution */ CY_SAR_SUB_RESOLUTION_8B, /* Subresolution 8 bit - not used */
/* .leftAlign */ false, /* Right align result data to bits[11:0] */
/* .singleEndedSigned */ true, /* Single ended channels are signed */
/* .differentialSigned */ true, /* Differential channels are signed */
/* .avgCnt */ CY_SAR_AVG_CNT_2, /* Set number of samples averaged to 2 - not used */
/* .avgShift */ true, /* Enable the averaged value right shifting - not used */
/* .trigMode */ CY_SAR_TRIGGER_MODE_FW_AND_HWEDGE, /* Hardware trigger is enabled - will be used to trigger SAR by TCPWM */
/* .eosEn */ false, /* Hardware EOS trigger is disabled - not used */
/* .sampleTime0 */ 4UL, /* Sample Time 0 set to 4 ADC clock cycles */
/* .sampleTime1 */ 4UL, /* Sample Time 1 set to 4 ADC clock cycles - not used */
/* .sampleTime2 */ 4UL, /* Sample Time 2 set to 4 ADC clock cycles - not used */
/* .sampleTime3 */ 4UL, /* Sample Time 3 set to 4 ADC clock cycles - not used */
/* .rangeThresLow */ 0x300UL, /* Lower limit of range detection is 0x300 - not used */
/* .rangeThresHigh */ 0xC00UL, /* Upper limit of range detection is 0xC00 - not used */
/* .rangeCond */ CY_SAR_RANGE_COND_OUTSIDE, /* Set limit condition to outside of lower and upper limits - not used */
/* .chanEn */ 0x07UL, /* Mask to enable channels 0, 1 and 2 (0b0111) */
/* .channelConfig */ {&channelSe0Cfg, &channelSe1Cfg, &channelDiffCfg, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
/* .routingConfig */ &routingConfig, /* Pointer to the routing configuration structure */
/* .vrefMvValue */ 3300UL /* Vdd is 3.3 V */
};

Initialization and Enable

As mentioned in a previous step, to configure the SAR subsystem, call Cy_SAR_Init function with pointers to SAR_Type and cy_stc_sar_config_t structures. After initialization, call Cy_SAR_Enable to enable the hardware.

cy_en_sar_status_t sarStatus = Cy_SAR_Init(SAR0, &config);
if (CY_SAR_SUCCESS != sarStatus)
{
/* insert error handling here */
}

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.

/* Scenario: The SysClk has been configured to output 24 MHz.
* Use one of the PeriClk dividers with a divider value of 12 to get a 2 MHz SAR clock. */
Cy_SysClk_PeriphDisableDivider(CY_SYSCLK_DIV_16_BIT, 2U); /* Disable divider before configuring */
Cy_SysClk_PeriphSetDivider(CY_SYSCLK_DIV_16_BIT, 2U, 11U); /* Set divider 12 resulting 2MHz */
Cy_SysClk_PeriphEnableDivider(CY_SYSCLK_DIV_16_BIT, 2U); /* Enable the divider */
Cy_SysClk_PeriphAssignDivider(PCLK_PASS0_CLOCK_SAR, CY_SYSCLK_DIV_16_BIT, 2U); /* Assign divider to the SAR0 */

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::trigMode field of 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::trigMode field of 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::trigMode field of config structure with CY_SAR_TRIGGER_MODE_FW_AND_HWLEVEL.

If the trigger occurs during a scan, a CY_SAR_INTR_FW_COLLISION interrupt occurs and the trigger is delayed until the end of the 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: TCPWM is used to trigger the SAR conversions.
* Connect the TCPWM to the SAR trigger input.
*/
#if (defined(CY_DEVICE_PSOC4AS3) || defined(CY_DEVICE_PSOC4AS4) || defined(CY_DEVICE_PSOC4AMC) || defined (CY_DEVICE_PSOC4HVMS64K))
/* Trigger multiplexing may slightly differ form device to device,
* for the PSOC4A 4100S Plus, 4100S Max and 4500S series the trigger group 2 is for SAR input trigger:
*/
cy_en_trigmux_status_t trigmuxStatus = Cy_TrigMux_Connect(TRIG2_IN_TCPWM_TR_COMPARE_MATCH2, TRIG2_OUT_PASS0_TR_SAR_IN);
#else /* other device family */
/* For other supported devices the trigger group 2 is for SAR input trigger: */
cy_en_trigmux_status_t trigmuxStatus = Cy_TrigMux_Connect(TRIG1_IN_TCPWM_TR_COMPARE_MATCH2, TRIG1_OUT_PASS0_TR_SAR_IN);
#endif /* PSOC4 device family */
if (CY_TRIGMUX_SUCCESS != trigmuxStatus)
{
/* insert error handling here */
}

Handling Interrupts

The SAR can generate interrupts on these events:

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.

int16_t adcResult[3] = {0, 0, 0}; /* Results storage */
void SAR0_Isr(void)
{
uint32_t intrMask = Cy_SAR_GetInterruptStatusMasked(SAR0);
if (0UL != (CY_SAR_INTR_EOS & intrMask))
{
adcResult[0] = Cy_SAR_GetResult16(SAR0, 0);
adcResult[1] = Cy_SAR_GetResult16(SAR0, 1);
adcResult[2] = Cy_SAR_GetResult16(SAR0, 2);
}
Cy_SAR_ClearInterrupt(SAR0, intrMask);
}

The following code snippet demonstrates how to configure and enable the interrupt.

/* Scenario: Configure and enable the SAR interrupt. */
cy_stc_sysint_t SAR0_IrqConfig =
{
/* .intrSrc = */ pass_0_interrupt_sar_IRQn, /* Interrupt source is the SAR interrupt */
/* .intrPriority = */ 3UL /* Interrupt priority is 3 */
};
/* Configure the interrupt with vector at SAR0_Isr(). */
cy_en_sysint_status_t sysintStatus = Cy_SysInt_Init(&SAR0_IrqConfig, SAR0_Isr);
if (CY_SYSINT_SUCCESS != sysintStatus)
{
/* insert error handling here */
}
/* Enable the interrupt. */
NVIC_EnableIRQ(SAR0_IrqConfig.intrSrc);
/* Clear possible interrupt erroneously raised during block enabling */

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. To customize the counts-to-volts conversion process, use Cy_SAR_SetChannelOffset and Cy_SAR_SetChannelGain functions.

Scan Rate

The scan rate is dependent on the following:

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 cy_stc_sar_channel_config_t. The four global aperture times are also set during initialization with from cy_stc_sar_config_t::sampleTime0 through cy_stc_sar_config_t::sampleTime3. Note that these global aperture times are in SAR clock cycles and the acquisition time is 1 less than that value in the register.

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.

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: accumulating or fixed (see cy_stc_sar_config_t::avgShift) are sampled multiple times per scan. The number of samples averaged are set during initialization using cy_stc_sar_config_t::avgCnt. Channels that are not averaged 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.

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:

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

sar_sarmux_switches.png

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

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. These switches need to be enabled for SARSEQ control if the CTB outputs are used as the SARMUX inputs.

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.

sar_sarmux_dedicated_port.png
{
/* .addr */ CY_SAR_ADDR_SARMUX_0, /* Use Pin 0 of the SARMUX */
/* .differential */ false, /* Single ended */
/* .resolution */ CY_SAR_MAX_RES, /* 12-bit */
/* .avgEn */ false, /* Disable averaging */
/* .sampleTimeSel */ 0UL, /* Aperture time is set by Sample Time 0 */
/* .rangeIntrEn */ false, /* Disable range interrupt */
/* .satIntEn */ false, /* Disable saturation interrupt */
#if defined (CY_IP_M0S8PASS4A_SAR_VERSION) && (4U <= CY_IP_M0S8PASS4A_SAR_VERSION)
/* .neg_addr */ CY_SAR_NEG_ADDR_SARMUX_7, /* Pin 7 of the SARMUX */
/* .negAddrEn */ false, /* Disable negative address */
/* .diagVplusSource */ false, /* Disable source current for Vplus */
/* .diagVplusSink */ false, /* Disable sink current for Vplus */
/* .diagVminusSoure */ false, /* Disable source current for Vminus */
/* .diagVminusSink */ false /* Disable sink current for Vminus */
#endif
};
{
/* .addr */ CY_SAR_ADDR_SARMUX_1, /* Use Pin 1 of the SARMUX */
/* .differential */ false, /* Single ended */
/* .resolution */ CY_SAR_MAX_RES, /* 12-bit */
/* .avgEn */ false, /* Disable averaging */
/* .sampleTimeSel */ 0UL, /* Aperture time is set by Sample Time 0 */
/* .rangeIntrEn */ false, /* Disable range interrupt */
/* .satIntEn */ false, /* Disable saturation interrupt */
#if defined (CY_IP_M0S8PASS4A_SAR_VERSION) && (4U <= CY_IP_M0S8PASS4A_SAR_VERSION)
/* .neg_addr */ CY_SAR_NEG_ADDR_SARMUX_7, /* Pin 7 of the SARMUX */
/* .negAddrEn */ false, /* Disable negative address */
/* .diagVplusSource */ false, /* Disable source current for Vplus */
/* .diagVplusSink */ false, /* Disable sink current for Vplus */
/* .diagVminusSoure */ false, /* Disable source current for Vminus */
/* .diagVminusSink */ false /* Disable sink current for Vminus */
#endif
};
cy_stc_sar_channel_config_t channelDiffCfg =
{
/* .addr */ CY_SAR_ADDR_SARMUX_0, /* Positive terminal is connected to Pin 0 and negative terminal is connected to Pin 1 of the SARMUX */
/* .differential */ true, /* Differential */
/* .resolution */ CY_SAR_MAX_RES, /* 12-bit */
/* .avgEn */ false, /* Disable averaging */
/* .sampleTimeSel */ 0UL, /* Aperture time is set by Sample Time 0 */
/* .rangeIntrEn */ false, /* Disable range interrupt */
/* .satIntEn */ false, /* Disable saturation interrupt */
#if defined (CY_IP_M0S8PASS4A_SAR_VERSION) && (4U <= CY_IP_M0S8PASS4A_SAR_VERSION)
/* .neg_addr */ CY_SAR_NEG_ADDR_SARMUX_7, /* Pin 7 of the SARMUX */
/* .negAddrEn */ false, /* Disable negative address */
/* .diagVplusSource */ false, /* Disable source current for Vplus */
/* .diagVplusSink */ false, /* Disable sink current for Vplus */
/* .diagVminusSoure */ false, /* Disable source current for Vminus */
/* .diagVminusSink */ false /* Disable sink current for Vminus */
#endif
};
{
/* .muxSwitch */ CY_SAR_MUX_FW_P0_VPLUS | /* Connect Pin 0 of the SARMUX to the positive terminal of the SARADC for the first single-ended channel */
CY_SAR_MUX_FW_P1_VPLUS | /* Connect Pin 1 of the SARMUX to the positive terminal of the SARADC for the second single-ended channel */
CY_SAR_MUX_FW_P1_VMINUS | /* Connect Pin 1 of the SARMUX to the negative terminal of the SARADC for the differential channel */
CY_SAR_MUX_FW_VSSA_VMINUS, /* Connect VSSA of the SARMUX to the negative terminal of the SARADC for the single-ended channels */
/* .muxSwitchHwCtrl */ CY_SAR_MUX_HW_CTRL_P0 | /* Enable sequencer control of Pins 0 of the SARMUX */
CY_SAR_MUX_HW_CTRL_P1 | /* Enable sequencer control of Pins 1 of the SARMUX */
CY_SAR_MUX_HW_CTRL_VSSA, /* Enable sequencer control of VSSA switch. */
/* .muxSwitch2 */ 0U,
/* .muxSwitchHwCtrl2*/ 0U
};

Input from CTB output via 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.

sar_sarmux_ctb.png

Use Input from SARMUX port code snippet for reference.

/* Check the device TRM for the CTB block presence */
channelSe0Cfg.addr = CY_SAR_ADDR_CTB0_OA0; /* Use CTB0 OA0 out */
channelSe1Cfg.addr = CY_SAR_ADDR_CTB0_OA1; /* Use CTB0 OA1 out */
channelDiffCfg.addr = CY_SAR_ADDR_CTB0_OA0; /* Use CTB0 OA0 for Vplus and CTB0 OA1 for Vminus */
routingConfig.muxSwitch = CY_SAR_MUX_FW_SARBUS0_VPLUS | /* Close switch between Vplus and SARBUS0 for Channels 0 and 2. */
CY_SAR_MUX_FW_SARBUS1_VPLUS | /* Close switch between Vplus and SARBUS0 for Channel 1. */
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 Channels 0 and 1. */
routingConfig.muxSwitchHwCtrl = CY_SAR_MUX_HW_CTRL_SARBUS0 | /* Enable SARSEQ control of SARBUS0 switch. */
CY_SAR_MUX_HW_CTRL_SARBUS1 | /* Enable SARSEQ control of SARBUS1 switch. */
CY_SAR_MUX_HW_CTRL_VSSA; /* Enable SARSEQ control of VSSA switch. */
/* Configure both CTB0 OpAmps as followers in 1x mode. */
const cy_stc_ctb_opamp_config_t opAmpConfig =
{
/* .power = */ CY_CTB_POWER_HIGH,
/* .outputMode = */ CY_CTB_MODE_OPAMP_EXTERNAL, /* Configure as an OpAmp with external drive. */
/* .pump = */ true,
/* .compEdge = */ CY_CTB_COMP_EDGE_DISABLE, /* Ignore comparator settings. */
/* .compLevel = */ CY_CTB_COMP_TRIGGER_OUT_PULSE,
/* .compBypass = */ false,
/* .compHyst = */ false,
/* .compIntrEn = */ false,
/* .switchCtrl = */ CY_CTB_SW_OA_NEG_OUT | CY_CTB_SW_OA_OUT_SARBUS0 | CY_CTB_SW_OA_OUT_SHORT_IN_EXT /* Both follower outputs to SARBUS0 */
};
const cy_stc_ctb_config_t ctbConfig =
{
/* .deepSleep = */ false,
/* .oa0 = */ &opAmpConfig,
/* .oa1 = */ &opAmpConfig, /* The same configuration for both OpAmps */
};
cy_en_ctb_status_t ctbStatus = Cy_CTB_Init(CTBM0, &ctbConfig);
if (CY_CTB_SUCCESS == ctbStatus)
{
Cy_CTB_SetAnalogSwitch(CTBM0, CY_CTB_OPAMP_0, CY_CTB_SW_OA0_POS_PIN6, true); /* OpAmp0 positive input to Pin 6 */
Cy_CTB_SetAnalogSwitch(CTBM0, CY_CTB_OPAMP_1, CY_CTB_SW_OA1_POS_PIN7 | CY_CTB_SW_OA1_OUT_SARBUS1, true); /* OpAmp1 positive input to Pin 7 and output to SARBUS1 */
Cy_CTB_EnableSarSeqCtrl(CTBM0, CY_CTB_SW_HW_CTRL_D51_D52_D62); /* Enable SARSEQ control of CTB switches */
Cy_CTB_Enable(CTBM0);
}
else
{
/* insert error handling here */
}

Then use Cy_SAR_Init and results retrieval as usual. For more information about CTB see CTB (Continuous Time Block).

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.

sar_sarmux_amuxbus.png

Use Input from SARMUX port code snippet for reference.

channelSe0Cfg.addr = CY_SAR_ADDR_SARMUX_AMUXBUS_A; /* Use Pin 0 of the SARMUX */
/* Configure pins */
Cy_GPIO_Pin_FastInit(GPIO_PRT1, 0UL, CY_GPIO_DM_ANALOG, 0UL, P1_0_AMUXA); /* Connect P1_0 to AMUXBUSA. */
Cy_GPIO_Pin_FastInit(GPIO_PRT1, 1UL, CY_GPIO_DM_ANALOG, 0UL, P1_1_AMUXB); /* Connect P1_1 to AMUXBUSB. */
routingConfig.muxSwitch = CY_SAR_MUX_FW_AMUXBUSA_VPLUS | /* Connect AMUXBUSA of the SARMUX to the positive terminal of the SARADC for the first single-ended and the differential channels */
CY_SAR_MUX_FW_AMUXBUSB_VPLUS | /* Connect AMUXBUSB of the SARMUX to the positive terminal of the SARADC for the second single-ended channel */
CY_SAR_MUX_FW_AMUXBUSB_VMINUS | /* Connect AMUXBUSBof the SARMUX to the negative terminal of the SARADC for the differential channel */
CY_SAR_MUX_FW_VSSA_VMINUS; /* Connect VSSA of the SARMUX to the negative terminal of the SARADC for the single-ended channels */
routingConfig.muxSwitchHwCtrl = CY_SAR_MUX_HW_CTRL_AMUXBUSA | /* Enable sequencer control of AMUXBUSA of the SARMUX */
CY_SAR_MUX_HW_CTRL_AMUXBUSB | /* Enable sequencer control of AMUXBUSB of the SARMUX */
CY_SAR_MUX_HW_CTRL_VSSA; /* Enable sequencer control of VSSA switch. */

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].

Die temperature measurement

The DieTemp sensor scanning typically is being done by the injection channel:

cy_stc_sar_channel_config_t injectionChannelConfig =
{
/* .addr */ CY_SAR_ADDR_SARMUX_DIE_TEMP, /* Positive terminal is connected to the die temperature sensor and negative terminal is connected to VSSA */
/* .differential */ false, /* Single ended */
/* .resolution */ CY_SAR_MAX_RES, /* 12-bit */
/* .avgEn */ true, /* Enable averaging */
/* .sampleTimeSel */ 0UL, /* Aperture time is set by Sample Time 0 */
/* .rangeIntrEn */ false, /* Disable range interrupt */
/* .satIntEn */ false, /* Disable saturation interrupt */
#if defined (CY_IP_M0S8PASS4A_SAR_VERSION) && (4U <= CY_IP_M0S8PASS4A_SAR_VERSION)
/* .neg_addr */ CY_SAR_NEG_ADDR_SARMUX_7, /* Pin 7 of the SARMUX */
/* .negAddrEn */ false, /* Disable negative address */
/* .diagVplusSource */ false, /* Disable source current for Vplus */
/* .diagVplusSink */ false, /* Disable sink current for Vplus */
/* .diagVminusSoure */ false, /* Disable source current for Vminus */
/* .diagVminusSink */ false /* Disable sink current for Vminus */
#endif
};
/* Scenario: Apart of those three ADC channels, configure the injection channel to measure the die temperature */
routingConfig.muxSwitch |= CY_SAR_MUX_FW_TEMP_VPLUS; /* Connect the die temperature sensor to the positive terminal of the SARADC for the injection single-ended channel */
routingConfig.muxSwitchHwCtrl |= CY_SAR_MUX_HW_CTRL_TEMP; /* Enable sequencer control of DIE_TEMP switch */
config.vrefSel = CY_SAR_VREF_SEL_BGR; /* Set Vref 1.2V for best temperature measurement precision */
config.vrefMvValue = 1200; /* 1.2V in millivolts */
config.avgCnt = CY_SAR_AVG_CNT_256; /* averaging to capture maximally stable and precise temperature value */
config.channelConfig[CY_SAR_INJ_CHANNEL] = &injectionChannelConfig;

Then the regular initialization is going on:

cy_en_sar_status_t sarStatus = Cy_SAR_Init(SAR0, &config);
if (CY_SAR_SUCCESS != sarStatus)
{
/* insert error handling here */
}

Then during the ADC working the injection channel is being activated:

/* Scenario: execute the injection channel at the tail of the nearest ADC scanning */

Then the retrieved injection channel result can be transformed into the temperature value:

int16_t injResult = 0;
{
}
/* now injResult contains the injection channel result */
int16_t temp = Cy_SAR_CountsTo_degreeC(SAR0, CY_SAR_INJ_CHANNEL, injResult);
/* now temp contains the die temperature is degrees Celsius */

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 the SARMUX can be configured to remain enabled in Deep Sleep mode by the cy_stc_sar_config_t::sarMuxDsEn setting. 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

VersionChangesReason for Change
2.50 Added the Cy_SAR_CountsTo_degreeC function API improvement
The configuration restoring during DeepSleep cycle is updated in the Cy_SAR_DeepSleepCallback function Bug fix
2.40 Added support for a new version of SAR.
Added support for PSOC4 HVMS/PA platform.
Updated APIs to incorporate PSOC4 HVMS/PA platform configuration.
Documentation enhancement.
New device support.
2.30 The Cy_SAR_DeepSleepCallback parameter type is changed to match with the cy_stc_syspm_callback_t::callback type Eliminate compiler warnings
The Cy_SAR_IsEndConversion timeout is corrected Fixed incorrect timeout value and related documentation
2.20 The Cy_SAR_CountsTo_uVolts is updated to avoid 64-bit math Memory consumption reduction
Update the paths to the code snippets. PDL structure update.
2.10 Added the cy_stc_sar_channel_config_t::rangeIntrEn and cy_stc_sar_channel_config_t::satIntrEn settings Bug fixing
Fixed the Cy_SAR_SetConvertMode function Bug fixing
Updated the Cy_SAR_CountsTo_uVolts, Cy_SAR_CountsTo_mVolts and Cy_SAR_CountsTo_Volts functions so that they now support sub-resolutions Bug fixing
2.0 Added the Cy_SAR_CountsTo_degreeC function Die temperature measurement support
Added the Cy_SAR_EnableChannels and Cy_SAR_DisableChannels functions API enhancement
Added code snippets how to interconnect with CTB (Continuous Time Block) CTB (Continuous Time Block) support
The type of cy_stc_sar_channel_config_t::sampleTimeSel is changed from uint32_t to cy_en_sar_channel_sampletime_t Improved the API error proofness
1.0.1 Minor documentation updates. Documentation enhancement
1.0 Initial version