MAX32625/MAX32630学习:10位ADC采样(解析及注意事项),中断式和非中断式

给大家分享一下MAX32630的ADC采样程序,包括中断式和非中断式。
首先,我们来比较一下STM32F4与MAX32630在ADC方面的区别:
STM32F4:
(1)12位ADC
(2)支持DMA
(3)每个ADC通道自带数据寄存器
(4)最大转换速率2.4MHz
MAX32630:
(1)10位ADC
(2)不支持DMA
(3)每个ADC通道共用一个数据寄存器
(4)最大转换速率8MHz

下面给出非中断式和中断式的ADC采样程序
[mw_shl_code=c,true]/***** Includes *****/
#include <stdio.h>
#include <stdint.h>
#include "mxc_config.h"
#include "led.h"
#include "adc.h"
#include "nhd12832.h"
#include "board.h"
#include "max14690.h"
#include "tmr_utils.h"

/***** Definitions *****/
const max14690_cfg_t max14690_cfg2 = {
  .ldo2mv = 3300, /**< 3.3v in mV, connected to VDDB */
  .ldo2mode = MAX14690_LDO_MPC1, /**< Enalbe LDO2 when +5v is present on VBUS */
  .ldo3mv = 3300,  /**< 3.3v is L3OUT -- optional */
  .ldo3mode = MAX14690_LDO_ENABLED /**< Enable the LDO. */
};


#define CLOCK 23
/*------------------------------------------------------------
                         usÑóê±oˉêy 
------------------------------------------------------------*/
void delay_us(uint32_t us)
{
        uint32_t n;                    
        while(us--)for(n=0;n<CLOCK;n++);          
}

/*------------------------------------------------------------
                         msÑóê±oˉêy
------------------------------------------------------------*/
void delay_ms(uint32_t ms)
{
        while(ms--)delay_us(1000);         
}

/* Change to #undef USE_INTERRUPTS for polling mode */
#define USE_INTERRUPTS 1
//#undef USE_INTERRUPTS  注释掉为中断式,不注释则为非中断式
/***** Globals *****/
#ifdef USE_INTERRUPTS
volatile unsigned int adc_done = 0;
#endif

/***** Functions *****/

#ifdef USE_INTERRUPTS
void AFE_IRQHandler(void)
{
    ADC_ClearFlags(MXC_F_ADC_INTR_ADC_DONE_IF);
    /* Signal bottom half that data is ready */
    adc_done = 1;
    
    return;
}
#endif
/* ************************************************************************* */
void ADC0_StartConvert(mxc_adc_chsel_t channel, unsigned int adc_scale, unsigned int bypass)
{
  uint32_t ctrl_tmp;

  /* Clear the ADC done flag */
  ADC_ClearFlags(MXC_F_ADC_INTR_ADC_DONE_IF);
        MXC_ADC->intr |= MXC_F_ADC_INTR_ADC_DONE_IE;
  /* Insert channel selection */
  ctrl_tmp = MXC_ADC->ctrl;
  ctrl_tmp &= ~(MXC_F_ADC_CTRL_ADC_CHSEL);
  ctrl_tmp |= ((channel << MXC_F_ADC_CTRL_ADC_CHSEL_POS) & MXC_F_ADC_CTRL_ADC_CHSEL);
  
  /* Clear channel configuration */
  ctrl_tmp &= ~(MXC_F_ADC_CTRL_ADC_REFSCL | MXC_F_ADC_CTRL_ADC_SCALE | MXC_F_ADC_CTRL_BUF_BYPASS);

  /* ADC reference scaling must be set for all channels but two*/
  if ((channel != ADC_CH_VDD18) && (channel != ADC_CH_VDD12)) {
    ctrl_tmp |= MXC_F_ADC_CTRL_ADC_REFSCL;
  }

  /* Finalize user-requested channel configuration */
  if (adc_scale || channel > ADC_CH_3) {
    ctrl_tmp |= MXC_F_ADC_CTRL_ADC_SCALE;
  }
  if (bypass) {
    ctrl_tmp |= MXC_F_ADC_CTRL_BUF_BYPASS;
  }
  
  /* Write this configuration */
  MXC_ADC->ctrl = ctrl_tmp;
  
  /* Start conversion */
  MXC_ADC->ctrl |= MXC_F_ADC_CTRL_CPU_ADC_START;

}
int main(void)
{
    uint16_t adc_val[4];
    unsigned int overflow[4];
    uint8_t fmtstr[40];   
    /* Initialize ADC */
    ADC_Init();
                MAX14690_Init(&max14690_cfg2);
    
#ifdef USE_INTERRUPTS
    NVIC_EnableIRQ(AFE_IRQn);
#endif
    
    while(1) {

        /* Convert channel 0 */
#ifdef USE_INTERRUPTS
        adc_done = 0;
        ADC0_StartConvert(ADC_CH_0, 0, 1);
        while (!adc_done);
#else
        ADC_StartConvert(ADC_CH_0, 0, 1);
#endif
        overflow[0] = (ADC_GetData(&adc_val[0]) == E_OVERFLOW ? 1 : 0);
        /* Delay for 1/4 second before next reading */
        TMR_Delay(MXC_TMR0, MSEC(250));

    }
}
[/mw_shl_code]

用KEIL开发的小伙伴们需要注意的几个问题是:
(1)//#undef USE_INTERRUPTS  注释掉为中断式,不注释则为非中断式
(2)ADC的参考电压为内部参考电压1.2V
MAX32625/MAX32630学习:10位ADC采样(解析及注意事项),中断式和非中断式 
(3)ADC源代码中断式采样会出现死循环,原因在于ADC_ClearFlags(MXC_F_ADC_INTR_ADC_DONE_IF);这条语句把ADC中断使能也清零了,如图所示,adc_done_ie清零,无法进入中断,程序会一直while (!adc_done);死循环。在源代码的void ADC0_StartConvert(这是我自己定义的函数,源代码中的为void ADC_StartConvert)中,在ADC_ClearFlags(MXC_F_ADC_INTR_ADC_DONE_IF);后加一条语句MXC_ADC->intr |= MXC_F_ADC_INTR_ADC_DONE_IE;,重新使能ADC中断,编译后测试成功
MAX32625/MAX32630学习:10位ADC采样(解析及注意事项),中断式和非中断式 
MAX32625/MAX32630学习:10位ADC采样(解析及注意事项),中断式和非中断式 


下次我给大家分享一下如何配置ADC通道的电压测量范围,主要有四种测量范围:(1)0~0.6V;(2)0~1.2V;(3)0~3V;(4)0~6V(AIN0和AIN1最大容忍电压为5V)。