Skip to content

驱动补充:example_adc_circle

MCU驱动使用 > 驱动补充:example_adc_circle

c
// example_adc_circle.c

#ifdef IPS_ANALOG_IP

#include "example.h"
#include "analog_ip.h"

//
// 开启DMA方式来循环读取ADC的多个channal的值
// 读完后,数据放到adc_table数组。
//
// 这里给出两个示例:
// 一个是调用了DMAC_ConfigCircular,这个函数是SDK1.3.2以后新增的。一个是没使用这个函数的。
// 其实两个示例最终走的流程都是一样的。

static uint32_t sclk_div = 9; // Divided by 20 = (9 + 1) * 2
static uint32_t adc_table[2]; // 以下示例中只采集了两路,这里就给2就行了

// 测试循环读取ADC
DMAC_LLI_TypeDef circular_lli; // 必须定义为全局或静态变量,不能是局部变量。因为DMA在运行中,会持续使用。局部变量在退出函数后会释放掉。

// 使用了DMAC_ConfigCircular函数的。
void TestCircleAdc2()
{
    PERIPHERAL_ENABLE(DMAC, 0);
    DMAC_Init();

    ADC_SetSeqLength(ADC0, ADC_SEQ_LENGTH2); // 设置DMA要读取的ADC的channal数
    ADC_SetSeqChannel(ADC0, 0, ADC_CHANNEL3); // channal-A,配置第一个channal。第二个参数seq决定dma读完后放到 adc_table 的哪个位置。
    ADC_SetSeqChannel(ADC0, 1, ADC_CHANNEL4); // channal-B,配置第二个channal

    DMAC_ConfigCircular(DMAC_CHANNEL1, // DMA的channal(跟ADC的channal无关)
                        (uint32_t)&ADC0->DATA, // 从哪个ADC读取
                        (uint32_t)adc_table, // 存放数据的数组
                        DMAC_ADDR_INCR_OFF, DMAC_ADDR_INCR_ON,
                        DMAC_WIDTH_32_BIT, DMAC_WIDTH_32_BIT, // 32位的,不能是16位
                        DMAC_BURST_1, DMAC_BURST_1,
                        2, // 一轮读取几个。跟上边的channal数对应。
                        DMAC_PERIPHERAL_TO_MEM_DMA_CTRL, ADC0_DMA_REQ, 0,
                        &circular_lli); // lli,注意这里要加取值符&
    ADC_StartDma(ADC0, sclk_div); // 开启DMA

    while(1)
    {
        printf("adc value:%d, %d\r\n", adc_table[0], adc_table[1]);
        UTIL_IdleUs(200e3);
    }
}

// 没有使用 DMAC_ConfigCircular 函数。
// 这里的配置方法,和上边的函数是一致的。注释部分参考上边的函数。
void TestCircleAdc()
{
    PERIPHERAL_ENABLE(DMAC, 0);
    DMAC_Init();

    ADC_SetSeqLength(ADC0, ADC_SEQ_LENGTH2); // Scan channels number
    ADC_SetSeqChannel(ADC0, 0, ADC_CHANNEL3); // channal-A
    ADC_SetSeqChannel(ADC0, 1, ADC_CHANNEL4); // channal-B

    circular_lli.SrcAddr = (uint32_t)&ADC0->DATA;
    circular_lli.DstAddr = (uint32_t)adc_table;
    circular_lli.LLI = (uint32_t)&circular_lli; // Points to itself for circular transfer
    circular_lli.Control = DMAC_MakeControl(DMAC_ADDR_INCR_OFF, DMAC_ADDR_INCR_ON,
                                            DMAC_WIDTH_32_BIT, DMAC_WIDTH_32_BIT, DMAC_BURST_1, DMAC_BURST_1, 2, DISABLE);
    DMAC_ConfigLLI(DMAC_CHANNEL1, DMAC_PERIPHERAL_TO_MEM_DMA_CTRL, ADC0_DMA_REQ, 0, (uint32_t)&circular_lli);

    ADC_StartDma(ADC0, sclk_div);

    while(1)
    {
        printf("adc value:%d, %d\r\n", adc_table[0], adc_table[1]);
        UTIL_IdleUs(200e3);
    }
}

#endif