SAADC

来源:互联网 发布:aws s3 java 编辑:程序博客网 时间:2024/06/05 05:50

电流 :EasyDMA draws about 1.2 mA, and added to the 700 uASAADC current it sums to ~2 mA。和实测差不多



官方例程解析:TIMER + PPI +SAADC。

特征:

1、       支持8/10/12位分辨率,和14位过采样分辨率

2、       8通道:单端输入最多可同时配置8个通道 和 差分输入最多可同时配置4个通道,也可以混合配置使用。多通道适配扫描模式。

3、       输入范围:(0 to VDD)

4、       通过任务从软件或采样触发PPI通道采样频率充分的灵活性源从低功率32.768千赫RTC或更准确的1/16MHz计时器

5、       采样一个单通道可以一次性转换

6、       扫描模式 是依次采样一系列通道。样本t + t conv消渠道之间的延迟可能不同渠道根据用户配置的ack

7、       EasyDMA,可以直接把数据打到RAM内

8、       中断在单个样本和全缓冲事件

9、       样品存储为162的补数值微分和单端取样

10、   连续采样,无需外部定时器

11、   内部电阻串

12、   限制检查


nrf_drv_saadc_buffer_convert():

这个函数实际是用来配置EasyDMA用的,也就是指定打到内存的位置和限制,但并不会开启转换。并且EasyDMA的指针是双buffer形式的,可以在前一个在使用的情况下直接更新。

如果处理4个通道的数据,SAMPLES_IN_BUFFER=4。各个通道采集一次就产生中断处理。

如果处理1个通道的数据,SAMPLES_IN_BUFFER也可以是4。表示对这个通道采集4次后才产生一次中断处理



nrf_drv_saadc_sample()这个就是正经开启一次转换的函数了。

即使使用TIMER+PPI触发,结合EasyDMA来传输数据,依旧存在一个缺陷,不能循环方式缓存,导致最终还是需要CPU的参与来维持正常的转换,一定程度上会减少CPU睡眠时间比例和持续长度。而且,使用库函数似乎并没有办法关掉ADC的中断,初始化的event_handler必须提供,且每次转换完成都会产生中断,势必唤醒CPU。这样的话,就导致使CPU在ADC连续采集一段时间之后,再批处理数据不太好实现了。


//输入范围

Input range = (+- 0.6 V or +-VDD/4)/Gain

Input range = (VDD/4)/(1/4) = VDD

Input range = (0.6 V)/(1/6) = 3.6 V

//增益GAIN,对输入电压处理。例如测量输入电压最大有1.2V,输入范围只有0.6V,则增益GAIN可为NRF_SAADC_GAIN1_2。


//结果

RESULT = [V(P) – V(N) ] * GAIN/REFERENCE *  2^(RESOLUTION - m)

m=0 if CONFIG.MODE=SE, or m=1 if CONFIG.MODE=Diff.

SE :NRF_SAADC_MODE_SINGLE_ENDED       ,Diff:NRF_SAADC_MODE_DIFFERENTIAL

 //参考电压

Reference

SAADC_CH_CONFIG_REFSEL_Internal (0.6V)

SAADC_CH_CONFIG_REFSEL_VDD1_4   (VDD/4 )


//简单例程

#define SAMPLES_IN_BUFFER 3//缓存大小
static const nrf_drv_timer_t   m_timer1 = NRF_DRV_TIMER_INSTANCE(1);//使用了协议栈,不能用定时器0
static nrf_saadc_value_t       m_buffer_pool[2][SAMPLES_IN_BUFFER];//开辟双缓存
static nrf_ppi_channel_t        m_ppi_channel;//

//已禁止定时器中断,所以不用处理
void timer1_handler(nrf_timer_event_t event_type, void* p_context)
{
}

void saadc_sampling_event_init(void)
{
    ret_code_t err_code;
    err_code = nrf_drv_ppi_init();
    APP_ERROR_CHECK(err_code);
    err_code = nrf_drv_timer_init(&m_timer1, NULL, timer1_handler);
    APP_ERROR_CHECK(err_code);
    /* setup m_timer for compare event every 400ms */
    uint32_t ticks = nrf_drv_timer_ms_to_ticks(&m_timer1, 400);
    nrf_drv_timer_extended_compare(&m_timer1, NRF_TIMER_CC_CHANNEL1, ticks,                                   NRF_TIMER_SHORT_COMPARE1_CLEAR_MASK, false);
    nrf_drv_timer_enable(&m_timer1);
    //get timer and saadc address
    uint32_t timer_compare_event_addr = nrf_drv_timer_compare_event_address_get(&m_timer1, NRF_TIMER_CC_CHANNEL1);
    uint32_t saadc_sample_event_addr = nrf_drv_saadc_sample_task_get();
    /* setup ppi channel so that timer compare event is triggering sample task in SAADC */
    err_code = nrf_drv_ppi_channel_alloc(&m_ppi_channel);//·ÖÅäppiͨµÀ
    APP_ERROR_CHECK(err_code);  
    /* assigning task and event endpoints to the PPI channel.*/
   err_code = nrf_drv_ppi_channel_assign(m_ppi_channel, timer_compare_event_addr, saadc_sample_event_addr);
    APP_ERROR_CHECK(err_code);
}

void saadc_sampling_event_enable(void)
{
    ret_code_t err_code = nrf_drv_ppi_channel_enable(m_ppi_channel);
    APP_ERROR_CHECK(err_code);
}
void saadc_sampling_event_disable(void)
{
ret_code_t err_code = nrf_drv_ppi_channel_disable(m_ppi_channel);
APP_ERROR_CHECK(err_code);
}

void saadc_callback(nrf_drv_saadc_evt_t const * p_event)

{

    int16_t adc_value1 = 0;
    int16_t adc_value2 = 0;
    int16_t adc_value3 = 0;

    if (p_event->type == NRF_DRV_SAADC_EVT_DONE)
    {
        ret_code_t err_code;
        err_code = nrf_drv_saadc_buffer_convert(p_event->data.done.p_buffer, SAMPLES_IN_BUFFER);
        APP_ERROR_CHECK(err_code);

adc_value1 =  p_event->data.done.p_buffer[0];
adc_value2 =  p_event->data.done.p_buffer[1];
adc_value3 =  p_event->data.done.p_buffer[2];
adc_value1 = adc_value1*0.6; //Vref
adc_value1 = adc_value1*2; // gain
adc_value1 = adc_value1/2.048f; // +-2^11 X 1000  == mv
adc_value2 = adc_value2*0.6; //Vref
adc_value2 = adc_value2*2; // gain
adc_value2 = adc_value2/2.048f; // +-2^11 X 1000  == mv
adc_value3 = adc_value3*0.6; //Vref
adc_value3 = adc_value3*2; // gain
adc_value3 = adc_value3/4.096f; // +-2^12 X 1000  == mv

printf("adc_value1=%d  ",adc_value1);
printf("adc_value2=%d  ",adc_value2);
printf("adc_value3=%d\r\n",adc_value3);
    }

}

void saadc_init(void)
{
    ret_code_t err_code;
    nrf_drv_saadc_config_t saadc_config = NRF_DRV_SAADC_DEFAULT_CONFIG;
    saadc_config.resolution = NRF_SAADC_RESOLUTION_12BIT; 

    //settings in differential mode.
    nrf_saadc_channel_config_t channel_0_config =
    NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_DIFFERENTIAL(NRF_SAADC_INPUT_AIN0,NRF_SAADC_INPUT_AIN1);
    channel_0_config.gain = NRF_SAADC_GAIN1_2;
    channel_0_config.reference = NRF_SAADC_REFERENCE_INTERNAL;

    //settings in differential mode.
    nrf_saadc_channel_config_t channel_1_config =
    NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_DIFFERENTIAL(NRF_SAADC_INPUT_AIN2,NRF_SAADC_INPUT_AIN3);
    channel_1_config.gain = NRF_SAADC_GAIN1_2;
    channel_1_config.reference = NRF_SAADC_REFERENCE_INTERNAL;

    //settings in single ended mode.
    nrf_saadc_channel_config_t channel_2_config =
    NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN5);
    channel_2_config.gain = NRF_SAADC_GAIN1_2;
    channel_2_config.reference = NRF_SAADC_REFERENCE_INTERNAL;

    //err_code = nrf_drv_saadc_init(NULL, saadc_callback);//settings in DEFAULT mode.
    err_code = nrf_drv_saadc_init( &saadc_config, saadc_callback );
    APP_ERROR_CHECK(err_code);

    //configures and enables the channel.
    err_code = nrf_drv_saadc_channel_init(0, &channel_0_config);
    APP_ERROR_CHECK(err_code);
    err_code = nrf_drv_saadc_channel_init(1, &channel_1_config);
    APP_ERROR_CHECK(err_code);
    err_code = nrf_drv_saadc_channel_init(2, &channel_2_config);
    APP_ERROR_CHECK(err_code);

    err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool[0],SAMPLES_IN_BUFFER);
    APP_ERROR_CHECK(err_code);
    err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool[1],SAMPLES_IN_BUFFER);
    APP_ERROR_CHECK(err_code);
}

//初始化

    saadc_sampling_event_init();
    saadc_init();
    saadc_sampling_event_enable();


存在未解决问题:功耗问题,关闭单个通道问题????








0 0
原创粉丝点击