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):
- 修改
minTemp的读取语句:scanf("%hd", &minTemp); - 修改
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
相关产品推荐
相关产品推荐

