经过修改增加了恒温模式下延时30分钟自动停止加热,和恒温模式下自动保存设置温度,下次开机默认上次的设置温度。
主函数:
#include "CONFIG.H"
/*------------
本程序根据嘉立创开源广场恒温加热台改编,利用 4位共阳数码管显示,具有恒温和回流焊两种功能,编码器控制加热开关,数码管前三位显示温度,
后一位显示恒温和回流标志,旋转编码器开关短按控制加热开/关,长按切换恒温和回流模式,在恒温模式下,
旋转编码器右转设置温度增加,左转设置温度减小.在回流模式下,双击控制回流状态切换,从预热温度-预热时间-回流
焊温度-回流焊时间之间切换,在各模式下旋转旋转编码器可以调整参数,调整完之后2秒自动转移到显示实际温度,短按开关键
开始加热,
------------*/
#define ENCODER_IDLE_TIME 40 //
#define MAX_RUN_SEC (30*60) //30分钟;工作限时,修改数字即可
//----------数码管应用变量-----------
sbit HEAT = P3^4; //pwm控制引脚
u16 Seg_Slow_Down; //数码管减速变量
u8 Seg_Buf[4] = {10,10,10,10}; //显示缓冲数组
u8 Seg_Point[4] = {0,0,0,0}; //小数点显示数组
u8 Seg_Pos=0; //数码管扫描变量
u8 Display_Timer=0; //编码器空闲计时,用于超时自动退出设置界面
/*------------显示界面状态枚举---------------*/
typedef enum
{
SCR_REFLOW,
SCR_CONSTCUR,
SCR_SETTING
}SCR_MODE;
SCR_MODE ScrState; //当前显示界面
bit last_mode_sw; //记录上一次模式状态,检测切换
bit Systim_Mode = 0; //系统模式,0 - 回流模式(按键长按切换加热模式),1- 恒温模式,
bit Systim_ON_OFF = 0; //系统开关,0- 关机,1- 开机
u16 run_timer_sec; //启动之后的累计秒计时
bit auto_shutdown_flag; //自动关机触发标记
//----------按键应用变量-----------
u8 Key_Val=0; //按键值
u8 Key_Slow_Down; //按键消抖
u8 Cnt_1ms = 0;
u8 Cnt_2ms = 0;
bit B_1msFlag=0;
u8 Cnt_200ms=0; //用于读取温度值
bit B_200msFlag=0;
u8 Cnt_50ms = 0; //50ms计时,用于旋转编码器扫描计时
bit B_50msFlag=0;
u8 Cnt_1s = 0; //计时1S用于回流焊时序计时
bit B_1sFlag=0;
u16 Cnt_500ms = 0; //小数点闪烁计时
bit B_500msFlag=0;
bit Blink_Flag; //小数点闪烁标志
bit ThermFault; //热电偶故障标记
//==================== EEPROM ====================
#define EE_ADDRESS 0x0000 //EEPROM 地址变量
u8 idata tmp[10]; // 临时数组
bit B_Save; //存储标志
//==================== 温度 ====================
int temp_raw;
float NowTemp, SetTemp;
float Manual_SetTemp; //恒温模式下手动设置温度变量
//==================== PID ====================
float err, last_err;
float integral; //积分累加值
float Kp = 5.0f;
float Ki = 0.02f;
float Kd = 0.0f;
float PID_Out;
u16 heat_pwm;
//==================== 回流焊 ====================
u8 run_flag = 0; //回流焊运行标志
u8 stage = 0; //回流曲线索引
u16 stage_time = 0; //回流焊曲线计时
// 标准SMT回流焊曲线
code u8 temp_curve[3] = {80, 130, 220};
code u16 time_curve[3] = {90, 90, 40};
bit stage_wait_temp=0 ; //回流焊等待温度达标标志
/*------------------------数码管显示函数----------------*/
void Display() //数码管显示函数
{
u16 t;
if(Seg_Slow_Down)return;
Seg_Slow_Down=1;
if(ThermFault == 1) //热电偶故障显示E0
{
//E的段码0x86
Seg_Buf[0]=11;
Seg_Buf[1]=11;
Seg_Buf[2]=15;
Seg_Buf[3]=0;
return;
}
t = (u16)NowTemp;
switch(ScrState)
{
case SCR_REFLOW: //回流焊显示界面
Seg_Buf[0] = (t / 100) %10;
Seg_Buf[1] = (t / 10) %10;
Seg_Buf[2] = t %10;
Seg_Buf[3] = 13;
break;
case SCR_CONSTCUR: //恒温加热显示界面
Seg_Buf[0] = (t / 100) %10;
Seg_Buf[1] = (t / 10) %10;
Seg_Buf[2] = t %10;
Seg_Buf[3] = 14;
break;
case SCR_SETTING: //恒温设置界面
t = (u16)Manual_SetTemp;
Seg_Buf[0] = (t / 100) %10;
Seg_Buf[1] = (t / 10) %10;
Seg_Buf[2] = t %10;
Seg_Buf[3] = 10;
break;
default:
ScrState = SCR_REFLOW; //开机显示回流焊界面
break;
}
if(HEAT==1 && Blink_Flag==1) //开始加热第三位数码管小数点闪烁
{
Seg_Point[2]=1;
}
else Seg_Point[2]=0;
if( Systim_ON_OFF)
Seg_Point[3]=1;
else Seg_Point[3]=0;
}
/*------------------------按键处理函数----------------*/
void Key_Proc()
{
if(Key_Slow_Down)return; //用于按键消抖
Key_Slow_Down=1;
Key_Val = KEY_Read(); //读取按键值
if(Key_Val==Single_KEY) //短按切换,加热/关闭
{
Systim_ON_OFF ^=1;
}
if(Key_Val==Long_KEY) //长按开始切换加热模式,0- 回流焊,1- 恒温加热
{
Systim_Mode ^= 1;
if(Systim_Mode==0)
{
ScrState = SCR_REFLOW; //回流焊界面
}
else
{
ScrState = SCR_CONSTCUR; //恒温界面
}
}
Key_Val=0;
}
/*------------------------函数声明----------------*/
void reflow(void);
void heat_ctrl(void);
void PID_Calc(void);
/*------------------------主函数----------------*/
void main()
{
static u8 Last_Systim_ON_OFF = 0; //记录上一次开关状态
SystemInit(); //系统初始化
Timer0_Init(); //定时器0初始化
Rotary_Init(); //旋转编码器初始化
KEY_Driver(); //按键驱动函数
EA = 1;
HEAT = 0;
run_flag = 0;
stage = 0;
stage_time = 0;
integral = 0;
//上电读取EEPROM存储的数据
EEPROM_Read_n(EE_ADDRESS,tmp,10);//EEPRON读数据 (u16 EE_Address,u8 *DataAddress,u16 Number)
if((tmp[0]==~tmp[4])&&(tmp[1] == ~tmp[5])&&(tmp[2] == ~tmp[6])&&(tmp[3] == ~tmp[7]))//数据校验正确
{
Manual_SetTemp = ((float *)&tmp)[0]; //读出上次设置的温度
if(Manual_SetTemp < 40.0f)Manual_SetTemp = 150.0f;
if(Manual_SetTemp > 400.0f)Manual_SetTemp = 150.0f;
}
else Manual_SetTemp = 150.0f;
Display(); //调用温度显示函数
while(1)
{
Key_Proc(); //按键处理函数
//检测开关是否打开
if(Systim_ON_OFF==1&&Last_Systim_ON_OFF==0) //加热开关打开
{
run_flag = 1;
ThermFault = 0; //热电偶断线标志
stage = 0;
stage_time = 0;
integral = 0; //启动清零积分,消除上次残留
stage_wait_temp = 1;
run_timer_sec = 0; //【新增】启动时清零总运行计时
auto_shutdown_flag = 0; //开关延时标志
}
else if(Systim_ON_OFF==0&&Last_Systim_ON_OFF==1) //加热开关关闭
{
run_flag = 0;
HEAT = 0;
}
Last_Systim_ON_OFF=Systim_ON_OFF; //存储上一次的开关状态
//检测模式发生切换:立刻停机,清零积分防止冲温
if(last_mode_sw != Systim_Mode)
{
Systim_ON_OFF = 0;
run_flag = 0;
HEAT =0;
integral = 0;
stage =0;
stage_time=0;
}
last_mode_sw = Systim_Mode; //存储上一次的模式状态
//温度设置
if(Systim_Mode==1) //恒温模式下,旋转编码器设置温度
{
if(B_50msFlag==1)
{
B_50msFlag=0;
if(Rotary_Read_Data!=0) //旋转编码器控制
{
if(ScrState != SCR_SETTING)
{
ScrState = SCR_SETTING; //如果不是设置界面,转到设置界面
Display_Timer=0;
}
else
{
Manual_SetTemp += (float)Rotary_Read_Data*5;
if(Manual_SetTemp > 400.0f) Manual_SetTemp = 400.0f; //设置最高400度
if(Manual_SetTemp < 40.0f) Manual_SetTemp = 40.0f; //最低40度
B_Save = 1; //请求保存
}
Rotary_Read_Data=0;
}
else
{
Display_Timer++; //设置界面显示延时时间
if(Display_Timer==ENCODER_IDLE_TIME)
{
Display_Timer=0;
ScrState = SCR_CONSTCUR;
}
}
}
}
//保存设置温度
if(B_Save)
{
B_Save = 0;
((float *)&tmp)[0] = Manual_SetTemp;
tmp[4] = ~tmp[0];
tmp[5] = ~tmp[1];
tmp[6] = ~tmp[2];
tmp[7] = ~tmp[3];
EEPROM_SectorErase(EE_ADDRESS); //EEPROM擦除扇区
EEPROM_Write_n(EE_ADDRESS,tmp,10); //写入数据
}
//读取温度
if(B_200msFlag)
{
B_200msFlag=0;
temp_raw = Read_MAX6675();
if(temp_raw == -1)
{
ThermFault = 1;
run_flag = 0;
HEAT = 0;
}
else
{
ThermFault = 0;
NowTemp = (float)temp_raw * 0.25f;
}
}
//超温锁死故障
if(Systim_Mode==0) //回流模式高温限制
{
if(NowTemp >= 265.0f)
{
run_flag = 0;
HEAT = 0;
}
}
Display();
PID_Calc();
reflow();
}
}
/*--------------PID----------------*/
void PID_Calc(void)
{
err = SetTemp - NowTemp;
if(fabs(err) < 100.0)
{
integral += err;
}
//积分限幅,抗积分饱和,非常重要!
if(integral > 800) integral = 800;
if(integral < -800) integral = -800;
PID_Out = Kp*err + Ki*integral + Kd*(err - last_err);
last_err = err;
if(PID_Out > 100.0f) PID_Out = 100.0f;
if(PID_Out < 0.0f) PID_Out = 0.0f;
heat_pwm = (u16)PID_Out;
}
/*--------------PWM 加热控制----------------*/
void heat_ctrl(void)
{
static u16 pwm_cnt = 0;
pwm_cnt++;
if(pwm_cnt >= 100)
pwm_cnt = 0;
/* 限幅保护,防止溢出导致持续加热 */
if(heat_pwm > 100) heat_pwm = 100;
if(Systim_Mode==0)
{
if(run_flag && NowTemp < 265 && heat_pwm > pwm_cnt && (!ThermFault))
HEAT = 1;
else
HEAT = 0;
}
else if(Systim_Mode==1)
{
if(run_flag && NowTemp < 400 && heat_pwm > pwm_cnt && (!ThermFault))
HEAT = 1;
else
HEAT = 0;
}
}
/*--------------回流焊----------------*/
void reflow(void)
{
if(!run_flag) return;
if(Systim_Mode==0)
{
//回流焊模式才跑阶段计时
if(B_1sFlag)
{
B_1sFlag = 0;
if(stage_wait_temp==0) //回流焊温度达标开始计时
{
stage_time++;
}
}
SetTemp = temp_curve[stage];
if(stage_wait_temp==1)
{
if(NowTemp>=temp_curve[stage]) //温度达标,清零标志位开始计时
{
stage_wait_temp = 0;
stage_time = 0;
}
}
else if(stage_time >= time_curve[stage])
{
stage_time = 0;
stage_wait_temp=1;
stage++;
if(stage >= 3)
{
run_flag = 0;
stage = 0;
stage_wait_temp = 0; //回流焊等待温度达标标志
}
}
}
else if(Systim_Mode)
{
if(auto_shutdown_flag == 0) //延时关机标志
{
if(B_1sFlag)
{
B_1sFlag = 0;
run_timer_sec++; //累计运行秒数+1
}
}
// 判断总运行时间是否达到30分钟(1800s),强制停机
if(run_timer_sec >= MAX_RUN_SEC)
{
auto_shutdown_flag = 1;
run_flag = 0; //停止回流焊流程
Systim_ON_OFF = 0; //系统运行标记清零
HEAT = 0; //关闭加热
// //可以选择打开风机冷却一会,复用cool_delay_run
// cool_delay_time =60;
// cool_delay_run =1;
// FAN =1;
}
//恒温模式:直接使用手动设定温度,不跑阶段时序
SetTemp = Manual_SetTemp;
return;
}
}
/*--------------定时器0中断服务函数----------------*/
void Timer0_Isr(void) interrupt 1
{
if(++Cnt_50ms==50)
{
Cnt_50ms=0;
B_50msFlag=1;
if(++Cnt_200ms==4)
{
Cnt_200ms = 0;
B_200msFlag=1;
}
if(++Cnt_500ms==10)
{
Cnt_500ms=0;
B_500msFlag=1;
Blink_Flag ^= 1;
if(++Cnt_1s==2)
{
Cnt_1s=0;
B_1sFlag=1;
}
}
}
if(++Key_Slow_Down==10)Key_Slow_Down=0; //按键消抖
if(++Seg_Slow_Down==500)Seg_Slow_Down=0;
if(++Cnt_2ms==2) //数码管动态扫描
{
Cnt_2ms=0;
if(++ Seg_Pos==4)Seg_Pos=0;
Seg_Display(Seg_Buf[Seg_Pos],Seg_Pos,Seg_Point[Seg_Pos]);
}
heat_ctrl();
Rotary_Scan();
}
回流焊加热台-2.zip
(369.48 KB, 下载次数: 0)
|