打造一个通用性MCU架构,支持CX32/AT32/NRF51/NRF52等。 OS支持RTX4/RTX5/FreeRtos。 采用VsCode+GCC组合,VsCode+KEIL5,超强开发方式。 QQ群:524408033

LiSun

打造一个通用性MCU架构,支持CX32/AT32/NRF51/NRF52等。 OS支持RTX4/RTX5/FreeRtos。 采用VsCode+GCC组合,VsCode+KEIL5,超强开发方式。 QQ群:524408033

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理
  1. ADC是模数转换器转换器 的供应商的英文简称,是一种能将模拟信号转变为数字信号的电子元件。通常是将信号采样并保持以后,再进行量化和编码,这两个过程是在转化的同时实现的。

分辨率-说明AD对输入信号的分辨能力,及数值部分的精度。一般模拟采样中使用16位还是24位的AD芯片说的就是分辨率.
例如:输入模拟电压的变化范围为0~3.3 V,输出16位二进制数可以分辨的最小模拟电压为3.3V / 216=0.05 mV;

  1. 转化误差-表示AD实际电压与理论电压的偏差,一般用最低有效位来表示,单位LSB,通常以相对误差的形式出现,比如相对误差≤±LSB/2,表明实际输出的数字量和理论量误差小于最低位的一半。

转换精度-这里一般用转化误差和分辨率来表述,具体就是AD最大量化过程中采用了四舍五入的方法及模拟处理部分的精度问题。

转化时间-即从信号输入开始到输出稳定的信号所经过的时间。不同的AD准换的速度不同,根据实际要求来选型。

工作电压和基准电压(内部或者外部基准):工作电压是AD芯片工作的额定电压,关键的是基准电压,又叫参考电压,可以来之芯片内部又或者外部接入,其决定了AD的分辨率,所有基准电压一定要稳。

模块简介

本芯片内部集成了一个 12 位高精度、高转换速率的逐次逼近(SAR)型模数转换器(ADC)模块。具
有以下特性:
⚫ 12 位转换精度
⚫ 1Msps 转换速度
⚫ 8 路转换通道:7 个引脚通道、1 个 VCAP 校准通道
⚫ 参考电压(Refence Voltage)为电源电压
⚫ ADC 的电压输入范围:0-VREF
⚫ 3 种转换模式:单次转换、连续转换、累加转换
⚫ ADC 的转换速率软件可配
⚫ 支持片内及外设中断自动触发 ADC 转换启动,有效降低芯片功耗、提高转换实时性
在这里插入图片描述

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

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

#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 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};

// 定义ADC采集完毕回调函数
typedef void(*bsp_adc0_callback)(void);
static bsp_adc0_callback irq_callback;

/****************结构体定义****************/
#if BS_ADC0_EN
ADC_HandleTypeDef adc0_handle_t =
{
    .Instance                = BS_ADC0_BASE,
    .Init.SamplingTime       = ADC_SAMPLE_8CYCLE,           // 采样周期
    .Init.ClkSel             = ADC_CLOCK_PCLK_DIV32,        // ADC时钟分频
    .Init.SingleContinueMode = ADC_MODE_CONTINUE,           // 连续转换模式
    .Init.NbrOfConversion    = BS_ADC0_SAMPLING_TIMES,      // 连续转换次数
    .Init.AutoAccumulation   = ADC_AUTOACC_DISABLE,         // 禁止ADC转换结果自动累加
    .Init.CircleMode         = ADC_MULTICHANNEL_NONCIRCLE,  // 禁止ADC循环转换模式
    .Init.ExternalTrigConv1  = ADC_SOFTWARE_START,          // 禁用自动触发ADC转换
};
#endif
/* External Variables --------------------------------------------------------*/
/* Public Function Prototypes ------------------------------------------------*/
#if BS_ADC0_EN
/**
 * @brief  ADC0初始化,并使能通道
 * @note   NULL
 * @retval None
 */
void bsp_adc0_init(void)
{
#if CH_NUM
    if (g_adc_init)
    {
        return;
    }
    __HAL_RCC_ADC_CLK_ENABLE();

    // 使能通道
    adc0_handle_t.Init.ContinueChannelSel =
#if BS_ADC0_CH0
                                           ADC_CONTINUE_CHANNEL_0|
#endif
#if BS_ADC0_CH1
                                           ADC_CONTINUE_CHANNEL_1|
#endif
#if BS_ADC0_CH2
                                           ADC_CONTINUE_CHANNEL_2|
#endif
#if BS_ADC0_CH3
                                           ADC_CONTINUE_CHANNEL_3|
#endif
#if BS_ADC0_CH4
                                           ADC_CONTINUE_CHANNEL_4|
#endif
#if BS_ADC0_CH5
                                           ADC_CONTINUE_CHANNEL_5|
#endif
#if BS_ADC0_CH6
                                           ADC_CONTINUE_CHANNEL_6|
#endif
#if BS_ADC0_CH7
                                           ADC_CONTINUE_CHANNEL_7|
#endif
                                           0;
    HAL_ADC_Init(&adc0_handle_t);

    // ADC comparison settings
    ADC_ThresholdConfTypeDef adc0_threshold_conf_t;
    adc0_threshold_conf_t.ITMode          = DISABLE;
    adc0_threshold_conf_t.CompareMode     = ADC_COMP_THRESHOLD_NONE;      // 禁止 ADC比较中断控制
    HAL_ADC_ThresholdConfig(&adc0_handle_t, &adc0_threshold_conf_t);
    HAL_NVIC_SetPriority(BS_ADC0_IRQn, 2);
    HAL_NVIC_EnableIRQ(BS_ADC0_IRQn);       // 使能ADC中断
    g_adc_init = true;
#endif
}

/**
 * @brief  ADC0功能关闭,并移除
 * @note   NULL
 * @retval None
 */
void bsp_adc0_deinit(void)
{
#if CH_NUM
    if (!g_adc_init)
    {
        return;
    }
    HAL_NVIC_DisableIRQ(BS_ADC0_IRQn);      // 关闭ADC中断
    HAL_ADC_DeInit(&adc0_handle_t);
    g_adc_init = false;
#endif
}

/**
 * @brief  ADC0 启动采样功能
 * @note   NULL
 * @retval None
 */
void bsp_adc0_start(void)
{
#if CH_NUM
    if (!g_adc_init)
    {
        return;
    }
    HAL_ADC_Start_IT(&adc0_handle_t);    // 启动ADC中断转换
#endif
}

#else
void bsp_adc0_init(void)
{
}

void bsp_adc0_deinit(void)
{
}

void bsp_adc0_start(void)
{
}
#endif

/**
  * @brief  Initializes the ADC MSP.
  * @param  hadc: ADC handle
  * @retval None
  */
void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc)
{
#if BS_ADC0_CH0
    BS_ADC0_CH0_GPIO_CLK_ENABLE();
    bsp_gpio_init_adc(BS_ADC0_CH0_GPIO_PORT, BS_ADC0_CH0_PIN);
#endif
#if BS_ADC0_CH1
    BS_ADC0_CH1_GPIO_CLK_ENABLE();
    bsp_gpio_init_adc(BS_ADC0_CH1_GPIO_PORT, BS_ADC0_CH1_PIN);
#endif
#if BS_ADC0_CH2
    BS_ADC0_CH2_GPIO_CLK_ENABLE();
    bsp_gpio_init_adc(BS_ADC0_CH2_GPIO_PORT, BS_ADC0_CH2_PIN);
#endif
#if BS_ADC0_CH3
    BS_ADC0_CH3_GPIO_CLK_ENABLE();
    bsp_gpio_init_adc(BS_ADC0_CH3_GPIO_PORT, BS_ADC0_CH3_PIN);
#endif
#if BS_ADC0_CH4
    BS_ADC0_CH4_GPIO_CLK_ENABLE();
    bsp_gpio_init_adc(BS_ADC0_CH4_GPIO_PORT, BS_ADC0_CH4_PIN);
#endif
#if BS_ADC0_CH5
    BS_ADC0_CH5_GPIO_CLK_ENABLE();
    bsp_gpio_init_adc(BS_ADC0_CH5_GPIO_PORT, BS_ADC0_CH5_PIN);
#endif
#if BS_ADC0_CH6
    BS_ADC0_CH6_GPIO_CLK_ENABLE();
    bsp_gpio_init_adc(BS_ADC0_CH6_GPIO_PORT, BS_ADC0_CH6_PIN);
#endif
// #if BS_ADC0_CH7
//     BS_ADC0_CH7_GPIO_CLK_ENABLE()
//     bsp_gpio_init_adc(BS_ADC0_CH7_GPIO_PORT, BS_ADC0_CH7_PIN);
// #endif
}

#if BS_ADC0_CH0
void HAL_ADC_MultiChannel0_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{
    if (hadc->Instance == BS_ADC0_BASE)
    {
        bsp_adc0_val[0] = HAL_ADC_GetValue(hadc, ADC_CONTINUE_CHANNEL_0);
    }
}
#endif

#if BS_ADC0_CH1
void HAL_ADC_MultiChannel1_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{
    if (hadc->Instance == BS_ADC0_BASE)
    {
        bsp_adc0_val[1] = HAL_ADC_GetValue(hadc, ADC_CONTINUE_CHANNEL_1);
    }
}
#endif

#if BS_ADC0_CH2
void HAL_ADC_MultiChannel2_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{
    if (hadc->Instance == BS_ADC0_BASE)
    {
        bsp_adc0_val[2] = HAL_ADC_GetValue(hadc, ADC_CONTINUE_CHANNEL_2);
    }
}
#endif

#if BS_ADC0_CH3
void HAL_ADC_MultiChannel3_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{
    if (hadc->Instance == BS_ADC0_BASE)
    {
        bsp_adc0_val[3] = HAL_ADC_GetValue(hadc, ADC_CONTINUE_CHANNEL_3);
    }
}
#endif

#if BS_ADC0_CH4
void HAL_ADC_MultiChannel4_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{
    if (hadc->Instance == BS_ADC0_BASE)
    {
        bsp_adc0_val[4] = HAL_ADC_GetValue(hadc, ADC_CONTINUE_CHANNEL_4);
    }
}
#endif

#if BS_ADC0_CH5
void HAL_ADC_MultiChannel5_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{
    if (hadc->Instance == BS_ADC0_BASE)
    {
        bsp_adc0_val[5] = HAL_ADC_GetValue(hadc, ADC_CONTINUE_CHANNEL_5);
    }
}
#endif

#if BS_ADC0_CH6
void HAL_ADC_MultiChannel6_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{
    if (hadc->Instance == BS_ADC0_BASE)
    {
        bsp_adc0_val[6] = HAL_ADC_GetValue(hadc, ADC_CONTINUE_CHANNEL_6);
    }
}
#endif

#if BS_ADC0_CH7
void HAL_ADC_MultiChannel7_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{
    if (hadc->Instance == BS_ADC0_BASE)
    {
        bsp_adc0_val[7] = HAL_ADC_GetValue(hadc, ADC_CONTINUE_CHANNEL_7);
    }
}
#endif

/**
 * @brief  [重定义] ADC采样完毕回调函数
 * @note   NULL
 * @param  hadc: ADC handle
 * @retval None
 */
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{
    if (hadc->Instance == BS_ADC0_BASE)
    {
        if (irq_callback)
        {
            irq_callback();
        }
    }
}

/**
 * @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采样完毕回调函数
 * @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

posted on 2022-08-13 11:00  xuejianqiang  阅读(141)  评论(0编辑  收藏  举报
打造一个通用性MCU架构,支持CX32/AT32/NRF51/NRF52等。 OS支持RTX4/RTX5/FreeRtos。 采用VsCode+GCC组合,VsCode+KEIL5,超强开发方式。 QQ群:524408033