打印
[STM32C0]

【STM32C092RC 测评】+09 使用内部ADC数据的采集功能

[复制链接]
31|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 聪聪哥哥 于 2025-5-23 20:24 编辑

使用ADC实现位移传感器的采集功能
内置的12位模数转换器嵌入到STM32C091xB/xC和STM32C092xB/xC设备中。该ADC最多有19个外部通道和2个内部通道。通道(温度传感器、电压参考)。LT在单次测量或扫描模式下执行转换。在扫描模式下,对选定的一组模拟输入执行自动转换。
ADC的频率独立于CPU的频率,即使在CPU速度较低的情况下,也可以达到2.5MSps的最大采样率。自动关机功能可确保除在活动转换阶段外ADC处于关机状态。
ADC可以由DMA控制器提供服务。它可以在整个VDD供电范围内运行。
模拟看门狗功能允许对一个、某些或所有扫描通道的转换电压进行非常精确的监控。当转换电压超出预定义的阈值时,将生成中断。
通用定时器(TIMx)产生的事件可以在内部连接到ADC开始触发器,使应用程序能够将A/D转换与定时器同步。

一:温度传感器
温度传感器
温度传感器(TS)产生一个随温度线性变化的电压VTS。
温度传感器与ADC输入端内部连接,将传感器输出电压转换为数字值。
该传感器具有良好的线性度,但必须进行校准才能获得良好的温度测量整体准确性。由于工艺变化,温度传感器的偏移可能会因部件而异,因此未校准的内部温度传感器仅适用于相对温度测量。
为了提高温度传感器的准确性,每个部分都单独由ST进行工厂校准,校准数据被存储在部分的工程字节中,在只读模式下可访问。

二:内部电压参考(VREFINT)
内部电压参考(VREFINT)为ADC提供稳定的(带隙)电压输出。VREFINT内部连接到ADC输入。VREFINT电压在生产测试期间由ST为每个部件单独精确测量,并存储在部件的工程字节中。它可以在只读模式下访问。三:STM32cube MX 软件配置


四:软件代码如下:
static void MX_ADC1_Init(void)
{

  /* USER CODE BEGIN ADC1_Init 0 */

  /* USER CODE END ADC1_Init 0 */

  ADC_ChannelConfTypeDef sConfig = {0};

  /* USER CODE BEGIN ADC1_Init 1 */

  /* USER CODE END ADC1_Init 1 */

  /** Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
  */
  hadc1.Instance = ADC1;
  hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
  hadc1.Init.Resolution = ADC_RESOLUTION_12B;
  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE;
  hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
  hadc1.Init.LowPowerAutoWait = DISABLE;
  hadc1.Init.LowPowerAutoPowerOff = DISABLE;
  hadc1.Init.ContinuousConvMode = DISABLE;
  hadc1.Init.NbrOfConversion = 3;
  hadc1.Init.DiscontinuousConvMode = ENABLE;
  hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
  hadc1.Init.DMAContinuousRequests = ENABLE;
  hadc1.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;
  hadc1.Init.SamplingTimeCommon1 = ADC_SAMPLETIME_79CYCLES_5;
  hadc1.Init.SamplingTimeCommon2 = ADC_SAMPLETIME_160CYCLES_5;
  hadc1.Init.OversamplingMode = DISABLE;
  hadc1.Init.TriggerFrequencyMode = ADC_TRIGGER_FREQ_HIGH;
  if (HAL_ADC_Init(&hadc1) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure Regular Channel
  */
  sConfig.Channel = ADC_CHANNEL_4;
  sConfig.Rank = ADC_REGULAR_RANK_1;
  sConfig.SamplingTime = ADC_SAMPLINGTIME_COMMON_1;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure Regular Channel
  */
  sConfig.Channel = ADC_CHANNEL_VREFINT;
  sConfig.Rank = ADC_REGULAR_RANK_2;
  sConfig.SamplingTime = ADC_SAMPLINGTIME_COMMON_2;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure Regular Channel
  */
  sConfig.Channel = ADC_CHANNEL_TEMPSENSOR;
  sConfig.Rank = ADC_REGULAR_RANK_3;
  sConfig.SamplingTime = ADC_SAMPLINGTIME_COMMON_1;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN ADC1_Init 2 */

  /* USER CODE END ADC1_Init 2 */

}
在主程序下添加如下代码:
    /* Start ADC group regular conversion */
    if (HAL_ADC_Start(&hadc1) != HAL_OK)
    {
      /* Error: ADC conversion start could not be performed */
      Error_Handler();
    }

    if(ubDmaTransferStatus == 1)
    {
      /* For this example purpose, calculate analog reference voltage (Vref+) */
      /* from ADC conversion of internal voltage reference VrefInt.           */
      /* This voltage should correspond to value of literal "VDDA_APPLI".     */
      /* Note: This calculation can be performed when value of voltage Vref+  */
      /*       is unknown in the application                                  */
      /*       (This is not the case in this example due to target board      */
      /*       supplied by a LDO regulator providing a known constant voltage */
      /*       of value "VDDA_APPLI").                                        */
      /*       In typical case of Vref+ connected to Vdd, it allows to        */
      /*       deduce Vdd value.                                              */
      uhADCxConvertedData_VrefAnalog_mVolt = __LL_ADC_CALC_VREFANALOG_VOLTAGE(uhADCxConvertedData[1], LL_ADC_RESOLUTION_12B);

      /* Computation of ADC conversions raw data to physical values           */
      /* using LL ADC driver helper macro.                                    */
      uhADCxConvertedData_VoltageGPIO_mVolt        = __LL_ADC_CALC_DATA_TO_VOLTAGE(uhADCxConvertedData_VrefAnalog_mVolt, uhADCxConvertedData[0], LL_ADC_RESOLUTION_12B);
      uhADCxConvertedData_VrefInt_mVolt            = __LL_ADC_CALC_DATA_TO_VOLTAGE(uhADCxConvertedData_VrefAnalog_mVolt, uhADCxConvertedData[1], LL_ADC_RESOLUTION_12B);
      hADCxConvertedData_Temperature_DegreeCelsius = __LL_ADC_CALC_TEMPERATURE_TYP_PARAMS(INTERNAL_TEMPSENSOR_AVGSLOPE,INTERNAL_TEMPSENSOR_V30,INTERNAL_TEMPSENSOR_V30_TEMP,VDDA_APPLI,uhADCxConvertedData[2],LL_ADC_RESOLUTION_12B);
      /* Update status variable of DMA transfer */
      ubDmaTransferStatus = 0;

      /* Toggle LED 4 times */
      tmp_index = 4*2;
      while(tmp_index != 0)
      {
        BSP_LED_Toggle(LED1);
        HAL_Delay(LED_BLINK_FAST);
        tmp_index--;
      }
      HAL_Delay(500); /* Delay to highlight toggle sequence */
    }
实测图如下:

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

64

主题

171

帖子

1

粉丝