- ADC是模數轉換器轉換器 的供應商的英文簡稱,是一種能将模拟信号轉變為數字信号的電子元件。通常是将信号采樣并保持以後,再進行量化和編碼,這兩個過程是在轉化的同時實作的。
分辨率-說明AD對輸入信号的分辨能力,及數值部分的精度。一般模拟采樣中使用16位還是24位的AD晶片說的就是分辨率.
例如:輸入模拟電壓的變化範圍為0~3.3 V,輸出16位二進制數可以分辨的最小模拟電壓為3.3V / 216=0.05 mV;
- 轉化誤差-表示AD實際電壓與理論電壓的偏差,一般用最低有效位來表示,機關LSB,通常以相對誤差的形式出現,比如相對誤差≤±LSB/2,表明實際輸出的數字量和理論量誤差小于最低位的一半。
轉換精度-這裡一般用轉化誤差和分辨率來表述,具體就是AD最大量化過程中采用了四舍五入的方法及模拟處理部分的精度問題。
轉化時間-即從信号輸入開始到輸出穩定的信号所經過的時間。不同的AD準換的速度不同,根據實際要求來選型。
工作電壓和基準電壓(内部或者外部基準):工作電壓是AD晶片工作的額定電壓,關鍵的是基準電壓,又叫參考電壓,可以來之晶片内部又或者外部接入,其決定了AD的分辨率,所有基準電壓一定要穩。
子產品簡介
本晶片内部內建了一個 12 位高精度、高轉換速率的逐次逼近(SAR)型模數轉換器(ADC)子產品。具
有以下特性:
⚫ 12 位轉換精度
⚫ 1Msps 轉換速度
⚫ 8 路轉換通道:7 個引腳通道、1 個 VCAP 校準通道
⚫ 參考電壓(Refence Voltage)為電源電壓
⚫ ADC 的電壓輸入範圍:0-VREF
⚫ 3 種轉換模式:單次轉換、連續轉換、累加轉換
⚫ 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