你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【STM32C0评测】使用ADC实现波形采集

[复制链接]
北方 发布时间:2025-4-23 12:01

1 STM32C071-nucleo开发板ADC功能介绍

TM32C071 Nucleo 开发板是一款基于 STM32C071xx 微控制器的高性价比开发平台,它提供了丰富的外设接口,其中就包括了 ADC(模数转换器)功能。

ADC 功能概述: STM32C071xx 微控制器集成了 12 位 ADC,支持单次转换和连续转换模式。 ADC 拥有多个通道,可以配置为单通道模式或多通道模式。 支持 16 个外部通道和 2 个内部通道(如 VREFINT 和 VBAT)。 ADC 特性: 12 位分辨率。 最高转换速率为 1 MSPS(兆采样/秒)。 支持扫描模式,可以连续转换多个通道。 支持注入通道,允许在正常转换过程中插入高优先级转换。 具有可编程的数据对齐方式(左对齐或右对齐)。 支持温度传感器测量。 具有可编程的采样时间,以适应不同的输入信号。 ADC 配置: 通过 STM32CubeMX 或直接编写代码进行配置。 可以配置 ADC 的时钟、分辨率、采样时间、转换模式等参数。 可以选择输入通道,配置外部触发源(如定时器)。

2 代码和逻辑设计

2.1 本示例基于 STM32C0xx ADC LL API,使用 ADC 外设连续转换单个通道,并从软件启动。

配置: ADC 配置为转换单个通道,在连续转换模式下,使用软件触发。 执行: 从主程序执行中,执行一次 ADC 软件启动,ADC 常规组会自动连续、无限地转换所选通道。 软件轮询第一次转换完成,然后按需(本示例中每秒)检索转换数据。LED1 用于监视程序执行状态:

正常操作:

可以通过 LED 切换观察到 ADC 常规组的活动: 检索 ADC 转换数据:LED 切换一次(每 1 秒) 错误:LED 保持点亮 调试:使用调试器监视的变量: "uhADCxConvertedData":ADC 常规组缓冲区转换数据(12 位分辨率) "uhADCxConvertedData_Voltage_mVolt":计算为电压值(单位:mV)的 ADC 常规组缓冲区转换数据 使用的其他外设: 1 个 GPIO 用于 LED1 1 个 GPIO 用于模拟输入:ADC 通道 4 在引脚 PA.04(Arduino 连接器 CN8 引脚 3 A2,Morpho 连接器 CN7 引脚 32)

2.2 主要代码

int main(void)
{

  LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SYSCFG);
  LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_PWR);

  NVIC_SetPriority(SysTick_IRQn, 3);
  SystemClock_Config();
  MX_GPIO_Init();
  MX_ADC1_Init();
  ADC_Activate();                              */
  ConversionStartPoll_ADC_GrpRegular();
  while (1)
  {
    uhADCxConvertedData = LL_ADC_REG_ReadConversionData32(ADC1);

    while(LL_ADC_IsActiveFlag_EOC(ADC1) == 0);
    LL_ADC_ClearFlag_EOC(ADC1);
    uhADCxConvertedData_Voltage_mVolt = __LL_ADC_CALC_DATA_TO_VOLTAGE(VDDA_APPLI, uhADCxConvertedData, LL_ADC_RESOLUTION_12B);

    LED_On();
    LL_mDelay(LED_BLINK_SLOW);
    LED_Off();
    LL_mDelay(LED_BLINK_SLOW);

  }
}

关于ADC的配置如下

static void MX_ADC1_Init(void)
{

  LL_ADC_InitTypeDef ADC_InitStruct = {0};
  LL_ADC_REG_InitTypeDef ADC_REG_InitStruct = {0};

  LL_GPIO_InitTypeDef GPIO_InitStruct = {0};

  LL_RCC_SetADCClockSource(LL_RCC_ADC_CLKSOURCE_SYSCLK);

  LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_ADC);

  LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOA);
  GPIO_InitStruct.Pin = LL_GPIO_PIN_4;
  GPIO_InitStruct.Mode = LL_GPIO_MODE_ANALOG;
  GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
  LL_GPIO_Init(GPIOA, &GPIO_InitStruct);

   #define ADC_CHANNEL_CONF_RDY_TIMEOUT_MS ( 1U)
   #if (USE_TIMEOUT == 1)
   uint32_t Timeout ; /* Variable used for Timeout management */
   #endif /* USE_TIMEOUT */

  ADC_InitStruct.Clock = LL_ADC_CLOCK_SYNC_PCLK_DIV4;
  ADC_InitStruct.Resolution = LL_ADC_RESOLUTION_12B;
  ADC_InitStruct.DataAlignment = LL_ADC_DATA_ALIGN_RIGHT;
  ADC_InitStruct.LowPowerMode = LL_ADC_LP_MODE_NONE;
  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_REG_InitStruct.SequencerLength = LL_ADC_REG_SEQ_SCAN_DISABLE;
  ADC_REG_InitStruct.ContinuousMode = LL_ADC_REG_CONV_CONTINUOUS;
  ADC_REG_InitStruct.DMATransfer = LL_ADC_REG_DMA_TRANSFER_NONE;
  ADC_REG_InitStruct.Overrun = LL_ADC_REG_OVR_DATA_OVERWRITTEN;
  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_REG_SetSequencerChAdd(ADC1, LL_ADC_CHANNEL_4);

   /* Poll for ADC channel configuration ready */
   #if (USE_TIMEOUT == 1)
   Timeout = ADC_CHANNEL_CONF_RDY_TIMEOUT_MS;
   #endif /* USE_TIMEOUT */
   while (LL_ADC_IsActiveFlag_CCRDY(ADC1) == 0)
     {
   #if (USE_TIMEOUT == 1)
   /* Check Systick counter flag to decrement the time-out value */
   if (LL_SYSTICK_IsActiveCounterFlag())
     {
   if(Timeout-- == 0)
         {
   Error_Handler();
         }
     }
   #endif /* USE_TIMEOUT */
     }
   LL_ADC_ClearFlag_CCRDY(ADC1);
  LL_ADC_SetSamplingTimeCommonChannels(ADC1, LL_ADC_SAMPLINGTIME_COMMON_1, LL_ADC_SAMPLINGTIME_79CYCLES_5);
  LL_ADC_DisableIT_EOC(ADC1);
  LL_ADC_DisableIT_EOS(ADC1);
   LL_ADC_EnableInternalRegulator(ADC1);
   uint32_t wait_loop_index;
   wait_loop_index = ((LL_ADC_DELAY_INTERNAL_REGUL_STAB_US * (SystemCoreClock / (100000 * 2))) / 10);
   while(wait_loop_index != 0)
     {
   wait_loop_index--;
  LL_ADC_EnableIT_EOC(ADC1);

  LL_ADC_EnableIT_OVR(ADC1);

}

3 演示效果

编译和下载

10.PNG

这个正常的运行就是每次采样成功后,led闪一次。如果采样失败就保持始终是亮着。

运行显示,led断续点亮,说明运行成功。

4 小结

对于ADC的采样,使用的是底层LL层的代码,这样可以保证采样的时序和稳定性,可以用在多种工程项目。

收藏 评论0 发布时间:2025-4-23 12:01

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版