SARADC

概述

BK7238内置了一个10位通用SAR_ADC,可编程采样时钟范围从5kHz到 26MHz。10位分辨率的ADC可以配置为12~14位。ADC最多支持6个通道。它可以在单次模式或连续模式下运行。ADC支持全幅输入范围(从0V到VBAT)或从0V到3.6V. 一般精度在 SARADC 驱动中不做动态调整。

SARADC 模式类型:

  • 休眠模式:

    休眠模式下 ADC 停止任何操作,相当于 power down 的状态

  • 单步模式:

    单步模式下 ADC 每次只会采集一个数据,采集完成之后自动变为休眠模式,相应的模式状态位也会变为休眠模式 然后等待 MCU 来读取数据,每一次的采样都需要将模式设置为单步模式.

  • 软件控制模式

    软件控制模式下会产生 ADC 中断,当处于此模式时,ADC 转换完成之后会产生一个中断,这个时候会等待 MCU 读取数据, 如果不读取数据就不会产生中断,如果MCU读取数据之后,清除掉中断后,ADC又开始新一轮的转换,继续等待 MCU 读取数据…

  • 连续模式

    连续模式是在软件控制的模式下,去掉了 MCU 读取数据的等待,不管 MCU 取不取数据,ADC 总是按照固定节拍采样转换数据 不受任何信号影响,只有停止 ADC 才能停止 ADC 读取数据.

注解

当 ADC 处于连续模式时会一直上报中断和采集数据,这样频繁产生中断,影响系统性能,所以当 ADC 模式处于连续模式的时候需要每采取一次到想要的 ADC 数据长度之后就停止 ADC.

SARADC 获取数据流程:

SARADC 在连续模式下转换数据如下图所示。

saradc Overview

SARADC Overview

如上图所示:

  • S1,S2。。。表示对 ADC 某一通道上电压进行一次采样和转换,采样一次输出 16 bits 数据;采样电压范围为 0 到 2.4v; 一次采样时长 16 个 clock.

  • Sample Rate:两次采样间隔的倒数为采样率,仅在连续模式下生效.

  • Sample Cnt:有两层含义,一方面,它表示 ADC 硬件 Buffer 的大小,单位为 16bits, ADC 将每次采样得到的数据存于硬件 Buffer;另一方面,它也表示中断上报时间点,即每经过多少次采样上报一次中断; Sample Cnt 可由 API bk_adc_set_sample_cnt() 进行配置,默认值为 32。

  • ADC Hardware Buffer: 即硬件存放采样数据的 Buffer,大小与 Sample Cnt 相同。

  • ADC Software Buffer: ADC 驱动存放采样数据的 Buffer,每次产生 ADC 中断后,ADC 驱动会将 ADC Hardware Buffer 中的数据 copy 到 ADC Software Buffer.

连续模式ADC测试例程

例程位于 demos/peripheral/adc/test_adc.c

saradc_desc_t test_adc_demo_adc1;
DD_HANDLE test_adc_demo_handle = -1;

void test_adc_demo_isr_cb(void)
{
    UINT32 sum = 0;
    float voltage = 0.0;

    if(test_adc_demo_adc1.data_buff_size <= test_adc_demo_adc1.current_sample_data_cnt)
    {
        ddev_close(test_adc_demo_handle);
        saradc_ensure_close();

        for(int i=0;i<test_adc_demo_adc1.data_buff_size;i++)
        {
            sum +=test_adc_demo_adc1.pData[i];
        }
        sum=sum/test_adc_demo_adc1.data_buff_size;

        test_adc_demo_adc1.pData[0] = sum;
        voltage = saradc_calculate(sum);
        os_printf("voltage is [%d] mv\r\n", (UINT32)(voltage * 1000));

    }
}

VOID test_adc_demo_start(void)
{
    uint32_t ret;
    UINT32 status;
    GLOBAL_INT_DECLARATION();

    os_memset(&test_adc_demo_adc1, 0x00, sizeof(saradc_desc_t));
    saradc_config_param_init(&test_adc_demo_adc1);

    test_adc_demo_adc1.channel = 1;
    test_adc_demo_adc1.data_buff_size = 20;
    test_adc_demo_adc1.mode = 3;
    test_adc_demo_adc1.current_read_data_cnt = 0;
    test_adc_demo_adc1.current_sample_data_cnt = 0;
    test_adc_demo_adc1.has_data = 0;
    test_adc_demo_adc1.p_Int_Handler = test_adc_demo_isr_cb;
    test_adc_demo_adc1.pData = os_malloc(sizeof(UINT16) * test_adc_demo_adc1.data_buff_size);
    if(!test_adc_demo_adc1.pData)
    {
        os_printf("malloc failed\n");
        return;
    }

    ret = 0;
    do {
        GLOBAL_INT_DISABLE();
        if(saradc_check_busy() == 0) {
            test_adc_demo_handle = ddev_open(SARADC_DEV_NAME, &status, (UINT32)&test_adc_demo_adc1);
            if(DD_HANDLE_UNVALID != test_adc_demo_handle)
            {
                GLOBAL_INT_RESTORE();
                break;
            }
        }
    GLOBAL_INT_RESTORE();

    rtos_delay_milliseconds(5);
    ret++;
    } while(ret<5);

    if(ret == 5) {
        os_free(test_adc_demo_adc1.pData);
        os_printf("adc_open failed\n");
        return;
    }
}

具体处理流程如下:

  • ADC Start: ddev_open(SARADC_DEV_NAME, &status, (UINT32)&test_adc_demo_adc1) 启动 ADC,开始采样。

  • ADC 硬件采样:硬件将每次采样数据存 Hardware Buffer。

  • ADC 中断产生:当采样 test_adc_demo_adc1.data_buff_size 次之后, ADC Software Buffer test_adc_demo_adc1.pData 缓存满了之后,调用 p_Int_Handler callback 回调上层获取采样结果,然后重新进行采样。