|
本帖最后由 jf201006 于 2025-9-3 21:50 编辑
五、弄个程序“复活”963
其实也不是复活,就是利用原来的硬件,换个单片机,写个程序,
让其能简单的控制温度而已。
程序不完善,有些是测试函数,还没有优化。若有使用者使用时,请根据实际情况修改。
- /*
- * ATMEGA168恒温焊台控制程序 内部8MHz
- * 版本:抗战胜利80周年版
- * 日期:2025年9月2日
- * 功能:恒温控制焊台,包括温度采集、PID控制、数码管显示、按键处理、
- * 蜂鸣器提示、休眠模式、温度校准等功能。
- * 软关机后只能通过重新上电唤醒。
- * 版权:坛友可用,本人不答疑哈
- */
- #define F_CPU 8000000UL // 8MHz内部RC振荡器(根据实际熔丝位配置)
- #include <avr/io.h> // AVR I/O端口和寄存器定义
- #include <avr/interrupt.h> // 中断处理函数
- #include <avr/eeprom.h> // EEPROM读写功能
- #include <util/delay.h> // 延时函数
- // ============================== 硬件引脚定义 ==============================
- // 数码管段选引脚定义 (共阳极,低电平点亮)
- #define SEG_A PB6 // PB6 - 数码管A段
- #define SEG_B PD0 // PD0 - 数码管B段
- #define SEG_C PD2 // PD2 - 数码管C段
- #define SEG_D PD4 // PD4 - 数码管D段
- #define SEG_E PD5 // PD5 - 数码管E段
- #define SEG_F PB7 // PB7 - 数码管F段
- #define SEG_G PD1 // PD1 - 数码管G段
- #define SEG_DP PD3 // PD3 - 数码管小数点
- // 数码管位选引脚定义 (高电平选通)
- #define DIGIT_1 PC1 // PC1 - 第一位数字(百位)
- #define DIGIT_2 PC4 // PC4 - 第二位数字(十位)
- #define DIGIT_3 PC5 // PC5 - 第三位数字(个位)
- // 按键引脚定义 (按下时接地,内部上拉电阻)
- #define KEY_DEC PB3 // K1 - 减温度按键
- #define KEY_FUNC PB4 // K2 - 功能键/快速设置按键
- #define KEY_INC PB5 // K3 - 加温度按键
- #define KEY_RST PC2 // S1 - 恢复出厂设置按键
- // 其他引脚定义
- #define VIBRATION_SENSOR PB0 // 振动传感器输入(低电平有效)
- #define SYNC_INPUT PD6 // 交流同步采样输入
- #define HEATER_CONTROL PB1 // 加热控制输出(高电平加热)
- #define BUZZER PC0 // 蜂鸣器控制输出
- // ADC通道定义
- #define TEMP_ADC 7 // ADC7 - 温度传感器输入
- // ============================== 数码管显示编码 ==============================
- // 数码管显示字符编码 (共阳极, 低电平有效)
- // 索引0-9对应数字0-9,10-14对应特殊字符
- const uint8_t seg_pattern[] = {
- 0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90, // 0-9
- 0x86, 0xBF, 0xFF, 0x92, 0x89 // E(10), -(11), 空格(12), S(13), H(14)
- };
- // ============================== EEPROM存储定义 ==============================
- // EEPROM存储地址定义
- #define EEPROM_FACTORY_PARAMS 0 // 出厂参数存储地址(12字节)
- #define EEPROM_USER_PARAMS 12 // 用户参数存储地址(12字节)
- #define EEPROM_MAGIC 24 // 魔术字存储地址(2字节)
- #define EEPROM_TEMP_SETTING 26 // 温度设置存储地址(2字节)
- #define EEPROM_TEMP_OFFSET 28 // 温度补偿偏移量(2字节)
- #define EEPROM_MAGIC_VALUE 0x55AA // 魔术字值,用于验证EEPROM数据有效性
- // ============================== 时间阈值定义 ==============================
- // 时间阈值定义(单位:主循环周期,每个周期约1ms)(根据实际修改)
- // 实测值(主循环每个周期约2.8ms 左右)
- #define SLEEP_THRESHOLD 100000 // 10分钟(220000)无活动进入休眠(测试用:5分钟)
- #define SHUTDOWN_THRESHOLD 120000 // 40分钟(850000)无活动进入软关机(测试用:5.5分钟)
- #define HEATING_TIMEOUT 12500 // 加热超时时间(35秒:12500 * 2.8ms = 35s)
- // ============================== 全局变量定义 ==============================
- // 温度相关变量
- volatile uint16_t current_temp = 0; // 当前测量的温度值(单位:℃)
- volatile uint16_t set_temp = 280; // 设定的目标温度值(单位:℃)
- volatile uint16_t previous_temp = 280; // 进入休眠前的温度设置
- volatile uint16_t adc_value = 0; // ADC采样原始值
- // 显示相关变量
- volatile uint8_t display_buffer[3] = {0, 0, 0}; // 数码管显示缓冲区(百位、十位、个位)
- volatile uint8_t display_index = 0; // 当前显示的数码管位索引(0-2)
- // 状态标志变量
- volatile uint8_t heating = 0; // 加热状态标志(0:停止加热,1:正在加热)
- volatile uint8_t error_state = 0; // 错误状态(0:无错误,1:传感器错误,2:加热错误)
- volatile uint8_t calibration_mode = 0; // 校准模式标志(0:正常模式,1:校准模式)
- volatile uint8_t setting_mode = 0; // 设置模式标志(0:正常显示,1:显示设置值)
- volatile uint8_t sleep_mode = 0; // 休眠模式标志(0:正常模式,1:休眠模式)
- volatile uint8_t shutdown_mode = 0; // 关机模式标志(0:正常模式,1:关机模式)
- // 时间计数变量
- volatile uint32_t heating_time = 0; // 加热时间计数(用于超时检测)
- volatile uint32_t inactive_time = 0; // 无活动时间计数(用于休眠检测)
- volatile uint32_t setting_timer = 0; // 设置模式计时器(用于自动退出设置模式)
- // 温度校准相关变量
- volatile uint8_t calibration_step = 0; // 校准步骤 (0:未校准, 1:第一点, 2:第二点)
- volatile uint32_t calibration_timer = 0; // 校准计时器
- #define CALIBRATION_TIMEOUT 100000 // 10分钟(600000)超时(测试用:5分钟)
- // 温度补偿相关变量
- volatile uint8_t compensation_mode = 0; // 温度补偿模式标志
- volatile int16_t temp_offset = 0; // 温度补偿偏移量
- // 显示效果变量
- volatile uint8_t blink_state = 0; // 闪烁状态(0:显示,1:隐藏)
- volatile uint32_t blink_timer = 0; // 闪烁计时器
- // 显示滤波相关变量
- #define SAMPLE_COUNT 30 // 采样次数
- volatile uint16_t temp_samples[SAMPLE_COUNT]; // 温度采样数组
- volatile uint8_t sample_index = 0; // 当前采样索引
- volatile uint32_t temp_sum = 0; // 温度总和
- volatile uint8_t samples_collected = 0; // 已收集的样本数
- volatile uint16_t display_temp = 0; // 滤波后的显示温度值
- // 同步加热相关变量
- volatile uint8_t sync_state = 0; // 同步信号状态
- volatile uint8_t sync_last_state = 0; // 上一次同步信号状态
- volatile uint8_t heating_request = 0; // 加热请求标志
- volatile uint8_t heating_active = 0; // 加热激活标志
- // 温度设置保存相关变量
- volatile uint8_t temp_setting_changed = 0; // 温度设置改变标志
- volatile uint32_t temp_setting_change_time = 0; // 温度设置改变时间
- #define SETTING_SAVE_DELAY 5000 // 5秒后保存温度设置
- // 校准模式相关变量
- volatile uint8_t cal_digit_edit = 0; // 当前编辑的位数(0:百位,1:十位,2:个位)
- volatile uint16_t cal_target_temp = 0; // 校准目标温度值
- volatile uint16_t cal_measured_temp = 0; // 校准测量温度值
- volatile uint8_t cal_heating_stable = 0; // 加热稳定标志
- volatile uint32_t cal_heating_timer = 0; // 加热计时器
- #define HEATING_STABLE_TIME 65000 // 加热稳定时间(约3分钟:65000 * 2.8ms )
- // 在全局变量区域添加
- volatile float temp_change_rate = 0; // 温度变化率 (°C/秒)
- volatile uint16_t prev_temp_history[5] = {0}; // 历史温度值
- volatile uint8_t temp_history_index = 0;
- // 蜂鸣器发声相关变量
- #define BEEP_SHORT 100 // 短声"滴"的持续时间(ms)
- #define BEEP_LONG 300 // 长声"嗒"的持续时间(ms)
- #define BEEP_PAUSE 100 // 蜂鸣声之间的间隔时间(ms)
- // PID控制参数结构体
- typedef struct {
- float kp; // 比例系数(升温快则调小,避免超调)
- float ki; // 积分系数(低温段调大,消除静态误差)
- float kd; // 微分系数(高温段调大,抑制波动)
- float integral; // 积分项累计值
- float prev_error; // 上一次误差值(用于微分计算)
- } PIDParams;
- // 两点法温度参数结构体
- typedef struct {
- uint16_t temp1; // 第一点温度值 (如200°C)
- uint16_t voltage1; // 第一点电压值 (如530mV)
- uint16_t temp2; // 第二点温度值 (如350°C)
- uint16_t voltage2; // 第二点电压值 (如975mV)
- float len_k; // 斜率 (计算得出)
- float len_b; // 截距 (计算得出)
- } TemperatureParams;
- // 全局结构体变量
- PIDParams pid_params; // PID控制参数
- TemperatureParams factory_params = {200, 530, 350, 975, 0, 0}; // 默认出厂参数
- TemperatureParams user_params; // 用户参数
- TemperatureParams current_params; // 当前使用的参数
- // ============================== 函数声明 ==============================
- // 初始化函数
- void init_ports(void); // 初始化所有I/O端口
- void init_adc(void); // 初始化ADC模块
- void init_timers(void); // 初始化定时器
- // 显示函数
- void update_display(void); // 更新数码管显示
- void display_segment(uint8_t seg); // 控制数码管段选输出
- void update_display_buffer(void); // 更新显示缓冲区
- void moving_average_filter(void); // 移动平均滤波函数
- // 温度相关函数
- void read_temperature(void); // 读取温度值
- void pid_control(void); // PID控制算法
- void calculate_slope_intercept(TemperatureParams *params); // 计算两点法的斜率和截距
- // 按键和传感器处理
- void check_buttons(void); // 检查按键状态
- void check_vibration_sensor(void); // 检查振动传感器
- void check_sync_signal(void); // 检查同步信号并控制加热
- // 状态管理函数
- void check_sleep_mode(void); // 检查休眠模式
- void enter_sleep_mode(void); // 进入休眠模式
- void enter_shutdown_mode(void);// 进入关机模式
- void exit_sleep_mode(void); // 退出休眠/关机模式
- // 校准和设置函数
- void enter_calibration_mode(void); // 进入校准模式
- void save_user_params(void); // 保存用户参数到EEPROM
- void restore_factory_settings(void); // 恢复出厂设置
- void enter_compensation_mode(void); // 进入温度补偿模式
- // 工具函数
- void beep(uint8_t type, uint8_t count); // 蜂鸣器发声
- void show_startup_display(void); // 显示启动画面
- void wait_for_button_release(void); // 等待所有按键释放
- void handle_errors(void); // 处理错误状态
- // ============================== 函数实现 ==============================
- /**
- * 简介: 初始化所有I/O端口
- * 功能: 配置数码管、按键、加热控制、蜂鸣器等引脚的输入输出方向和初始状态
- */
- void init_ports(void) {
- // 数码管段选引脚设置为输出
- DDRB |= (1 << SEG_A) | (1 << SEG_F);
- DDRD |= (1 << SEG_B) | (1 << SEG_C) | (1 << SEG_D) |
- (1 << SEG_E) | (1 << SEG_G) | (1 << SEG_DP);
-
- // 数码管位选引脚设置为输出
- DDRC |= (1 << DIGIT_1) | (1 << DIGIT_2) | (1 << DIGIT_3);
-
- // 初始关闭所有数码管(段选高电平,位选低电平)
- PORTB |= (1 << SEG_A) | (1 << SEG_F);
- PORTD |= (1 << SEG_B) | (1 << SEG_C) | (1 << SEG_D) |
- (1 << SEG_E) | (1 << SEG_G) | (1 << SEG_DP);
- PORTC &= ~((1 << DIGIT_1) | (1 << DIGIT_2) | (1 << DIGIT_3));
-
- // 按键引脚设置为输入,启用上拉电阻
- DDRB &= ~((1 << KEY_DEC) | (1 << KEY_FUNC) | (1 << KEY_INC));
- PORTB |= (1 << KEY_DEC) | (1 << KEY_FUNC) | (1 << KEY_INC);
-
- DDRC &= ~(1 << KEY_RST);
- PORTC |= (1 << KEY_RST);
-
- // 振动传感器设置为输入,启用上拉电阻
- DDRB &= ~(1 << VIBRATION_SENSOR);
- PORTB |= (1 << VIBRATION_SENSOR);
-
- // 加热控制引脚设置为输出,初始关闭加热
- DDRB |= (1 << HEATER_CONTROL);
- PORTB &= ~(1 << HEATER_CONTROL);
-
- // 蜂鸣器引脚设置为输出,初始关闭蜂鸣器
- DDRC |= (1 << BUZZER);
- PORTC &= ~(1 << BUZZER);
-
- // 同步输入引脚设置为输入
- DDRD &= ~(1 << SYNC_INPUT);
- PORTD &= ~(1 << SYNC_INPUT);
- }
- /**
- * 简介: 初始化ADC模块
- * 功能: 配置ADC参考电压、输入通道和预分频器,进行第一次转换丢弃
- */
- void init_adc(void) {
- // 使用外部AREF作为参考电压,选择ADC7通道
- ADMUX = (0 << REFS1) | (0 << REFS0) | (TEMP_ADC & 0x0F);
- // 使能ADC,预分频128
- ADCSRA = (1 << ADEN) | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0);
- // 第一次转换丢弃,确保ADC稳定
- ADCSRA |= (1 << ADSC);
- while(ADCSRA & (1 << ADSC));
- }
- /**
- * 简介: 初始化定时器
- * 功能: 配置定时器0用于数码管扫描和按键检测(约1ms中断)
- */
- void init_timers(void) {
- // 定时器0用于数码管扫描和按键检测 (CTC模式,64分频)
- TCCR0A = (1 << WGM01); // CTC模式
- TCCR0B = (1 << CS01) | (1 << CS00); // 64分频
- // OCR0A = 15; // 1ms中断 (1MHz/64/16 = 1024μs ≈ 1ms)
- OCR0A = 124; // 1ms中断 (8MHz/64/125 = 1000μs = 1ms)
- TIMSK0 = (1 << OCIE0A); // 启用比较匹配中断
- }
- /**
- * 简介: 显示启动画面
- * 功能: 显示"963"启动画面并发出蜂鸣声,禁用中断确保显示完整
- */
- void show_startup_display(void) {
- // 保存当前中断状态并禁用中断,确保启动画面显示不受干扰
- uint8_t sreg = SREG;
- cli();
-
- // 显示"963"启动画面,持续约500ms
- for(uint16_t i = 0; i < 178; i++) { // 178 * 2.8 = 498 ms
- // 显示第一位数字9
- PORTC &= ~((1 << DIGIT_1) | (1 << DIGIT_2) | (1 << DIGIT_3));
- display_segment(seg_pattern[9]);
- PORTC |= (1 << DIGIT_1);
- _delay_ms(1);
-
- // 显示第二位数字6
- PORTC &= ~((1 << DIGIT_1) | (1 << DIGIT_2) | (1 << DIGIT_3));
- display_segment(seg_pattern[6]);
- PORTC |= (1 << DIGIT_2);
- _delay_ms(1);
-
- // 显示第三位数字3
- PORTC &= ~((1 << DIGIT_1) | (1 << DIGIT_2) | (1 << DIGIT_3));
- display_segment(seg_pattern[3]);
- PORTC |= (1 << DIGIT_3);
- _delay_ms(1);
- }
-
- // 蜂鸣提示
- beep(0,1);
-
- // 恢复中断状态
- SREG = sreg;
- }
- /**
- * 简介: 更新显示缓冲区
- * 功能: 根据当前状态(正常、错误、校准、设置)更新显示缓冲区内容
- */
- void update_display_buffer(void) {
- if (compensation_mode) {
- // 温度补偿模式显示补偿值
- int16_t display_offset = temp_offset;
- uint8_t sign = 0; // 0:正数, 1:负数
-
- if (display_offset < 0) {
- sign = 1;
- display_offset = -display_offset;
- }
-
- display_buffer[0] = sign ? 11 : 12; // "-"或空格
- display_buffer[1] = display_offset / 10;
- display_buffer[2] = display_offset % 10;
- }
- else if (calibration_mode) {
- if (cal_heating_stable) {
- // 加热稳定后,显示测量温度值
- display_buffer[0] = cal_measured_temp / 100;
- display_buffer[1] = (cal_measured_temp % 100) / 10;
- display_buffer[2] = cal_measured_temp % 10;
- } else {
- // 加热过程中,显示目标温度值
- display_buffer[0] = cal_target_temp / 100;
- display_buffer[1] = (cal_target_temp % 100) / 10;
- display_buffer[2] = cal_target_temp % 10;
- }
- }
- else if (error_state == 1) {
- // 传感器错误显示"S-E"
- display_buffer[0] = 13; // S
- display_buffer[1] = 11; // -
- display_buffer[2] = 10; // E
- } else if (error_state == 2) {
- // 加热错误显示"H-E"
- display_buffer[0] = 14; // H
- display_buffer[1] = 11; // -
- display_buffer[2] = 10; // E
- } else if (setting_mode) {
- // 设置模式显示设置值
- display_buffer[0] = set_temp / 100;
- display_buffer[1] = (set_temp % 100) / 10;
- display_buffer[2] = set_temp % 10;
- } else if (shutdown_mode) {
- // 关机模式显示空白
- display_buffer[0] = 12; // 空格
- display_buffer[1] = 12; // 空格
- display_buffer[2] = 12; // 空格
- } else if (sleep_mode) {
- // 休眠模式显示当前温度(可能闪烁)
- if (blink_state) {
- display_buffer[0] = display_temp / 100;
- display_buffer[1] = (display_temp % 100) / 10;
- display_buffer[2] = display_temp % 10;
- } else {
- display_buffer[0] = 12; // 空格
- display_buffer[1] = 12; // 空格
- display_buffer[2] = 12; // 空格
- }
- } else {
- // 正常模式显示当前温度
- display_buffer[0] = display_temp / 100;
- display_buffer[1] = (display_temp % 100) / 10;
- display_buffer[2] = display_temp % 10;
- }
- }
- /**
- * 简介: 更新数码管显示
- * 功能: 根据当前显示索引,更新对应数码管的显示内容
- * 在定时器中断中调用
- */
- void update_display(void) {
- // 关闭所有位选
- PORTC &= ~((1 << DIGIT_1) | (1 << DIGIT_2) | (1 << DIGIT_3));
-
- // 根据错误状态显示相应内容
- if (error_state && blink_state) {
- // 错误状态下闪烁显示
- return;
- }
- uint8_t digit = display_buffer[display_index];
- uint8_t pattern = seg_pattern[digit];
-
- // 如果是最后一位且正在加热,显示小数点
- if (display_index == 2 && heating) {
- pattern &= ~(1 << 7); // 点亮小数点(清零DP位)
- }
-
- // 校准模式下且加热稳定后,闪烁当前编辑的数字位
- if (calibration_mode && cal_heating_stable && display_index == cal_digit_edit && blink_state) {
- pattern = 0xFF; // 全部熄灭(隐藏当前位)
- }
- // 第一步:计算亮度补偿因子
- uint8_t lit_segments = 0;
- for(uint8_t i = 0; i < 8; i++) {
- if(!(pattern & (1 << i))) lit_segments++;
- }
- if(lit_segments < 3) lit_segments = 3;
- uint8_t display_cycles = 12 - lit_segments;
-
- display_segment(pattern);
-
- // 选择对应的位
- switch(display_index) {
- case 0: PORTC |= (1 << DIGIT_1); break; // 选通百位
- case 1: PORTC |= (1 << DIGIT_2); break; // 选通十位
- case 2: PORTC |= (1 << DIGIT_3); break; // 选通个位
- }
- // 第二步:亮度补偿
- for(uint8_t i = 0; i < display_cycles; i++) {
- _delay_us(80);
- }
-
- // 更新显示索引(循环0-2)
- display_index = (display_index + 1) % 3;
- }
- /**
- * 简介: 控制数码管段选输出
- * 参数: seg 段选模式(8 bit,每bit对应一个段)
- * 功能: 根据段选模式控制对应的段选引脚输出
- */
- void display_segment(uint8_t seg) {
- // PORTB处理:A段(PB6)和F段(PB7)
- if(!(seg & 0x01)) PORTB &= ~(1 << SEG_A); // A段点亮
- else PORTB |= (1 << SEG_A); // A段熄灭
- if(!(seg & 0x20)) PORTB &= ~(1 << SEG_F); // F段点亮
- else PORTB |= (1 << SEG_F); // F段熄灭
-
- // PORTD处理:B,C,D,E,G,DP段
- if(!(seg & 0x02)) PORTD &= ~(1 << SEG_B); // B段点亮
- else PORTD |= (1 << SEG_B); // B段熄灭
- if(!(seg & 0x04)) PORTD &= ~(1 << SEG_C); // C段点亮
- else PORTD |= (1 << SEG_C); // C段熄灭
- if(!(seg & 0x08)) PORTD &= ~(1 << SEG_D); // D段点亮
- else PORTD |= (1 << SEG_D); // D段熄灭
- if(!(seg & 0x10)) PORTD &= ~(1 << SEG_E); // E段点亮
- else PORTD |= (1 << SEG_E); // E段熄灭
- if(!(seg & 0x40)) PORTD &= ~(1 << SEG_G); // G段点亮
- else PORTD |= (1 << SEG_G); // G段熄灭
- if(!(seg & 0x80)) PORTD &= ~(1 << SEG_DP); // DP段点亮
- else PORTD |= (1 << SEG_DP); // DP段熄灭
- }
- /**
- * 简介: 读取温度值
- * 功能: 启动ADC转换,读取ADC值,计算电压和温度值,
- * 应用校准参数,检查传感器故障
- */
- void read_temperature(void) {
- // 启动ADC转换
- ADCSRA |= (1 << ADSC);
- // 等待转换完成
- while(ADCSRA & (1 << ADSC));
-
- // 读取ADC值
- adc_value = ADC;
-
- // 计算电压值 (mV)
- uint32_t voltage = (adc_value * 2500UL) / 1024;
-
- // 检查传感器故障 (电压超过2.2V)
- if(voltage > 2200) {
- error_state = 1;
- return;
- }
-
- // 使用两点法计算温度
- // current_temp = (voltage - len_b) / len_k
- float temp_float = ((float)voltage - current_params.len_b) / current_params.len_k;
-
- // 应用温度补偿
- int16_t temp_compensated = (int16_t)temp_float + eeprom_read_word((uint16_t*)EEPROM_TEMP_OFFSET);
-
- // 限制温度范围
- if (temp_compensated < 0) temp_compensated = 0;
- if (temp_compensated > 999) temp_compensated = 999;
-
- current_temp = (uint16_t)temp_compensated;
- }
- void update_temp_history(void) {
- prev_temp_history[temp_history_index] = current_temp;
- temp_history_index = (temp_history_index + 1) % 5;
-
- // 计算温度变化率 (近5次采样的平均变化)
- int16_t sum_diff = 0;
- for(uint8_t i = 0; i < 4; i++) {
- sum_diff += (int16_t)prev_temp_history[(temp_history_index + i) % 5] -
- (int16_t)prev_temp_history[(temp_history_index + i + 1) % 5];
- }
- temp_change_rate = (float)sum_diff / (4.0 * 5.0); // 5次采样间隔约5*5ms=25ms
- }
- /**
- * 简介: 改进的PID控制算法
- * 功能: 加入温度变化率预测,提前减少加热功率
- */
- void improved_pid_control(void) {
- if(error_state) {
- heating_request = 0;
- heating = 0;
- heating_time = 0;
- return;
- }
-
- static float integral = 0;
- static float prev_measurement = 0;
-
- // PID参数
- float kp = 3.0;
- float ki = 0.02;
- float kd = 6.0;
-
- float error = set_temp - current_temp;
-
- // 比例项
- float p_term = kp * error;
-
- // 积分项 - 条件积分
- if(fabs(error) > 5 || integral * error > 0) {
- integral += error;
- }
- // 积分限幅
- if(integral > 80) integral = 80;
- if(integral < -80) integral = -80;
- float i_term = ki * integral;
-
- // 微分项 - 基于测量值的变化率
- float derivative = (current_temp - prev_measurement);
- float d_term = kd * derivative;
- prev_measurement = current_temp;
-
- // 基本PID输出
- float output = p_term + i_term - d_term;
-
- // 温度变化率预测修正
- if(temp_change_rate > 2.0 && current_temp > set_temp - 10) {
- // 温度上升较快,提前减少加热
- output -= temp_change_rate * 5.0;
- }
-
- // 限制输出范围
- if(output > 100) output = 100;
- if(output < 0) output = 0;
-
- // 设置加热请求标志
- if(output > 15 && current_temp < set_temp + 8) {
- heating_request = 1;
- heating = 1;
- heating_time++;
- } else {
- heating_request = 0;
- heating = 0;
- heating_time = 0;
- }
-
- // 检查加热超时
- if(heating_time > HEATING_TIMEOUT) {
- error_state = 2;
- }
- }
- /**
- * 简介: 加权移动平均滤波函数
- * 功能: 使用指数加权移动平均,对新数据给予更高权重
- */
- void weighted_moving_average_filter(void) {
- // 指数加权移动平均 (EWMA)
- // 新样本权重为0.7,旧平均值权重为0.3
- display_temp = (uint16_t)(0.7 * current_temp + 0.3 * display_temp);
- }
- /**
- * 简介: 检查同步信号并控制加热 - 优化版本
- * 功能: 改进加热控制逻辑,减少过冲
- */
- void check_sync_signal_optimized(void) {
- // 读取同步信号状态
- sync_state = (PIND & (1 << SYNC_INPUT)) ? 1 : 0;
-
- // 检测同步信号边沿(上升沿或下降沿)
- if (sync_state != sync_last_state) {
- sync_last_state = sync_state;
-
- // 如果有加热请求,在过零点开启加热
- if (heating_request && !heating_active) {
- // 温度接近设定值时,减少加热时间
- if(current_temp > set_temp - 5) {
- // 只加热半波
- PORTB |= (1 << HEATER_CONTROL);
- _delay_us(8000); // 约半波时间(10ms/2)
- PORTB &= ~(1 << HEATER_CONTROL);
- } else {
- // 全波加热
- PORTB |= (1 << HEATER_CONTROL);
- heating_active = 1;
- }
- }
- }
-
- // 如果不是过零点,保持或关闭加热
- if (!heating_request && heating_active) {
- PORTB &= ~(1 << HEATER_CONTROL);
- heating_active = 0;
- }
- }
- /**
- * 简介: 计算两点法的斜率和截距
- * 参数: params 温度参数结构体指针
- */
- void calculate_slope_intercept(TemperatureParams *params) {
- // 计算斜率 len_k = (voltage2 - voltage1) / (temp2 - temp1)
- params->len_k = (float)(params->voltage2 - params->voltage1) /
- (float)(params->temp2 - params->temp1);
-
- // 计算截距 len_b = voltage1 - len_k * temp1
- params->len_b = (float)params->voltage1 - params->len_k * params->temp1;
- }
- /**
- * 简介: 移动平均滤波函数
- * 功能: 使用30次采样值的移动平均来平滑温度显示
- * 大约每150ms更新一次显示温度(30*5ms)
- */
- void moving_average_filter(void) {
- // 减去最旧的样本值
- temp_sum -= temp_samples[sample_index];
-
- // 添加最新的样本值
- temp_samples[sample_index] = current_temp;
- temp_sum += current_temp;
-
- // 更新样本索引
- sample_index = (sample_index + 1) % SAMPLE_COUNT;
-
- // 计算移动平均值
- if (samples_collected < SAMPLE_COUNT) {
- samples_collected++;
- }
-
- display_temp = (temp_sum + samples_collected/2) / samples_collected; // 四舍五入
- }
- /**
- * 简介: 等待所有按键释放
- * 功能: 检测所有按键是否已释放,防止误操作
- */
- void wait_for_button_release(void) {
- // 等待所有按键释放
- while(!(PINB & (1 << KEY_DEC)) ||
- !(PINB & (1 << KEY_FUNC)) ||
- !(PINB & (1 << KEY_INC)) ||
- !(PINC & (1 << KEY_RST))) {
- _delay_ms(10);
- }
-
- // 添加去抖动延迟
- _delay_ms(50);
- }
- /**
- * 简介: 检查按键状态
- * 功能: 检测按键按下、长按等事件,处理按键功能,
- * 包括温度调整、快速设置、进入校准模式等
- */
- void check_buttons(void) {
- // 如果在软关机模式下,直接返回
- if (shutdown_mode) {
- return;
- }
-
- static uint8_t last_key_state = 0;
- static uint32_t key_press_time = 0;
- static uint32_t key_repeat_time = 0;
- static uint32_t combo_timer = 0;
- static uint8_t cal_key_released = 1; // 校准按键释放标志
- static uint32_t k2_press_time = 0;
- static uint8_t quick_set_index = 0;
- uint8_t current_key_state = 0;
-
- // 读取K1、K2、K3按键状态
- if(!(PINB & (1 << KEY_DEC))) current_key_state |= 1;
- if(!(PINB & (1 << KEY_FUNC))) current_key_state |= 2;
- if(!(PINB & (1 << KEY_INC))) current_key_state |= 4;
-
- // 检测组合键按下(K1+K2+K3同时按下)
- if((current_key_state & 7) == 7 && !calibration_mode && !compensation_mode) {
- combo_timer++;
-
- if(combo_timer > 100) { // 约280ms后确认组合键(250 * 2.8ms = 280ms)
- enter_calibration_mode();
- combo_timer = 0;
- }
- } else {
- // 重置组合键计时器
- combo_timer = 0;
- }
-
- // 如果当前处于校准模式,处理校准按键
- if (calibration_mode) {
- // 重置无活动时间
- inactive_time = 0;
-
- // 检查超时 (10分钟)
- calibration_timer++;
- if (calibration_timer >= CALIBRATION_TIMEOUT) {
- calibration_mode = 0;
- calibration_step = 0;
- cal_heating_stable = 0;
- beep(0, 1); // 超时提示
- return;
- }
-
- // 检查加热是否稳定
- if (!cal_heating_stable) {
- cal_heating_timer++;
- if (cal_heating_timer >= HEATING_STABLE_TIME) {
- cal_heating_stable = 1;
- cal_digit_edit = 0; // 从百位开始编辑
- beep(0, 1); // 加热稳定提示
- }
- return; // 加热过程中不处理按键
- }
-
- // 检测按键按下
- if (current_key_state && cal_key_released) {
- cal_key_released = 0;
-
- if (calibration_step == 1) {
- // 第一点校准 - 输入测量温度值
- if (current_key_state & 2) { // K2键 - 切换位或确认
- if (cal_digit_edit < 2) {
- // 切换到下一位
- cal_digit_edit++;
- } else {
- // 确认第一点测量值
- if (cal_measured_temp >= 150 && cal_measured_temp <= 500) {
- user_params.temp1 = cal_measured_temp;
-
- // 读取当前电压值
- ADCSRA |= (1 << ADSC);
- while(ADCSRA & (1 << ADSC));
- user_params.voltage1 = (ADC * 2500UL) / 1024;
-
- // 进入第二点校准
- calibration_step = 2;
- cal_heating_stable = 0; // 重置加热稳定标志
- cal_heating_timer = 0; // 重置加热计时器
-
- // 设置第二个校准点的目标温度
- cal_target_temp = 350; // 默认第二点目标温度
- set_temp = cal_target_temp; // 设置系统目标温度
- eeprom_write_word((uint16_t*)EEPROM_TEMP_SETTING, set_temp);
-
- // 初始化测量温度值
- cal_measured_temp = cal_target_temp;
-
- beep(0, 1); // "滴"一声提示
- }
- }
- }
- else if (current_key_state & 4) { // K3键增加当前位数值
- uint16_t multiplier = 1;
- for (uint8_t i = 0; i < (2 - cal_digit_edit); i++) {
- multiplier *= 10;
- }
- cal_measured_temp += multiplier;
- if (cal_measured_temp > 500) cal_measured_temp = 150;
- }
- else if (current_key_state & 1) { // K1键减少当前位数值
- uint16_t multiplier = 1;
- for (uint8_t i = 0; i < (2 - cal_digit_edit); i++) {
- multiplier *= 10;
- }
- if (cal_measured_temp < multiplier + 150) cal_measured_temp = 500;
- else cal_measured_temp -= multiplier;
- }
- }
- else if (calibration_step == 2) {
- // 第二点校准 - 输入测量温度值
- if (current_key_state & 2) { // K2键 - 切换位或确认
- if (cal_digit_edit < 2) {
- // 切换到下一位
- cal_digit_edit++;
- } else {
- // 确认第二点测量值
- if (cal_measured_temp >= 150 && cal_measured_temp <= 500) {
- user_params.temp2 = cal_measured_temp;
-
- // 读取当前电压值
- ADCSRA |= (1 << ADSC);
- while(ADCSRA & (1 << ADSC));
- user_params.voltage2 = (ADC * 2500UL) / 1024;
-
- // 完成校准,保存参数
- calculate_slope_intercept(&user_params);
- save_user_params();
- current_params = user_params;
-
- calibration_mode = 0;
- calibration_step = 0;
- cal_heating_stable = 0;
- beep(0, 2); // "滴滴"两声提示
- }
- }
- }
- else if (current_key_state & 4) { // K3键增加当前位数值
- uint16_t multiplier = 1;
- for (uint8_t i = 0; i < (2 - cal_digit_edit); i++) {
- multiplier *= 10;
- }
- cal_measured_temp += multiplier;
- if (cal_measured_temp > 500) cal_measured_temp = 150;
- }
- else if (current_key_state & 1) { // K1键减少当前位数值
- uint16_t multiplier = 1;
- for (uint8_t i = 0; i < (2 - cal_digit_edit); i++) {
- multiplier *= 10;
- }
- if (cal_measured_temp < multiplier + 150) cal_measured_temp = 500;
- else cal_measured_temp -= multiplier;
- }
- }
- }
-
- // 检测按键释放
- if (!current_key_state) {
- cal_key_released = 1;
- }
-
- return; // 在校准模式下,不处理其他按键
- }
-
- // 如果当前处于补偿模式,处理补偿按键
- if (compensation_mode) {
- // 重置无活动时间
- inactive_time = 0;
-
- // 检测按键按下
- if (current_key_state && cal_key_released) {
- cal_key_released = 0;
-
- if (current_key_state & 2) { // K2键确认
- // 保存温度补偿值
- eeprom_write_word((uint16_t*)EEPROM_TEMP_OFFSET, temp_offset);
- compensation_mode = 0;
- beep(0, 2); // "滴滴"两声提示
- }
- else if (current_key_state & 4) { // K3键增加补偿值
- temp_offset++;
- if (temp_offset > 50) temp_offset = -50;
- }
- else if (current_key_state & 1) { // K1键减少补偿值
- temp_offset--;
- if (temp_offset < -50) temp_offset = 50;
- }
- }
-
- // 检测按键释放
- if (!current_key_state) {
- cal_key_released = 1;
- }
-
- return; // 在补偿模式下,不处理其他按键
- }
-
- // 检测长按K2键进入温度补偿模式
- if(!(PINB & (1 << KEY_FUNC))) {
- k2_press_time++;
- if(k2_press_time > 2000) { // 长按2秒
- if(!compensation_mode && !calibration_mode) {
- enter_compensation_mode();
- }
- k2_press_time = 0;
- }
- } else {
- k2_press_time = 0;
- }
-
- // 检测按键按下
- if(current_key_state && !last_key_state) {
- key_press_time = 0;
- key_repeat_time = 0;
-
- // 退出休眠模式
- if(sleep_mode) {
- exit_sleep_mode();
- } else {
- // 重置无活动时间
- inactive_time = 0;
- }
-
- // 快速设置温度
- if((current_key_state & 2) && !calibration_mode && !compensation_mode) {
- uint16_t quick_set_temps[] = {250, 330, 380};
- set_temp = quick_set_temps[quick_set_index];
- quick_set_index = (quick_set_index + 1) % 3;
- temp_setting_changed = 1; // 标记温度设置已改变
- temp_setting_change_time = 0; // 重置改变时间
- setting_mode = 1;
- setting_timer = 0;
- }
- // 增加温度
- else if((current_key_state & 4) && set_temp < 500 && !calibration_mode && !compensation_mode) {
- set_temp++;
- temp_setting_changed = 1; // 标记温度设置已改变
- temp_setting_change_time = 0; // 重置改变时间
- setting_mode = 1;
- setting_timer = 0;
- }
- // 减少温度
- else if((current_key_state & 1) && set_temp > 150 && !calibration_mode && !compensation_mode) {
- set_temp--;
- temp_setting_changed = 1; // 标记温度设置已改变
- temp_setting_change_time = 0; // 重置改变时间
- setting_mode = 1;
- setting_timer = 0;
- }
- }
-
- // 检测长按
- if(current_key_state == last_key_state && current_key_state) {
- key_press_time++;
-
- // 长按500ms后加速调整 (178 * 2.8ms = 498ms)
- if(key_press_time > 178) {
- key_repeat_time++;
- // 每19.6ms重复一次 (7 * 2.8ms = 19.6ms)
- if(key_repeat_time > 7) {
- key_repeat_time = 0;
-
- if((current_key_state & 4) && set_temp < 500 && !calibration_mode && !compensation_mode) {
- set_temp++;
- temp_setting_changed = 1; // 标记温度设置已改变
- temp_setting_change_time = 0; // 重置改变时间
- setting_mode = 1;
- setting_timer = 0;
- }
- if((current_key_state & 1) && set_temp > 150 && !calibration_mode && !compensation_mode) {
- set_temp--;
- temp_setting_changed = 1; // 标记温度设置已改变
- temp_setting_change_time = 0; // 重置改变时间
- setting_mode = 1;
- setting_timer = 0;
- }
- }
- }
- }
-
- // 温度设置改变后延迟保存
- if (temp_setting_changed) {
- temp_setting_change_time++;
- if (temp_setting_change_time >= SETTING_SAVE_DELAY) {
- eeprom_write_word((uint16_t*)EEPROM_TEMP_SETTING, set_temp);
- temp_setting_changed = 0; // 重置改变标志
- }
- }
-
- // 设置模式计时
- if (setting_mode) {
- setting_timer++;
- // 2秒后退出设置模式 (700 * 2.8ms = 1.96s)
- if (setting_timer > 700) {
- setting_mode = 0;
- }
- }
-
- last_key_state = current_key_state;
- }
- /**
- * 简介: 检查振动传感器
- * 功能: 检测振动传感器状态变化,用于唤醒休眠模式
- */
- void check_vibration_sensor(void) {
- // 如果在软关机模式下,直接返回
- if (shutdown_mode) {
- return;
- }
-
- static uint8_t last_vibration_state = 1; // 默认高电平(无振动)
- static uint32_t debounce_timer = 0;
-
- uint8_t current_state = (PINB & (1 << VIBRATION_SENSOR)) ? 1 : 0;
-
- // 检测状态变化
- if (current_state != last_vibration_state) {
- debounce_timer = 0;
- last_vibration_state = current_state;
- return;
- }
-
- // 确认状态变化
- if (current_state == 0) { // 低电平表示有振动
- // 重置休眠计时
- inactive_time = 0;
-
- // 如果是从休眠中唤醒,恢复原温度
- if (sleep_mode) {
- exit_sleep_mode();
- }
- }
-
- last_vibration_state = current_state;
- }
- /**
- * 简介: PID控制算法
- * 功能: 根据当前温度与设定温度的误差,计算PID输出, 控制加热器工作状态
- * 针对加热过冲问题进行了优化,加入了抗积分饱和和微分先行
- */
- void pid_control(void) {
- if(error_state) {
- heating_request = 0;
- heating = 0;
- heating_time = 0;
- return;
- }
-
- static float prev_error = 0;
- static float integral = 0;
- static uint8_t first_run = 1;
-
- // 初始化PID参数 - 根据系统特性调整这些值
- float kp = 3.0; // 比例系数 (原2.0)
- float ki = 0.03; // 积分系数 (原0.1,减小以减少超调)
- float kd = 5.0; // 微分系数 (原1.0,增加以抑制超调)
-
- // 清除积分项当设定值变化较大时
- if(fabs(set_temp - current_temp) > 30) {
- integral = 0;
- }
-
- float error = set_temp - current_temp;
-
- // 比例项
- float p_term = kp * error;
-
- // 积分项 - 抗积分饱和
- integral += error;
- // 积分限幅 - 更严格的限制
- if(integral > 50) integral = 50;
- if(integral < -50) integral = -50;
- float i_term = ki * integral;
-
- // 微分项 - 微分先行(只对测量值微分,不对设定值微分)
- static float prev_measurement = 0;
- float derivative = 0;
- if(!first_run) {
- derivative = (current_temp - prev_measurement);
- }
- first_run = 0;
- float d_term = kd * derivative;
- prev_measurement = current_temp;
-
- // PID输出
- float output = p_term + i_term - d_term; // 注意微分项符号
-
- // 当温度接近设定值时,减小积分作用
- if(fabs(error) < 10) {
- output = p_term - d_term + 0.2 * i_term;
- }
-
- // 限制输出范围
- if(output > 100) output = 100;
- if(output < 0) output = 0;
-
- // 设置加热请求标志
- // 修改加热启动条件,提前开始加热
- if(output > 20 && current_temp < set_temp + 5) { // 原条件: output > 30
- heating_request = 1;
- heating = 1;
- heating_time++;
- } else {
- heating_request = 0;
- heating = 0;
- heating_time = 0;
- }
-
- // 检查加热超时
- if(heating_time > HEATING_TIMEOUT) {
- error_state = 2;
- }
-
- prev_error = error;
- }
- /**
- * 简介: 检查同步信号并控制加热
- * 功能: 检测交流电过零信号,在过零点开启加热
- */
- void check_sync_signal(void) {
- // 读取同步信号状态
- sync_state = (PIND & (1 << SYNC_INPUT)) ? 1 : 0;
-
- // 检测同步信号边沿(上升沿或下降沿)
- if (sync_state != sync_last_state) {
- // 检测到过零点
- sync_last_state = sync_state;
-
- // 如果有加热请求,在过零点开启加热
- if (heating_request && !heating_active) {
- PORTB |= (1 << HEATER_CONTROL); // 开启加热
- heating_active = 1;
- }
- }
-
- // 如果不是过零点,保持或关闭加热
- // 注意:BTA16会在电流过零时自动关断,所以我们不需要主动关断
- // 但为了确保安全,如果加热请求被取消,立即关闭加热
- if (!heating_request && heating_active) {
- PORTB &= ~(1 << HEATER_CONTROL); // 关闭加热
- heating_active = 0;
- }
- }
- /**
- * 简介: 处理错误状态
- * 功能: 在错误状态下停止加热,并定时蜂鸣提醒
- */
- void handle_errors(void) {
- static uint32_t error_beep_timer = 0;
-
- if(error_state) {
- // 每17秒蜂鸣一次 (6000 * 2.8ms = 16.8s)
- error_beep_timer++;
- if(error_beep_timer >= 6000) {
- beep(0,4); // 四声"滴" - 提示错误
- error_beep_timer = 0;
- }
- }
- }
- /**
- * 简介: 检查休眠模式
- * 功能: 检测无活动时间,控制进入休眠和软关机模式
- */
- void check_sleep_mode(void) {
- static uint32_t last_check_time = 0;
-
- // 每1.5秒检查一次休眠和关机状态
- if (inactive_time - last_check_time < 600) { // 600 * 2.8ms = 1.68s
- return;
- }
- last_check_time = inactive_time;
-
- // 10分钟无活动进入休眠
- if (inactive_time > SLEEP_THRESHOLD && !sleep_mode && !shutdown_mode) {
- enter_sleep_mode();
- }
-
- // 40分钟无活动进入软关机
- if (inactive_time > SHUTDOWN_THRESHOLD && !shutdown_mode) {
- enter_shutdown_mode();
- }
- }
- /**
- * 简介: 进入休眠模式
- * 功能: 设置休眠模式标志,保存当前温度设置,设定休眠温度
- */
- void enter_sleep_mode(void) {
- sleep_mode = 1;
- previous_temp = set_temp;
- set_temp = 200; // 休眠温度
- beep(0,1); // 提示进入休眠
- }
- /**
- * 简介: 进入关机模式
- * 功能: 设置关机模式标志,关闭加热和显示,进入无限循环等待重新上电
- */
- void enter_shutdown_mode(void) {
- shutdown_mode = 1;
- set_temp = 0; // 关机温度
-
- // 确保加热关闭
- PORTB &= ~(1 << HEATER_CONTROL);
- heating_request = 0;
- heating = 0;
-
- // 关闭数码管显示
- PORTC &= ~((1 << DIGIT_1) | (1 << DIGIT_2) | (1 << DIGIT_3));
- // 关闭段选
- PORTB |= (1 << SEG_A) | (1 << SEG_F);
- PORTD |= (1 << SEG_B) | (1 << SEG_C) | (1 << SEG_D) |
- (1 << SEG_E) | (1 << SEG_G) | (1 << SEG_DP);
-
- TIMSK0 &= ~(1 << OCIE0A); // 关闭定时器0中断,停止显示更新
-
- beep(1,1); // 提示进入关机
-
- // 进入无限循环,等待重新上电
- while (1) {
- // 低功耗模式或简单延迟
- _delay_ms(1000);
- }
- }
- /**
- * 简介: 退出休眠/关机模式
- * 功能: 退出休眠或关机模式,恢复原来的温度设置
- */
- void exit_sleep_mode(void) {
- if (sleep_mode) {
- sleep_mode = 0;
- set_temp = previous_temp;
- beep(0,2); // 提示唤醒
- }
-
- if (shutdown_mode) {
- shutdown_mode = 0;
- set_temp = previous_temp;
- beep(0,2); // 提示唤醒
-
- // 重新启用定时器0中断,恢复显示更新
- TIMSK0 |= (1 << OCIE0A);
- }
- }
- /**
- * 简介: 加载温度参数从EEPROM
- * 功能: 从EEPROM读取校准参数和温度设置,如果EEPROM中没有有效数据,则使用默认参数
- */
- void load_temperature_params(void) {
- // 检查EEPROM中是否有有效数据
- uint16_t magic = eeprom_read_word((uint16_t*)EEPROM_MAGIC);
-
- if(magic == EEPROM_MAGIC_VALUE) {
- // 读取用户参数
- eeprom_read_block(&user_params, (void*)EEPROM_USER_PARAMS, sizeof(TemperatureParams));
-
- // 读取出厂参数
- eeprom_read_block(&factory_params, (void*)EEPROM_FACTORY_PARAMS, sizeof(TemperatureParams));
-
- // 计算斜率和截距
- calculate_slope_intercept(&user_params);
-
- // 使用用户参数
- current_params = user_params;
-
- // 加载保存的温度设置
- set_temp = eeprom_read_word((uint16_t*)EEPROM_TEMP_SETTING);
- if(set_temp < 150 || set_temp > 500) {
- set_temp = 280; // 默认温度
- }
- } else {
- // EEPROM中没有有效数据,使用默认出厂参数
- calculate_slope_intercept(&factory_params);
- current_params = factory_params;
- set_temp = 280;
-
- // 保存出厂参数到EEPROM
- eeprom_write_block(&factory_params, (void*)EEPROM_FACTORY_PARAMS, sizeof(TemperatureParams));
-
- // 初始化温度补偿偏移量为0
- eeprom_write_word((uint16_t*)EEPROM_TEMP_OFFSET, 0);
-
- // 写入魔术字
- eeprom_write_word((uint16_t*)EEPROM_MAGIC, EEPROM_MAGIC_VALUE);
- }
- }
- /**
- * 简介: 保存用户参数到EEPROM
- * 功能: 将用户校准参数保存到EEPROM,并写入魔术字标记有效数据
- */
- void save_user_params(void) {
- eeprom_write_block(&user_params, (void*)EEPROM_USER_PARAMS, sizeof(TemperatureParams));
- eeprom_write_word((uint16_t*)EEPROM_MAGIC, EEPROM_MAGIC_VALUE);
- }
- /**
- * 简介: 恢复出厂设置
- * 功能: 将用户参数恢复为出厂参数,重置温度补偿值
- */
- void restore_factory_settings(void) {
- // 复制出厂参数到用户参数
- user_params = factory_params;
- calculate_slope_intercept(&user_params);
-
- // 保存用户参数
- save_user_params();
-
- // 使用出厂参数
- current_params = user_params;
-
- // 重置温度补偿
- eeprom_write_word((uint16_t*)EEPROM_TEMP_OFFSET, 0);
-
- // 蜂鸣器三声"滴"提示
- beep(0, 3);
- }
- /**
- * 简介: 进入校准模式
- * 功能: 设置校准模式标志,初始化校准参数,设置第一个校准点的目标温度
- */
- void enter_calibration_mode(void) {
- // 等待所有按键释放
- wait_for_button_release();
-
- calibration_mode = 1;
- calibration_step = 1; // 开始第一点校准
- calibration_timer = 0;
- cal_digit_edit = 0; // 从百位开始编辑
- cal_heating_stable = 0; // 重置加热稳定标志
- cal_heating_timer = 0; // 重置加热计时器
-
- // 设置第一个校准点的目标温度
- cal_target_temp = 200; // 默认第一点目标温度
- set_temp = cal_target_temp; // 设置系统目标温度
- eeprom_write_word((uint16_t*)EEPROM_TEMP_SETTING, set_temp);
-
- // 初始化测量温度值
- cal_measured_temp = cal_target_temp;
-
- // 蜂鸣器"嗒嗒"两声提示
- beep(1, 2);
- }
- /**
- * 简介: 进入温度补偿模式
- * 功能: 通过长按K2键进入温度补偿模式,读取当前温度补偿值
- */
- void enter_compensation_mode(void) {
- // 等待所有按键释放
- wait_for_button_release();
-
- compensation_mode = 1;
- temp_offset = eeprom_read_word((uint16_t*)EEPROM_TEMP_OFFSET);
-
- // 蜂鸣器"滴"一声提示
- beep(0, 1);
- }
- /**
- * 简介: 蜂鸣器发声函数
- * 参数1: type 发声类型:0-短声"滴",1-长声"嗒"
- * 参数2: count 发声次数
- * 功能: 根据指定类型和次数发出蜂鸣声
- */
- void beep(uint8_t type, uint8_t count) {
- // 保存当前中断状态并禁用中断,确保蜂鸣声不被中断
- uint8_t sreg = SREG;
- cli();
-
- // 循环产生指定次数的蜂鸣声
- for(uint8_t i = 0; i < count; i++) {
- uint16_t duration = (type == 0) ? BEEP_SHORT : BEEP_LONG;
-
- // 产生指定持续时间的蜂鸣声(约500us,2kHz频率)
- for(uint16_t j = 0; j < duration; j++) {
- PORTC |= (1 << BUZZER); // 蜂鸣器引脚置高
- _delay_us(250); // 250us高电平
- PORTC &= ~(1 << BUZZER); // 蜂鸣器引脚置低
- _delay_us(250); // 250us低电平
- }
-
- // 如果不是最后一次蜂鸣,添加间隔
- if(i < count - 1) {
- _delay_ms(BEEP_PAUSE);
- }
- }
-
- // 恢复中断状态
- SREG = sreg;
- }
- // ============================== 中断服务程序 ==============================
- /**
- * 简介: 定时器0比较匹配中断服务程序 (1ms)
- * 功能: 用于数码管扫描和闪烁控制
- */
- ISR(TIMER0_COMPA_vect) {
- // 更新数码管显示
- update_display();
-
- // 闪烁控制(500ms周期)
- blink_timer++;
- if(blink_timer >= 500) {
- blink_timer = 0;
- blink_state = !blink_state;
- }
- }
- // ============================== 主函数 ==============================
- /**
- * 简介: 主函数
- * 功能: 程序入口点,初始化硬件后进入主循环,
- * 循环执行温度读取、按键检测、PID控制等功能
- */
- int main(void) {
- // 初始化硬件
- init_ports();
- // 开机时检测S1按键(恢复出厂设置)
- if(!(PINC & (1 << KEY_RST))) {
- // 等待按键释放
- _delay_ms(100);
- while(!(PINC & (1 << KEY_RST)));
-
- // 恢复出厂设置
- restore_factory_settings();
- }
-
- init_adc(); // 继续初始化硬件
- init_timers();
-
- // 显示启动画面
- show_startup_display();
-
- // 加载温度参数
- load_temperature_params();
- // 初始化温度采样数组
- for(uint8_t i = 0; i < SAMPLE_COUNT; i++) {
- temp_samples[i] = current_temp;
- temp_sum += current_temp;
- }
- samples_collected = SAMPLE_COUNT;
- display_temp = current_temp;
-
- // 启用全局中断
- sei();
-
- // 主循环
- while(1) {
- // 如果在软关机模式下,只执行最低限度的操作
- if (shutdown_mode) {
- // 低功耗模式或简单延迟
- _delay_ms(1000);
- continue;
- }
-
- read_temperature();
- update_temp_history(); // 更新温度历史记录
- weighted_moving_average_filter(); // 使用加权移动平均滤波
- //moving_average_filter(); // 移动平均滤波
- check_buttons();
- check_vibration_sensor();// 检查振动传感器
-
- if (!error_state) {
- improved_pid_control(); // 使用改进的PID控制
- //pid_control(); //只设置heating_request标志
- check_sync_signal(); // 检查同步信号并控制加热
- check_sleep_mode();
- }
-
- handle_errors();
- update_display_buffer();
- // 增加无活动时间计数
- inactive_time++;
- // 增加温度设置改变时间计数
- if (temp_setting_changed) {
- temp_setting_change_time++;
- }
-
- // 增加加热稳定时间计数
- if (calibration_mode && !cal_heating_stable) {
- cal_heating_timer++;
- }
-
- _delay_ms(2);
- }
- }
复制代码
|
打赏
-
查看全部打赏
|