You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C/C++技术问题:输入maxTemp后minTemp变量被重置为0

NTC热敏电阻ADC计数列表生成程序变量异常问题排查

问题描述

编写的NTC热敏电阻ADC计数列表生成程序,在Pelles C和GCC(VS Code + MinGW)环境中运行时出现异常:

  • 用户输入maxTemp后,此前正常保存-40值的minTemp变量会被重置为0
  • 输入minTemp=-40、maxTemp=125时,程序仅生成0-126的温度列表
  • 调试确认:执行maxTemp的scanf输入操作后,minTemp被清零

原因分析

核心问题是**scanf格式符与变量类型不匹配,导致内存越界覆盖**:

  • maxTemp和minTemp均为int16_t(2字节短整型)
  • 代码中使用%d格式符读取输入,%d对应int类型(通常为4字节)
  • 当scanf通过%d向2字节的maxTemp写入数据时,会额外写入相邻的2字节内存,恰好覆盖了同栈帧中相邻的minTemp变量,导致其值被清零

修复方案

将读取int16_t类型变量的scanf格式符从%d改为%hd(%hd是C标准中对应short int的格式符,而int16_t本质是typedef的short int):

  1. 修改minTemp的读取语句:scanf("%hd", &minTemp);
  2. 修改maxTemp的读取语句:scanf("%hd", &maxTemp);

同时,后续输出minTemp和maxTemp时,也应使用%hd格式符保证类型匹配,避免潜在的输出异常。

完整修正代码

#include <stdio.h>
#include <stdint.h>
#include <math.h>
#include <stdlib.h>

/******************************************************************************
* Defines
******************************************************************************/
/*! @brief 0 degree Celsius converted to Kelvin. */
#define NTC_DEGC_0                                  (273.15)
/*! @brief Maximal voltage (5V). */
#define NTC_VCOM                                    (5.0)
/*! @brief Resolution of measured voltage in Volts (U = 152.58789 uV *
 *  register_value), with 5V maximal voltage. */
#define NTC_REGISTER_RES                            (0.00015258789) // Can be calculated from ADC resolution and ADC reference voltage

/******************************************************************************
* Types
***************************************************************************** */
typedef struct
{
    uint32_t beta;         /*!< Beta parameter of NTC thermistor in [K].
                                Admissible range is from 1 to 1000000. */
    uint32_t rntc;         /*!< R_NTC - NTC fixed resistance in [Ohm].
                                Admissible range is from 1 to 1000000. */
    uint32_t refRes;       /*!< NTC Reference Resistance in [Ohm].
                                Admissible range is from 1 to 1000000. */
    uint8_t refTemp;       /*!< NTC Reference Temperature in degrees [Celsius].
                                Admissible range is from 0 to 200. */
} ntc_config_t;

/******************************************************************************
* Local Variables
******************************************************************************/
long double NtcRegisterRes;

/******************************************************************************
* Function Prototypes
******************************************************************************/
static void FillNtcTable(const ntc_config_t* const ntcConfig, int16_t minTemp,
                         int16_t maxTemp, uint16_t table[]);

/******************************************************************************
* Global Functions
******************************************************************************/
int main(void)
{
    ntc_config_t ntcConfig;
    long double voltRef = 5.0;
    long double res;
    int16_t minTemp = -40;
    int16_t maxTemp;
    uint16_t *table;
    int tableSize = 0;

    printf("This program will generate the NTC table based on various inputs.\n\n");
    // Beta
    printf("Beta: ");
    scanf("%d", &ntcConfig.beta);
    printf("%d\n", ntcConfig.beta);

    // Pull up resistance
    printf("Pull-up Resistance: ");
    scanf("%d", &ntcConfig.rntc);
    printf("%d\n", ntcConfig.rntc);

    // Reference temp
    printf("Reference Temperature (Degrees C): ");
    scanf("%hhu", &ntcConfig.refTemp);
    printf("%hhu\n", ntcConfig.refTemp);

    // Reference resistance
    printf("Reference Resistance (Ohms): ");
    scanf("%d", &ntcConfig.refRes);
    printf("%d\n", ntcConfig.refRes);

    // ADC voltage reference
    printf("ADC Reference Voltage: ");
    scanf("%Lf", &voltRef);
    printf("%Lf\n", voltRef);

    // ADC resolutions (in bits)
    printf("ADC Resolution (in bits): ");
    scanf("%Lf", &res);
    printf("%Lf\n", res);

    // NTC Register Resolution
    NtcRegisterRes = (long double)voltRef / pow(2, res);
    printf("%Le\n", NtcRegisterRes);

    // Min Temp for Table
    printf("Min Temp: ");
    scanf("%hd", &minTemp);
    printf("min temp: %hd\n", minTemp);

    // Max Temp for Table
    printf("Max Temp: ");
    scanf("%hd", &maxTemp);
    printf("max temp: %hd\n", maxTemp);
    
    tableSize = (maxTemp + abs(minTemp)) + 1;
    printf("table size: %d\n", tableSize);
    table = (uint16_t *)malloc(tableSize * sizeof(uint16_t));
    FillNtcTable(&ntcConfig, minTemp, maxTemp, table);
    
    // Print table
    for (int i = 0; i < tableSize; i++)
    {
        printf("Temp:\t%d\tADC:\t%d\n", (minTemp+i), table[i]);
    }

    // Free the memory
    free(table);

    return(0);
}

/******************************************************************************
* Local Functions
******************************************************************************/
/*!
 * @brief This function fills the NTC look up table.
 *
 * NTC look up table is intended for resistance to temperature conversion.
 * An array item contains raw value from a register. Index of the item is
 * temperature value.
 *
 * ArrayItem = (Vcom * Rntc) / (0.00015258789 * (NTC + Rntc))
 * Where:
 *  - ArrayItem is an item value of the table,
 *  - Vcom is maximal voltage (5V),
 *  - NTC is the resistance of NTC thermistor (Ohm),
 *  - 0.00015258789 is resolution of measured voltage in Volts
 *    (V = 152.58789 uV * Register_value),
 *  - Rntc is value of a resistor connected to Vcom (see MC3377x datasheet,
 *    section MC3377x PCB components).
 *
 * Beta formula used to calculate temperature based on NTC resistance:
 *   1 / T = 1 / T0 + (1 / Beta) * ln(Rt / R0)
 * Where:
 *  - R0 is the resistance (Ohm) at temperature T0 (Kelvin),
 *  - Beta is material constant (Kelvin),
 *  - T is temperature corresponding to resistance of the NTC thermistor.
 *
 * Equation for NTC value is given from the Beta formula:
 *   NTC = R0 * exp(Beta * (1/T - 1/T0))
 *
 * @param ntcConfig Pointer to NTC components configuration.
 */
static void FillNtcTable(const ntc_config_t* const ntcConfig, int16_t minTemp,
                         int16_t maxTemp, uint16_t table[])
{
    double ntcVal;
    double expArg;
    uint16_t i = 0;
    int32_t temp;

    for (temp = minTemp; temp <= maxTemp; temp++)
    {
        expArg = ntcConfig->beta * ((1.0 / (NTC_DEGC_0 + temp)) - (1.0 / (NTC_DEGC_0 + ntcConfig->refTemp)));
        ntcVal = exp(expArg) * ntcConfig->refRes;
        table[i] = (uint16_t)round(((NTC_VCOM * ntcVal) / (ntcVal + (double)ntcConfig->rntc)) / NtcRegisterRes);
        i++;
    }
}

内容的提问来源于stack exchange,提问作者aliamir

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 07:45:18