数码之家

 找回密码
 立即注册

QQ登录

只需一步,快速开始

微信登录

微信扫一扫,快速登录

搜索
查看: 79|回复: 3

[工仪] 一个老快克(963)焊台的重生

[复制链接]
发表于 昨天 21:39 | 显示全部楼层 |阅读模式
今天是2025年9月3日,在纪念中国人民抗日战争暨世界反法西斯战争胜利80周年之际,

匆匆一帖,缅怀先烈,开创未来!
本帖分为五部分:

一、自己搞坏的QUICK963主机;
二、用过的手柄;
三、QUICK963主机原理;
四、鉴赏一下KD-931型恒温电烙铁;

五、弄个程序“复活”963。


一、历史长河中快克的QUICK963焊台
快克智能装备股份有限公司是1993年创立的,QUICK963焊台应该是2006年的产品,当时的智能精密焊接设备。

这个老家伙跟随了我十几年了,期间磕碰、摔落、手柄坏等,几经修理,主机的外壳也裂了,不敢拆动。由于表面的类肤涂层老化,特别是到了夏天,根本不能徒手搬动,搬完就会后悔(手上黑的),终于,去(2024)年它又不好好工作了,现象是开机就显示五六百度慢慢下降,不加热,要等到下降到设置温度才加热,之后也能正常使用。就是每次开机比较烦人,某一天忍不住了,对其下手。
机子前后面

从后面拆开。

前面板拆开,记录接线情况。

机器是2007年7月的,变压器比较大。

主板正面:
是QUICK968的型号,版本是1.1,日期是2005年11月3日。

主板背面:
贴了一个标签,968版本1.53,真乱啊。

主要接口:

主机手柄接口和手柄插头:

维修也是很简单,考虑到使用的年限太久,又是需要开机很长时间(预热)才能正常使用,
首当其冲的是检查电容,

果然是电容容量下降,10uF的电容有的只剩下6uF了,
找出新的10uF电容,测一下容量,很足:

全部更换10uF电容后的主板,
注意电容C5,原机是正负极装反了的,

至此,焊台工作正常了。
不出意外的话就要出意外了,
既然拆开了,就测量一下,同时想备份一下单片机的程序。
根据电路板,抄了下电路:

先测量一下加热的同步情况
CH1测量交流电同步采样,CH2测量单片机送出的加热信号

图中可见:
同步采样是有正负的,单片机内应该使用的是脉冲沿触发加热信号的。
加热信号会在脉冲沿后延时产生,延时大约1毫秒。
当达到设定温度后,单片机的1脚间歇输出加热信号。

再看一下,发热体两端的电压及可控硅Q1的导通情况:
CH1测量发热体两端电压,CH2测量可控硅的导通,

从上图对应时间关系可见,当加热时,
可控硅的导通是滞交流电过零点1毫秒的。
当达到设定温度后的波形如下:

发热体两端只有间歇的半波进行加热了。
发热体两端的电压及可控硅的导通各种情况如下图:

悲剧就是发生在想备份一下单片内的程序,
由于不慎,JP4的接口接错线序,片机挂了。
随后联系了快克智能装备股份有限公司,本想要一个程序,自己换一个MCU刷程序进去,但QUICK公司说机子太老了,要寄回公司进行维修。
当机子到了公司几天后,说无法维修,可以考虑补差价换个其它型号的。
当然是好事,但我还是选择了原物寄回来,留个情怀吧。



二、这个焊台使用过的手柄
QUICK963原装的手柄很难买到,所以其坏了后就换用了968的手柄了,
十几年用了三个手柄。

原装的手柄是因为摔过后,热耦故障,
稍不注意,烙铁头就加热到暗红。
当时可以在网上找到,但价格离谱,就换了968的手柄,
两种手柄结构不一样的。

先看看原装的手柄:

内部看似很简单。

玄机是在保护套上的。

手柄的基本情况如下:

保护套上面有一根外置的热电耦,

这个热电耦的顶部是通过保护套顶部的小孔,
直接接触到加热头上的,如下图:

热耦的连接则是通过保护套上的触点,
与手柄上的弹簧触点相接触,进而连接到手柄电路板上的。
如下图

手柄电路板上除了完成线路转接,还有一个振动传感器。

这个原装的手柄使用的是外置热耦采样,
其弊端是:采样不准确,热耦容易因意外磕碰而故障。
而QUICK907F的手柄则使用的是内置热耦采样。

拆开头部

拆下手柄套后:

发热体与热耦的布局:

电路板背面

加热线与热耦线的连接:

下图可见,加热体是中空的,热耦从中间穿出,顶在烙铁头上,
陶瓷发热芯可以看清其回路,

这种结构的优点是:采样更准确。
缺点是:热耦容易在陶瓷发热处烧断,乃至粘连在陶瓷发热芯中间的孔内。
我曾有一个热耦烧断在发热芯内,新的热耦穿不进去,只能两个同时更换。



三、QUICK963焊台主机原理
电路也比较简单,是以ATMEGA8L为核心的,
分为电源、显示、基准电源、按键、热采样放大、输出驱动、交流同步采样几部分:

(一)电源及基准电源
JP1是电源接口,有两组交流电源:30V和8V。
30V是供加热用的,8V是供主板用的。
交流8V经过D8和D9进行半波整流,输出正负两组电压,
正电压经过U3稳压到5V供MCU和基准电源用,
负电压经过Z2稳压,供运放U6使用。
基准电源是由U4(TL431)稳压产生的2.5V,供ADC采样用。
(二)显示部分
核心是三位8段共阳数码管,由MCU直接驱动,
这部分应该采用的是三位数字轮流扫描显示的。
(三)按键
这部分没有接限流电阻,也没有消抖电路,
应该都是在MCU内实现的。
(四)采样放大
热耦的电势比较小,为了与ADC采样相匹配,使用了运算放大器对热耦电压进行放大,这里U6的电压放大倍数是101倍。

实际测量结果如下

是线性关系

(五)可控硅驱动
加热开关使用的是可控硅BAT16,
驱动可控硅使用的是非零交叉双可控硅耦合器MOC3021,
是不带过过零开关功能的,所以MCU必须检测过零点。
若使用零交叉双可控硅耦合器的话,就更简单一些了,
不需要交流两步采样和计算同步输出了。
(六)振动及交流同步采样
振动信号是通过R12和C17进入MCU的,C17完成了硬件消抖。
交流同步采样是由R14和Z1完成的,R14限流,Z1限幅,
使得正脉冲不超过4.3V,负脉冲不超过0.6V。

四、KD-931型恒温电烙铁

这是单位一位快退休的老前辈送的一堆电子垃圾中的,

是一个恒温电烙铁,
应该是九十年代末或二十世纪初的高级货了吧,
外壳还是很硬,没有老化,很重。
从底部拆开,内部已经是锈迹斑斑了。

稍微一动头就断了,补焊线头,进一步打理一下。

从主机接线情况看,不像是能恒温的,
所以手柄也拆开,

进一步分解开烙铁头,

看来玄机在加热腔内,
再拆,

先从尾部拉出来的是温控部分,

由于无法进一步拆解,只能从结构中分析其控温原理:
这根金属杆的顶部是贴着烙铁头的,可以感知其温度,
底部如上图,在一根细的陶瓷杆上固定着双触点,
这个陶瓷杆是可以上下移动的,平时两对触是闭合的。
当顶部达到某个温度时,陶瓷杆向外运动,带着两对触点分开,
这里就相当一相温度开关,串在加热回路里。
实现简单的机械式控温。
继续将加热部分拽出来:

主要由发热丝和云母纸构成,
原理相当于外热式烙铁。
把烙铁头放上去看看。

妥妥的外热式电烙铁哈。
全部打理完毕后的样子:

一直没路面的正脸:

江苏南通市康达电子装配工具公司大约也是1993左右成立的,
也是江苏,南通市在长江北,而快克公司的常州市在长江南,
两者相距不远。扯远了哈
加电,正常加热。

达到一定温度后,能停止加热。

没有测量其恒温的温度值,化锡很轻松
烙铁头也很好,焊接大焊点时,回温慢。

只能是情怀了。



QUICK963换了单片机,仿其功能造了个简单的程序,放到楼下吧。



本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册 微信登录

x

打赏

参与人数 2家元 +60 收起 理由
b26359 + 30 優秀文章
8139 + 30 優秀文章

查看全部打赏

 楼主| 发表于 昨天 21:41 | 显示全部楼层
本帖最后由 jf201006 于 2025-9-3 21:50 编辑

五、弄个程序“复活”963
其实也不是复活,就是利用原来的硬件,换个单片机,写个程序,
让其能简单的控制温度而已。
程序不完善,有些是测试函数,还没有优化。若有使用者使用时,请根据实际情况修改。
  1. /*
  2. * ATMEGA168恒温焊台控制程序 内部8MHz
  3. * 版本:抗战胜利80周年版
  4. * 日期:2025年9月2日
  5. * 功能:恒温控制焊台,包括温度采集、PID控制、数码管显示、按键处理、
  6. *       蜂鸣器提示、休眠模式、温度校准等功能。
  7. *       软关机后只能通过重新上电唤醒。
  8. * 版权:坛友可用,本人不答疑哈
  9. */

  10. #define F_CPU 8000000UL  // 8MHz内部RC振荡器(根据实际熔丝位配置)

  11. #include <avr/io.h>         // AVR I/O端口和寄存器定义
  12. #include <avr/interrupt.h>  // 中断处理函数
  13. #include <avr/eeprom.h>     // EEPROM读写功能
  14. #include <util/delay.h>     // 延时函数

  15. // ============================== 硬件引脚定义 ==============================

  16. // 数码管段选引脚定义 (共阳极,低电平点亮)
  17. #define SEG_A   PB6   // PB6 - 数码管A段
  18. #define SEG_B   PD0   // PD0 - 数码管B段
  19. #define SEG_C   PD2   // PD2 - 数码管C段
  20. #define SEG_D   PD4   // PD4 - 数码管D段
  21. #define SEG_E   PD5   // PD5 - 数码管E段
  22. #define SEG_F   PB7   // PB7 - 数码管F段
  23. #define SEG_G   PD1   // PD1 - 数码管G段
  24. #define SEG_DP  PD3   // PD3 - 数码管小数点

  25. // 数码管位选引脚定义 (高电平选通)
  26. #define DIGIT_1 PC1   // PC1 - 第一位数字(百位)
  27. #define DIGIT_2 PC4   // PC4 - 第二位数字(十位)
  28. #define DIGIT_3 PC5   // PC5 - 第三位数字(个位)

  29. // 按键引脚定义 (按下时接地,内部上拉电阻)
  30. #define KEY_DEC  PB3   // K1 - 减温度按键
  31. #define KEY_FUNC PB4   // K2 - 功能键/快速设置按键
  32. #define KEY_INC  PB5   // K3 - 加温度按键
  33. #define KEY_RST  PC2   // S1 - 恢复出厂设置按键

  34. // 其他引脚定义
  35. #define VIBRATION_SENSOR PB0  // 振动传感器输入(低电平有效)
  36. #define SYNC_INPUT       PD6  // 交流同步采样输入
  37. #define HEATER_CONTROL   PB1  // 加热控制输出(高电平加热)
  38. #define BUZZER           PC0  // 蜂鸣器控制输出

  39. // ADC通道定义
  40. #define TEMP_ADC 7        // ADC7 - 温度传感器输入

  41. // ============================== 数码管显示编码 ==============================

  42. // 数码管显示字符编码 (共阳极, 低电平有效)
  43. // 索引0-9对应数字0-9,10-14对应特殊字符
  44. const uint8_t seg_pattern[] = {
  45.     0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90, // 0-9
  46.     0x86, 0xBF, 0xFF, 0x92, 0x89  // E(10), -(11), 空格(12), S(13), H(14)
  47. };

  48. // ============================== EEPROM存储定义 ==============================

  49. // EEPROM存储地址定义
  50. #define EEPROM_FACTORY_PARAMS 0    // 出厂参数存储地址(12字节)
  51. #define EEPROM_USER_PARAMS    12   // 用户参数存储地址(12字节)
  52. #define EEPROM_MAGIC          24   // 魔术字存储地址(2字节)
  53. #define EEPROM_TEMP_SETTING   26   // 温度设置存储地址(2字节)
  54. #define EEPROM_TEMP_OFFSET    28   // 温度补偿偏移量(2字节)
  55. #define EEPROM_MAGIC_VALUE    0x55AA // 魔术字值,用于验证EEPROM数据有效性

  56. // ============================== 时间阈值定义 ==============================

  57. // 时间阈值定义(单位:主循环周期,每个周期约1ms)(根据实际修改)
  58. // 实测值(主循环每个周期约2.8ms 左右)
  59. #define SLEEP_THRESHOLD    100000  // 10分钟(220000)无活动进入休眠(测试用:5分钟)
  60. #define SHUTDOWN_THRESHOLD 120000  // 40分钟(850000)无活动进入软关机(测试用:5.5分钟)
  61. #define HEATING_TIMEOUT    12500   // 加热超时时间(35秒:12500 * 2.8ms = 35s)

  62. // ============================== 全局变量定义 ==============================

  63. // 温度相关变量
  64. volatile uint16_t current_temp = 0;      // 当前测量的温度值(单位:℃)
  65. volatile uint16_t set_temp = 280;        // 设定的目标温度值(单位:℃)
  66. volatile uint16_t previous_temp = 280;   // 进入休眠前的温度设置
  67. volatile uint16_t adc_value = 0;         // ADC采样原始值

  68. // 显示相关变量
  69. volatile uint8_t display_buffer[3] = {0, 0, 0}; // 数码管显示缓冲区(百位、十位、个位)
  70. volatile uint8_t display_index = 0;      // 当前显示的数码管位索引(0-2)

  71. // 状态标志变量
  72. volatile uint8_t heating = 0;            // 加热状态标志(0:停止加热,1:正在加热)
  73. volatile uint8_t error_state = 0;        // 错误状态(0:无错误,1:传感器错误,2:加热错误)
  74. volatile uint8_t calibration_mode = 0;   // 校准模式标志(0:正常模式,1:校准模式)
  75. volatile uint8_t setting_mode = 0;       // 设置模式标志(0:正常显示,1:显示设置值)
  76. volatile uint8_t sleep_mode = 0;         // 休眠模式标志(0:正常模式,1:休眠模式)
  77. volatile uint8_t shutdown_mode = 0;      // 关机模式标志(0:正常模式,1:关机模式)

  78. // 时间计数变量
  79. volatile uint32_t heating_time = 0;      // 加热时间计数(用于超时检测)
  80. volatile uint32_t inactive_time = 0;     // 无活动时间计数(用于休眠检测)
  81. volatile uint32_t setting_timer = 0;     // 设置模式计时器(用于自动退出设置模式)

  82. // 温度校准相关变量
  83. volatile uint8_t calibration_step = 0;    // 校准步骤 (0:未校准, 1:第一点, 2:第二点)
  84. volatile uint32_t calibration_timer = 0;  // 校准计时器
  85. #define CALIBRATION_TIMEOUT 100000        // 10分钟(600000)超时(测试用:5分钟)

  86. // 温度补偿相关变量
  87. volatile uint8_t compensation_mode = 0;   // 温度补偿模式标志
  88. volatile int16_t temp_offset = 0;         // 温度补偿偏移量

  89. // 显示效果变量
  90. volatile uint8_t blink_state = 0;        // 闪烁状态(0:显示,1:隐藏)
  91. volatile uint32_t blink_timer = 0;       // 闪烁计时器

  92. // 显示滤波相关变量
  93. #define SAMPLE_COUNT 30  // 采样次数
  94. volatile uint16_t temp_samples[SAMPLE_COUNT]; // 温度采样数组
  95. volatile uint8_t sample_index = 0;            // 当前采样索引
  96. volatile uint32_t temp_sum = 0;               // 温度总和
  97. volatile uint8_t samples_collected = 0;       // 已收集的样本数
  98. volatile uint16_t display_temp = 0;           // 滤波后的显示温度值

  99. // 同步加热相关变量
  100. volatile uint8_t sync_state = 0;        // 同步信号状态
  101. volatile uint8_t sync_last_state = 0;   // 上一次同步信号状态
  102. volatile uint8_t heating_request = 0;   // 加热请求标志
  103. volatile uint8_t heating_active = 0;    // 加热激活标志

  104. // 温度设置保存相关变量
  105. volatile uint8_t temp_setting_changed = 0; // 温度设置改变标志
  106. volatile uint32_t temp_setting_change_time = 0; // 温度设置改变时间
  107. #define SETTING_SAVE_DELAY 5000 // 5秒后保存温度设置

  108. // 校准模式相关变量
  109. volatile uint8_t cal_digit_edit = 0;       // 当前编辑的位数(0:百位,1:十位,2:个位)
  110. volatile uint16_t cal_target_temp = 0;     // 校准目标温度值
  111. volatile uint16_t cal_measured_temp = 0;   // 校准测量温度值
  112. volatile uint8_t cal_heating_stable = 0;   // 加热稳定标志
  113. volatile uint32_t cal_heating_timer = 0;   // 加热计时器
  114. #define HEATING_STABLE_TIME 65000         // 加热稳定时间(约3分钟:65000 * 2.8ms )

  115. // 在全局变量区域添加
  116. volatile float temp_change_rate = 0;    // 温度变化率 (°C/秒)
  117. volatile uint16_t prev_temp_history[5] = {0}; // 历史温度值
  118. volatile uint8_t temp_history_index = 0;

  119. // 蜂鸣器发声相关变量
  120. #define BEEP_SHORT 100  // 短声"滴"的持续时间(ms)
  121. #define BEEP_LONG  300  // 长声"嗒"的持续时间(ms)
  122. #define BEEP_PAUSE 100  // 蜂鸣声之间的间隔时间(ms)

  123. // PID控制参数结构体
  124. typedef struct {
  125.     float kp;           // 比例系数(升温快则调小,避免超调)
  126.     float ki;           // 积分系数(低温段调大,消除静态误差)
  127.     float kd;           // 微分系数(高温段调大,抑制波动)
  128.     float integral;     // 积分项累计值
  129.     float prev_error;   // 上一次误差值(用于微分计算)
  130. } PIDParams;

  131. // 两点法温度参数结构体
  132. typedef struct {
  133.     uint16_t temp1;     // 第一点温度值 (如200°C)
  134.     uint16_t voltage1;  // 第一点电压值 (如530mV)
  135.     uint16_t temp2;     // 第二点温度值 (如350°C)
  136.     uint16_t voltage2;  // 第二点电压值 (如975mV)
  137.     float len_k;        // 斜率 (计算得出)
  138.     float len_b;        // 截距 (计算得出)
  139. } TemperatureParams;

  140. // 全局结构体变量
  141. PIDParams pid_params;          // PID控制参数
  142. TemperatureParams factory_params = {200, 530, 350, 975, 0, 0}; // 默认出厂参数
  143. TemperatureParams user_params;                                 // 用户参数
  144. TemperatureParams current_params;                             // 当前使用的参数

  145. // ============================== 函数声明 ==============================

  146. // 初始化函数
  147. void init_ports(void);         // 初始化所有I/O端口
  148. void init_adc(void);           // 初始化ADC模块
  149. void init_timers(void);        // 初始化定时器

  150. // 显示函数
  151. void update_display(void);     // 更新数码管显示
  152. void display_segment(uint8_t seg); // 控制数码管段选输出
  153. void update_display_buffer(void);  // 更新显示缓冲区
  154. void moving_average_filter(void);  // 移动平均滤波函数

  155. // 温度相关函数
  156. void read_temperature(void);   // 读取温度值
  157. void pid_control(void);        // PID控制算法
  158. void calculate_slope_intercept(TemperatureParams *params); // 计算两点法的斜率和截距

  159. // 按键和传感器处理
  160. void check_buttons(void);      // 检查按键状态
  161. void check_vibration_sensor(void); // 检查振动传感器
  162. void check_sync_signal(void);  // 检查同步信号并控制加热

  163. // 状态管理函数
  164. void check_sleep_mode(void);   // 检查休眠模式
  165. void enter_sleep_mode(void);   // 进入休眠模式
  166. void enter_shutdown_mode(void);// 进入关机模式
  167. void exit_sleep_mode(void);    // 退出休眠/关机模式

  168. // 校准和设置函数
  169. void enter_calibration_mode(void); // 进入校准模式
  170. void save_user_params(void);    // 保存用户参数到EEPROM
  171. void restore_factory_settings(void); // 恢复出厂设置
  172. void enter_compensation_mode(void); // 进入温度补偿模式

  173. // 工具函数
  174. void beep(uint8_t type, uint8_t count);   // 蜂鸣器发声
  175. void show_startup_display(void); // 显示启动画面
  176. void wait_for_button_release(void); // 等待所有按键释放
  177. void handle_errors(void);        // 处理错误状态

  178. // ============================== 函数实现 ==============================

  179. /**
  180. * 简介: 初始化所有I/O端口
  181. * 功能: 配置数码管、按键、加热控制、蜂鸣器等引脚的输入输出方向和初始状态
  182. */
  183. void init_ports(void) {
  184.     // 数码管段选引脚设置为输出
  185.     DDRB |= (1 << SEG_A) | (1 << SEG_F);
  186.     DDRD |= (1 << SEG_B) | (1 << SEG_C) | (1 << SEG_D) |
  187.             (1 << SEG_E) | (1 << SEG_G) | (1 << SEG_DP);
  188.    
  189.     // 数码管位选引脚设置为输出
  190.     DDRC |= (1 << DIGIT_1) | (1 << DIGIT_2) | (1 << DIGIT_3);
  191.    
  192.     // 初始关闭所有数码管(段选高电平,位选低电平)
  193.     PORTB |= (1 << SEG_A) | (1 << SEG_F);
  194.     PORTD |= (1 << SEG_B) | (1 << SEG_C) | (1 << SEG_D) |
  195.              (1 << SEG_E) | (1 << SEG_G) | (1 << SEG_DP);
  196.     PORTC &= ~((1 << DIGIT_1) | (1 << DIGIT_2) | (1 << DIGIT_3));
  197.    
  198.     // 按键引脚设置为输入,启用上拉电阻
  199.     DDRB &= ~((1 << KEY_DEC) | (1 << KEY_FUNC) | (1 << KEY_INC));
  200.     PORTB |= (1 << KEY_DEC) | (1 << KEY_FUNC) | (1 << KEY_INC);
  201.    
  202.     DDRC &= ~(1 << KEY_RST);
  203.     PORTC |= (1 << KEY_RST);
  204.    
  205.     // 振动传感器设置为输入,启用上拉电阻
  206.     DDRB &= ~(1 << VIBRATION_SENSOR);
  207.     PORTB |= (1 << VIBRATION_SENSOR);
  208.    
  209.     // 加热控制引脚设置为输出,初始关闭加热
  210.     DDRB |= (1 << HEATER_CONTROL);
  211.     PORTB &= ~(1 << HEATER_CONTROL);
  212.    
  213.     // 蜂鸣器引脚设置为输出,初始关闭蜂鸣器
  214.     DDRC |= (1 << BUZZER);
  215.     PORTC &= ~(1 << BUZZER);
  216.    
  217.     // 同步输入引脚设置为输入
  218.     DDRD &= ~(1 << SYNC_INPUT);
  219.     PORTD &= ~(1 << SYNC_INPUT);
  220. }

  221. /**
  222. * 简介: 初始化ADC模块
  223. * 功能: 配置ADC参考电压、输入通道和预分频器,进行第一次转换丢弃
  224. */
  225. void init_adc(void) {
  226.     // 使用外部AREF作为参考电压,选择ADC7通道
  227.     ADMUX = (0 << REFS1) | (0 << REFS0) | (TEMP_ADC & 0x0F);
  228.     // 使能ADC,预分频128
  229.     ADCSRA = (1 << ADEN) | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0);
  230.     // 第一次转换丢弃,确保ADC稳定
  231.     ADCSRA |= (1 << ADSC);
  232.     while(ADCSRA & (1 << ADSC));
  233. }

  234. /**
  235. * 简介: 初始化定时器
  236. * 功能: 配置定时器0用于数码管扫描和按键检测(约1ms中断)
  237. */
  238. void init_timers(void) {
  239.     // 定时器0用于数码管扫描和按键检测 (CTC模式,64分频)
  240.     TCCR0A = (1 << WGM01); // CTC模式
  241.     TCCR0B = (1 << CS01) | (1 << CS00); // 64分频
  242.     // OCR0A = 15; // 1ms中断 (1MHz/64/16 = 1024μs ≈ 1ms)
  243.     OCR0A = 124;  // 1ms中断 (8MHz/64/125 = 1000μs = 1ms)
  244.     TIMSK0 = (1 << OCIE0A); // 启用比较匹配中断

  245. }

  246. /**
  247. * 简介: 显示启动画面
  248. * 功能: 显示"963"启动画面并发出蜂鸣声,禁用中断确保显示完整
  249. */
  250. void show_startup_display(void) {
  251.     // 保存当前中断状态并禁用中断,确保启动画面显示不受干扰
  252.     uint8_t sreg = SREG;
  253.     cli();
  254.    
  255.     // 显示"963"启动画面,持续约500ms
  256.     for(uint16_t i = 0; i < 178; i++) { // 178 * 2.8 = 498 ms
  257.         // 显示第一位数字9
  258.         PORTC &= ~((1 << DIGIT_1) | (1 << DIGIT_2) | (1 << DIGIT_3));
  259.         display_segment(seg_pattern[9]);
  260.         PORTC |= (1 << DIGIT_1);
  261.         _delay_ms(1);
  262.         
  263.         // 显示第二位数字6
  264.         PORTC &= ~((1 << DIGIT_1) | (1 << DIGIT_2) | (1 << DIGIT_3));
  265.         display_segment(seg_pattern[6]);
  266.         PORTC |= (1 << DIGIT_2);
  267.         _delay_ms(1);
  268.         
  269.         // 显示第三位数字3
  270.         PORTC &= ~((1 << DIGIT_1) | (1 << DIGIT_2) | (1 << DIGIT_3));
  271.         display_segment(seg_pattern[3]);
  272.         PORTC |= (1 << DIGIT_3);
  273.         _delay_ms(1);
  274.     }
  275.    
  276.     // 蜂鸣提示
  277.     beep(0,1);
  278.    
  279.     // 恢复中断状态
  280.     SREG = sreg;
  281. }

  282. /**
  283. * 简介: 更新显示缓冲区
  284. * 功能: 根据当前状态(正常、错误、校准、设置)更新显示缓冲区内容
  285. */
  286. void update_display_buffer(void) {
  287.     if (compensation_mode) {
  288.         // 温度补偿模式显示补偿值
  289.         int16_t display_offset = temp_offset;
  290.         uint8_t sign = 0; // 0:正数, 1:负数
  291.         
  292.         if (display_offset < 0) {
  293.             sign = 1;
  294.             display_offset = -display_offset;
  295.         }
  296.         
  297.         display_buffer[0] = sign ? 11 : 12; // "-"或空格
  298.         display_buffer[1] = display_offset / 10;
  299.         display_buffer[2] = display_offset % 10;
  300.     }
  301.     else if (calibration_mode) {
  302.         if (cal_heating_stable) {
  303.             // 加热稳定后,显示测量温度值
  304.             display_buffer[0] = cal_measured_temp / 100;
  305.             display_buffer[1] = (cal_measured_temp % 100) / 10;
  306.             display_buffer[2] = cal_measured_temp % 10;
  307.         } else {
  308.             // 加热过程中,显示目标温度值
  309.             display_buffer[0] = cal_target_temp / 100;
  310.             display_buffer[1] = (cal_target_temp % 100) / 10;
  311.             display_buffer[2] = cal_target_temp % 10;
  312.         }
  313.     }
  314.     else if (error_state == 1) {
  315.         // 传感器错误显示"S-E"
  316.         display_buffer[0] = 13; // S
  317.         display_buffer[1] = 11; // -
  318.         display_buffer[2] = 10; // E
  319.     } else if (error_state == 2) {
  320.         // 加热错误显示"H-E"
  321.         display_buffer[0] = 14; // H
  322.         display_buffer[1] = 11; // -
  323.         display_buffer[2] = 10; // E
  324.     } else if (setting_mode) {
  325.         // 设置模式显示设置值
  326.         display_buffer[0] = set_temp / 100;
  327.         display_buffer[1] = (set_temp % 100) / 10;
  328.         display_buffer[2] = set_temp % 10;
  329.     } else if (shutdown_mode) {
  330.         // 关机模式显示空白
  331.         display_buffer[0] = 12; // 空格
  332.         display_buffer[1] = 12; // 空格
  333.         display_buffer[2] = 12; // 空格
  334.     } else if (sleep_mode) {
  335.         // 休眠模式显示当前温度(可能闪烁)
  336.         if (blink_state) {
  337.             display_buffer[0] = display_temp / 100;
  338.             display_buffer[1] = (display_temp % 100) / 10;
  339.             display_buffer[2] = display_temp % 10;
  340.         } else {
  341.             display_buffer[0] = 12; // 空格
  342.             display_buffer[1] = 12; // 空格
  343.             display_buffer[2] = 12; // 空格
  344.         }
  345.     } else {
  346.         // 正常模式显示当前温度
  347.         display_buffer[0] = display_temp / 100;
  348.         display_buffer[1] = (display_temp % 100) / 10;
  349.         display_buffer[2] = display_temp % 10;
  350.     }
  351. }

  352. /**
  353. * 简介: 更新数码管显示
  354. * 功能: 根据当前显示索引,更新对应数码管的显示内容
  355. *          在定时器中断中调用
  356. */
  357. void update_display(void) {
  358.     // 关闭所有位选
  359.     PORTC &= ~((1 << DIGIT_1) | (1 << DIGIT_2) | (1 << DIGIT_3));
  360.    
  361.     // 根据错误状态显示相应内容
  362.     if (error_state && blink_state) {
  363.         // 错误状态下闪烁显示
  364.         return;
  365.     }

  366.     uint8_t digit = display_buffer[display_index];
  367.     uint8_t pattern = seg_pattern[digit];
  368.    
  369.     // 如果是最后一位且正在加热,显示小数点
  370.     if (display_index == 2 && heating) {
  371.         pattern &= ~(1 << 7); // 点亮小数点(清零DP位)
  372.     }
  373.    
  374.     // 校准模式下且加热稳定后,闪烁当前编辑的数字位
  375.     if (calibration_mode && cal_heating_stable && display_index == cal_digit_edit && blink_state) {
  376.         pattern = 0xFF; // 全部熄灭(隐藏当前位)
  377.     }

  378.     // 第一步:计算亮度补偿因子
  379.     uint8_t lit_segments = 0;
  380.     for(uint8_t i = 0; i < 8; i++) {
  381.         if(!(pattern & (1 << i))) lit_segments++;
  382.     }
  383.     if(lit_segments < 3) lit_segments = 3;
  384.     uint8_t display_cycles = 12 - lit_segments;
  385.    
  386.     display_segment(pattern);
  387.    
  388.     // 选择对应的位
  389.     switch(display_index) {
  390.         case 0: PORTC |= (1 << DIGIT_1); break; // 选通百位
  391.         case 1: PORTC |= (1 << DIGIT_2); break; // 选通十位
  392.         case 2: PORTC |= (1 << DIGIT_3); break; // 选通个位
  393.     }

  394.     // 第二步:亮度补偿
  395.     for(uint8_t i = 0; i < display_cycles; i++) {
  396.         _delay_us(80);
  397.     }
  398.    
  399.     // 更新显示索引(循环0-2)
  400.     display_index = (display_index + 1) % 3;
  401. }

  402. /**
  403. * 简介: 控制数码管段选输出
  404. * 参数: seg 段选模式(8 bit,每bit对应一个段)
  405. * 功能: 根据段选模式控制对应的段选引脚输出
  406. */
  407. void display_segment(uint8_t seg) {
  408.     // PORTB处理:A段(PB6)和F段(PB7)
  409.     if(!(seg & 0x01)) PORTB &= ~(1 << SEG_A);  // A段点亮
  410.     else PORTB |= (1 << SEG_A);               // A段熄灭
  411.     if(!(seg & 0x20)) PORTB &= ~(1 << SEG_F);  // F段点亮
  412.     else PORTB |= (1 << SEG_F);               // F段熄灭
  413.    
  414.     // PORTD处理:B,C,D,E,G,DP段
  415.     if(!(seg & 0x02)) PORTD &= ~(1 << SEG_B);  // B段点亮
  416.     else PORTD |= (1 << SEG_B);               // B段熄灭
  417.     if(!(seg & 0x04)) PORTD &= ~(1 << SEG_C);  // C段点亮
  418.     else PORTD |= (1 << SEG_C);               // C段熄灭
  419.     if(!(seg & 0x08)) PORTD &= ~(1 << SEG_D);  // D段点亮
  420.     else PORTD |= (1 << SEG_D);               // D段熄灭
  421.     if(!(seg & 0x10)) PORTD &= ~(1 << SEG_E);  // E段点亮
  422.     else PORTD |= (1 << SEG_E);               // E段熄灭
  423.     if(!(seg & 0x40)) PORTD &= ~(1 << SEG_G);  // G段点亮
  424.     else PORTD |= (1 << SEG_G);               // G段熄灭
  425.     if(!(seg & 0x80)) PORTD &= ~(1 << SEG_DP); // DP段点亮
  426.     else PORTD |= (1 << SEG_DP);              // DP段熄灭
  427. }

  428. /**
  429. * 简介: 读取温度值
  430. * 功能: 启动ADC转换,读取ADC值,计算电压和温度值,
  431. *          应用校准参数,检查传感器故障
  432. */
  433. void read_temperature(void) {
  434.     // 启动ADC转换
  435.     ADCSRA |= (1 << ADSC);
  436.     // 等待转换完成
  437.     while(ADCSRA & (1 << ADSC));
  438.    
  439.     // 读取ADC值
  440.     adc_value = ADC;
  441.    
  442.     // 计算电压值 (mV)
  443.     uint32_t voltage = (adc_value * 2500UL) / 1024;
  444.    
  445.     // 检查传感器故障 (电压超过2.2V)
  446.     if(voltage > 2200) {
  447.         error_state = 1;
  448.         return;
  449.     }
  450.    
  451.     // 使用两点法计算温度
  452.     // current_temp = (voltage - len_b) / len_k
  453.     float temp_float = ((float)voltage - current_params.len_b) / current_params.len_k;
  454.    
  455.     // 应用温度补偿
  456.     int16_t temp_compensated = (int16_t)temp_float + eeprom_read_word((uint16_t*)EEPROM_TEMP_OFFSET);
  457.    
  458.     // 限制温度范围
  459.     if (temp_compensated < 0) temp_compensated = 0;
  460.     if (temp_compensated > 999) temp_compensated = 999;
  461.    
  462.     current_temp = (uint16_t)temp_compensated;
  463. }

  464. void update_temp_history(void) {
  465.     prev_temp_history[temp_history_index] = current_temp;
  466.     temp_history_index = (temp_history_index + 1) % 5;
  467.    
  468.     // 计算温度变化率 (近5次采样的平均变化)
  469.     int16_t sum_diff = 0;
  470.     for(uint8_t i = 0; i < 4; i++) {
  471.         sum_diff += (int16_t)prev_temp_history[(temp_history_index + i) % 5] -
  472.                    (int16_t)prev_temp_history[(temp_history_index + i + 1) % 5];
  473.     }
  474.     temp_change_rate = (float)sum_diff / (4.0 * 5.0); // 5次采样间隔约5*5ms=25ms
  475. }


  476. /**
  477. * 简介: 改进的PID控制算法
  478. * 功能: 加入温度变化率预测,提前减少加热功率
  479. */
  480. void improved_pid_control(void) {
  481.     if(error_state) {
  482.         heating_request = 0;
  483.         heating = 0;
  484.         heating_time = 0;
  485.         return;
  486.     }
  487.    
  488.     static float integral = 0;
  489.     static float prev_measurement = 0;
  490.    
  491.     // PID参数
  492.     float kp = 3.0;
  493.     float ki = 0.02;
  494.     float kd = 6.0;
  495.    
  496.     float error = set_temp - current_temp;
  497.    
  498.     // 比例项
  499.     float p_term = kp * error;
  500.    
  501.     // 积分项 - 条件积分
  502.     if(fabs(error) > 5 || integral * error > 0) {
  503.         integral += error;
  504.     }
  505.     // 积分限幅
  506.     if(integral > 80) integral = 80;
  507.     if(integral < -80) integral = -80;
  508.     float i_term = ki * integral;
  509.    
  510.     // 微分项 - 基于测量值的变化率
  511.     float derivative = (current_temp - prev_measurement);
  512.     float d_term = kd * derivative;
  513.     prev_measurement = current_temp;
  514.    
  515.     // 基本PID输出
  516.     float output = p_term + i_term - d_term;
  517.    
  518.     // 温度变化率预测修正
  519.     if(temp_change_rate > 2.0 && current_temp > set_temp - 10) {
  520.         // 温度上升较快,提前减少加热
  521.         output -= temp_change_rate * 5.0;
  522.     }
  523.    
  524.     // 限制输出范围
  525.     if(output > 100) output = 100;
  526.     if(output < 0) output = 0;
  527.    
  528.     // 设置加热请求标志
  529.     if(output > 15 && current_temp < set_temp + 8) {
  530.         heating_request = 1;
  531.         heating = 1;
  532.         heating_time++;
  533.     } else {
  534.         heating_request = 0;
  535.         heating = 0;
  536.         heating_time = 0;
  537.     }
  538.    
  539.     // 检查加热超时
  540.     if(heating_time > HEATING_TIMEOUT) {
  541.         error_state = 2;
  542.     }
  543. }

  544. /**
  545. * 简介: 加权移动平均滤波函数
  546. * 功能: 使用指数加权移动平均,对新数据给予更高权重
  547. */
  548. void weighted_moving_average_filter(void) {
  549.     // 指数加权移动平均 (EWMA)
  550.     // 新样本权重为0.7,旧平均值权重为0.3
  551.     display_temp = (uint16_t)(0.7 * current_temp + 0.3 * display_temp);
  552. }

  553. /**
  554. * 简介: 检查同步信号并控制加热 - 优化版本
  555. * 功能: 改进加热控制逻辑,减少过冲
  556. */
  557. void check_sync_signal_optimized(void) {
  558.     // 读取同步信号状态
  559.     sync_state = (PIND & (1 << SYNC_INPUT)) ? 1 : 0;
  560.    
  561.     // 检测同步信号边沿(上升沿或下降沿)
  562.     if (sync_state != sync_last_state) {
  563.         sync_last_state = sync_state;
  564.         
  565.         // 如果有加热请求,在过零点开启加热
  566.         if (heating_request && !heating_active) {
  567.             // 温度接近设定值时,减少加热时间
  568.             if(current_temp > set_temp - 5) {
  569.                 // 只加热半波
  570.                 PORTB |= (1 << HEATER_CONTROL);
  571.                 _delay_us(8000); // 约半波时间(10ms/2)
  572.                 PORTB &= ~(1 << HEATER_CONTROL);
  573.             } else {
  574.                 // 全波加热
  575.                 PORTB |= (1 << HEATER_CONTROL);
  576.                 heating_active = 1;
  577.             }
  578.         }
  579.     }
  580.    
  581.     // 如果不是过零点,保持或关闭加热
  582.     if (!heating_request && heating_active) {
  583.         PORTB &= ~(1 << HEATER_CONTROL);
  584.         heating_active = 0;
  585.     }
  586. }


  587. /**
  588. * 简介: 计算两点法的斜率和截距
  589. * 参数: params 温度参数结构体指针
  590. */
  591. void calculate_slope_intercept(TemperatureParams *params) {
  592.     // 计算斜率 len_k = (voltage2 - voltage1) / (temp2 - temp1)
  593.     params->len_k = (float)(params->voltage2 - params->voltage1) /
  594.                     (float)(params->temp2 - params->temp1);
  595.    
  596.     // 计算截距 len_b = voltage1 - len_k * temp1
  597.     params->len_b = (float)params->voltage1 - params->len_k * params->temp1;
  598. }

  599. /**
  600. * 简介: 移动平均滤波函数
  601. * 功能: 使用30次采样值的移动平均来平滑温度显示
  602. *          大约每150ms更新一次显示温度(30*5ms)
  603. */
  604. void moving_average_filter(void) {
  605.     // 减去最旧的样本值
  606.     temp_sum -= temp_samples[sample_index];
  607.    
  608.     // 添加最新的样本值
  609.     temp_samples[sample_index] = current_temp;
  610.     temp_sum += current_temp;
  611.    
  612.     // 更新样本索引
  613.     sample_index = (sample_index + 1) % SAMPLE_COUNT;
  614.    
  615.     // 计算移动平均值
  616.     if (samples_collected < SAMPLE_COUNT) {
  617.         samples_collected++;
  618.     }
  619.    
  620.     display_temp = (temp_sum + samples_collected/2) / samples_collected; // 四舍五入
  621. }

  622. /**
  623. * 简介: 等待所有按键释放
  624. * 功能: 检测所有按键是否已释放,防止误操作
  625. */
  626. void wait_for_button_release(void) {
  627.     // 等待所有按键释放
  628.     while(!(PINB & (1 << KEY_DEC)) ||
  629.           !(PINB & (1 << KEY_FUNC)) ||
  630.           !(PINB & (1 << KEY_INC)) ||
  631.           !(PINC & (1 << KEY_RST))) {
  632.         _delay_ms(10);
  633.     }
  634.    
  635.     // 添加去抖动延迟
  636.     _delay_ms(50);
  637. }

  638. /**
  639. * 简介: 检查按键状态
  640. * 功能: 检测按键按下、长按等事件,处理按键功能,
  641. *          包括温度调整、快速设置、进入校准模式等
  642. */
  643. void check_buttons(void) {
  644.     // 如果在软关机模式下,直接返回
  645.     if (shutdown_mode) {
  646.         return;
  647.     }
  648.    
  649.     static uint8_t last_key_state = 0;
  650.     static uint32_t key_press_time = 0;
  651.     static uint32_t key_repeat_time = 0;
  652.     static uint32_t combo_timer = 0;
  653.     static uint8_t cal_key_released = 1; // 校准按键释放标志
  654.     static uint32_t k2_press_time = 0;
  655.     static uint8_t quick_set_index = 0;
  656.     uint8_t current_key_state = 0;
  657.    
  658.     // 读取K1、K2、K3按键状态
  659.     if(!(PINB & (1 << KEY_DEC))) current_key_state |= 1;
  660.     if(!(PINB & (1 << KEY_FUNC))) current_key_state |= 2;
  661.     if(!(PINB & (1 << KEY_INC))) current_key_state |= 4;
  662.    
  663.     // 检测组合键按下(K1+K2+K3同时按下)
  664.     if((current_key_state & 7) == 7 && !calibration_mode && !compensation_mode) {
  665.         combo_timer++;
  666.         
  667.         if(combo_timer > 100) { // 约280ms后确认组合键(250 * 2.8ms = 280ms)
  668.             enter_calibration_mode();
  669.             combo_timer = 0;
  670.         }
  671.     } else {
  672.         // 重置组合键计时器
  673.         combo_timer = 0;
  674.     }
  675.    
  676.     // 如果当前处于校准模式,处理校准按键
  677.     if (calibration_mode) {
  678.         // 重置无活动时间
  679.         inactive_time = 0;
  680.         
  681.         // 检查超时 (10分钟)
  682.         calibration_timer++;
  683.         if (calibration_timer >= CALIBRATION_TIMEOUT) {
  684.             calibration_mode = 0;
  685.             calibration_step = 0;
  686.             cal_heating_stable = 0;
  687.             beep(0, 1); // 超时提示
  688.             return;
  689.         }
  690.         
  691.         // 检查加热是否稳定
  692.         if (!cal_heating_stable) {
  693.             cal_heating_timer++;
  694.             if (cal_heating_timer >= HEATING_STABLE_TIME) {
  695.                 cal_heating_stable = 1;
  696.                 cal_digit_edit = 0; // 从百位开始编辑
  697.                 beep(0, 1); // 加热稳定提示
  698.             }
  699.             return; // 加热过程中不处理按键
  700.         }
  701.         
  702.         // 检测按键按下
  703.         if (current_key_state && cal_key_released) {
  704.             cal_key_released = 0;
  705.             
  706.             if (calibration_step == 1) {
  707.                 // 第一点校准 - 输入测量温度值
  708.                 if (current_key_state & 2) { // K2键 - 切换位或确认
  709.                     if (cal_digit_edit < 2) {
  710.                         // 切换到下一位
  711.                         cal_digit_edit++;
  712.                     } else {
  713.                         // 确认第一点测量值
  714.                         if (cal_measured_temp >= 150 && cal_measured_temp <= 500) {
  715.                             user_params.temp1 = cal_measured_temp;
  716.                            
  717.                             // 读取当前电压值
  718.                             ADCSRA |= (1 << ADSC);
  719.                             while(ADCSRA & (1 << ADSC));
  720.                             user_params.voltage1 = (ADC * 2500UL) / 1024;
  721.                            
  722.                             // 进入第二点校准
  723.                             calibration_step = 2;
  724.                             cal_heating_stable = 0; // 重置加热稳定标志
  725.                             cal_heating_timer = 0;  // 重置加热计时器
  726.                            
  727.                             // 设置第二个校准点的目标温度
  728.                             cal_target_temp = 350; // 默认第二点目标温度
  729.                             set_temp = cal_target_temp; // 设置系统目标温度
  730.                             eeprom_write_word((uint16_t*)EEPROM_TEMP_SETTING, set_temp);
  731.                            
  732.                             // 初始化测量温度值
  733.                             cal_measured_temp = cal_target_temp;
  734.                            
  735.                             beep(0, 1); // "滴"一声提示
  736.                         }
  737.                     }
  738.                 }
  739.                 else if (current_key_state & 4) { // K3键增加当前位数值
  740.                     uint16_t multiplier = 1;
  741.                     for (uint8_t i = 0; i < (2 - cal_digit_edit); i++) {
  742.                         multiplier *= 10;
  743.                     }
  744.                     cal_measured_temp += multiplier;
  745.                     if (cal_measured_temp > 500) cal_measured_temp = 150;
  746.                 }
  747.                 else if (current_key_state & 1) { // K1键减少当前位数值
  748.                     uint16_t multiplier = 1;
  749.                     for (uint8_t i = 0; i < (2 - cal_digit_edit); i++) {
  750.                         multiplier *= 10;
  751.                     }
  752.                     if (cal_measured_temp < multiplier + 150) cal_measured_temp = 500;
  753.                     else cal_measured_temp -= multiplier;
  754.                 }
  755.             }
  756.             else if (calibration_step == 2) {
  757.                 // 第二点校准 - 输入测量温度值
  758.                 if (current_key_state & 2) { // K2键 - 切换位或确认
  759.                     if (cal_digit_edit < 2) {
  760.                         // 切换到下一位
  761.                         cal_digit_edit++;
  762.                     } else {
  763.                         // 确认第二点测量值
  764.                         if (cal_measured_temp >= 150 && cal_measured_temp <= 500) {
  765.                             user_params.temp2 = cal_measured_temp;
  766.                            
  767.                             // 读取当前电压值
  768.                             ADCSRA |= (1 << ADSC);
  769.                             while(ADCSRA & (1 << ADSC));
  770.                             user_params.voltage2 = (ADC * 2500UL) / 1024;
  771.                            
  772.                             // 完成校准,保存参数
  773.                             calculate_slope_intercept(&user_params);
  774.                             save_user_params();
  775.                             current_params = user_params;
  776.                            
  777.                             calibration_mode = 0;
  778.                             calibration_step = 0;
  779.                             cal_heating_stable = 0;
  780.                             beep(0, 2); // "滴滴"两声提示
  781.                         }
  782.                     }
  783.                 }
  784.                 else if (current_key_state & 4) { // K3键增加当前位数值
  785.                     uint16_t multiplier = 1;
  786.                     for (uint8_t i = 0; i < (2 - cal_digit_edit); i++) {
  787.                         multiplier *= 10;
  788.                     }
  789.                     cal_measured_temp += multiplier;
  790.                     if (cal_measured_temp > 500) cal_measured_temp = 150;
  791.                 }
  792.                 else if (current_key_state & 1) { // K1键减少当前位数值
  793.                     uint16_t multiplier = 1;
  794.                     for (uint8_t i = 0; i < (2 - cal_digit_edit); i++) {
  795.                         multiplier *= 10;
  796.                     }
  797.                     if (cal_measured_temp < multiplier + 150) cal_measured_temp = 500;
  798.                     else cal_measured_temp -= multiplier;
  799.                 }
  800.             }
  801.         }
  802.         
  803.         // 检测按键释放
  804.         if (!current_key_state) {
  805.             cal_key_released = 1;
  806.         }
  807.         
  808.         return; // 在校准模式下,不处理其他按键
  809.     }
  810.    
  811.     // 如果当前处于补偿模式,处理补偿按键
  812.     if (compensation_mode) {
  813.         // 重置无活动时间
  814.         inactive_time = 0;
  815.         
  816.         // 检测按键按下
  817.         if (current_key_state && cal_key_released) {
  818.             cal_key_released = 0;
  819.             
  820.             if (current_key_state & 2) { // K2键确认
  821.                 // 保存温度补偿值
  822.                 eeprom_write_word((uint16_t*)EEPROM_TEMP_OFFSET, temp_offset);
  823.                 compensation_mode = 0;
  824.                 beep(0, 2); // "滴滴"两声提示
  825.             }
  826.             else if (current_key_state & 4) { // K3键增加补偿值
  827.                 temp_offset++;
  828.                 if (temp_offset > 50) temp_offset = -50;
  829.             }
  830.             else if (current_key_state & 1) { // K1键减少补偿值
  831.                 temp_offset--;
  832.                 if (temp_offset < -50) temp_offset = 50;
  833.             }
  834.         }
  835.         
  836.         // 检测按键释放
  837.         if (!current_key_state) {
  838.             cal_key_released = 1;
  839.         }
  840.         
  841.         return; // 在补偿模式下,不处理其他按键
  842.     }
  843.    
  844.     // 检测长按K2键进入温度补偿模式
  845.     if(!(PINB & (1 << KEY_FUNC))) {
  846.         k2_press_time++;
  847.         if(k2_press_time > 2000) { // 长按2秒
  848.             if(!compensation_mode && !calibration_mode) {
  849.                 enter_compensation_mode();
  850.             }
  851.             k2_press_time = 0;
  852.         }
  853.     } else {
  854.         k2_press_time = 0;
  855.     }
  856.    
  857.     // 检测按键按下
  858.     if(current_key_state && !last_key_state) {
  859.         key_press_time = 0;
  860.         key_repeat_time = 0;
  861.         
  862.         // 退出休眠模式
  863.         if(sleep_mode) {
  864.             exit_sleep_mode();
  865.         } else {
  866.             // 重置无活动时间
  867.             inactive_time = 0;
  868.         }
  869.         
  870.         // 快速设置温度
  871.         if((current_key_state & 2) && !calibration_mode && !compensation_mode) {
  872.             uint16_t quick_set_temps[] = {250, 330, 380};
  873.             set_temp = quick_set_temps[quick_set_index];
  874.             quick_set_index = (quick_set_index + 1) % 3;
  875.             temp_setting_changed = 1; // 标记温度设置已改变
  876.             temp_setting_change_time = 0; // 重置改变时间
  877.             setting_mode = 1;
  878.             setting_timer = 0;
  879.         }
  880.         // 增加温度
  881.         else if((current_key_state & 4) && set_temp < 500 && !calibration_mode && !compensation_mode) {
  882.             set_temp++;
  883.             temp_setting_changed = 1; // 标记温度设置已改变
  884.             temp_setting_change_time = 0; // 重置改变时间
  885.             setting_mode = 1;
  886.             setting_timer = 0;
  887.         }
  888.         // 减少温度
  889.         else if((current_key_state & 1) && set_temp > 150 && !calibration_mode && !compensation_mode) {
  890.             set_temp--;
  891.             temp_setting_changed = 1; // 标记温度设置已改变
  892.             temp_setting_change_time = 0; // 重置改变时间
  893.             setting_mode = 1;
  894.             setting_timer = 0;
  895.         }
  896.     }
  897.    
  898.     // 检测长按
  899.     if(current_key_state == last_key_state && current_key_state) {
  900.         key_press_time++;
  901.         
  902.         // 长按500ms后加速调整 (178 * 2.8ms = 498ms)
  903.         if(key_press_time > 178) {
  904.             key_repeat_time++;
  905.             // 每19.6ms重复一次 (7 * 2.8ms = 19.6ms)
  906.             if(key_repeat_time > 7) {
  907.                 key_repeat_time = 0;
  908.                
  909.                 if((current_key_state & 4) && set_temp < 500 && !calibration_mode && !compensation_mode) {
  910.                     set_temp++;
  911.                     temp_setting_changed = 1; // 标记温度设置已改变
  912.                     temp_setting_change_time = 0; // 重置改变时间
  913.                     setting_mode = 1;
  914.                     setting_timer = 0;
  915.                 }
  916.                 if((current_key_state & 1) && set_temp > 150 && !calibration_mode && !compensation_mode) {
  917.                     set_temp--;
  918.                     temp_setting_changed = 1; // 标记温度设置已改变
  919.                     temp_setting_change_time = 0; // 重置改变时间
  920.                     setting_mode = 1;
  921.                     setting_timer = 0;
  922.                 }
  923.             }
  924.         }
  925.     }
  926.    
  927.     // 温度设置改变后延迟保存
  928.     if (temp_setting_changed) {
  929.         temp_setting_change_time++;
  930.         if (temp_setting_change_time >= SETTING_SAVE_DELAY) {
  931.             eeprom_write_word((uint16_t*)EEPROM_TEMP_SETTING, set_temp);
  932.             temp_setting_changed = 0; // 重置改变标志
  933.         }
  934.     }
  935.    
  936.     // 设置模式计时
  937.     if (setting_mode) {
  938.         setting_timer++;
  939.         // 2秒后退出设置模式 (700 * 2.8ms = 1.96s)
  940.         if (setting_timer > 700) {
  941.             setting_mode = 0;
  942.         }
  943.     }
  944.    
  945.     last_key_state = current_key_state;
  946. }

  947. /**
  948. * 简介: 检查振动传感器
  949. * 功能: 检测振动传感器状态变化,用于唤醒休眠模式
  950. */
  951. void check_vibration_sensor(void) {
  952.     // 如果在软关机模式下,直接返回
  953.     if (shutdown_mode) {
  954.         return;
  955.     }
  956.    
  957.     static uint8_t last_vibration_state = 1; // 默认高电平(无振动)
  958.     static uint32_t debounce_timer = 0;
  959.    
  960.     uint8_t current_state = (PINB & (1 << VIBRATION_SENSOR)) ? 1 : 0;
  961.    
  962.     // 检测状态变化
  963.     if (current_state != last_vibration_state) {
  964.         debounce_timer = 0;
  965.         last_vibration_state = current_state;
  966.         return;
  967.     }
  968.    
  969.     // 确认状态变化
  970.     if (current_state == 0) { // 低电平表示有振动
  971.         // 重置休眠计时
  972.         inactive_time = 0;
  973.         
  974.         // 如果是从休眠中唤醒,恢复原温度
  975.         if (sleep_mode) {
  976.             exit_sleep_mode();
  977.         }
  978.     }
  979.    
  980.     last_vibration_state = current_state;
  981. }

  982. /**
  983. * 简介: PID控制算法
  984. * 功能: 根据当前温度与设定温度的误差,计算PID输出, 控制加热器工作状态
  985. *          针对加热过冲问题进行了优化,加入了抗积分饱和和微分先行
  986. */
  987. void pid_control(void) {
  988.     if(error_state) {
  989.         heating_request = 0;
  990.         heating = 0;
  991.         heating_time = 0;
  992.         return;
  993.     }
  994.    
  995.     static float prev_error = 0;
  996.     static float integral = 0;
  997.     static uint8_t first_run = 1;
  998.    
  999.     // 初始化PID参数 - 根据系统特性调整这些值
  1000.     float kp = 3.0;    // 比例系数 (原2.0)
  1001.     float ki = 0.03;   // 积分系数 (原0.1,减小以减少超调)
  1002.     float kd = 5.0;    // 微分系数 (原1.0,增加以抑制超调)
  1003.    
  1004.     // 清除积分项当设定值变化较大时
  1005.     if(fabs(set_temp - current_temp) > 30) {
  1006.         integral = 0;
  1007.     }
  1008.    
  1009.     float error = set_temp - current_temp;
  1010.    
  1011.     // 比例项
  1012.     float p_term = kp * error;
  1013.    
  1014.     // 积分项 - 抗积分饱和
  1015.     integral += error;
  1016.     // 积分限幅 - 更严格的限制
  1017.     if(integral > 50) integral = 50;
  1018.     if(integral < -50) integral = -50;
  1019.     float i_term = ki * integral;
  1020.    
  1021.     // 微分项 - 微分先行(只对测量值微分,不对设定值微分)
  1022.     static float prev_measurement = 0;
  1023.     float derivative = 0;
  1024.     if(!first_run) {
  1025.         derivative = (current_temp - prev_measurement);
  1026.     }
  1027.     first_run = 0;
  1028.     float d_term = kd * derivative;
  1029.     prev_measurement = current_temp;
  1030.    
  1031.     // PID输出
  1032.     float output = p_term + i_term - d_term; // 注意微分项符号
  1033.    
  1034.     // 当温度接近设定值时,减小积分作用
  1035.     if(fabs(error) < 10) {
  1036.         output = p_term - d_term + 0.2 * i_term;
  1037.     }
  1038.    
  1039.     // 限制输出范围
  1040.     if(output > 100) output = 100;
  1041.     if(output < 0) output = 0;
  1042.    
  1043.     // 设置加热请求标志
  1044.     // 修改加热启动条件,提前开始加热
  1045.     if(output > 20 && current_temp < set_temp + 5) { // 原条件: output > 30
  1046.         heating_request = 1;
  1047.         heating = 1;
  1048.         heating_time++;
  1049.     } else {
  1050.         heating_request = 0;
  1051.         heating = 0;
  1052.         heating_time = 0;
  1053.     }
  1054.    
  1055.     // 检查加热超时
  1056.     if(heating_time > HEATING_TIMEOUT) {
  1057.         error_state = 2;
  1058.     }
  1059.    
  1060.     prev_error = error;
  1061. }

  1062. /**
  1063. * 简介: 检查同步信号并控制加热
  1064. * 功能: 检测交流电过零信号,在过零点开启加热
  1065. */
  1066. void check_sync_signal(void) {
  1067.     // 读取同步信号状态
  1068.     sync_state = (PIND & (1 << SYNC_INPUT)) ? 1 : 0;
  1069.    
  1070.     // 检测同步信号边沿(上升沿或下降沿)
  1071.     if (sync_state != sync_last_state) {
  1072.         // 检测到过零点
  1073.         sync_last_state = sync_state;
  1074.         
  1075.         // 如果有加热请求,在过零点开启加热
  1076.         if (heating_request && !heating_active) {
  1077.             PORTB |= (1 << HEATER_CONTROL); // 开启加热
  1078.             heating_active = 1;
  1079.         }
  1080.     }
  1081.    
  1082.     // 如果不是过零点,保持或关闭加热
  1083.     // 注意:BTA16会在电流过零时自动关断,所以我们不需要主动关断
  1084.     // 但为了确保安全,如果加热请求被取消,立即关闭加热
  1085.     if (!heating_request && heating_active) {
  1086.         PORTB &= ~(1 << HEATER_CONTROL); // 关闭加热
  1087.         heating_active = 0;
  1088.     }
  1089. }

  1090. /**
  1091. * 简介: 处理错误状态
  1092. * 功能: 在错误状态下停止加热,并定时蜂鸣提醒
  1093. */
  1094. void handle_errors(void) {
  1095.     static uint32_t error_beep_timer = 0;
  1096.    
  1097.     if(error_state) {
  1098.         // 每17秒蜂鸣一次 (6000 * 2.8ms = 16.8s)
  1099.         error_beep_timer++;
  1100.         if(error_beep_timer >= 6000) {
  1101.             beep(0,4); // 四声"滴" - 提示错误
  1102.             error_beep_timer = 0;
  1103.         }
  1104.     }
  1105. }

  1106. /**
  1107. * 简介: 检查休眠模式
  1108. * 功能: 检测无活动时间,控制进入休眠和软关机模式
  1109. */
  1110. void check_sleep_mode(void) {
  1111.     static uint32_t last_check_time = 0;
  1112.    
  1113.     // 每1.5秒检查一次休眠和关机状态
  1114.     if (inactive_time - last_check_time < 600) { // 600 * 2.8ms = 1.68s
  1115.         return;
  1116.     }
  1117.     last_check_time = inactive_time;
  1118.    
  1119.     // 10分钟无活动进入休眠
  1120.     if (inactive_time > SLEEP_THRESHOLD && !sleep_mode && !shutdown_mode) {
  1121.         enter_sleep_mode();
  1122.     }
  1123.    
  1124.     // 40分钟无活动进入软关机
  1125.     if (inactive_time > SHUTDOWN_THRESHOLD && !shutdown_mode) {
  1126.         enter_shutdown_mode();
  1127.     }
  1128. }

  1129. /**
  1130. * 简介: 进入休眠模式
  1131. * 功能: 设置休眠模式标志,保存当前温度设置,设定休眠温度
  1132. */
  1133. void enter_sleep_mode(void) {
  1134.     sleep_mode = 1;
  1135.     previous_temp = set_temp;
  1136.     set_temp = 200; // 休眠温度
  1137.     beep(0,1); // 提示进入休眠
  1138. }

  1139. /**
  1140. * 简介: 进入关机模式
  1141. * 功能: 设置关机模式标志,关闭加热和显示,进入无限循环等待重新上电
  1142. */
  1143. void enter_shutdown_mode(void) {
  1144.     shutdown_mode = 1;
  1145.     set_temp = 0; // 关机温度
  1146.    
  1147.     // 确保加热关闭
  1148.     PORTB &= ~(1 << HEATER_CONTROL);
  1149.     heating_request = 0;
  1150.     heating = 0;
  1151.    
  1152.     // 关闭数码管显示
  1153.     PORTC &= ~((1 << DIGIT_1) | (1 << DIGIT_2) | (1 << DIGIT_3));
  1154.     // 关闭段选
  1155.     PORTB |= (1 << SEG_A) | (1 << SEG_F);
  1156.     PORTD |= (1 << SEG_B) | (1 << SEG_C) | (1 << SEG_D) |
  1157.              (1 << SEG_E) | (1 << SEG_G) | (1 << SEG_DP);
  1158.             
  1159.     TIMSK0 &= ~(1 << OCIE0A); // 关闭定时器0中断,停止显示更新
  1160.    
  1161.     beep(1,1); // 提示进入关机
  1162.    
  1163.     // 进入无限循环,等待重新上电
  1164.     while (1) {
  1165.         // 低功耗模式或简单延迟
  1166.         _delay_ms(1000);
  1167.     }
  1168. }

  1169. /**
  1170. * 简介: 退出休眠/关机模式
  1171. * 功能: 退出休眠或关机模式,恢复原来的温度设置
  1172. */
  1173. void exit_sleep_mode(void) {
  1174.     if (sleep_mode) {
  1175.         sleep_mode = 0;
  1176.         set_temp = previous_temp;
  1177.         beep(0,2); // 提示唤醒
  1178.     }
  1179.    
  1180.     if (shutdown_mode) {
  1181.         shutdown_mode = 0;
  1182.         set_temp = previous_temp;
  1183.         beep(0,2); // 提示唤醒
  1184.         
  1185.         // 重新启用定时器0中断,恢复显示更新
  1186.         TIMSK0 |= (1 << OCIE0A);
  1187.     }
  1188. }

  1189. /**
  1190. * 简介: 加载温度参数从EEPROM
  1191. * 功能: 从EEPROM读取校准参数和温度设置,如果EEPROM中没有有效数据,则使用默认参数
  1192. */
  1193. void load_temperature_params(void) {
  1194.     // 检查EEPROM中是否有有效数据
  1195.     uint16_t magic = eeprom_read_word((uint16_t*)EEPROM_MAGIC);
  1196.    
  1197.     if(magic == EEPROM_MAGIC_VALUE) {
  1198.         // 读取用户参数
  1199.         eeprom_read_block(&user_params, (void*)EEPROM_USER_PARAMS, sizeof(TemperatureParams));
  1200.         
  1201.         // 读取出厂参数
  1202.         eeprom_read_block(&factory_params, (void*)EEPROM_FACTORY_PARAMS, sizeof(TemperatureParams));
  1203.         
  1204.         // 计算斜率和截距
  1205.         calculate_slope_intercept(&user_params);
  1206.         
  1207.         // 使用用户参数
  1208.         current_params = user_params;
  1209.         
  1210.         // 加载保存的温度设置
  1211.         set_temp = eeprom_read_word((uint16_t*)EEPROM_TEMP_SETTING);
  1212.         if(set_temp < 150 || set_temp > 500) {
  1213.             set_temp = 280; // 默认温度
  1214.         }
  1215.     } else {
  1216.         // EEPROM中没有有效数据,使用默认出厂参数
  1217.         calculate_slope_intercept(&factory_params);
  1218.         current_params = factory_params;
  1219.         set_temp = 280;
  1220.         
  1221.         // 保存出厂参数到EEPROM
  1222.         eeprom_write_block(&factory_params, (void*)EEPROM_FACTORY_PARAMS, sizeof(TemperatureParams));
  1223.         
  1224.         // 初始化温度补偿偏移量为0
  1225.         eeprom_write_word((uint16_t*)EEPROM_TEMP_OFFSET, 0);
  1226.         
  1227.         // 写入魔术字
  1228.         eeprom_write_word((uint16_t*)EEPROM_MAGIC, EEPROM_MAGIC_VALUE);
  1229.     }
  1230. }

  1231. /**
  1232. * 简介: 保存用户参数到EEPROM
  1233. * 功能: 将用户校准参数保存到EEPROM,并写入魔术字标记有效数据
  1234. */
  1235. void save_user_params(void) {
  1236.     eeprom_write_block(&user_params, (void*)EEPROM_USER_PARAMS, sizeof(TemperatureParams));
  1237.     eeprom_write_word((uint16_t*)EEPROM_MAGIC, EEPROM_MAGIC_VALUE);
  1238. }

  1239. /**
  1240. * 简介: 恢复出厂设置
  1241. * 功能: 将用户参数恢复为出厂参数,重置温度补偿值
  1242. */
  1243. void restore_factory_settings(void) {
  1244.     // 复制出厂参数到用户参数
  1245.     user_params = factory_params;
  1246.     calculate_slope_intercept(&user_params);
  1247.    
  1248.     // 保存用户参数
  1249.     save_user_params();
  1250.    
  1251.     // 使用出厂参数
  1252.     current_params = user_params;
  1253.    
  1254.     // 重置温度补偿
  1255.     eeprom_write_word((uint16_t*)EEPROM_TEMP_OFFSET, 0);
  1256.    
  1257.     // 蜂鸣器三声"滴"提示
  1258.     beep(0, 3);
  1259. }

  1260. /**
  1261. * 简介: 进入校准模式
  1262. * 功能: 设置校准模式标志,初始化校准参数,设置第一个校准点的目标温度
  1263. */
  1264. void enter_calibration_mode(void) {
  1265.     // 等待所有按键释放
  1266.     wait_for_button_release();
  1267.    
  1268.     calibration_mode = 1;
  1269.     calibration_step = 1; // 开始第一点校准
  1270.     calibration_timer = 0;
  1271.     cal_digit_edit = 0;   // 从百位开始编辑
  1272.     cal_heating_stable = 0; // 重置加热稳定标志
  1273.     cal_heating_timer = 0;  // 重置加热计时器
  1274.    
  1275.     // 设置第一个校准点的目标温度
  1276.     cal_target_temp = 200; // 默认第一点目标温度
  1277.     set_temp = cal_target_temp; // 设置系统目标温度
  1278.     eeprom_write_word((uint16_t*)EEPROM_TEMP_SETTING, set_temp);
  1279.    
  1280.     // 初始化测量温度值
  1281.     cal_measured_temp = cal_target_temp;
  1282.    
  1283.     // 蜂鸣器"嗒嗒"两声提示
  1284.     beep(1, 2);
  1285. }

  1286. /**
  1287. * 简介: 进入温度补偿模式
  1288. * 功能: 通过长按K2键进入温度补偿模式,读取当前温度补偿值
  1289. */
  1290. void enter_compensation_mode(void) {
  1291.     // 等待所有按键释放
  1292.     wait_for_button_release();
  1293.    
  1294.     compensation_mode = 1;
  1295.     temp_offset = eeprom_read_word((uint16_t*)EEPROM_TEMP_OFFSET);
  1296.    
  1297.     // 蜂鸣器"滴"一声提示
  1298.     beep(0, 1);
  1299. }

  1300. /**
  1301. * 简介: 蜂鸣器发声函数
  1302. * 参数1: type 发声类型:0-短声"滴",1-长声"嗒"
  1303. * 参数2: count 发声次数
  1304. * 功能: 根据指定类型和次数发出蜂鸣声
  1305. */
  1306. void beep(uint8_t type, uint8_t count) {
  1307.     // 保存当前中断状态并禁用中断,确保蜂鸣声不被中断
  1308.     uint8_t sreg = SREG;
  1309.     cli();
  1310.    
  1311.     // 循环产生指定次数的蜂鸣声
  1312.     for(uint8_t i = 0; i < count; i++) {
  1313.         uint16_t duration = (type == 0) ? BEEP_SHORT : BEEP_LONG;
  1314.         
  1315.         // 产生指定持续时间的蜂鸣声(约500us,2kHz频率)
  1316.         for(uint16_t j = 0; j < duration; j++) {
  1317.             PORTC |= (1 << BUZZER);    // 蜂鸣器引脚置高
  1318.             _delay_us(250);            // 250us高电平
  1319.             PORTC &= ~(1 << BUZZER);   // 蜂鸣器引脚置低
  1320.             _delay_us(250);            // 250us低电平
  1321.         }
  1322.         
  1323.         // 如果不是最后一次蜂鸣,添加间隔
  1324.         if(i < count - 1) {
  1325.             _delay_ms(BEEP_PAUSE);
  1326.         }
  1327.     }
  1328.    
  1329.     // 恢复中断状态
  1330.     SREG = sreg;
  1331. }

  1332. // ============================== 中断服务程序 ==============================

  1333. /**
  1334. * 简介: 定时器0比较匹配中断服务程序 (1ms)
  1335. * 功能: 用于数码管扫描和闪烁控制
  1336. */
  1337. ISR(TIMER0_COMPA_vect) {
  1338.     // 更新数码管显示
  1339.     update_display();
  1340.             
  1341.     // 闪烁控制(500ms周期)
  1342.     blink_timer++;
  1343.     if(blink_timer >= 500) {
  1344.         blink_timer = 0;
  1345.         blink_state = !blink_state;
  1346.     }
  1347. }

  1348. // ============================== 主函数 ==============================

  1349. /**
  1350. * 简介: 主函数
  1351. * 功能: 程序入口点,初始化硬件后进入主循环,
  1352. *          循环执行温度读取、按键检测、PID控制等功能
  1353. */
  1354. int main(void) {
  1355.     // 初始化硬件
  1356.     init_ports();

  1357.     // 开机时检测S1按键(恢复出厂设置)
  1358.     if(!(PINC & (1 << KEY_RST))) {
  1359.         // 等待按键释放
  1360.         _delay_ms(100);
  1361.         while(!(PINC & (1 << KEY_RST)));
  1362.         
  1363.         // 恢复出厂设置
  1364.         restore_factory_settings();
  1365.     }
  1366.    
  1367.     init_adc();    // 继续初始化硬件
  1368.     init_timers();
  1369.    
  1370.     // 显示启动画面
  1371.     show_startup_display();
  1372.    
  1373.     // 加载温度参数
  1374.     load_temperature_params();

  1375.     // 初始化温度采样数组
  1376.     for(uint8_t i = 0; i < SAMPLE_COUNT; i++) {
  1377.         temp_samples[i] = current_temp;
  1378.         temp_sum += current_temp;
  1379.     }
  1380.     samples_collected = SAMPLE_COUNT;
  1381.     display_temp = current_temp;
  1382.    
  1383.     // 启用全局中断
  1384.     sei();
  1385.    
  1386.     // 主循环
  1387.     while(1) {
  1388.         // 如果在软关机模式下,只执行最低限度的操作
  1389.         if (shutdown_mode) {
  1390.             // 低功耗模式或简单延迟
  1391.             _delay_ms(1000);
  1392.             continue;
  1393.         }
  1394.         
  1395.         read_temperature();
  1396.         update_temp_history(); // 更新温度历史记录
  1397.         weighted_moving_average_filter();  // 使用加权移动平均滤波
  1398.         //moving_average_filter();  // 移动平均滤波
  1399.         check_buttons();
  1400.         check_vibration_sensor();// 检查振动传感器
  1401.         
  1402.         if (!error_state) {
  1403.             improved_pid_control();  // 使用改进的PID控制
  1404.             //pid_control();  //只设置heating_request标志
  1405.             check_sync_signal(); // 检查同步信号并控制加热
  1406.             check_sleep_mode();
  1407.         }
  1408.         
  1409.         handle_errors();
  1410.         update_display_buffer();

  1411.         // 增加无活动时间计数
  1412.         inactive_time++;

  1413.          // 增加温度设置改变时间计数
  1414.         if (temp_setting_changed) {
  1415.             temp_setting_change_time++;
  1416.         }
  1417.    
  1418.         // 增加加热稳定时间计数
  1419.         if (calibration_mode && !cal_heating_stable) {
  1420.           cal_heating_timer++;
  1421.         }
  1422.    
  1423.         _delay_ms(2);
  1424.     }
  1425. }
复制代码


打赏

参与人数 1家元 +30 收起 理由
8139 + 30 優秀文章

查看全部打赏

回复 支持 反对

使用道具 举报

发表于 4 小时前 | 显示全部楼层
前排学习 老哥维修烙铁,单片机坏了,自己重新写个程序,牛叉

烙铁修好了,老哥可以去维修保养JL-1、巨浪3、DF31BJ、DF61和DF5C了


二零二五年九月三日,中国人民抗日战争暨世界反法西斯战争胜利80周年纪念日,缅怀革命的先烈,他们为了国家和民族,死战不退,那么多先烈牺牲在了冲锋的路上,换来了我们和平的国家和安宁的生活,致敬革命的先烈和保家卫国的将士们!


回复 支持 反对

使用道具 举报

发表于 3 小时前 来自手机浏览器 | 显示全部楼层
高深的烙铁贴子,过程悲壮,软硬件全面攻坚,最终得以重生。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册 微信登录

本版积分规则

APP|手机版|小黑屋|关于我们|联系我们|法律条款|技术知识分享平台

闽公网安备35020502000485号

闽ICP备2021002735号-2

GMT+8, 2025-9-4 04:59 , Processed in 0.156000 second(s), 10 queries , Gzip On, Redis On.

Powered by Discuz!

© 2006-2025 MyDigit.Net

快速回复 返回顶部 返回列表