一、代码功能概述 ( ̄▽ ̄)ゞ
核心功能
- 温度采集:输入3位数字+小数点表示温度(如2.57°C)
- 数据显示:显示当前温度值
- 参数设置:设置温度上下限(10°C~70°C)
- LED PWM控制:根据温度范围调整LED亮度(3档)
- 长按支持:S14/S15支持短按和长按调整参数
三种显示模式
┌──────┬──────────────┬────────────────────────────┐
│ 模式 │ 功能 │ 显示格式 │
├──────┼──────────────┼────────────────────────────┤
│ 0 │ 温度采集界面 │ A–XXX(输入3位+小数点) │
├──────┼──────────────┼────────────────────────────┤
│ 1 │ 数据显示界面 │ C—XX(显示温度整数部分) │
├──────┼──────────────┼────────────────────────────┤
│ 2 │ 参数设置界面 │ P-XXYY(上限XX,下限YY) │
└──────┴──────────────┴────────────────────────────┘
二、需要注意的问题与解决方案 ![]()
问题1:长按检测代码重复 ![]()
问题代码:
// S14的长按检测(第51-74行)
if(Seg_Disp_Mode == 2)
{
if(Key_Down == 14)
Time_Flag = 1;
}
if(Count_500Ms < 500) // 短按
{
if(Key_Up == 14)
{
Time_Flag = Count_500Ms = 0;
if(++Parameter[Parameter_Index] > 70)
Parameter[Parameter_Index] = 10;
}
}
else // 长按
{
if(Key_Old == 14)
{
if(++Parameter[Parameter_Index] > 70)
Parameter[Parameter_Index] = 10;
}
if(Key_Up == 14)
Time_Flag = Count_500Ms = 0;
}
// S15的长按检测(第77-100行)
// 几乎完全相同的代码!
问题分析:
- S14和S15的长按检测代码几乎完全重复
- 代码冗余,不利于维护
- 如果要修改逻辑,需要改两处
改进方案:
// ✓ 封装成函数
void Handle_Long_Press(unsigned char key_code, char increment)
{
if(Seg_Disp_Mode != 2) return; // 只在参数设置界面有效
// 按下时启动计时
if(Key_Down == key_code)
Time_Flag = 1;
// 短按处理
if(Count_500Ms < 500)
{
if(Key_Up == key_code)
{
Time_Flag = Count_500Ms = 0;
Parameter[Parameter_Index] += increment;
if(Parameter[Parameter_Index] > 70 || Parameter[Parameter_Index] < 10)
Parameter[Parameter_Index] = (increment > 0) ? 10 : 70;
}
}
// 长按处理
else
{
if(Key_Old == key_code)
{
Parameter[Parameter_Index] += increment;
if(Parameter[Parameter_Index] > 70 || Parameter[Parameter_Index] < 10)
Parameter[Parameter_Index] = (increment > 0) ? 10 : 70;
}
if(Key_Up == key_code)
Time_Flag = Count_500Ms = 0;
}
}
// 使用时
Handle_Long_Press(14, 1); // S14:参数+1
Handle_Long_Press(15, -1); // S15:参数-1
问题2:复杂的位运算表达式 ![]()
问题代码:
// 第247行
ucLed[1] = (!((int)Temperature / Parameter_Ctrol[0])) & ((int)Temperature / Parameter_Ctrol[1]);
问题分析:
- 表达式过于复杂,难以理解
- 使用了多重类型转换和位运算
- 可读性极差
表达式含义:
Temperature < Parameter_Ctrol[0] 且 Temperature >= Parameter_Ctrol[1]
即:温度在下限和上限之间时,LED1点亮
改进方案:
// ✓ 方法1:拆分成清晰的逻辑
unsigned char is_below_upper = (Temperature < Parameter_Ctrol[0]);
unsigned char is_above_lower = (Temperature >= Parameter_Ctrol[1]);
ucLed[1] = is_below_upper && is_above_lower;
// ✓ 方法2:直接用条件判断
if(Temperature < Parameter_Ctrol[0] && Temperature >= Parameter_Ctrol[1])
ucLed[1] = 1;
else
ucLed[1] = 0;
// ✓ 方法3:三元运算符
ucLed[1] = (Temperature < Parameter_Ctrol[0] && Temperature >= Parameter_Ctrol[1]) ? 1 : 0;
问题3:除零风险 ![]()
![]()
问题代码:
// 第246-248行
ucLed[0] = (int)Temperature / Parameter_Ctrol[0];
ucLed[1] = (!((int)Temperature / Parameter_Ctrol[0])) & ((int)Temperature / Parameter_Ctrol[1]);
ucLed[2] = !((int)Temperature / Parameter_Ctrol[1]);
风险分析:
- 如果Parameter_Ctrol[0]或Parameter_Ctrol[1]为0,会导致除零错误
- 虽然初始值是30和20,但如果代码有BUG导致参数被错误修改,就会崩溃
可能导致除零的场景:
场景1:参数设置时出现BUG
→ Parameter[0]或Parameter[1]被设为0
→ 保存到Parameter_Ctrol时,值为0
→ 除零崩溃!
场景2:内存被意外修改
→ 野指针或数组越界
→ Parameter_Ctrol被改为0
→ 除零崩溃!
改进方案:
// ✓ 添加除零保护
void Led_Proc()
{
// 参数有效性检查
if(Parameter_Ctrol[0] == 0) Parameter_Ctrol[0] = 30;
if(Parameter_Ctrol[1] == 0) Parameter_Ctrol[1] = 20;
// LED亮度控制
if(Temperature > Parameter_Ctrol[0])
Led_Pwm = 3;
else if(Temperature < Parameter_Ctrol[0] && Temperature > Parameter_Ctrol[1])
Led_Pwm = 6;
else
Led_Pwm = 9;
// LED状态控制(添加除零保护)
ucLed[0] = (Parameter_Ctrol[0] > 0) ? ((int)Temperature / Parameter_Ctrol[0]) : 0;
ucLed[1] = (Temperature < Parameter_Ctrol[0] && Temperature >= Parameter_Ctrol[1]) ? 1 : 0;
ucLed[2] = (Parameter_Ctrol[1] > 0) ? (!((int)Temperature / Parameter_Ctrol[1])) : 0;
ucLed[3] = Error_Flag;
}
问题4:参数边界判断不完整 ![]()
问题代码:
// 第168行
if(Parameter[0] >= Parameter[1] && Parameter[0] <= 70 && Parameter[1] >= 10)
{
Error_Flag = 0;
Parameter_Ctrol[0] = Parameter[0];
Parameter_Ctrol[1] = Parameter[1];
}
else
Error_Flag = 1;
问题分析:
- 只检查了Parameter[0] <= 70和Parameter[1] >= 10
- 没有检查Parameter[0] >= 10(上限可能小于10)
- 没有检查Parameter[1] <= 70(下限可能大于70)
可能的问题场景:
场景1:上限设为5°C
→ Parameter[0] = 5
→ 5 >= 20(下限)? 否
→ Error_Flag = 1 ✓(正确拒绝)
场景2:下限设为75°C
→ Parameter[1] = 75
→ 30 >= 75? 否
→ Error_Flag = 1 ✓(正确拒绝)
但是:如果上限是8°C,下限是5°C
→ 8 >= 5 ✓, 8 <= 70 ✓, 5 >= 10 ✗
→ Error_Flag = 1 ✓(正确拒绝)
看起来逻辑是对的,但不够清晰
改进方案:
// ✓ 更清晰的边界检查
if(Parameter[0] >= 10 && Parameter[0] <= 70 && // 上限范围检查
Parameter[1] >= 10 && Parameter[1] <= 70 && // 下限范围检查
Parameter[0] >= Parameter[1]) // 上限≥下限
{
Error_Flag = 0;
Parameter_Ctrol[0] = Parameter[0];
Parameter_Ctrol[1] = Parameter[1];
}
else
{
Error_Flag = 1;
}
问题5:长按时参数调整速度问题 ![]()
问题代码:
// 第67-71行
if(Key_Old == 14) // S14长按
{
if(++Parameter[Parameter_Index] > 70)
Parameter[Parameter_Index] = 10;
}
问题分析:
- 长按时,每10ms(按键扫描周期)就会执行一次参数加1
- 调整速度太快,用户难以精确控制
- 从10调到70需要60次,按住0.6秒就完成了
改进方案:
// ✓ 方法1:添加长按减速
static unsigned char long_press_slow_down = 0;
if(Key_Old == 14)
{
if(++long_press_slow_down >= 10) // 每100ms调整一次
{
long_press_slow_down = 0;
if(++Parameter[Parameter_Index] > 70)
Parameter[Parameter_Index] = 10;
}
}
else
{
long_press_slow_down = 0; // 松开时复位
}
// ✓ 方法2:根据长按时间加速
if(Key_Old == 14)
{
if(Count_500Ms < 1000) // 前1秒:慢速
{
if(++long_press_slow_down >= 10)
{
long_press_slow_down = 0;
Parameter[Parameter_Index]++;
}
}
else // 1秒后:快速
{
if(++long_press_slow_down >= 3)
{
long_press_slow_down = 0;
Parameter[Parameter_Index]++;
}
}
if(Parameter[Parameter_Index] > 70)
Parameter[Parameter_Index] = 10;
}
问题6:注释掉的代码 ![]()
问题代码:
// 第182-195行
//\t\tcase 14://参数+1
//\t\t\tif(Seg_Disp_Mode == 2)//处于参数设置界面
//\t\t\t{
//\t\t\t\tif(++Parameter[Parameter_Index] > 70)//超过上限值
//\t\t\t\t\tParameter[Parameter_Index] = 10;
//\t\t\t}
//\t\tbreak;
问题分析:
- 注释掉的代码说明这是旧版本的实现
- 新版本改用了长按检测(第51-100行)
- 但注释掉的代码没有删除,影响代码整洁度
建议:
// ✓ 删除注释掉的代码
// 如果需要保留历史记录,使用版本控制系统(Git)
// 不要在代码中保留大段注释掉的代码
三、代码优点 ✓
本小姐要表扬一下这个代码的优点!( ̄▽ ̄*)
- 编码正确:使用UTF-8编码,注释正常显示
- 长按支持:实现了短按和长按功能,用户体验好
- PWM调光:LED亮度分3档,根据温度自动调整
- 参数验证:切换界面时会验证参数合理性
- 代码优化:第239行注释掉的复杂表达式被简化了
- 边界检查:第45行正确判断了数组索引范围
四、改进建议总结 o( ̄▽ ̄)d
优先级1(必须修复)
- 添加除零保护:防止Parameter_Ctrol为0导致崩溃
- 封装长按检测:消除代码重复
优先级2(强烈建议)
- 简化位运算表达式:提高可读性
- 添加长按减速:改善用户体验
- 完善边界检查:使参数验证逻辑更清晰
优先级3(建议)
- 删除注释代码:保持代码整洁
- 添加宏定义:替换魔法数字
五、完整改进示例 (* ̄︶ ̄)
// 添加宏定义
#define TEMP_MIN 10
#define TEMP_MAX 70
#define TEMP_UPPER_DEFAULT 30
#define TEMP_LOWER_DEFAULT 20
#define LED_PWM_HIGH 3 // 高温:暗
#define LED_PWM_MID 6 // 中温:中
#define LED_PWM_LOW 9 // 低温:亮
// 改进的LED处理函数
void Led_Proc()
{
// 参数有效性检查(防止除零)
if(Parameter_Ctrol[0] == 0) Parameter_Ctrol[0] = TEMP_UPPER_DEFAULT;
if(Parameter_Ctrol[1] == 0) Parameter_Ctrol[1] = TEMP_LOWER_DEFAULT;
// LED亮度控制(清晰的逻辑)
if(Temperature > Parameter_Ctrol[0])
Led_Pwm = LED_PWM_HIGH;
else if(Temperature > Parameter_Ctrol[1])
Led_Pwm = LED_PWM_MID;
else
Led_Pwm = LED_PWM_LOW;
// LED状态控制(清晰的逻辑)
ucLed[0] = (Temperature > Parameter_Ctrol[0]) ? 1 : 0;
ucLed[1] = (Temperature <= Parameter_Ctrol[0] && Temperature > Parameter_Ctrol[1]) ? 1 : 0;
ucLed[2] = (Temperature <= Parameter_Ctrol[1]) ? 1 : 0;
ucLed[3] = Error_Flag;
}
// 改进的参数验证
if(Parameter[0] >= TEMP_MIN && Parameter[0] <= TEMP_MAX &&
Parameter[1] >= TEMP_MIN && Parameter[1] <= TEMP_MAX &&
Parameter[0] >= Parameter[1])
{
Error_Flag = 0;
Parameter_Ctrol[0] = Parameter[0];
Parameter_Ctrol[1] = Parameter[1];
}
else
{
Error_Flag = 1;
}