简述
N32G452的12位ADC使用的是逐次逼近的高速模数转换器。他有多个通道,每个通道的A/D转换有四种执行模式:
- 单次
- 连续
- 扫描
- 间断
ADC转换值储存(左对齐/右对齐)在16位数据寄存器中。可以通过模拟看门狗检测输入电压是否在用户定义的高/低阈值内,并且ADC的输入时钟的最大频率为72MHZ。
ADC框图
ADC引脚
ADC时钟
ADC转换的四种模式:
- 单次转换模式:在该模式下,外部触发或者ADC_CTRL2.ON=1(仅适用于规则通道)启动ADC转化,ADC只进行一次转换,转换完成后ADC停止。
void ADC_Initl()
{
/*打开ADC1引脚时钟*/
RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOC, ENABLE);
/*打开ADC1总线时钟*/
RCC_EnableAHBPeriphClk(RCC_AHB_PERIPH_ADC1 ,ENABLE);
/*将ADCHCLK配置为DIV16*/
ADC_ConfigClk(ADC_CTRL3_CKMOD_AHB,RCC_ADCHCLK_DIV16);
/*设置ADC1M时钟来源为HSE*/
RCC_ConfigAdc1mClk(RCC_ADC1MCLK_SRC_HSE, RCC_ADC1MCLK_DIV8);
/*初始化ADC引脚*/
GPIO_InitType GPIO_InitStructure;
/* PC0 PC1 -------------------------*/
GPIO_InitStructure.Pin = GPIO_PIN_0 | GPIO_PIN_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_InitPeripheral(GPIOC, &GPIO_InitStructure);
/* ADC初始化 -----------------------*/
ADC_InitType ADC_InitStructure;
ADC_InitStructure.WorkMode = ADC_WORKMODE_INDEPENDENT;//独立输入模式
ADC_InitStructure.MultiChEn = DISABLE;//多通道禁用
ADC_InitStructure.ContinueConvEn = DISABLE;//连续转化禁用
ADC_InitStructure.ExtTrigSelect = ADC_EXT_TRIGCONV_NONE;//外部触发选择
ADC_InitStructure.DatAlign = ADC_DAT_ALIGN_R;//数据右对齐
ADC_InitStructure.ChsNumber = 1;//通道数
ADC_Init(ADCx, &ADC_InitStructure);
/* 使能 ADC */
ADC_Enable(ADCx, ENABLE);
while(ADC_GetFlagStatusNew(ADCx,ADC_FLAG_RDY) == RESET);
/* ADC校准 */
ADC_StartCalibration(ADCx);
while (ADC_GetCalibrationStatus(ADCx));
}
uint16_t ADC_GetData(ADC_Module* ADCx, uint8_t ADC_Channel)
{
uint16_t dat;
ADC_ConfigRegularChannel(ADCx, ADC_Channel, 1,ADC_SAMP_TIME_239CYCLES5);
/* Start ADC Software Conversion */
ADC_EnableSoftwareStartConv(ADCx, ENABLE);
while(ADC_GetFlagStatus(ADCx, ADC_FLAG_ENDC)==0){
}
ADC_ClearFlag(ADCx, ADC_FLAG_ENDC);
ADC_ClearFlag(ADCx, ADC_FLAG_STR);
dat=ADC_GetDat(ADCx);
return dat;
}
- 连续转换模式:ADC 可以通过配置 ADC_CTRL2.CTU 为 1 进入连续转换模式。在该模式下,外部触发或设置ADC_CTRL2.ON 为 1 可以启动 ADC 开始转换,ADC 会持续转换选择的通道。连续模式仅对规则通道有
效,对注入通道无效。
UINT16 adc_value;
void ADC_Initl()
{
RCC_EnableAHBPeriphClk(RCC_AHB_PERIPH_DMA1, ENABLE);//使能DMA时钟
/* DMA1 通道配置 ----------------------------------------------*/
DMA_InitType DMA_InitStructure;
DMA_DeInit(DMA1_CH1);
DMA_InitStructure.PeriphAddr = (uint32_t)&ADC1->DAT;//外设地址
DMA_InitStructure.MemAddr = (uint32_t)&adc_value;//内存地址
DMA_InitStructure.Direction = DMA_DIR_PERIPH_SRC;//外设到内存
DMA_InitStructure.BufSize = 1;//缓存区大小
DMA_InitStructure.PeriphInc = DMA_PERIPH_INC_DISABLE;
DMA_InitStructure.DMA_MemoryInc = DMA_MEM_INC_DISABLE;
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(DMA1_CH1, &DMA_InitStructure);
/* Enable DMA1 channel1 */
DMA_EnableChannel(DMA1_CH1, ENABLE);
/*打开ADC1总线时钟*/
RCC_EnableAHBPeriphClk(RCC_AHB_PERIPH_ADC1 ,ENABLE);
/*将ADCHCLK配置为DIV16*/
ADC_ConfigClk(ADC_CTRL3_CKMOD_AHB,RCC_ADCHCLK_DIV16);
/*设置ADC1M时钟来源为HSE*/
RCC_ConfigAdc1mClk(RCC_ADC1MCLK_SRC_HSE, RCC_ADC1MCLK_DIV8);
/* ADC初始化 -----------------------*/
ADC_InitType ADC_InitStructure;
ADC_InitStructure.WorkMode = ADC_WORKMODE_INDEPENDENT;//独立输入模式
ADC_InitStructure.MultiChEn = DISABLE;//多通道禁用
ADC_InitStructure.ContinueConvEn = ENABLE;//连续转化禁用
ADC_InitStructure.ExtTrigSelect = ADC_EXT_TRIGCONV_NONE;//外部触发选择
ADC_InitStructure.DatAlign = ADC_DAT_ALIGN_R;//数据右对齐
ADC_InitStructure.ChsNumber = 1;//通道数
ADC_Init(ADC1, &ADC_InitStructure);
/*配置ADC1通道*/
ADC_ConfigRegularChannel(ADC1, ADC1_Channel_01_PA0, 1, ADC_SAMP_TIME_55CYCLES5);
/*使能DMA*/
ADC_EnableDMA(ADC1, ENABLE);
/* 使能 ADC */
ADC_Enable(ADC1, ENABLE);
while(ADC_GetFlagStatusNew(ADC1,ADC_FLAG_RDY) == RESET);
/* ADC校准 */
ADC_StartCalibration(ADC1);
while (ADC_GetCalibrationStatus(ADC1));
/*开启连续转化*/
ADC_EnableSoftwareStartConv(ADC1, ENABLE);
}
- 扫描模式:通过配置 ADC_CTRL1.SCAMD 为 1 可以开启扫描转换模式,通过配置四个寄存器 ADC_RSEQ1、ADC_RSEQ2、ADC_RSEQ3、ADC_JSEQ 可以选择转换通道序列,ADC 会对所有选择的规则或注入通道进行扫描转换。转换开始后,通道将一个一个转换。如果此时 ADC_CTRL2.CTU 为 1,则在所有选中的规则
通道的转换完成后,将从转换序列的第一个通道重新开始转换。
void ADC_Initl()
{
RCC_EnableAHBPeriphClk(RCC_AHB_PERIPH_DMA1, ENABLE);
/* DMA1 channel1 configuration ----------------------------------------------*/
DMA_InitType DMA_InitStructure;
DMA_DeInit(DMA1_CH1);
DMA_InitStructure.PeriphAddr = (uint32_t)&ADC1->DAT;
DMA_InitStructure.MemAddr = (uint32_t)&adc_value;
DMA_InitStructure.Direction = DMA_DIR_PERIPH_SRC;
DMA_InitStructure.BufSize = 2;
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(DMA1_CH1, &DMA_InitStructure);
/* Enable DMA1 channel1 */
DMA_EnableChannel(DMA1_CH1, ENABLE);
/*打开ADC1总线时钟*/
RCC_EnableAHBPeriphClk(RCC_AHB_PERIPH_ADC1 ,ENABLE);
/*将ADCHCLK配置为DIV16*/
ADC_ConfigClk(ADC_CTRL3_CKMOD_AHB,RCC_ADCHCLK_DIV16);
/*设置ADC1M时钟来源为HSE*/
RCC_ConfigAdc1mClk(RCC_ADC1MCLK_SRC_HSE, RCC_ADC1MCLK_DIV8);
/* ADC初始化 -----------------------*/
ADC_InitType ADC_InitStructure;
ADC_InitStructure.WorkMode = ADC_WORKMODE_INDEPENDENT;//独立输入模式
ADC_InitStructure.MultiChEn = ENABLE;//多通道禁用
ADC_InitStructure.ContinueConvEn = ENABLE;//连续转化禁用
ADC_InitStructure.ExtTrigSelect = ADC_EXT_TRIGCONV_NONE;//外部触发选择
ADC_InitStructure.DatAlign = ADC_DAT_ALIGN_R;//数据右对齐
ADC_InitStructure.ChsNumber = 2;//通道数
ADC_Init(ADC1, &ADC_InitStructure);
ADC_ConfigRegularChannel(ADC1, ADC1_Channel_01_PA0, 1, ADC_SAMP_TIME_55CYCLES5);
ADC_ConfigRegularChannel(ADC1, ADC1_Channel_02_PA1, 2, ADC_SAMP_TIME_55CYCLES5);
ADC_EnableDMA(ADC1, ENABLE);
/* 使能 ADC */
ADC_Enable(ADC1, ENABLE);
while(ADC_GetFlagStatusNew(ADC1,ADC_FLAG_RDY) == RESET);
/* ADC校准 */
ADC_StartCalibration(ADC1);
while (ADC_GetCalibrationStatus(ADC1));
ADC_EnableSoftwareStartConv(ADC1, ENABLE);
}
- 间断模式:
在这里插入代码片