基于TraeSolo的物联网放风机

1.摘要:

使用trae solo,排查代码,并按照给出的建议进行代码优化,代码评分由35分,优化到80分

2.背景:

我是一名STM32的开发工程师,原本程序能够正常,运行,但是由于理解不到位出现了很多隐患和代码不清晰的地方,现在使用traesolo,进行代码的评分和优化,实现了代码的优化,将本来1周左右的工作缩短到1-2天即可完成,大大提高了效率

3.实践过程

通读代码,给出项目分析及结构

然后让solo给出代码评分

并给出优化建议和步骤

按照优化步骤进行优化

优化后再次给出评分

然后让solo持续优化,评分不低于80分

项目分析如下

# ProCubeZsce04_dalindun 代码分析与优化建议

## 1. 项目概述

**项目名称**: ProCubeZsce04_dalindun (智能放风机控制器)

**硬件平台**: STM32F103RBTx (ARM Cortex-M3, 64MHz)

**软件平台**: STM32CubeIDE + FreeRTOS (协作式调度, configUSE_PREEMPTION=0)

**版本**: V2.08 (2025-10-15)

-–

## 2. 系统架构

### 2.1 硬件层次

```

┌─────────────────────────────────────────────────────────────┐

│ STM32F103RBTx │

├─────────────────────────────────────────────────────────────┤

│ USART1 (4G模块EC600N) │ USART2 (调试串口) │

│ I2C1 (AT24C02 EEPROM) │ TIM1 (行程计数) │

│ GPIO (按键/LED/继电器) │ IWDG (看门狗) │

└─────────────────────────────────────────────────────────────┘

```

### 2.2 软件层次

```

┌─────────────────────────────────────────────────────────────┐

│ 应用层 (Application) │

│ my_zsce_fun.c | my_motor.c | ec600n.c | my_key.c │

├─────────────────────────────────────────────────────────────┤

│ 驱动层 (HAL Drivers) │

│ usart.c | i2c.c | gpio.c | tim.c | rtc.c │

├─────────────────────────────────────────────────────────────┤

│ 硬件抽象层 (CMSIS/HAL) │

├─────────────────────────────────────────────────────────────┤

│ FreeRTOS Kernel │

└─────────────────────────────────────────────────────────────┘

```

-–

## 3. 业务流程

### 3.1 系统启动流程

```

main()

├─ HAL_Init()

├─ SystemClock_Config() // 64MHz PLL

├─ MX_GPIO_Init()

├─ MX_I2C1_Init()

├─ MX_IWDG_Init()

├─ MX_RTC_Init()

├─ MX_USART1_UART_Init() // 4G模块

├─ MX_USART2_UART_Init() // 调试串口

├─ MX_TIM1_Init()

├─ fun_init() // 用户初始化

│ ├─ fun_ring_off()

│ ├─ fun_ec600n_init() // 4G模块初始化

│ ├─ fun_led_link_on_off(0)

│ ├─ fun_load_para() // 从AT24C02加载参数

│ ├─ fun_load_user_cs() // 加载用户策略

│ ├─ fun_sth_power_on() // 温湿度传感器上电

│ ├─ fun_motor_init() // 电机初始化

│ └─ Init_DSLED() // 数码管初始化

├─ MX_FREERTOS_Init()

└─ osKernelStart() // 启动RTOS调度

```

### 3.2 任务调度 (协作式, 10ms轮转)

```

┌─────────────────────────────────────────────────────────────┐

│ FreeRTOS Tasks │

├─────────────────────────────────────────────────────────────┤

│ defaultTask (256栈) │ StartDefaultTask → fun_main_loop │

│ EC600Task (640栈) │ vEC600Task → fun_e600_loop │

│ pingShowTask (256栈) │ vPingShowTask → fun_show_loop │

│ keepTask (128栈, idle)│ KeepTask → 监控/重启崩溃线程 │

└─────────────────────────────────────────────────────────────┘

```

### 3.3 各任务核心逻辑

#### defaultTask → fun_main_loop() [1s周期]

```c

void fun_main_loop() {

// 1. MCU运行指示灯 (1s翻转)

fun_mcu_run();



// 2. 4G连接超时检测

if (fun_out_time_change_to_auto()) {

    s_status.get_conn = 0;

    fun_led_link_on_off(LED_OFF);

}



// 3. 行程计数保存 (每5秒)

fun_counter_save();



// 4. 温湿度采集 (每2秒)

get_dsp_temp_humi(&s_status);



// 5. 自动控制 (每5秒)

auto_control();



// 6. 行程传感器扫描 (每100ms, 位点模式)

if (md_mode == MD_AC_POINT || MD_DC_POINT) {

    fun_ac_loop();

    incounter_err_fuc();

    fun_e03_loop();

}



// 7. 状态更新

update_status(&s_status);



// 8. 电机控制

fun_loop_start();

fun_tim_stop();



// 9. 按键处理

fun_key_loop();



// 10. 喂狗

fun_watchdog_fresh();

}

```

#### EC600Task → fun_e600_loop() [1s周期]

```c

void fun_e600_loop() {

// 1. 4G模块拨号/连接

if (flag_ec600 == 1) {

    ec600n_start();

    connect_server(&s_uart_1);

    http_get_para();

    fun_4g_alive();

}



// 2. 串口数据处理

fun_uart_rec_treate();



// 3. 告警检测与上报

if (is_connect_server()) {

    if (flag_getconfig && flag_getusercs) {

        fun_alarm(s_status.f_temp, s_status.f_humi);

        send_alarm();

        send_current_to_server();

        send_version_to_server();

    }

}

}

```

#### pingShowTask → fun_show_loop() [500ms周期]

```c

void fun_show_loop() {

// 1. 版本号显示 (首次)

if (show_first == 0) {

    fun_show_num(HARDWARE_VER\*100 + SOFTWARE_VER);

    show_first = 1;

}



// 2. 主显示刷新 (每500ms)

fun_show_main();



// 3. LED状态指示

// - 电机正转: LED_SWA 500ms闪烁

// - 电机反转: LED_SWA 100ms闪烁

// - 电机停止: LED_SWA 常亮/常灭 (根据模式)

fun_led_mode(s_status.flag_SMODE == 0 ? 1 : 0);

fun_led_humi(...);

}

```

### 3.4 温湿度自动控制 (auto_control)

#### 控制策略匹配

```

时间窗口匹配 → 找到对应用户策略 → single_user_cs_control()

策略类型:

├─ AUTO_CONTROL_FORCE (mode=0) 强制控制 (直接设置开口CM)

└─ AUTO_CONTROL_WENDU (mode=1) 范围控制 (温度区间控制)

```

#### 温度控制逻辑 (范围控制)

```

温度 < (下限-0.5°C) → fun_close_all() 全关

温度 在[下限±0.5°C] → fun_open_hold() 保持搭边

温度 在[中心±AUTO_WENDU] → fun_close_step() / fun_open_step() 步进

温度 > 上限 → fun_open_step() 步进打开

```

### 3.5 4G通信流程 (EC600N模块)

```

连接服务器步骤:

1. AT+CSQ 获取信号强度

2. AT+QCCID 获取SIM卡号

3. AT+QIFGCNT 配置前置端口

4. AT+QIMODE 透传模式

5. AT+QITCFG 数据格式

6. AT+QIOPEN 连接TCP服务器

7. 发送LOGIN指令 登录认证

```

-–

## 4. 代码结构分析

### 4.1 核心文件

| 文件 | 职责 | 规模 |

|------|------|------|

| my_zsce_fun.c | 主业务逻辑: 参数加载/存储, 自动控制, 告警 | ~2600行 |

| my_motor.c | 电机驱动: 正转/反转/停止, 行程计数, 位点控制 | ~970行 |

| ec600n.c | 4G模块通信: AT指令, TCP连接, 透传数据处理 | ~1400行 |

| my_key.c | 按键处理: 模式切换, 参数设置, 电机控制 | ~1050行 |

| STH3x.c | 温湿度传感器驱动: SHT3x I2C通信 | ~330行 |

| DSLED.c | 数码管显示驱动: TM1629控制 | ~680行 |

| my_uart.c | 串口封装: 接收/发送/命令解析 | ~490行 |

| file_at24c_rw.c | AT24C02 EEPROM读写 | ~94行 |

### 4.2 关键数据结构

```c

// 设备参数 (存储于AT24C02)

struct_device {

u8  store_sn;           // 设备序号

u8  smartCover;         // 压膜宽度 (搭边距离)

u16 smartScopeLimitUp;  // 行程上限 (CM)

u8  smartGear;          // 钢管档位 (1/2/3)

u8  control_mode;       // 0=自动, 1=手动

u8  emergency_enable;    // 应急控制使能

u8  emergency_low/high;  // 应急温度阈值

u8  auto_cm;            // 每次步进开口 (CM)

u8  auto_stop_time;     // 开风口间隔 (秒)

u8  auto_stop_time_close; // 关风口间隔 (秒)

u8  baoliu_start/stop;  // 保留风口时间段

...

};

// 用户控制策略 (最多12条)

struct_user_cs {

u16 start_time;         // 启动时间 (HHMM)

u16 end_time;           // 结束时间 (HHMM)

u8  control_mode_enable; // bit7\~4使能, bit3\~0控制模式

u16 range_low_or_scope; // 强制:开口CM / 范围:下限温度

u16 range_high;         // 上限温度

u8  run_time;           // 运行时长

u8  stop_time;          // 间隔时间

};

// 系统状态

struct_status {

int  f_temp;           // 温度值 (放大10倍)

u16  f_humi;           // 湿度值 (放大10倍)

short data_cm;          // 当前行程 (圈数)

u8   status;           // 状态字节 (电机方向+传感器状态)

u8   direction;        // 1=正转, 2=反转, 3=停止

u8   flag_SMODE;       // 0=远程模式, 1=本地模式

u32  time_stop;        // 停止时刻

u32  time_server_connect; // 服务器心跳

...

};

// 电机控制

struct_control {

u8  control_mode;      // 0=网络, 1=按键

u8  control_flag;      // 0=停止, 1=启动

u16 control_cm;        // 目标位置 (圈数)

u8  flag_process;      // 处理标志

};

```

### 4.3 通信协议

```

AT24C02地址映射 (0x00~0xFF, 256字节):

├─ 0x00~0x08: 网关ID/出厂日期

├─ 0x09: 设备序号

├─ 0x0A~0x10: 压膜宽度/档位/行程/温湿度校准

├─ 0x11: 自动/手动模式

├─ 0x12~0x22: 应急控制/风口保持参数

├─ 0x24~0x79: 用户策略存储 (12条x6字节)

└─ 0x9D~: 历史数据

串口协议 (RS485):

帧格式: [网关ID(5B)] [长度] [命令] [数据] [CRC16高] [CRC16低]

命令: 0x01=读出厂, 0x03=读状态, 0x04=电机控制, 0x05=参数设置

```

-–

## 5. 优化建议

### 5.1 内存与栈溢出风险 [高优先级]

**问题**: 多处代码在中断或临界区使用大数组

```c

// ec600n.c:1404

char c_send[500] = { 0 }; // 栈上分配500字节

// my_zsce_fun.c:730

u8 cmd01_data[50] = { 0 }; // 频繁分配

```

**建议**: 将大数组改为static或全局变量,避免栈溢出

### 5.2 I2C EEPROM写入延迟阻塞 [中优先级]

**问题**: `file_at24c_rw.c:54`使用阻塞式HAL_Delay(10)

```c

void AT24CXX_Write(…) {

HAL_I2C_Mem_Write(...);

HAL_Delay(10);  // 阻塞10ms!

}

```

**建议**: 改用DMA+中断方式,或至少使用osDelay替代HAL_Delay避免阻塞RTOS调度

### 5.3 魔法数字与硬编码 [中优先级]

**问题**: 代码中大量未定义的魔法数字

```c

// my_motor.c:624

if ((HAL_GetTick() - tick_fd) >= E03_OUT_TIMES*1000) // E03_OUT_TIMES=30

// my_zsce_fun.c:1800

limit1 = low - 5; // 为什么是5度?

// my_key.c:895

if ((HAL_GetTick() - s_key_mode.tick_pressed) >= 1000) // 长按1秒

```

**建议**: 统一宏定义, 避免重复计算

```c

#define AUTO_WENDU_RANGE 5 // 已在my_struct.h定义

#define KEY_LONG_PRESS_MS 1000

#define E03_TIMEOUT_SEC 30

```

### 5.4 重复代码片段 [中优先级]

**问题**: `extract_num_from_str`与`extract_num_from_str_line`逻辑高度相似

```c

// my_tools.c:262 vs 342

u8 extract_num_from_str(…) {

// 大约80行相似逻辑

}

u8 extract_num_from_str_line(…) {

// 几乎完全相同的80行

}

```

**建议**: 提取公共函数,添加参数区分

### 5.5 sprintf/float格式化开销 [中优先级]

**问题**: 嵌入式环境下sprintf和float运算开销大

```c

// ec600n.c:1151

sprintf(arr_value, “%.1f”, alarm_value / 10.0f); // float除法+格式化

```

**建议**: 使用整数运算替代

```c

sprintf(arr_value, “%d.%d”, alarm_value/10, alarm_value%10);

```

### 5.6 冗余的HAL_Delay调用 [低优先级]

**问题**: `my_motor.c`中多处使用osDelay(1000)进行电机延时

```c

// my_motor.c:499

osDelay(2000); // 电机停止后等待2秒

```

**建议**: 考虑使用状态机替代阻塞延时,提高响应性

### 5.7 中断与临界区处理 [低优先级]

**问题**: `my_uart.c:390`在UART中断中禁用全局中断

```c

void fun_usart_treate(…) {

if (s_uart->flag_rec == 1) {

    HAL_NVIC_DisableIRQ(USART2_IRQn);  // 禁用所有中断!

    ...

    HAL_NVIC_EnableIRQ(USART2_IRQn);

}

}

```

**建议**: 使用RTOS临界区或仅禁用特定UART中断

### 5.8 调试输出未统一管理 [低优先级]

**问题**: printf分散在多处,debug_show标志冗余

```c

extern u8 debug_show; // 在多个文件中重复声明

if (debug_show == 1) {

printf(...);

}

```

**建议**: 统一调试级别宏定义

```c

#define DEBUG_LEVEL 0 // 0=关闭, 1=错误, 2=Info, 3=Debug

#define debug_printf(level, fmt, …) do { if(level <= DEBUG_LEVEL) printf(fmt, ##_VA_ARGS_); } while(0)

```

### 5.9 看门狗喂狗分布不合理 [低优先级]

**问题**: 喂狗代码分散在每个任务的循环中,每10ms一次

```c

// freertos.c:178,198,218,264

fun_watchdog_fresh(); // 在每个任务中调用

```

**建议**: 考虑在看门狗硬件定时器中断中统一喂狗,或减少喂狗频率

### 5.10 代码注释语言不一致 [低优先级]

**问题**: 注释中英文混杂

```c

// 出厂信息的回复

// response 01 command

// 回应07命令

```

**建议**: 统一为英文或中文

-–

## 6. 已知问题与局限

1. **协作式调度限制**: 所有任务必须主动osDelay(10)让出CPU,长时间阻塞操作会饿死其他任务

2. **浮点数依赖**: 代码中多处使用float进行温度/湿度计算,STM32F1无FPU,效率较低

3. **栈空间紧张**: EC600Task 640字节栈在4G通信处理时可能接近上限

4. **缺乏OTA**: 固件更新依赖外部工具

5. **RTC精度**: 使用外部32.768kHz晶振,误差约±2分钟/天

-–

## 7. 测试建议

1. **边界测试**: 温度-45°C~125°C, 行程0~999cm

2. **通信超时**: 4G模块断网后60秒自动切应急控制

3. **电机堵转**: E03告警触发(30秒无位点变化)

4. **掉电恢复**: EEPROM参数正确加载, 行程数据不丢失

5. **并发测试**: 4G数据和按键同时操作的响应

1 个赞