Analog to Digital Converter (ADC)

The 10 bit incremental Analog to Digital Converter (ADC) enables sampling of up to 8 external signals through a front-end multiplexer. The ADC has configurable input, reference prescaling, and sample resolution (8, 9, and 10 bit).

  • Note: The ADC module uses the same analog inputs as the LPCOMP module (AIN0 - AIN7 and AREF0 - AREF1). Only one of the modules can be enabled at the same time.

10位增量模数转换器(ADC)允许通过前端多路复用器采样多达8个外部信号。 ADC具有可配置的输入、参考预分级和采样分辨率(8、9和10位)。

  • 注意:ADC模块使用与LPCOMP模块(AIN0 - AIN7和AREF0 - AREF1)相同的模拟输入。 只能同时启用其中一个模块。

下面代码将介绍ADC功能如何使用:

/********************************************************************************
* @file bsp_adc.c
* @author jianqiang.xue
* @version V1.0.0
* @date 2021-07-06
* @brief NULL
********************************************************************************/

/* Includes ------------------------------------------------------------------*/
#include "RTE_Components.h"
#include CMSIS_device_header

#include "nrf_adc.h"
#include "nrf_drv_adc.h"
#include "sdk_errors.h"

#include "bsp_gpio.h"
#include "bsp_exti.h"
#include "bsp_adc.h"

/* Private Includes ----------------------------------------------------------*/
#include "business_gpio.h"
#include "business_function.h"

/* Private Define ------------------------------------------------------------*/
#define ADC0_CH_NUM 8

#define ADC0_CH0 0
#define ADC0_CH1 1
#define ADC0_CH2 2
#define ADC0_CH3 3
#define ADC0_CH4 4
#define ADC0_CH5 5
#define ADC0_CH6 6
#define ADC0_CH7 7

#define CH_NUM (BS_ADC0_CH0 + BS_ADC0_CH1 + BS_ADC0_CH2 + BS_ADC0_CH3 + BS_ADC0_CH4 + BS_ADC0_CH5 + BS_ADC0_CH6 + BS_ADC0_CH7)
/* Private Variables ---------------------------------------------------------*/
// ADC初始化状态(0--deinit 1--init)
static bool g_adc_init = false;
// ADC采集数据存储buff
uint16_t bsp_adc0_val[ADC0_CH_NUM] = {0};
uint16_t bsp_adc0_temp_val[CH_NUM] = {0};
// 定义ADC采集完毕回调函数
typedef void(*bsp_adc0_callback)(void);
static bsp_adc0_callback irq_callback;

/****************结构体定义****************/
#if CH_NUM > 0
nrf_drv_adc_config_t nrf_adc_config = NRF_DRV_ADC_DEFAULT_CONFIG;
#endif
/**< Channel instance. Default configuration used. */
#if BS_ADC0_CH0
static nrf_drv_adc_channel_t m_channel0_config = NRF_DRV_ADC_DEFAULT_CHANNEL(NRF_ADC_CONFIG_INPUT_0);
#endif
#if BS_ADC0_CH1
static nrf_drv_adc_channel_t m_channel1_config = NRF_DRV_ADC_DEFAULT_CHANNEL(NRF_ADC_CONFIG_INPUT_1);
#endif
#if BS_ADC0_CH2
static nrf_drv_adc_channel_t m_channel2_config = NRF_DRV_ADC_DEFAULT_CHANNEL(NRF_ADC_CONFIG_INPUT_2);
#endif
#if BS_ADC0_CH3
static nrf_drv_adc_channel_t m_channel3_config = NRF_DRV_ADC_DEFAULT_CHANNEL(NRF_ADC_CONFIG_INPUT_3);
#endif
#if BS_ADC0_CH4
static nrf_drv_adc_channel_t m_channel4_config = NRF_DRV_ADC_DEFAULT_CHANNEL(NRF_ADC_CONFIG_INPUT_4);
#endif
#if BS_ADC0_CH5
static nrf_drv_adc_channel_t m_channel5_config = NRF_DRV_ADC_DEFAULT_CHANNEL(NRF_ADC_CONFIG_INPUT_5);
#endif
#if BS_ADC0_CH6
static nrf_drv_adc_channel_t m_channel6_config = NRF_DRV_ADC_DEFAULT_CHANNEL(NRF_ADC_CONFIG_INPUT_6);
#endif
#if BS_ADC0_CH7
static nrf_drv_adc_channel_t m_channel7_config = NRF_DRV_ADC_DEFAULT_CHANNEL(NRF_ADC_CONFIG_INPUT_7);
#endif


/* External Variables --------------------------------------------------------*/
/* Private Function Prototypes -----------------------------------------------*/
#if BS_ADC0_EN
/**
* @brief 将ADC采集的值重新排序到另一个数组
* @note NULL
* @retval None
*/
static void bsp_adc0_val_copy(void)
{
uint8_t num = 0;
bool flag = false;

for (uint8_t i = 0; i < ADC0_CH_NUM; i++)
{
if (i == ADC0_CH0 && BS_ADC0_CH0)
{
flag = true;
}
else if(i == ADC0_CH1 && BS_ADC0_CH1)
{
flag = true;
}
else if(i == ADC0_CH2 && BS_ADC0_CH2)
{
flag = true;
}
else if(i == ADC0_CH3 && BS_ADC0_CH3)
{
flag = true;
}
else if(i == ADC0_CH4 && BS_ADC0_CH4)
{
flag = true;
}
else if(i == ADC0_CH5 && BS_ADC0_CH5)
{
flag = true;
}
else if(i == ADC0_CH6 && BS_ADC0_CH6)
{
flag = true;
}
else if(i == ADC0_CH7 && BS_ADC0_CH7)
{
flag = true;
}
if (flag)
{
flag = false;
bsp_adc0_val[i] = bsp_adc0_temp_val[num];
num++;
if (num == CH_NUM)
{
break;
}
}
}
}

/**
* @brief ADC interrupt handler.
*/
static void adc_event_handler(nrf_drv_adc_evt_t const * p_event)
{
if (p_event->type == NRF_DRV_ADC_EVT_DONE)
{
bsp_adc0_val_copy();
nrf_drv_adc_buffer_convert(p_event->data.done.p_buffer, CH_NUM);
if (irq_callback)
{
irq_callback();
}
}
}

/* Public Function Prototypes ------------------------------------------------*/
/**
* @brief ADC0初始化,并使能通道
* @note NULL
* @retval None
*/
void bsp_adc0_init(void)
{
#if CH_NUM > 0
if (g_adc_init)
{
return;
}
APP_ERROR_CHECK(nrf_drv_adc_init(&nrf_adc_config, adc_event_handler));
#if BS_ADC0_CH0
nrf_drv_adc_channel_enable(&m_channel0_config);
#endif
#if BS_ADC0_CH1
nrf_drv_adc_channel_enable(&m_channel1_config);
#endif
#if BS_ADC0_CH2
nrf_drv_adc_channel_enable(&m_channel2_config);
#endif
#if BS_ADC0_CH3
nrf_drv_adc_channel_enable(&m_channel3_config);
#endif
#if BS_ADC0_CH4
nrf_drv_adc_channel_enable(&m_channel4_config);
#endif
#if BS_ADC0_CH5
nrf_drv_adc_channel_enable(&m_channel5_config);
#endif
#if BS_ADC0_CH6
nrf_drv_adc_channel_enable(&m_channel6_config);
#endif
#if BS_ADC0_CH7
nrf_drv_adc_channel_enable(&m_channel7_config);
#endif
nrf_drv_adc_buffer_convert((nrf_adc_value_t *)bsp_adc0_temp_val, CH_NUM);
g_adc_init = true;
#endif
}

/**
* @brief ADC0功能关闭,并移除
* @note NULL
* @retval None
*/
void bsp_adc0_deinit(void)
{
#if CH_NUM > 0
if (!g_adc_init)
{
return;
}
#if BS_ADC0_CH0
nrf_drv_adc_channel_disable(&m_channel0_config);
#endif
#if BS_ADC0_CH1
nrf_drv_adc_channel_disable(&m_channel1_config);
#endif
#if BS_ADC0_CH2
nrf_drv_adc_channel_disable(&m_channel2_config);
#endif
#if BS_ADC0_CH3
nrf_drv_adc_channel_disable(&m_channel3_config);
#endif
#if BS_ADC0_CH4
nrf_drv_adc_channel_disable(&m_channel4_config);
#endif
#if BS_ADC0_CH5
nrf_drv_adc_channel_disable(&m_channel5_config);
#endif
#if BS_ADC0_CH6
nrf_drv_adc_channel_disable(&m_channel6_config);
#endif
#if BS_ADC0_CH7
nrf_drv_adc_channel_disable(&m_channel7_config);
#endif
nrf_drv_adc_uninit();
g_adc_init = false;
#endif
}

/**
* @brief ADC0 启动采样功能
* @note NULL
* @retval None
*/
void bsp_adc0_start(void)
{
#if CH_NUM
if (!g_adc_init)
{
return;
}
if (!nrf_adc_is_busy())
{
nrf_drv_adc_sample();
}
#endif
}

#else
void bsp_adc0_init(void)
{
}

void bsp_adc0_deinit(void)
{
}

void bsp_adc0_start(void)
{
}
#endif

/**
* @brief 得到ADC0采样值
* @note NULL
* @param ch_num: 通道值
* @retval 通道对应的ADC值
*/
uint16_t bsp_adc0_get_ch_val(uint8_t ch_num)
{
if (ch_num >= ADC0_CH_NUM)
{
return 0xFFFF;
}
return bsp_adc0_val[ch_num];
}

/**
* @brief 注册ADC0采样完毕回调函数(一般在本函数重新启动ADC采集)
* @note NULL
* @param *event: 绑定回调事件
* @retval 0--失败 1--成功
*/
bool bsp_adc0_irq_callback(void *event)
{
if (irq_callback != NULL)
{
return false;
}
else
{
irq_callback = (bsp_adc0_callback)event;
}
return true;
}
/********************************************************************************
* @file bsp_adc.h
* @author jianqiang.xue
* @version V1.0.0
* @date 2021-04-10
* @brief ADC操作
********************************************************************************/

#ifndef __BSP_ADC_H
#define __BSP_ADC_H

/* Includes ------------------------------------------------------------------*/
#include <stdint.h>
#include <stdbool.h>

/* Public Function Prototypes -----------------------------------------------*/

void bsp_adc0_init(void);
void bsp_adc0_deinit(void);

void bsp_adc0_start(void);

uint16_t bsp_adc0_get_ch_val(uint8_t ch_num);

bool bsp_adc0_irq_callback(void *event);

#endif