SAADC — Successive approximation analog-todigital converter,逐次逼近模数转换器。
八路模拟信号单端或者差分输入,支持8/10/12位采样精度,多次采样模式下采样精度可以达到14位,支持电压采样范围0-VDD,支持RTC或者外部高精度时钟定时执行,同时也支持PPI配置的事件触发执行,支持采样门限值检测,支持EasyDMA可以连续采样到指定RAM空间。
NRF_SAADC->ENABLE = (SAADC_ENABLE_ENABLE_Enabled << SAADC_ENABLE_ENABLE_Pos);
NRF_SAADC->ENABLE = (SAADC_ENABLE_ENABLE_Disabled << SAADC_ENABLE_ENABLE_Pos);
NRF_SAADC->INTENSET = saadc_int_mask;
/** @brief Analog-to-digital converter interrupt masks. */
typedef enum
{
NRF_SAADC_INT_STARTED = SAADC_INTENSET_STARTED_Msk, ///< Interrupt on EVENTS_STARTED event.
NRF_SAADC_INT_END = SAADC_INTENSET_END_Msk, ///< Interrupt on EVENTS_END event.
NRF_SAADC_INT_DONE = SAADC_INTENSET_DONE_Msk, ///< Interrupt on EVENTS_DONE event.
NRF_SAADC_INT_RESULTDONE = SAADC_INTENSET_RESULTDONE_Msk, ///< Interrupt on EVENTS_RESULTDONE event.
NRF_SAADC_INT_CALIBRATEDONE = SAADC_INTENSET_CALIBRATEDONE_Msk, ///< Interrupt on EVENTS_CALIBRATEDONE event.
NRF_SAADC_INT_STOPPED = SAADC_INTENSET_STOPPED_Msk, ///< Interrupt on EVENTS_STOPPED event.
NRF_SAADC_INT_CH0LIMITH = SAADC_INTENSET_CH0LIMITH_Msk, ///< Interrupt on EVENTS_CH[0].LIMITH event.
NRF_SAADC_INT_CH0LIMITL = SAADC_INTENSET_CH0LIMITL_Msk, ///< Interrupt on EVENTS_CH[0].LIMITL event.
NRF_SAADC_INT_CH1LIMITH = SAADC_INTENSET_CH1LIMITH_Msk, ///< Interrupt on EVENTS_CH[1].LIMITH event.
NRF_SAADC_INT_CH1LIMITL = SAADC_INTENSET_CH1LIMITL_Msk, ///< Interrupt on EVENTS_CH[1].LIMITL event.
NRF_SAADC_INT_CH2LIMITH = SAADC_INTENSET_CH2LIMITH_Msk, ///< Interrupt on EVENTS_CH[2].LIMITH event.
NRF_SAADC_INT_CH2LIMITL = SAADC_INTENSET_CH2LIMITL_Msk, ///< Interrupt on EVENTS_CH[2].LIMITL event.
NRF_SAADC_INT_CH3LIMITH = SAADC_INTENSET_CH3LIMITH_Msk, ///< Interrupt on EVENTS_CH[3].LIMITH event.
NRF_SAADC_INT_CH3LIMITL = SAADC_INTENSET_CH3LIMITL_Msk, ///< Interrupt on EVENTS_CH[3].LIMITL event.
NRF_SAADC_INT_CH4LIMITH = SAADC_INTENSET_CH4LIMITH_Msk, ///< Interrupt on EVENTS_CH[4].LIMITH event.
NRF_SAADC_INT_CH4LIMITL = SAADC_INTENSET_CH4LIMITL_Msk, ///< Interrupt on EVENTS_CH[4].LIMITL event.
NRF_SAADC_INT_CH5LIMITH = SAADC_INTENSET_CH5LIMITH_Msk, ///< Interrupt on EVENTS_CH[5].LIMITH event.
NRF_SAADC_INT_CH5LIMITL = SAADC_INTENSET_CH5LIMITL_Msk, ///< Interrupt on EVENTS_CH[5].LIMITL event.
NRF_SAADC_INT_CH6LIMITH = SAADC_INTENSET_CH6LIMITH_Msk, ///< Interrupt on EVENTS_CH[6].LIMITH event.
NRF_SAADC_INT_CH6LIMITL = SAADC_INTENSET_CH6LIMITL_Msk, ///< Interrupt on EVENTS_CH[6].LIMITL event.
NRF_SAADC_INT_CH7LIMITH = SAADC_INTENSET_CH7LIMITH_Msk, ///< Interrupt on EVENTS_CH[7].LIMITH event.
NRF_SAADC_INT_CH7LIMITL = SAADC_INTENSET_CH7LIMITL_Msk, ///< Interrupt on EVENTS_CH[7].LIMITL event.
NRF_SAADC_INT_ALL = 0x7FFFFFFFUL ///< Mask of all interrupts.
} nrf_saadc_int_mask_t;
NRF_SAADC->CH[channel].CONFIG =
((config->resistor_p << SAADC_CH_CONFIG_RESP_Pos) & SAADC_CH_CONFIG_RESP_Msk)
| ((config->resistor_n << SAADC_CH_CONFIG_RESN_Pos) & SAADC_CH_CONFIG_RESN_Msk)
| ((config->gain << SAADC_CH_CONFIG_GAIN_Pos) & SAADC_CH_CONFIG_GAIN_Msk)
| ((config->reference << SAADC_CH_CONFIG_REFSEL_Pos) & SAADC_CH_CONFIG_REFSEL_Msk)
| ((config->acq_time << SAADC_CH_CONFIG_TACQ_Pos) & SAADC_CH_CONFIG_TACQ_Msk)
| ((config->mode << SAADC_CH_CONFIG_MODE_Pos) & SAADC_CH_CONFIG_MODE_Msk)
| ((config->burst << SAADC_CH_CONFIG_BURST_Pos) & SAADC_CH_CONFIG_BURST_Msk);
NRF_SAADC->CH[channel].PSELN = pseln;
NRF_SAADC->CH[channel].PSELP = pselp;
*((volatile uint32_t *)((uint8_t *)NRF_SAADC + (uint32_t)task)) = 0x1UL;
/** @brief Analog-to-digital converter tasks. */
typedef enum
{
NRF_SAADC_TASK_START = offsetof(NRF_SAADC_Type, TASKS_START), ///< Start the ADC and prepare the result buffer in RAM.
NRF_SAADC_TASK_SAMPLE = offsetof(NRF_SAADC_Type, TASKS_SAMPLE), ///< Take one ADC sample. If scan is enabled, all channels are sampled.
NRF_SAADC_TASK_STOP = offsetof(NRF_SAADC_Type, TASKS_STOP), ///< Stop the ADC and terminate any ongoing conversion.
NRF_SAADC_TASK_CALIBRATEOFFSET = offsetof(NRF_SAADC_Type, TASKS_CALIBRATEOFFSET), ///< Starts offset auto-calibration.
} nrf_saadc_task_t;
NRF_SAADC->CH[channel].PSELN = NRF_SAADC_INPUT_DISABLED;
NRF_SAADC->CH[channel].PSELP = NRF_SAADC_INPUT_DISABLED;
//SAADC初始化
nrfx_saadc_config_t saadc_config = NRFX_SAADC_DEFAULT_CONFIG;
saadc_config.resolution = NRF_SAADC_RESOLUTION_10BIT;
saadc_config.oversample = NRF_SAADC_OVERSAMPLE_DISABLED;
saadc_config.low_power_mode = false;
saadc_config.interrupt_priority = UART_VIR_IRQ_PRIORITY;
nrfx_err = nrfx_saadc_init(&saadc_config, saadc_event_handler);
// For some reason, setting Continuous Mode is not a part of the driver/HAL...
uint32_t cc_value = ADC_SAMPLERATE_CC_VALUE(sample_rate) + 2;
NRF_SAADC->SAMPLERATE = (ADC_SAMPLERATE_MODE_TIMER << ADC_SAMPLERATE_MODE_OFFSET) | cc_value;
//SAADC通道初始化
channel_config.mode = NRF_SAADC_MODE_SINGLE_ENDED;
channel_config.acq_time = NRF_SAADC_ACQTIME_3US;
channel_config.burst = NRF_SAADC_BURST_DISABLED;
channel_config.gain = ADC_SAMPLE_GAIN;
channel_config.pin_p = input_p;
channel_config.pin_n = NRF_SAADC_INPUT_DISABLED;
channel_config.resistor_p = NRF_SAADC_RESISTOR_DISABLED;//NRF_SAADC_RESISTOR_PULLDOWN;
channel_config.resistor_n = NRF_SAADC_RESISTOR_DISABLED;
channel_config.reference = NRF_SAADC_REFERENCE_INTERNAL;
nrfx_err = nrfx_saadc_channel_init(ADC_CHANNEL, &channel_config);
//SAADC中断函数
/**@brief Function for handling events from nrfx_saadc */
static void saadc_event_handler(nrfx_saadc_evt_t const * p_event)
{
switch (p_event->type)
{
case NRFX_SAADC_EVT_DONE:
{
NRF_LOG_INFO(“saadc_event_handler ptr = %x, size = %d, ticks = %d…”, p_event->data.done.p_buffer, p_event->data.done.size, NRF_RTC0->COUNTER);
break;
}
case NRFX_SAADC_EVT_CALIBRATEDONE:
{
break;
}
case NRFX_SAADC_EVT_LIMIT:
{
break;
}
default:
{
break;
}
}
}
//SAADC关闭
nrfx_saadc_channel_uninit(ADC_CHANNEL);
nrfx_saadc_uninit();
1: http://www.nordicsemi.com/
2: https://infocenter.nordicsemi.com/index.jsp
3: https://devzone.nordicsemi.com/