外部的模拟信号需要转变成数字信号才能由MCU进一步处理。内部集成了一个12位高精度、高转换速率的逐次逼近型模数转换器(SAR ADC)模块。

1M SPS 转换速度;
12 路转换通道:9 个引脚通道、内置温度传感器、内置 1.2v 基准电压、1/3 电源电压;
4 种参考源:电源电压、ExRef 引脚、内置 1.5v 参考电压、内置 2.5v 参考电压;
ADC 的电压输入范围:0~Vref;
3 种转换模式:单次转换、连续转换、累加转换;
软件可配置 ADC 的转换速率;
内置信号放大器,可转换高阻信号;
支持片内外设自动触发ADC转换,有效降低芯片功耗并提高转换的实时性。

ADC 框图

adc动态特性计算python程序 adc例程_引脚

ADC 转换速度与 ADC 参考电压及 VCC 电压相关,最高转换速度如下表所示: 

adc动态特性计算python程序 adc例程_单片机_02

开发板的配置为最后一个,也就是理论上转换速度可以达到1M。 

例程就是adc的几种转换模式,单次,连续,累加,外部触发,然后在有查询和中断两种,一个8个例程,这里就比较典型的连续和外部触发讲解一下,其他的步骤在文档里有详细的说明,可以对照代码查看。

adc_scan_polling_sw连续触发,查询模式

Gpio_SetAnalog(3, 2, TRUE);  // AIN2
    Gpio_SetAnalog(3, 3, TRUE);  // AIN3
    Gpio_SetAnalog(3, 4, TRUE);  // AIN4

    Adc_Enable();
    M0P_BGR->CR_f.BGR_EN = 0x1u;  // BGR必须使能
    M0P_BGR->CR_f.TS_EN = 0x1u;
    delay100us(1);

    stcAdcCfg.enAdcOpMode = AdcScanMode;  //扫描采样模式
    stcAdcCfg.enAdcClkSel = AdcClkSysTDiv8;
    stcAdcCfg.enAdcSampTimeSel = AdcSampTime4Clk;

    stcAdcCfg.enAdcRefVolSel = RefVolSelAVDD;
    stcAdcCfg.bAdcInBufEn = FALSE;
    stcAdcCfg.enAdcTrig0Sel = AdcTrigDisable;
    stcAdcCfg.enAdcTrig1Sel = AdcTrigDisable;
    Adc_Init(&stcAdcCfg);

    stcAdcScanCfg.u8AdcScanModeCh = ADC_SCAN_CH2_EN | ADC_SCAN_CH3_EN | ADC_SCAN_CH4_EN;
    stcAdcScanCfg.u8AdcSampCnt = 0x6;
    Adc_ConfigScanMode(&stcAdcCfg, &stcAdcScanCfg);

    while (1) {
        Adc_Start();
        while (FALSE != Adc_PollBusyState())
            ;
        for (u8Channel = 0; u8Channel < 8; u8Channel++) {
            Adc_GetScanResult(u8Channel, &u16ScanResult[u8Channel]);

            if ((1 << u8Channel) & stcAdcScanCfg.u8AdcScanModeCh) {
                printf("CH: %d is enabled, AdcVal: 0x%X\n", u8Channel, u16ScanResult[u8Channel]);
            } else {
                printf("CH: %d is disabled, AdcVal: 0x%X\n", u8Channel, u16ScanResult[u8Channel]);
            }

        }
        delay1ms(1000);
        Adc_Init(&stcAdcCfg);
        Adc_ConfigScanMode(&stcAdcCfg, &stcAdcScanCfg);
    }

配置P32,P33,P34为adc,并配置u8AdcScanModeCh设置扫描通道。然后Adc_Start()开始转换。

查询转换结束Adc_PollBusyState(),读取转换结果Adc_GetScanResult(u8Channel, &u16ScanResult[u8Channel]);

adc_uart_polling_sw串口触发

stcAdcCfg.enAdcOpMode = AdcNormalMode;  //单次采样模式
    stcAdcCfg.enAdcClkSel = AdcClkSysTDiv1;
    stcAdcCfg.enAdcSampTimeSel = AdcSampTime4Clk;
    stcAdcCfg.enAdcRefVolSel = RefVolSelExtern1;
    stcAdcCfg.bAdcInBufEn = FALSE;
    stcAdcCfg.u32AdcRegHighThd = 0x0fffu;
    stcAdcCfg.u32AdcRegLowThd = 0u;
    stcAdcCfg.enAdcTrig0Sel = AdcTrigUart1;
    Adc_Init(&stcAdcCfg);

    M0P_ADC->CR1_f.REGCMP = 1;

    stcAdcNormCfg.enAdcNormModeCh = AdcExInputCH4;
    stcAdcNormCfg.bAdcResultAccEn = FALSE;
    Adc_ConfigNormMode(&stcAdcCfg, &stcAdcNormCfg);

    stcUartIrqCb.pfnRxIrqCb = RxIntCallback;
    stcUartIrqCb.pfnTxIrqCb = TxIntCallback;
    stcUartIrqCb.pfnRxErrIrqCb = ErrIntCallback;
    stcConfig.pstcIrqCb = &stcUartIrqCb;
    stcConfig.bTouchNvic = TRUE;

    stcConfig.enRunMode = UartMode1;  //测试项,更改此处来转换4种模式测试

    stcMulti.enMulti_mode = UartNormal;  //测试项,更改此处来转换多主机模式,mode2/3才有多主机模式
    enTb8 = Data;
    Uart_SetMMDOrCk(UARTCH1, enTb8);
    stcConfig.pstcMultiMode = &stcMulti;

    stcBaud.bDbaud = 0u;         //双倍波特率功能
    stcBaud.u32Baud = 9600u;     //更新波特率位置
    stcBaud.u8Mode = UartMode1;  //计算波特率需要模式参数
    pclk = Clk_GetPClkFreq();
    timer = Uart_SetBaudRate(UARTCH1, pclk, &stcBaud);

    stcBtConfig.enMD = BtMode2;
    stcBtConfig.enCT = BtTimer;
    Bt_Init(TIM1, &stcBtConfig);  //调用basetimer1设置函数产生波特率
    Bt_ARRSet(TIM1, timer);
    Bt_Cnt16Set(TIM1, timer);
    Bt_Run(TIM1);

    Uart_Init(UARTCH1, &stcConfig);
    Uart_EnableIrq(UARTCH1, UartRxIrq);
    Uart_ClrStatus(UARTCH1, UartRxFull);
    Uart_EnableFunc(UARTCH1, UartRx);

    while (1) {
        while (FALSE == M0P_ADC->IFR_f.REG_INTF)
            ;
        M0P_ADC->ICLR_f.REG_INTC = 0u;
        Adc_GetResult(&u16AdcResult);
        Adc_ClrAccResult();

        Gpio_SetIO(2, 3, 1);
        delay1ms(200);
        Gpio_SetIO(2, 3, 0);
        u32RxData[0] = '0';
        u32RxData[1] = 'x';
        if ((u16AdcResult >> 12) > 9) {
            u32RxData[2] = (u16AdcResult >> 12) - 10 + 'A';
        } else {
            u32RxData[2] = (u16AdcResult >> 12) + '0';
        }
        if (((u16AdcResult >> 8) & 0xF) > 9) {
            u32RxData[3] = ((u16AdcResult >> 8) & 0xF) - 10 + 'A';
        } else {
            u32RxData[3] = ((u16AdcResult >> 8) & 0xF) + '0';
        }
        if (((u16AdcResult >> 4) & 0xF) > 9) {
            u32RxData[4] = ((u16AdcResult >> 4) & 0xF) - 10 + 'A';
        } else {
            u32RxData[4] = ((u16AdcResult >> 4) & 0xF) + '0';
        }
        if (((u16AdcResult)&0xF) > 9) {
            u32RxData[5] = ((u16AdcResult)&0xF) - 10 + 'A';
        } else {
            u32RxData[5] = ((u16AdcResult)&0xF) + '0';
        }
        u32RxData[6] = '\n';
        for (u8TxCnt = 0; u8TxCnt < 7; u8TxCnt++) {
            Uart_SendData(UARTCH1, u32RxData[u8TxCnt]);
        }
    }

外部触发意思就是当你设置的外部触发中断时,自动开始进行转换,比如例程中设置的    stcAdcCfg.enAdcTrig0Sel = AdcTrigUart1;串口1触发,就是串口1产生中断就会开始adc转换,所以需要同时配置uart1中断。Uart_EnableIrq(UARTCH1, UartRxIrq);,当产生接收中断时开始转换。