ADC规则通道转换
概述
- 支持 1 个 ADC,支持单端输入和差分输入,最多可测量 16 个外部和 3 个内部源。
- 支持 12 位、10 位、8 位、6 位分辨率。
- ADC 时钟源分为工作时钟源、采样时钟源和计时时钟源
- 仅可配置 AHB_CLK 作为工作时钟源。
- 可配置 PLL 作为采样时钟源,最高可到 64MHz,支持分频 1,2,4,6,8,10,12,16,32,64,128,256。
- 可配置 AHB_CLK 作为采样时钟源,最高可到 64MHz,支持分频 1,2,4,6,8,10,12,16,32。
- 计时时钟用于内部计时功能,频率必须配置成 1MHz。
- 支持触发采样,包括 EXTI/TIMER。
- 各通道的采样时间间隔可编程
- ADC 的工作电压在 1.8V 到 3.6V 之间。
- ADC 支持转换的电压在 VREF-和 VREF+之间。
- 内部通道支持 TempSensor、VREFINT(内部 1.2V BG)、VREFBUFF(2.048V)
- 支持内部参考电压(2.048V)
- 注入通道最多4个
- 规则通道最多16个
时钟
内部通道
- 温度传感器和通道 ADC_IN17 相连接。
- VREFINT 和通道 ADC_IN0 相连接。
- VREFBUFF和 ADC_IN18 相连接。
- VOP1(运放)OUT输出和通道 ADC_IN3 相连接。
- VOP2(运放)OUT输出和通道 ADC_IN7 相连接。
单次采集就是每次采集一个通道
连续采集就是采集这个规则组或注入组
扫描模式就是一轮接着一轮的扫描,扫描模式就是讲一个规则组转换完成后,又进行下一轮转换,注入组不支持扫描模式
模拟看门狗
-
模拟看门狗的高阈值
-
模拟看门狗的低阈值
-
当 ADC 转换的值高于模拟看门狗的高阈值或低于模拟看门狗的低阈值时,如果 ADC_CTRL1.AWDGIEN 已配置,则模拟看门狗标志 (ADC_STS.AWDG) 将 被 置 为 1 , 此 时 会 产 生 中 断
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7ozJtAUS-1689953222576)(./picture/image-20230718190636870.png)]
间断模式
规则组:每次触发后转换 n 个通道
注入组:每次触发后转换 1个通道
实例
使用规则通道+dma数据传输+连续转换+软件触发
bsp_adc_regular.h
#ifndef _BSP_ADC_H_
#define _BSP_ADC_H_
#include <stdint.h>
#include "n32l40x.h"
typedef struct{
GPIO_Module* gpiox;
uint16_t pin;
uint8_t adc_ch;
}adc_ch_t;
typedef enum
{
AIR_PRESS,//气压值
BATTERY,//电池电压
ADC_CH_NUM
}ADC_ID;
/**
* adc 相关的gpio初始化
*/
void bsp_adc_init(void);
/*
获取adc的采样值
返回:0xff,参数错误
*/
uint16_t bsp_adc_get_value(ADC_ID id);
#endif
bsp_adc_regular.c
#include"adc/bsp_adc.h"
adc_ch_t adc_chanles[ADC_CH_NUM]= {
{GPIOA,GPIO_PIN_3,ADC_CH_4_PA3},
{GPIOA,GPIO_PIN_4,ADC_CH_5_PA4},
};
static uint16_t ADCConvertedValue[ADC_CH_NUM];
/*
获取adc的采样值
返回:0xff,参数错误
*/
uint16_t bsp_adc_get_value(ADC_ID id)
{
if(id<ADC_CH_NUM)
{
return ADCConvertedValue[id];
}
else
{
return 0xffff;
}
}
//配置dma通道
static void bsp_adc_dma_config(void)
{
DMA_InitType DMA_InitStructure;
RCC_EnableAHBPeriphClk(RCC_AHB_PERIPH_DMA, ENABLE);
DMA_DeInit(DMA_CH1);
DMA_InitStructure.PeriphAddr = (uint32_t)&ADC->DAT;
DMA_InitStructure.MemAddr = (uint32_t)ADCConvertedValue;
DMA_InitStructure.Direction = DMA_DIR_PERIPH_SRC;
DMA_InitStructure.BufSize = ADC_CH_NUM;//adc传输数量
DMA_InitStructure.PeriphInc = DMA_PERIPH_INC_DISABLE;
DMA_InitStructure.DMA_MemoryInc = DMA_MEM_INC_ENABLE;
DMA_InitStructure.PeriphDataSize = DMA_PERIPH_DATA_SIZE_HALFWORD;
DMA_InitStructure.MemDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.CircularMode = DMA_MODE_CIRCULAR;
DMA_InitStructure.Priority = DMA_PRIORITY_HIGH;
DMA_InitStructure.Mem2Mem = DMA_M2M_DISABLE;
DMA_Init(DMA_CH1, &DMA_InitStructure);
DMA_RequestRemap(DMA_REMAP_ADC1, DMA, DMA_CH1, ENABLE);
/* Enable DMA channel1 */
DMA_EnableChannel(DMA_CH1, ENABLE);
/* Enable ADC DMA */
ADC_EnableDMA(ADC, ENABLE);
}
/**
* @brief adc 相关的gpio初始化
*/
static void bsp_adc_gpio_config(adc_ch_t *padc)
{
if(padc->gpiox==GPIOA)
{
RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOA, ENABLE);
}
else if(padc->gpiox==GPIOB)
{
RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOB, ENABLE);
}
if(padc->gpiox==GPIOC)
{
RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOC, ENABLE);
}
if(padc->gpiox==GPIOD)
{
RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOD, ENABLE);
}
GPIO_InitType GPIO_InitStructure;
GPIO_InitStruct(&GPIO_InitStructure);
/* Configure PC.02 (in12)as analog input -------------------------*/
GPIO_InitStructure.Pin = padc->pin;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Analog;
GPIO_InitPeripheral(padc->gpiox, &GPIO_InitStructure);
}
/**
* @brief adc初始化
*/
void bsp_adc_init()
{
ADC_InitType ADC_InitStructure;
/* adc 时钟初始化*/
RCC_EnableAHBPeriphClk(RCC_AHB_PERIPH_ADC, ENABLE);
ADC_ConfigClk(ADC_CTRL3_CKMOD_AHB, RCC_ADCHCLK_DIV16);
RCC_ConfigAdc1mClk(RCC_ADC1MCLK_SRC_HSE, RCC_ADC1MCLK_DIV8); //selsect HSE as RCC ADC1M CLK Source
/* GPIO 配置 */
for(int i=0; i<ADC_CH_NUM; i++)
{
bsp_adc_gpio_config(adc_chanles+i);
}
ADC_DeInit(ADC);
/* adc基本参数配置*/
ADC_InitStructure.MultiChEn = ENABLE;
ADC_InitStructure.ContinueConvEn = ENABLE; //持续转换
ADC_InitStructure.ExtTrigSelect = ADC_EXT_TRIGCONV_NONE; //ADC触发选择
ADC_InitStructure.DatAlign = ADC_DAT_ALIGN_R;
ADC_InitStructure.ChsNumber = ADC_CH_NUM;//adc规则通道数量
ADC_Init(ADC, &ADC_InitStructure);
//DMA相关的配置
bsp_adc_dma_config();
/* ADC1 规则通道配置 */
for(int i=0; i<ADC_CH_NUM; i++)
{
ADC_ConfigRegularChannel(ADC, adc_chanles[i].adc_ch, i+1, ADC_SAMP_TIME_71CYCLES5);
}
/* 使能 ADC */
ADC_Enable(ADC, ENABLE);
/* Check ADC Ready */
while(ADC_GetFlagStatusNew(ADC,ADC_FLAG_RDY) == RESET)
;
/* 开始标定ADC */
ADC_StartCalibration(ADC);
/* 等待ADC标定结束 */
while (ADC_GetCalibrationStatus(ADC))
;
/* 软件启动ADC转换*/
ADC_EnableSoftwareStartConv(ADC, ENABLE);
}