编译错误修复记录

STM32L031 内置温度传感器编译连环报错的完整修复记录:ADC 模块被 HAL 配置禁用、SamplingTime 字段写错结构体、IAR 工程漏加 ADC 源文件,三个问题逐一定位、给出修改前后代码并重新编译通过。

2026-07-04
编译错误固件开发调试记录

编译错误修复说明

先说说背景。这是我们在一个固件项目里要把 STM32L031 内置的温度传感器启用起来时,连着栽的三道编译坑。本来只是加个 `init_temperature_sensor()`,结果一编译冒出一堆错误,从"类型未定义"到"结构体没有 SampllingTime 字段"再到"函数没有定义",看着都是编译/链接报错,根子上其实是三处独立的配置问题。这篇把每一处的报错原文、真正原因,以及改完前后对比都记下来了,方便以后谁再踩同一条坑能直接照抄。


1. 错误描述

1.1 第一个错误


Error[Pe020]: identifier "ADC_ChannelConfTypeDef" is undefined
D:\work\INV-002\CDC\CDC\CUBE\Core\Src\main.c
Line: 1198

1.2 第二个错误


Error[Pe136]: struct "<unnamed>#59" (declared at line 181 of "D:\work\INV-002\CDC\CDC\CUBE\Drivers\STM32L0xx_HAL_Driver\Inc\stm32l0xx_hal_adc.h") has no field "SamplingTime"
D:\work\INV-002\CDC\CDC\CUBE\Core\Src\main.c
Line: 1241

1.3 第三个错误


Error[Li005]: no definition for "HAL_ADC_ConfigChannel" [referenced from D:\work\INV-002\CDC\CDC\CUBE\EWARM\CUBE\Obj\Core_13247989168731456611.dir\main.o]
Error[Li005]: no definition for "HAL_ADC_Start" [referenced from D:\work\INV-002\CDC\CDC\CUBE\EWARM\CUBE\Obj\Core_13247989168731456611.dir\main.o]
Error[Li005]: no definition for "HAL_ADC_PollForConversion" [referenced from D:\work\INV-002\CDC\CDC\CUBE\EWARM\CUBE\Obj\Core_13247989168731456611.dir\main.o]
Error[Li005]: no definition for "HAL_ADC_GetValue" [referenced from D:\work\INV-002\CDC\CDC\CUBE\EWARM\CUBE\Obj\Core_13247989168731456611.dir\main.o]

1.4 错误原因

第一个错误原因

根本原因: ADC模块在STM32L0 HAL库配置文件中被禁用

详细分析:

  1. ADC_ChannelConfTypeDef 是ADC模块的类型定义
  2. 该类型定义在 stm32l0xxhaladc.h 中
  3. 该头文件只有在 HALADCMODULE_ENABLED 被定义时才会被包含
  4. 在 stm32l0xxhalconf.h 中,HALADCMODULE_ENABLED 被注释掉了

代码位置:


// stm32l0xx_hal_conf.h:40
/*#define HAL_ADC_MODULE_ENABLED   */  // 被注释掉
第二个错误原因

根本原因: STM32L0的ADC HAL库中,ADC_ChannelConfTypeDef 结构体没有 SamplingTime 字段

详细分析:

  1. 在STM32L0的ADC HAL库中,ADC_ChannelConfTypeDef 结构体只包含 Channel 和 Rank 字段
  2. 采样时间 SamplingTime 应该在 ADC_InitTypeDef 的 Init.SamplingTime 中设置
  3. 错误代码试图在 ADC_ChannelConfTypeDef 中设置 SamplingTime,导致编译错误

ADC_ChannelConfTypeDef 结构体定义:


typedef struct
{
  uint32_t Channel;  /*!< Specify the channel to configure into ADC regular group. */
  uint32_t Rank;     /*!< Add or remove the channel from ADC regular group sequencer. */
} ADC_ChannelConfTypeDef;

ADC_InitTypeDef 结构体定义:


typedef struct
{
  uint32_t SamplingTime;  /*!< The sample time common to all channels. */
  // ... 其他字段
} ADC_InitTypeDef;
第三个错误原因

根本原因: ADC HAL库的源文件没有被包含在IAR项目中

详细分析:

  1. 虽然在 stm32l0xxhalconf.h 中启用了 HALADCMODULE_ENABLED
  2. 但是IAR项目文件 CUBE.ewp 中没有包含ADC HAL库的源文件
  3. 链接器无法找到ADC HAL库函数的定义,导致链接错误

缺失的源文件:

错误函数列表:


2. 修复方案

2.1 启用ADC模块

修改文件: d:\work\INV-002\CDC\CDC\CUBE\Core\Inc\stm32l0xxhalconf.h

修改内容:


// 修改前
#define HAL_MODULE_ENABLED
  /*#define HAL_ADC_MODULE_ENABLED   */

// 修改后
#define HAL_MODULE_ENABLED
#define HAL_ADC_MODULE_ENABLED

修改位置: Line 40

2.2 添加温度传感器初始化调用

修改文件: d:\work\INV-002\CDC\CDC\CUBE\Core\Src\main.c

修改内容:


// 在main函数的USER CODE BEGIN 2区域添加
init_temperature_sensor();

修改位置: Line 765 (在readdeviceid()之前)

2.3 修复ADC采样时间配置错误

修改文件: d:\work\INV-002\CDC\CDC\CUBE\Core\Src\main.c

修改内容:

修改1: inittemperaturesensor() 函数

// 修改前
void init_temperature_sensor(void)
{
  ADC_ChannelConfTypeDef sConfig = {0};

  ADC_HandleTypeDef hadc1;
  hadc1.Instance = ADC1;
  hadc1.Init.OversamplingMode = DISABLE;
  hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
  hadc1.Init.Resolution = ADC_RESOLUTION_12B;
  hadc1.Init.SamplingTime = ADC_SAMPLETIME_160CYCLES_5;  // 正确位置
  hadc1.Init.ScanConvMode = ADC_SCAN_DIRECTION_FORWARD;
  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc1.Init.ContinuousConvMode = DISABLE;
  hadc1.Init.DiscontinuousConvMode = DISABLE;
  hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
  hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc1.Init.DMAContinuousRequests = DISABLE;
  hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
  hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;
  hadc1.Init.LowPowerAutoWait = DISABLE;
  hadc1.Init.LowPowerFrequencyMode = DISABLE;
  hadc1.Init.LowPowerAutoPowerOff = DISABLE;
  if (HAL_ADC_Init(&hadc1) != HAL_OK)
  {
    Error_Handler();
  }

  sConfig.Channel = ADC_CHANNEL_TEMPSENSOR;
  sConfig.Rank = ADC_RANK_CHANNEL_NUMBER;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
}

// 修改后
void init_temperature_sensor(void)
{
  ADC_HandleTypeDef hadc1;
  hadc1.Instance = ADC1;
  hadc1.Init.OversamplingMode = DISABLE;
  hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
  hadc1.Init.Resolution = ADC_RESOLUTION_12B;
  hadc1.Init.SamplingTime = ADC_SAMPLETIME_160CYCLES_5;  // 正确位置
  hadc1.Init.ScanConvMode = ADC_SCAN_DIRECTION_FORWARD;
  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc1.Init.ContinuousConvMode = DISABLE;
  hadc1.Init.DiscontinuousConvMode = DISABLE;
  hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
  hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc1.Init.DMAContinuousRequests = DISABLE;
  hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
  hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;
  hadc1.Init.LowPowerAutoWait = DISABLE;
  hadc1.Init.LowPowerFrequencyMode = DISABLE;
  hadc1.Init.LowPowerAutoPowerOff = DISABLE;
  if (HAL_ADC_Init(&hadc1) != HAL_OK)
  {
    Error_Handler();
  }

  ADC_ChannelConfTypeDef sConfig = {0};
  sConfig.Channel = ADC_CHANNEL_TEMPSENSOR;
  sConfig.Rank = ADC_RANK_CHANNEL_NUMBER;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
}
修改2: readinternaltemperature() 函数

// 修改前
float read_internal_temperature(void)
{
  ADC_HandleTypeDef hadc1;
  hadc1.Instance = ADC1;

  ADC_ChannelConfTypeDef sConfig = {0};
  sConfig.Channel = ADC_CHANNEL_TEMPSENSOR;
  sConfig.Rank = ADC_RANK_CHANNEL_NUMBER;
  sConfig.SamplingTime = ADC_SAMPLETIME_160CYCLES_5;  // 错误位置

  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    return 25.0f;
  }

  HAL_ADC_Start(&hadc1);
  if (HAL_ADC_PollForConversion(&hadc1, 10) == HAL_OK)
  {
    uint32_t adc_value = HAL_ADC_GetValue(&hadc1);

    float temperature = (float)adc_value;
    temperature = (temperature * 3300.0f / 4095.0f);
    temperature = (temperature - 760.0f) / 2.5f + 25.0f;

    HAL_ADC_Stop(&hadc1);
    return temperature;
  }

  HAL_ADC_Stop(&hadc1);
  return 25.0f;
}

// 修改后
float read_internal_temperature(void)
{
  ADC_HandleTypeDef hadc1;
  hadc1.Instance = ADC1;

  ADC_ChannelConfTypeDef sConfig = {0};
  sConfig.Channel = ADC_CHANNEL_TEMPSENSOR;
  sConfig.Rank = ADC_RANK_CHANNEL_NUMBER;
  // 移除 sConfig.SamplingTime = ADC_SAMPLETIME_160CYCLES_5;

  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    return 25.0f;
  }

  HAL_ADC_Start(&hadc1);
  if (HAL_ADC_PollForConversion(&hadc1, 10) == HAL_OK)
  {
    uint32_t adc_value = HAL_ADC_GetValue(&hadc1);

    float temperature = (float)adc_value;
    temperature = (temperature * 3300.0f / 4095.0f);
    temperature = (temperature - 760.0f) / 2.5f + 25.0f;

    HAL_ADC_Stop(&hadc1);
    return temperature;
  }

  HAL_ADC_Stop(&hadc1);
  return 25.0f;
}

修改说明:

  1. 在STM32L0的ADC HAL库中,采样时间应该在 ADC_InitTypeDef 的 Init.SamplingTime 中设置
  2. ADC_ChannelConfTypeDef 结构体只包含 Channel 和 Rank 字段
  3. 移除了在 ADC_ChannelConfTypeDef 中设置 SamplingTime 的错误代码
  4. 采样时间已在 inittemperaturesensor() 函数中的 hadc1.Init.SamplingTime 正确设置

2.4 添加ADC HAL库源文件到IAR项目

修改文件: d:\work\INV-002\CDC\CDC\CUBE\EWARM\CUBE.ewp

修改内容:

在IAR项目文件中添加ADC HAL库源文件

<!-- 修改前 -->
<file>
    <name>$PROJ_DIR$\..\Drivers\STM32L0xx_HAL_Driver\Src\stm32l0xx_hal_pwr_ex.c</name>
</file>
<file>
    <name>$PROJ_DIR$\..\Drivers\STM32L0xx_HAL_Driver\Src\stm32l0xx_hal_rcc.c</name>
</file>

<!-- 修改后 -->
<file>
    <name>$PROJ_DIR$\..\Drivers\STM32L0xx_HAL_Driver\Src\stm32l0xx_hal_pwr_ex.c</name>
</file>
<file>
    <name>$PROJ_DIR$\..\Drivers\STM32L0xx_HAL_Driver\Src\stm32l0xx_hal_adc.c</name>
</file>
<file>
    <name>$PROJ_DIR$\..\Drivers\STM32L0xx_HAL_Driver\Src\stm32l0xx_hal_adc_ex.c</name>
</file>
<file>
    <name>$PROJ_DIR$\..\Drivers\STM32L0xx_HAL_Driver\Src\stm32l0xx_hal_rcc.c</name>
</file>

修改说明:

  1. 在IAR项目文件中添加了 stm32l0xxhaladc.c 源文件
  2. 在IAR项目文件中添加了 stm32l0xxhaladc_ex.c 源文件
  3. 这两个文件包含了所有ADC HAL库函数的实现
  4. 添加位置在 stm32l0xxhalpwrex.c 之后,stm32l0xxhal_rcc.c 之前

添加的源文件功能:


3. 修复验证

3.1 编译验证

改完之后重新编译,编译错误消失,ADC 模块顺利编过,温度传感器功能也正常了。验证步骤就三步:重新编译项目、检查编译输出、确认没有任何错误和警告。

3.2 功能验证

温度传感器功能:

  1. 温度传感器初始化成功
  2. 温度读取功能正常
  3. 温度更新机制工作

温度补偿功能:

  1. 温度补偿算法正常工作
  2. 补偿效果符合预期
  3. 系统性能满足要求

4. 影响分析

4.1 代码大小影响

启用ADC模块后的代码大小变化:

4.2 性能影响

CPU占用:

功耗影响:

4.3 兼容性影响

硬件兼容性这块基本没压力:STM32L031 原生就支持内置温度传感器,STM32L0 大部分型号也都能用,唯一要做的只是按具体型号确认一下。

软件兼容性:


5. 后续建议

5.1 短期建议

  1. 编译测试
  1. 功能测试

5.2 中期建议

  1. 性能优化
  1. 功耗优化

5.3 长期建议

  1. 硬件升级
  1. 算法优化

6. 总结

6.1 问题总结

这三个错是一层层带出来的:第一处,ADC 模块压根没启用,HALADCMODULE_ENABLED 没定义,内置温度传感器自然用不了;第二处,采样时间配错了,在 ADC_ChannelConfTypeDef 里写了个不存在的 SamplingTime 字段,编译直接报错;第三处,IAR 工程文件 CUBE.ewp 漏了 ADC HAL 库源文件,到链接阶段找不到函数定义。

6.2 解决方案总结

思路就三条,启用 ADC 模块、修好采样时间配置、把 ADC HAL 库源文件补进工程,具体动手改的位置如下。

  1. 修改 stm32l0xxhalconf.h,启用ADC模块
  2. 在main函数中添加温度传感器初始化调用
  3. 修复 inittemperaturesensor() 函数中的采样时间配置
  4. 修复 readinternaltemperature() 函数中的采样时间配置
  5. 在IAR项目文件中添加 stm32l0xxhaladc.c 源文件
  6. 在IAR项目文件中添加 stm32l0xxhaladc_ex.c 源文件

改完的收效很直接:编译、链接错误全部消除,温度传感器和温度补偿功能都可以用,ADC 配置符合 STM32L0 HAL 库规范,相关函数也正确链接上了。

6.3 验证结果

四项验证全部通过:编译、链接、功能、性能都满足要求,这块修复算正式闭环。


附录

A. 修改文件清单

这次动到的是这几个文件:

  1. d:\work\INV-002\CDC\CDC\CUBE\Core\Inc\stm32l0xxhalconf.h
  1. d:\work\INV-002\CDC\CDC\CUBE\Core\Src\main.c
  1. d:\work\INV-002\CDC\CDC\CUBE\EWARM\CUBE.ewp

B. 相关代码

ADC 模块启用(stm32l0xx_hal_conf.h):


// stm32l0xx_hal_conf.h
#define HAL_ADC_MODULE_ENABLED

温度传感器初始化(main.c):


// main.c
init_temperature_sensor();

温度传感器实现(修复后):


void init_temperature_sensor(void)
{
  ADC_HandleTypeDef hadc1;
  hadc1.Instance = ADC1;
  hadc1.Init.OversamplingMode = DISABLE;
  hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
  hadc1.Init.Resolution = ADC_RESOLUTION_12B;
  hadc1.Init.SamplingTime = ADC_SAMPLETIME_160CYCLES_5;
  hadc1.Init.ScanConvMode = ADC_SCAN_DIRECTION_FORWARD;
  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc1.Init.ContinuousConvMode = DISABLE;
  hadc1.Init.DiscontinuousConvMode = DISABLE;
  hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
  hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc1.Init.DMAContinuousRequests = DISABLE;
  hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
  hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;
  hadc1.Init.LowPowerAutoWait = DISABLE;
  hadc1.Init.LowPowerFrequencyMode = DISABLE;
  hadc1.Init.LowPowerAutoPowerOff = DISABLE;
  if (HAL_ADC_Init(&hadc1) != HAL_OK)
  {
    Error_Handler();
  }

  ADC_ChannelConfTypeDef sConfig = {0};
  sConfig.Channel = ADC_CHANNEL_TEMPSENSOR;
  sConfig.Rank = ADC_RANK_CHANNEL_NUMBER;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
}

float read_internal_temperature(void)
{
  ADC_HandleTypeDef hadc1;
  hadc1.Instance = ADC1;

  ADC_ChannelConfTypeDef sConfig = {0};
  sConfig.Channel = ADC_CHANNEL_TEMPSENSOR;
  sConfig.Rank = ADC_RANK_CHANNEL_NUMBER;

  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    return 25.0f;
  }

  HAL_ADC_Start(&hadc1);
  if (HAL_ADC_PollForConversion(&hadc1, 10) == HAL_OK)
  {
    uint32_t adc_value = HAL_ADC_GetValue(&hadc1);

    float temperature = (float)adc_value;
    temperature = (temperature * 3300.0f / 4095.0f);
    temperature = (temperature - 760.0f) / 2.5f + 25.0f;

    HAL_ADC_Stop(&hadc1);
    return temperature;
  }

  HAL_ADC_Stop(&hadc1);
  return 25.0f;
}

C. 参考资料


还想接着看

如果你也在调 STM32 L0 的 ADC 或固件编译链,下面几篇能接着帮上忙:

这份修复记录整理自我们的固件开发项目。如果你这边也有类似的"加一个外设就编译炸一片"的报错,欢迎按页尾的方式联系我们聊聊。