ADC中断函数

volatile bool gCheckADC;
volatile uint16_t gAdcResult;

void ADC12_0_INST_IRQHandler(void)
{
    switch (DL_ADC12_getPendingInterrupt(ADC12_0_INST)) {
        case DL_ADC12_IIDX_MEM0_RESULT_LOADED:
            gCheckADC = true;
            break;
        default:
            break;
    }
}

在主函数中,使能ADC中断函数后,通过调用DL_ADC12_startConversion开始转换,并通过gCheckADC判断转换是否完成

转换时间=采样时间 +12.5×ADC 时钟周期

在单次采样模式中,每次while循环完成adc转换后边封装为串口屏的波形显示指令,发送到串口屏上

while (1) {
        DL_ADC12_startConversion(ADC12_0_INST);

        while (false == gCheckADC) {

        }

        gAdcResult = DL_ADC12_getMemResult(ADC12_0_INST, DL_ADC12_MEM_IDX_0);
        sprintf(str,"add s0.id,0,%d\xff\xff\xff",gAdcResult);//将波形数据发送至串口屏端
        sendString(str);
        if (gAdcResult > 0x7ff) {
            DL_GPIO_clearPins(GPIO_LEDS_PORT, GPIO_LEDS_USER_LED_1_PIN);
        } else {
            DL_GPIO_setPins(GPIO_LEDS_PORT, GPIO_LEDS_USER_LED_1_PIN);
        }
        gCheckADC = false;
        DL_ADC12_enableConversions(ADC12_0_INST);
    }

DMA

DMA(Direct Memory Access)控制器提供了一种硬件的方式在外设和存储器之间或者存储器和存储器之间传输数据,而无需 CPU 的介入,避免了 CPU 多次进入中断进行大规模的数据拷贝,最终提高整体的系统性能。

数据传输方式

一般情况下实现存储器和外设之间的数据传输,有三种常用的方法:轮询法(polling),中断法(interrupt)以及 DMA。

  轮询法(polling): 在主循环中,CPU 不断检查外设的相关标志位,来判断其是否需要进行数据的传输,如果需要,则 CPU 将数据在外设和内存之间搬运,实现数据传输。当数据传输服务请求频繁或者传输的数据量很大时,会影响其他任务的实时性。

  中断法(interrupt): 当外设需要传输数据时,会触发中断,CPU 会暂停正在处理的任务,转而去执行中断服务函数,接着处理外设的数据传输任务。CPU 无需反复检查外设的标志位,中断机制会指示 CPU 何时去处理外设数据,但是依然需要 CPU 去完成数据搬运和传输过程。当外设数据传输服务不频繁且数据量不大时,中断法也是不错的选择。当中断连续不断且频繁发生时,中断法变得不再高效,因为在恢复主流程的执行和中断相应的上下文切换会占用大量的 CPU 时间。

  DMA: DMA 控制器是单片机中的硬件单元,它在存储器和外设之间有专用的通道,允许外设和存储器之间高效传输数据,且传输过程无需 CPU 参与。

通过引入DMA存储ADC转换后的数据,可以路径更短,无需 CPU 干预

在Sysconfig界面的ADC配置界面,开启DMA Configuration

image.png

在main函数中,设置DMA搬运数据的起始地址与终点地址,同时定义存储空间

volatile uint16_t ADC_VALUE[20];

       //设置DMA搬运的起始地址
       DL_DMA_setSrcAddr(DMA, DMA_CH0_CHAN_ID, (uint32_t) &ADC0->ULLMEM.MEMRES[0]);
       //设置DMA搬运的目的地址
       DL_DMA_setDestAddr(DMA, DMA_CH0_CHAN_ID, (uint32_t) &ADC_VALUE[0]);
       //开启DMA
       DL_DMA_enableChannel(DMA, DMA_CH0_CHAN_ID);
       //开启ADC转换
       DL_ADC12_startConversion(ADC12_0_INST);

在主函数中调用printf,串口发送ADC存储的数据