文章
博客 网店

 STM32G0 LL库示例 - ADC不完全序列模式


不完全序列模式下转换顺序不能配置以外,所有输入通道都能转换,每次也可以转换全部通道,是推荐使用的模式;


//adc.c
#include "CAFrame.h"

#define ADC_CH_COUNT  5                          //实际需要转换的通道个数
static uint16_t g_AdcDmaBuffer[ADC_CH_COUNT];   //ADC转换结果缓冲区

//DMA初始化
static void ADC_DMA_Init(void)
{
  LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_DMA1);
  
  LL_DMA_SetPeriphRequest(DMA1, LL_DMA_CHANNEL_1, LL_DMAMUX_REQ_ADC1);
  LL_DMA_SetDataTransferDirection(DMA1, LL_DMA_CHANNEL_1, LL_DMA_DIRECTION_PERIPH_TO_MEMORY);//配置ADC到内存的传输
  LL_DMA_SetChannelPriorityLevel(DMA1, LL_DMA_CHANNEL_1, LL_DMA_PRIORITY_LOW);
  LL_DMA_SetMode(DMA1, LL_DMA_CHANNEL_1, LL_DMA_MODE_CIRCULAR);
  LL_DMA_SetPeriphIncMode(DMA1, LL_DMA_CHANNEL_1, LL_DMA_PERIPH_NOINCREMENT);
  LL_DMA_SetMemoryIncMode(DMA1, LL_DMA_CHANNEL_1, LL_DMA_MEMORY_INCREMENT);
  LL_DMA_SetPeriphSize(DMA1, LL_DMA_CHANNEL_1, LL_DMA_PDATAALIGN_HALFWORD);
  LL_DMA_SetMemorySize(DMA1, LL_DMA_CHANNEL_1, LL_DMA_MDATAALIGN_HALFWORD);

  // 设置DMA传输源和目标地址
  LL_DMA_SetPeriphAddress(DMA1, LL_DMA_CHANNEL_1, (uint32_t)&ADC1->DR);
  LL_DMA_SetMemoryAddress(DMA1, LL_DMA_CHANNEL_1, (uint32_t)g_AdcDmaBuffer);
  LL_DMA_SetDataLength(DMA1, LL_DMA_CHANNEL_1, ADC_CH_COUNT);

  //启用DMA传输完成中断 
  LL_DMA_EnableIT_TC(DMA1, LL_DMA_CHANNEL_1);

  // 配置NVIC
  NVIC_SetPriority(DMA1_Channel1_IRQn, 0);
  NVIC_EnableIRQ(DMA1_Channel1_IRQn);
  
  LL_DMA_EnableChannel(DMA1,LL_DMA_CHANNEL_1);
}

void AdcInit(void)
{
  LL_ADC_InitTypeDef ADC_InitStruct = {0};
  LL_ADC_REG_InitTypeDef ADC_REG_InitStruct = {0};
  LL_GPIO_InitTypeDef GPIO_InitStruct = {0};

  //打开并设置adc时钟
  LL_RCC_SetADCClockSource(LL_RCC_ADC_CLKSOURCE_SYSCLK);
  LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_ADC);

  //PA0,PA1,PA2,PA3
  GPIO_InitStruct.Pin = LL_GPIO_PIN_0|LL_GPIO_PIN_1|LL_GPIO_PIN_2|LL_GPIO_PIN_3;
  GPIO_InitStruct.Mode = LL_GPIO_MODE_ANALOG;
  GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
  LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    
  ADC_InitStruct.Clock = LL_ADC_CLOCK_SYNC_PCLK_DIV2;        //选择采样时钟来源
  ADC_InitStruct.Resolution = LL_ADC_RESOLUTION_12B;         //采样分辨率
  ADC_InitStruct.DataAlignment = LL_ADC_DATA_ALIGN_RIGHT;    //采样数据对齐方式,右对齐高位补0,左对齐低位补0.
  ADC_InitStruct.LowPowerMode = LL_ADC_LP_MODE_NONE;        //低功耗模式,使用DMA的话无法使用,这里关闭
  LL_ADC_Init(ADC1, &ADC_InitStruct);
  
  LL_ADC_REG_SetSequencerConfigurable(ADC1, LL_ADC_REG_SEQ_FIXED);//配置为不完全序列模式
  
  
  ADC_REG_InitStruct.TriggerSource = LL_ADC_REG_TRIG_SOFTWARE; //ADC定时转化触发条件来源,可以为软件触发或硬件(外部中断、定时器)触发。
  ADC_REG_InitStruct.SequencerLength = LL_ADC_REG_SEQ_SCAN_ENABLE_5RANKS;//ADC顺序采集通道的个数,根据自己需要的通道个数设置
  ADC_REG_InitStruct.SequencerDiscont = LL_ADC_REG_SEQ_DISCONT_DISABLE;
  ADC_REG_InitStruct.ContinuousMode = LL_ADC_REG_CONV_SINGLE;//采集方式,单次采集还是连续采集
  ADC_REG_InitStruct.DMATransfer = LL_ADC_REG_DMA_TRANSFER_LIMITED; //使能DMA,并使用无限传输,如果DMA保存方式为循环覆盖的话才可以使用无限传输。
  ADC_REG_InitStruct.Overrun = LL_ADC_REG_OVR_DATA_PRESERVED; //采集的数据循环覆盖模式
  LL_ADC_REG_Init(ADC1, &ADC_REG_InitStruct);
  
  LL_ADC_REG_SetSequencerScanDirection(ADC1, LL_ADC_REG_SEQ_SCAN_DIR_FORWARD);
  LL_ADC_SetOverSamplingScope(ADC1, LL_ADC_OVS_DISABLE);//失能过采样
  LL_ADC_SetTriggerFrequencyMode(ADC1, LL_ADC_CLOCK_FREQ_MODE_HIGH); //采样时钟使用高频模式
  LL_ADC_SetCommonPathInternalCh(__LL_ADC_COMMON_INSTANCE(ADC1), LL_ADC_AWD_CH_VREFINT_REG);//使能内部参考电压
  LL_ADC_SetSamplingTimeCommonChannels(ADC1, LL_ADC_SAMPLINGTIME_COMMON_1, LL_ADC_SAMPLINGTIME_160CYCLES_5);
  //LL_ADC_SetSamplingTimeCommonChannels(ADC1, LL_ADC_SAMPLINGTIME_COMMON_2, LL_ADC_SAMPLINGTIME_160CYCLES_5);
  LL_ADC_DisableIT_EOC(ADC1);//禁用通道采样结束中断
  LL_ADC_DisableIT_EOS(ADC1);//禁用序列采样结束中断,因为使用的是单次软件触发所以这里关闭这些中断

  //打开ADC电源
  LL_ADC_EnableInternalRegulator(ADC1);
  drv_delay_us(100);
  
  //选择要转换的通道,转换结果按序号顺序存储到缓冲区
  LL_ADC_REG_SetSequencerChannels(ADC1,LL_ADC_CHANNEL_0|LL_ADC_CHANNEL_1|LL_ADC_CHANNEL_2|LL_ADC_CHANNEL_3|LL_ADC_CHANNEL_VREFINT);

  LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_VREFINT, LL_ADC_SAMPLINGTIME_COMMON_1); //设置通道采样时间
  LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_0, LL_ADC_SAMPLINGTIME_COMMON_1); //设置通道采样时间
  LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_1, LL_ADC_SAMPLINGTIME_COMMON_1);  //设置通道采样时间
  LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_2, LL_ADC_SAMPLINGTIME_COMMON_1); //设置通道采样时间
  LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_3, LL_ADC_SAMPLINGTIME_COMMON_1);  //设置通道采样时间
  
  
  LL_ADC_StartCalibration(ADC1); //校准
  while( LL_ADC_IsCalibrationOnGoing(ADC1)); 
  
  ADC_DMA_Init();//配置DMA
  
  LL_ADC_Enable(ADC1);//使能ADC
}


//DMA传输完成中断处理函数
void DMA1_Channel1_IRQHandler(void)
{
    if (LL_DMA_IsActiveFlag_TC1(DMA1) == 1) 
    {
        LL_DMA_ClearFlag_TC1(DMA1);//清除传输完成标志
        
        frm_set_event(EVENT_ADC_ID);
    }
}

void AdcTrig(void)//软件触发ADC转换
{
    LL_ADC_REG_StartConversion(ADC1);
}

//读转换结果
uint16_t* AdcGetValue(void)
{
  return g_AdcDmaBuffer;
}






芯艺工作室    蒙ICP备06005492号
Copyright© 2004-2025 ChipArt Studio All Rights Reserved