[MCU framework] [BSP layer] [cx32l003][bsp_adc] ADC configuration and use

  1. ADC is the English abbreviation of the supplier of analog-to-digital converter. It is an electronic component that can convert analog signals into digital signals. Usually, after sampling and holding the signal, quantization and coding are carried out. These two processes are realized at the same time of transformation.

Resolution - describes the resolution of the ad to the input signal and the accuracy of the numerical part. Generally, 16 bit or 24 bit AD chip is used in analog sampling, which means resolution
For example, the variation range of the input analog voltage is 0 ~ 3.3 V, and the minimum analog voltage that can be distinguished by the output 16 bit binary number is 3.3V / 216 = 0.05 mV;

  1. Conversion error - represents the deviation between the actual voltage and the theoretical voltage of AD, which is generally expressed in the least significant bit. The unit LSB usually appears in the form of relative error, such as relative error ≤± LSB/2, indicating that the error between the actual output digital quantity and the theoretical quantity is less than half of the lowest bit.

Conversion accuracy - it is generally expressed by conversion error and resolution. Specifically, the rounding method is adopted in the process of AD maximum quantization and the accuracy of simulation processing.

Conversion time - that is, the time from the beginning of signal input to the output of a stable signal. Different AD standards have different replacement speeds, so they are selected according to the actual requirements.

Working voltage and reference voltage (internal or external reference): the working voltage is the rated voltage of ad chip. The key is the reference voltage, also known as reference voltage. It can be accessed internally or externally from the chip, which determines the resolution of AD. all reference voltages must be stable.

/********************************************************************************
* @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 initialization status (0--deinit 1--init)
static bool g_adc_init = false;
// ADC acquisition data storage buff
uint16_t bsp_adc0_val[ADC0_CH_NUM] = {0};

// Define ADC collection completion callback function
typedef void(*bsp_adc0_callback)(void);
static bsp_adc0_callback irq_callback;

/****************Structure definition****************/
#if BS_ADC0_EN
ADC_HandleTypeDef adc0_handle_t =
{
    .Instance                = BS_ADC0_BASE,
    .Init.SamplingTime       = ADC_SAMPLE_8CYCLE,           // sampling period 
    .Init.ClkSel             = ADC_CLOCK_PCLK_DIV32,        // ADC clock division
    .Init.SingleContinueMode = ADC_MODE_CONTINUE,           // Continuous conversion mode
    .Init.NbrOfConversion    = BS_ADC0_SAMPLING_TIMES,      // Continuous conversion times
    .Init.AutoAccumulation   = ADC_AUTOACC_DISABLE,         // Automatic accumulation of ADC conversion results is prohibited
    .Init.CircleMode         = ADC_MULTICHANNEL_NONCIRCLE,  // Disable ADC cyclic conversion mode
    .Init.ExternalTrigConv1  = ADC_SOFTWARE_START,          // Disable auto trigger ADC conversion
};
#endif
/* External Variables --------------------------------------------------------*/
/* Public Function Prototypes ------------------------------------------------*/
#if BS_ADC0_EN
/**
 * @brief  ADC0 Initialize and enable the channel
 * @note   NULL
 * @retval None
 */
void bsp_adc0_init(void)
{
#if CH_NUM
    if (g_adc_init)
    {
        return;
    }
    __HAL_RCC_ADC_CLK_ENABLE();

    // Enable channel
    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;      // Disable ADC compare interrupt control
    HAL_ADC_ThresholdConfig(&adc0_handle_t, &adc0_threshold_conf_t);
    HAL_NVIC_SetPriority(BS_ADC0_IRQn, 2);
    HAL_NVIC_EnableIRQ(BS_ADC0_IRQn);       // Enable ADC interrupt
    g_adc_init = true;
#endif
}

/**
 * @brief  ADC0 The function is turned off and removed
 * @note   NULL
 * @retval None
 */
void bsp_adc0_deinit(void)
{
#if CH_NUM
    if (!g_adc_init)
    {
        return;
    }
    HAL_NVIC_DisableIRQ(BS_ADC0_IRQn);      // Turn off ADC interrupt
    HAL_ADC_DeInit(&adc0_handle_t);
    g_adc_init = false;
#endif
}

/**
 * @brief  ADC0 Start sampling function
 * @note   NULL
 * @retval None
 */
void bsp_adc0_start(void)
{
#if CH_NUM
    if (!g_adc_init)
    {
        return;
    }
    HAL_ADC_Start_IT(&adc0_handle_t);    // Start ADC interrupt conversion
#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  [Redefine] ADC sampling completion callback function
 * @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  Get ADC0 sampling value
 * @note   NULL
 * @param  ch_num: Channel value
 * @retval ADC value corresponding to the channel
 */
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  Register ADC0 sampling completion callback function
 * @note   NULL
 * @param  *event: Bind callback event
 * @retval 0--Failure 1 -- success
 */
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 operation
********************************************************************************/

#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

Tags: Single-Chip Microcomputer stm32

Posted on Fri, 15 Oct 2021 16:32:24 -0400 by wanda46