【0基础嵌入式学习日志】Day08配置头文件 config.h、阈值宏管理与消除魔法数字一、前言今天继续进行嵌入式 C 语言基础学习。前面几天已经完成了 C 工程结构、多文件拆分、Makefile 自动化编译、头文件依赖追踪、DEBUG 调试日志等内容。Day01基础 C 工程结构 Day02函数封装、结构体指针、故障判断 Day03多文件拆分.h / .c 配合 Day04.c → .o → 可执行文件 Day05Makefile 自动化、模式规则、增量编译 Day06.d 依赖文件头文件依赖追踪 Day07条件编译、DEBUG 开关与日志打印模块Day08 的重点是进一步提高工程代码的规范性使用config.h配置头文件统一管理系统初始值、传感器模拟值和故障判断阈值。在之前的代码中很多数字是直接写在.c文件里的例如sys-voltage9.5f;sys-current2.5f;sys-temperature75.0f;if(sys-temperature60.0f)这些直接写死在代码中的数字被称为魔法数字。魔法数字的问题是别人看到9.5f、2.5f、75.0f、60.0f时不一定马上知道它们代表什么含义。因此Day08 的目标就是把这些关键参数统一放到config.h中管理让代码更加清晰、可维护。二、Day08 学习目标本次 Day08 主要学习以下内容理解什么是魔法数字理解为什么嵌入式工程需要配置头文件学会使用config.h统一管理系统初始值学会使用config.h统一管理传感器模拟值学会使用config.h统一管理故障判断阈值修改system.c、sensor.c、fault.c让它们使用配置宏验证修改config.h后程序行为是否发生变化。三、Day08 工程结构Day08 是在 Day07 的基础上复制并修改得到的新增了一个配置头文件include/config.h工程结构如下day08 ├── Makefile ├── include │ ├── config.h │ ├── debug.h │ ├── fault_code.h │ ├── fault.h │ ├── sensor.h │ ├── system.h │ └── system_type.h ├── src │ ├── fault.c │ ├── main.c │ ├── sensor.c │ └── system.c └── build └── day08_test其中config.h统一管理系统配置参数debug.h调试打印宏fault_code.h故障码定义system.c系统初始化和状态打印sensor.c模拟传感器数据更新fault.c故障判断逻辑Makefile自动化编译、运行和清理。四、什么是魔法数字所谓魔法数字就是直接写在代码里的固定数字。例如if(sys-temperature60.0f)这里的60.0f是什么意思如果不看上下文可能并不清楚它代表过温故障判断阈值再比如sys-voltage9.5f;这里的9.5f表示模拟传感器电压值但是如果没有命名说明代码可读性就比较差。所以魔法数字的问题主要有三个1. 可读性差不知道数字代表什么含义 2. 修改麻烦后期要改参数时需要在多个 .c 文件里查找 3. 容易出错多个位置写同一个参数时可能漏改或改错。因此在工程中更推荐使用有意义的宏名来代替这些数字。五、config.h 的作用config.h是一个配置头文件用来集中管理项目中的关键参数。Day08 中config.h主要管理三类参数1. 系统初始化参数 2. 传感器模拟参数 3. 故障判断阈值。这样做的好处是以后如果要修改电压、电流、温度或故障阈值只需要修改config.h不需要去system.c、sensor.c、fault.c中到处找数字。六、config.h 内容Day08 新增的config.h内容如下#ifndefCONFIG_H#defineCONFIG_H#defineSYS_INIT_LED_STATE0#defineSYS_INIT_VOLTAGE12.5f#defineSYS_INIT_CURRENT1.2f#defineSYS_INIT_TEMPERATURE35.6f#defineSENSOR_SIM_VOLTAGE9.5f#defineSENSOR_SIM_CURRENT2.5f#defineSENSOR_SIM_TEMPERATURE75.0f#defineFAULT_LOW_VOLTAGE_TH10.0f#defineFAULT_OVER_CURRENT_TH2.0f#defineFAULT_OVER_TEMP_TH60.0f#endif这里的参数可以分为三组。七、系统初始值宏第一组是系统初始值#defineSYS_INIT_LED_STATE0#defineSYS_INIT_VOLTAGE12.5f#defineSYS_INIT_CURRENT1.2f#defineSYS_INIT_TEMPERATURE35.6f这些宏用于system_init()函数。原来代码中直接写sys-led_state0;sys-voltage12.5f;sys-current1.2f;sys-temperature35.6f;修改后变成sys-led_stateSYS_INIT_LED_STATE;sys-voltageSYS_INIT_VOLTAGE;sys-currentSYS_INIT_CURRENT;sys-temperatureSYS_INIT_TEMPERATURE;这样一看就知道这些值是系统初始化参数。八、传感器模拟值宏第二组是传感器模拟值#defineSENSOR_SIM_VOLTAGE9.5f#defineSENSOR_SIM_CURRENT2.5f#defineSENSOR_SIM_TEMPERATURE75.0f这些宏用于sensor_update()函数。原来代码中直接写sys-voltage9.5f;sys-current2.5f;sys-temperature75.0f;修改后变成sys-voltageSENSOR_SIM_VOLTAGE;sys-currentSENSOR_SIM_CURRENT;sys-temperatureSENSOR_SIM_TEMPERATURE;这样可以更清楚地看出这些数据是模拟传感器采集值。九、故障判断阈值宏第三组是故障判断阈值#defineFAULT_LOW_VOLTAGE_TH10.0f#defineFAULT_OVER_CURRENT_TH2.0f#defineFAULT_OVER_TEMP_TH60.0f这些宏用于fault_check()函数。原来代码中直接写if(sys-voltage10.0f)if(sys-current2.0f)if(sys-temperature60.0f)修改后变成if(sys-voltageFAULT_LOW_VOLTAGE_TH)if(sys-currentFAULT_OVER_CURRENT_TH)if(sys-temperatureFAULT_OVER_TEMP_TH)这样代码含义更加明确FAULT_LOW_VOLTAGE_TH低电压阈值 FAULT_OVER_CURRENT_TH过电流阈值 FAULT_OVER_TEMP_TH过温阈值十、修改 system.c在system.c中需要包含config.h#includeconfig.h修改后的system_init()函数如下#includestdio.h#includesystem.h#includefault_code.h#includedebug.h#includeconfig.hvoidsystem_init(SystemStatus*sys){sys-led_stateSYS_INIT_LED_STATE;sys-voltageSYS_INIT_VOLTAGE;sys-currentSYS_INIT_CURRENT;sys-temperatureSYS_INIT_TEMPERATURE;sys-fault_codeFAULT_NONE;DEBUG_PRINT(system init done\n);}这里不再直接写0、12.5f、1.2f、35.6f而是使用config.h中定义好的宏。十一、修改 sensor.c在sensor.c中也需要包含config.h#includeconfig.h修改后的sensor_update()函数如下#includesensor.h#includedebug.h#includeconfig.hvoidsensor_update(SystemStatus*sys){sys-voltageSENSOR_SIM_VOLTAGE;sys-currentSENSOR_SIM_CURRENT;sys-temperatureSENSOR_SIM_TEMPERATURE;DEBUG_PRINT(sensor update done\n);}这样传感器模拟值全部来自config.h。十二、修改 fault.c在fault.c中同样需要包含config.h#includeconfig.h修改后的fault_check()函数如下#includefault.h#includefault_code.h#includedebug.h#includeconfig.hvoidfault_check(SystemStatus*sys){sys-fault_codeFAULT_NONE;if(sys-voltageFAULT_LOW_VOLTAGE_TH){sys-fault_code|FAULT_LOW_VOLTAGE;}if(sys-currentFAULT_OVER_CURRENT_TH){sys-fault_code|FAULT_OVER_CURRENT;}if(sys-temperatureFAULT_OVER_TEMP_TH){sys-fault_code|FAULT_OVER_TEMP;}DEBUG_PRINT(fault check done\n);}这里的判断逻辑没有变化只是把数字换成了更有意义的宏。十三、编译与运行进入 Day08 目录cd/root/Embedded_14Days/day08清理旧编译产物makeclean编译make运行makerun运行结果如下[DEBUG]system initdone[DEBUG]sensor updatedone[DEBUG]fault checkdoneLED state:0Voltage:9.50V Current:2.50A temperature:75.00C Fault code: 0x0007 Fault: Low voltage Fault: Over current Fault: Over temperature说明修改后程序仍然正常运行。当前模拟数据为Voltage 9.50 V Current 2.50 A temperature 75.00 C故障判断阈值为低电压阈值10.0 V 过电流阈值2.0 A 过温阈值60.0 C所以会同时触发低电压故障 过电流故障 过温故障故障码为0x0007也就是0x0001 | 0x0002 | 0x0004 0x0007十四、修改阈值验证 config.h 是否生效为了验证config.h是否真正生效将过温阈值临时从60.0f改成80.0f。原来是#defineFAULT_OVER_TEMP_TH60.0f临时改成#defineFAULT_OVER_TEMP_TH80.0f当前模拟温度是#defineSENSOR_SIM_TEMPERATURE75.0f此时75.0 80.0所以不再触发过温故障。重新执行makecleanmakemakerun运行结果变为[DEBUG]system initdone[DEBUG]sensor updatedone[DEBUG]fault checkdoneLED state:0Voltage:9.50V Current:2.50A temperature:75.00C Fault code: 0x0003 Fault: Low voltage Fault: Over current可以看到不再输出Fault: Over temperature故障码也从0x0007变成了0x0003原因是现在只剩低电压0x0001 过电流0x0002 0x0001 | 0x0002 0x0003这说明修改config.h中的配置参数确实会影响程序运行行为。验证完成后需要将阈值恢复为#defineFAULT_OVER_TEMP_TH60.0f十五、Makefile 目标修改因为 Day08 是从 Day07 复制过来的所以需要将 Makefile 中的目标文件名改成 Day08 对应名称TARGET build/day08_test这样运行时生成的可执行文件就是build/day08_test而不是 Day07 的day07_test。十六、Day07 和 Day08 的区别Day07 主要解决的是调试日志开关问题通过 debug.h 定义 DEBUG_PRINT 通过 Makefile 的 -DDEBUG 控制调试打印是否输出Day08 主要解决的是参数集中管理问题通过 config.h 统一管理系统初始值、传感器模拟值和故障判断阈值也就是说Day07解决调试日志是否输出的问题 Day08解决关键参数写死在代码里的问题这两步都是工程化开发中的重要习惯。十七、遇到的问题和解决方法1. 修改错目录一开始把 Day08 的代码改到了 Day07 目录中例如day07/src/system.c day07/src/sensor.c day07/src/fault.c但今天实际应该修改的是day08/src/system.c day08/src/sensor.c day08/src/fault.c解决方法是将改好的内容复制到 Day08然后恢复 Day07。这个问题说明每天新建工程目录后修改文件前一定要确认当前文件路径。2. 宏名拼写错误在system.c中曾经把SYS_INIT_LED_STATE误写成SYS_INIR_LED_STATE编译时报错error: ‘SYS_INIR_LED_STATE’ undeclared did you mean ‘SYS_INIT_LED_STATE’?这个错误说明宏名必须和config.h中定义的名字完全一致。最终改成sys-led_stateSYS_INIT_LED_STATE;3. 阈值宏拼写错误在config.h中曾经把FAULT_LOW_VOLTAGE_TH误写成了类似FAULT_LOW_VPLTAGE_TH这种拼写错误会导致fault.c中找不到对应宏。解决方法是统一检查宏名保证定义和使用完全一致。十八、今日总结通过 Day08 的学习主要掌握了以下内容理解了什么是魔法数字理解了魔法数字会降低代码可读性和可维护性学会了使用config.h统一管理工程配置参数将系统初始值从system.c中提取到config.h将传感器模拟值从sensor.c中提取到config.h将故障判断阈值从fault.c中提取到config.h验证了修改config.h后程序行为会随之变化进一步理解了嵌入式工程中的参数集中管理思想。Day08 的核心可以总结为一句话不要把关键参数直接写死在 .c 文件里 应该通过 config.h 统一管理系统配置和判断阈值。这一步虽然代码变化不复杂但对后续嵌入式工程开发非常重要。随着项目越来越大统一配置管理可以明显提高代码的可读性、可维护性和扩展性。十九、项目源码本次 Day08 学习代码将上传至 GitHubhttps://github.com/jdai10590-afk/Embedded-C-Learning-Projects/tree/main/day08