切换到宽版
  • 18174阅读
  • 60回复

[C51]闲的无聊,发个白光T12控制器固件玩玩 [复制链接]

上一主题 下一主题
离线金向维
 

发帖
4647
M币
704
专家
82
粉丝
407
只看楼主 倒序阅读 使用道具 楼主  发表于: 2015-07-01
   白光T12控制器电路就不说了,烂大街了.
   此固件对硬件的要求: 1:共阴数码管; 2:单片机P1.6,P1.7脚并联接蜂鸣器正极,蜂鸣器负极接地; 3:采用SGM8551,SGM8552,OPA336等失调电压极低,轨到轨的运放,LM358之类的就算了吧; 4: 运算放大器的增益设定为250倍; 5:NTC电阻一端接地,另一端接10K定值电阻,10K电阻的另一端接+5V;
   大道至简,折腾多了就会发现简单的才是实用的. 去掉了P01等等的参数设置模式,只有一个可调参数用来校准温度,长按编码器进入校准模式,转动编码器使实际温度为350度就行了.
   原来实用的自动休眠,自动关机,手动关机,温度加强等均保留. 关机显示OFF,不插T12显示ERR并蜂鸣报警,各种操作有蜂鸣器提示.
    关键参数在代码开头处有宏定义,想改的坛友改个数字就行了.

以下为正文:

本文内容包含图片或附件,获取更多资讯,请 登录 后查看;或者 注册 成为会员获得更多权限
本帖最近打赏记录:共20条打赏M币+74
懒虫包子 M币 +10 - 2016-04-22
xixia001 M币 +3 - 2015-10-11
deyafe M币 +3 謝謝分享 2015-10-03
zjalone M币 +3 優秀文章 2015-08-05
zkele M币 +3 原創內容 2015-07-12
xktx09 M币 +3 来个编译好的网盘地址啊 2015-07-03
mugeda M币 +3 謝謝分享 2015-07-03
我是鑫鑫 M币 +1 看你的温控算法全是判断语句啊啊啊,建议用PID 2015-07-02
xxdz12345 M币 +3 必须得加 。。。 2015-07-02
yaojil M币 +3 原創內容 2015-07-02
12
离线金向维

发帖
4647
M币
704
专家
82
粉丝
407
只看该作者 1楼 发表于: 2015-07-01
/*****************STC15F204EA单片机旋转编码器版白光T12控制器代码(by金向维)***********************/
#include "STC15F204EA.h"//单片机头文件,24MHz时钟频率
#include "INTRINS.h"//头文件
#define canshu0 250//运放增益(倍)
#define canshu1    10//温度步进(度)
#define canshu2    3//休眠时间(分钟)
#define canshu3    5//关机时间(分钟)
#define canshu4    0//关机唤醒方式(0:震动开关+编码器;1:编码器)
#define canshu5    50//温度加强读数(摄氏度)
#define canshu6    40//温度加强持续时间(秒)
#define canshu7 180//休眠温度(摄氏度)
unsigned char code duanma[15]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x73,0x79,0x71,0x50,0x40};//共阴数码管段码数据0,1,2,3,4,5,6,7,8,9,P,E,F,R,-
unsigned char code wendubiao[52]={2,6,12,16,21,22,30,35,40,45,50,51,53,57,59,67,73,80,86,93,100,107,114,121,127,133,139,145,151,156,165,167,172,177,181,186,190,195,200,204,209,213,217,222,226,230,234,238,242,247,250,254};//根据NTC电阻随温度变化进而引起电压变化得出的数据,用来查表计算室温(进而对热电偶冷端补偿)
unsigned char code wendubiao2[29]={9,20,31,43,54,65,76,88,99,104,111,118,125,132,142,148,157,165,173,181,189,196,203,210,216,222,228,233,238};
sbit dot=P2^7;//数码管的小数点接P2.7
sbit t12=P2^0;//T12通过P2.0控制
sbit bw=P3^4;//数码管百位位选为P3.4
sbit sw=P3^5;//数码管十位位选为P3.5
sbit gw=P3^6;//数码管个位位选为P3.6
sbit tihuan=P3^7;//数码管的a段本应该用P1.0控制,由于P1.0被用来控制T12,所以要用P3.7替代P1.0
sbit encoderb=P1^4;//编码器的b脚接P1.4
sbit encodera=P3^2;//编码器的a脚接P3.2
sbit zhendongkaiguan=P0^1;//震动开关接P0.1
sbit bianmaanniu=P3^3;//编码器的按键接P3.3
sbit a7=P2^7;//数码管dot
sbit a6=P2^6;//数码管g段
sbit a5=P2^5;//数码管f段
sbit a4=P2^4;//数码管e段
sbit a3=P2^3;//数码管d段
sbit a2=P2^2;//数码管c段
sbit a1=P2^1;//数码管b段
sbit speaker=P1^6;//P1.6和P1.7并联接蜂鸣器正极
sbit speaker2=P1^7;//P1.6和P1.7并联接蜂鸣器正极
bit e,f,g,h;//e,f,h用来保存编码器上一次的状态,g用来保存震动开关上一次的状态
bit huancunkaiguan;//用于改变设定温度后延时显示设定温度(而不是立刻显示t12温度)
bit xiumiankaiguan;//定义休眠开关
bit xiumianjishukaiguan;//定义休眠计数开关
bit ganggangkaiji=1;//定义刚刚开机(确保刚开机未震动手柄能进入休眠状态,因为每次休眠计时是通过震动传感器状态改变触发的,而刚开机手柄没有震动所以要特殊处理)
bit guanjikaiguan;//定义关机开关
bit guanjijishukaiguan;//定义关机计数开关
bit shezhimoshi;//设置模式还是正常工作模式
bit shezhixianshijishukaiguan;//用于设置模式延时显示P01,P02等菜单项
bit jinzhicaozuo=1;//用于设置模式下某时刻禁止编码器操作
bit wendujiaqiang;//温度加强开关
bit wendujiaqiangjishukaiguan;//温度加强计数开关
bit moshijishukaiguan;//编码器按下时间计数开关,用来判断长按还是短按
bit shijian4;//如果开机时间小于1秒,掉电时不保存数据
bit qiehuan;//旋转编码器功能切换
bit yijing;//已经转动过编码器
bit flag;//闹钟响标志位
bit flag2;//到达设定温度蜂鸣标志
bit jiluguanji;//记录上次是否为关机模式
unsigned char shiwen;//室温(允许的室温范围为0度至80度)
unsigned char zhouqijishu=199;//加热周期200ms计数
unsigned char moshixuanze;//编码器按下模式,有效值0,1,2,3,4
unsigned char shijian2;//用于快速转动编码器从休眠,关机,温度加强模式唤醒而不造成设定温度改变
unsigned char shijian3;//用于震动开关状态改变时,显示百位小数点
unsigned char huancunjishu;//用于改变设定温度后保持显示设定温度一段时间再显示t12温度(而不是立刻显示t12温度)
unsigned char wendujiaqiangjishu;//多长时间退出温度加强模式(单位S)
unsigned char shezhixianshijishu;//设置模式中用于延时显示菜单项
unsigned char jiaoyan;//检查eeprom数据有效性的校验码
unsigned char m;//用于蜂鸣类型3
unsigned char fengmingleixing;//蜂鸣类型
unsigned char fengmingcishu=1;//蜂鸣类型3重复蜂鸣的次数
unsigned int moshijishu;//编码器按下时间计数,用来判断长按还是短按
unsigned int xindizhi;//用于读取不同扇区的参数
unsigned int xiumianjishu;//等待多长时间进入休眠状态(单位s)
unsigned int guanjijishu;//等待多长时间进入关机状态(单位s)
unsigned int shedingwendu;//设定温度(范围200~450度)
unsigned int huancun;//显示函数直接显示huancun,要显示一个数据将必须这个数据赋值给缓存
unsigned int jiareshu;//每200ms加热周期内需要加热的次数(一次等于1ms,相当于加热占空比)
unsigned int dianyuandianya;//电源电压(单位mV)
unsigned int t12dianya;//热电偶经放大器放大后的电压(单位mV)
unsigned int ntcdianya;//NTC根据室温得到的电压(单位mV)
unsigned long cankaodianya0;//参考电压(ADC后的直接数据,未转换为mV)
signed int t12wendu;//T12烙铁头的实际温度(非热电偶的温差)
signed int wencha;//T12两个周期间的温差
union gongyongti {unsigned int a;unsigned char b[2];} jiaozhun;//温度校准参数(热电偶℃/mV)
/************************************函数声明****************************************/
void shezhihanshu(void);
void eepromgonggong(void);
void Byte_Program(unsigned int add, unsigned char dat);
void Sector_Erase(unsigned int add);
void delay_ms(unsigned int a);
void xianshigonggong(unsigned char a);
void adc(void);
void timer0init(void);
void tuichujiaqiang(void);
void tuichuyiqie(void);
void bianmaqizhuangtai(void);
void xiumian(void);
void anxiamoshi(void);
void bianmaqi1(void);
void duqushezhishuju(void);
void baocunshuju(void);
void diaodiancunchu(void);
void bianmaqi2(void);
void zhendongxiumian(void);
unsigned char Byte_Read(unsigned int add);
unsigned int adcdianyuan(void);
/************************************1ms延时函数***********************************************/
void delay_ms(unsigned int a)//24MHz时钟时的1毫秒延时函数
{
unsigned int b;
while(a--)
{
  for(b=0;b<1200;b++);
}
}
/********************************EEPROM公共函数************************************************/
void eepromgonggong(void)
{
IAP_TRIG = 0x5a;//发送5ah到触发寄存器
IAP_TRIG = 0xa5;//发送a5h到触发寄存器
_nop_();//延时
IAP_CONTR = 0;//关闭IAP 功能
IAP_CMD = 0;//清空命令寄存器
IAP_TRIG = 0;//清空命令触发寄存器
IAP_ADDRH = 0;//清空地址高位
IAP_ADDRL = 0;//清空地址低位
}
/********************************字节读函数****************************************************/
unsigned char Byte_Read(unsigned int add)
{
IAP_DATA = 0x00;//清空数据
IAP_CONTR = 0x81;//打开IAP,设置操作等待时间
IAP_CMD = 0x01;//字节读命令
IAP_ADDRH = add>>8;//设置高8位地址
IAP_ADDRL = add&0x00ff;//设置低8位地址
eepromgonggong();
return (IAP_DATA);//返回读到的数据
}
/********************************字节编程函数************************************************/
void Byte_Program(unsigned int add, unsigned char dat)
{
IAP_CONTR = 0x81;//打开IAP,设置操作等待时间
IAP_CMD = 0x02;//字节编程命令
IAP_ADDRH = add>>8;//设置高8位地址
IAP_ADDRL = add&0x00ff;//设置低8位地址
IAP_DATA = dat;//要编程的数据先送进IAP_DATA 寄存器
eepromgonggong();
}
/********************************扇区擦除函数************************************************/
void Sector_Erase(unsigned int add)
{
IAP_CONTR = 0x81;//打开IAP,设置操作等待时间
IAP_CMD = 0x03;//扇区擦除命令
IAP_ADDRH = add>>8;//设置高8位地址
IAP_ADDRL = add&0x00ff;//设置低8位地址
eepromgonggong();
}
/********************************读取设置数据函数******************************************/
void duqushezhishuju(void)//读取控制器的参数
{
jiaozhun.b[0]=Byte_Read(xindizhi);//读取温度校准参数
jiaozhun.b[1]=Byte_Read(xindizhi+1);//读取温度校准参数
jiaoyan=Byte_Read(xindizhi+2);//读取校验码
}
/********************************保存数据函数**********************************************/
void baocunshuju(void)//保存控制器数据到EEPROM
{
jiaoyan=0x55;//写入校验码
Sector_Erase(xindizhi);//擦除扇区
Byte_Program(xindizhi,jiaozhun.b[0]);//写入温度校准参数
Byte_Program(xindizhi+1,jiaozhun.b[1]);//写入温度校准参数
Byte_Program(xindizhi+2,jiaoyan);//写入校验码
}
/********************************掉电存储函数*********************************************/
void diaodiancunchu(void)//用于关机时存储温度数据,以便下次开机时恢复温度
{
adcdianyuan();//检测电源电压
if(dianyuandianya<4800)//如果电源电压降低到4.80V说明掉电了
  {    
   P2=0x00;//关闭数码管位选和t12(即停止显示,停止加热),节约电量
   P3=0x70;//关闭替换脚,关闭位选脚,节约电量    
   ADC_CONTR=0x00;//关闭ADC电源,节约电量
   speaker=0;//关闭蜂鸣器
   speaker2=0;//关闭蜂鸣器
   if(shijian4==1)//如果开机时间大于1秒
    {
     xindizhi=0x200;//准备读写第二扇区
     baocunshuju();//保存参数到第二扇区
     Byte_Program(0x02ff,(shedingwendu-200));//保存设定温度
    }
   t12=1;//加热t12以尽快耗尽电容电量,加速关机
   delay_ms(1000);//最多加热1000ms
   IAP_CONTR=0x20;//复位单片机
  }
}
/********************************显示公共函数********************************************/
void xianshigonggong(unsigned char a)
{
a7=a&0x80;//dot
a6=a&0x40;//g
a5=a&0x20;//f
a4=a&0x10;//e
a3=a&0x08;//d
a2=a&0x04;//c
a1=a&0x02;//b
tihuan=a&0x01;//a
}

/********************************ADC测电源电压函数**************************************************/
unsigned int adcdianyuan(void)//此函数测量单片机电源电压
{
ADC_CONTR=0x88;//ADC_POWER, SPEED1, SPEED0, ADC_FLAG---ADC_START, CHS2, CHS1, CHS0
while(!(ADC_CONTR&0x10));//等待转换结束
cankaodianya0=(ADC_RES*4+ADC_RESL);//把结果转换成十进制数据(10位ADC,最大值1023)
dianyuandianya=2549760/cankaodianya0;//计算电源电压,单位mV
return dianyuandianya;//返回结果
}
/********************************ADC测其他电压函数************************************************/
void adc (void)//ADC函数,用于测量和计算各种电压
{
unsigned int b;//两次温度求平均值用
ADC_CONTR=0x89;//ADC_POWER, SPEED1, SPEED0, ADC_FLAG---ADC_START, CHS2, CHS1, CHS0 转换采用最低速度速,低速更精确(测量t12电压务必使用最低速度AD转换,实测高速误差大)
while(!(ADC_CONTR&0x10));//等待转换结束
t12dianya=(ADC_RES*4+ADC_RESL);//把结果转换成十进制数据(10位ADC,最大值1023)
t12dianya=2490*(unsigned long)t12dianya/cankaodianya0;//计算t12电压,单位mV                                                            
ADC_CONTR=0x8a;//ADC_POWER, SPEED1, SPEED0, ADC_FLAG---ADC_START, CHS2, CHS1, CHS0    
while(!(ADC_CONTR&0x10));//等待转换结束
ntcdianya=(ADC_RES*4+ADC_RESL);//把结果转换成十进制数据(10位ADC,最大值1023)
ntcdianya=2490*(unsigned long)ntcdianya/cankaodianya0;//计算ntc电压,单位mV
ntcdianya=dianyuandianya-ntcdianya;//NTC一端接地需要此行代码;如果NTC一端接+5V,请屏蔽此行代码
for(shiwen=0;((unsigned int)wendubiao[shiwen]*9+1300)<ntcdianya;shiwen++)//查表计算室温(0-51度)
  {
   if(shiwen>=51)//如果超出表的范围就取51度
    break;//并且退出查表
  }
if(ntcdianya>3590)//查表计算室温(52-80度)
  {
   for(shiwen=52;((unsigned int)wendubiao[shiwen-52]*3+3600)<ntcdianya;shiwen++)//查表计算室温
    {
     if(shiwen>=80)//如果超出表的范围就取允许的最高温度(80度)
     break;//并且退出查表
    }
  }
t12wendu=(unsigned long)t12dianya*jiaozhun.a/canshu0/10+shiwen;//计算t12的实际温度
if(t12wendu-b<200)//如果两次温度相差不超过200度
  t12wendu=(t12wendu+b)/2;//就两次温度求平均值
b=t12wendu;//记录上一次温度
if(t12wendu>500)//如果得出的温度超过500度,说明没有插入烙铁头或参数错误(因为烙铁头的温度不可能超过500度)
  {
   t12wendu=500;//用500作为错误指示
   tuichuyiqie();//退出休眠,关机,加强状态
   fengmingleixing=5;//蜂鸣类型5
   flag2=0;//允许下次达到设定温度时蜂鸣
  }
if(!shezhimoshi)//如果不是设置模式
  huancun=t12wendu;//显示t12温度
if(huancunkaiguan)//如果缓存开关开
  huancun=shedingwendu;//显示设定温度
}
/********************************退出温度加强函数************************************/
void tuichujiaqiang(void)
{
wendujiaqiangjishukaiguan=0;//温度加强计数关闭
wendujiaqiangjishu=0;//清零温度加强计数
wendujiaqiang=0;//退出温度加强
}
/********************************退出休眠关机加强函数******************************************/
void tuichuyiqie(void)
{
ganggangkaiji=0;//已经开机
xiumiankaiguan=0;//停止休眠
xiumianjishukaiguan=1;//允许新的一次休眠计时
xiumianjishu=0;//从0开始计时
guanjijishukaiguan=0;//停止关机计数
guanjikaiguan=0;//退出关机状态
tuichujiaqiang();//退出温度加强
shezhimoshi=0;//退出设置模式
jinzhicaozuo=1;//下次刚进入设置模式时禁止操作编码器
}
/************************************休眠函数****************************************/
void xiumian(void)
{
ganggangkaiji=0;//已经开机
xiumiankaiguan=1;//进入休眠状态
xiumianjishukaiguan=0;//停止休眠计数
xiumianjishu=0;//清零休眠计数
guanjijishu=0;//清零关机计数
guanjijishukaiguan=1;//允许关机计数
}
/********************************震动休眠函数**********************************************/
void zhendongxiumian(void)
{
if(zhendongkaiguan!=g)//震动开关状态改变,说明晃动了手柄
  {
   shijian3=200;//时间3重新赋值
   ganggangkaiji=0;//已经开机
   xiumianjishu=0;//清零休眠计数
   xiumianjishukaiguan=1;//开始新的休眠计数
   if((xiumiankaiguan==1&&guanjikaiguan==0)||(xiumiankaiguan==1&&guanjikaiguan==1&&canshu4==0))//如果是休眠模式,或者是关机模式并且允许震动唤醒
    {
     flag2=0;//允许下次到达设定温度时蜂鸣
     if(guanjikaiguan||xiumiankaiguan)//如果是休眠模式或关机模式
      fengmingleixing=2;//蜂鸣类型2
     xiumiankaiguan=0;//停止休眠
     xiumianjishukaiguan=1;//允许新一次休眠计数
     xiumianjishu=0;//从0开始计数
     guanjijishukaiguan=0;//停止关机计数
     guanjikaiguan=0;//退出关机状态(如果原来是关机状态的话)
    }
  }
if(shijian3>0)//时间3倒计时(百位小数点延时显示)
  shijian3--;
g=zhendongkaiguan;//保存当前震动传感器状态(用于和下一次比较,以便确定是否震动了)
}
/********************************记录编码器状态函数**********************************/
void bianmaqizhuangtai(void)
{
e=encodera;//记录编码器a脚此次状态
f=encoderb;//记录编码器b脚此次状态
h=bianmaanniu;//记录编码按钮此次状态
}
/********************************确定按下模式函数************************************/
void anxiamoshi(void)
{
if(h==1&&bianmaanniu==0)//如果按下了编码器
  moshijishukaiguan=1;//允许按下时间计数
if((moshijishukaiguan&&bianmaanniu)||(moshijishukaiguan&&moshijishu>3000))//如果在计数过程中编码器松开
  {
   moshijishukaiguan=0;//停止按下时间计数
   if(moshijishu>2500)//如果按下时间大于2.5s
    {
     moshixuanze=3;//就是长按
     if(jinzhicaozuo)//显示校准温度350度时
      fengmingcishu=2;//蜂鸣类型2
     else//退出校准模式时
      fengmingleixing=3;//蜂鸣类型3
      fengmingcishu=1;//蜂鸣次数1次
    }
   else if(moshijishu>250&&moshijishu<1200)//如果按下时间为0.25s-1.2秒
    {
     moshixuanze=2;//就是稍微长按
     fengmingleixing=3;//蜂鸣类型3
     fengmingcishu=1;//蜂鸣次数1次
    }
   else if(moshijishu<=250)//如果按下时间不超过0.25秒
    {
     moshixuanze=1;//就是短按;
     fengmingleixing=2;//蜂鸣类型2
    }
   moshijishu=0;//清零计数
   yijing=0;//清零转动过编码器标志
  }
}
/********************************编码器函数1(加热模式调用)********************************/
void bianmaqi1(void)
{
if(e==1&&f==1&&encodera==1&&encoderb==0)//和前一次状态比较确定为右旋
  {
   if(t12wendu!=500)//如果不是没插T12
    fengmingleixing=1;//蜂鸣类型1
   if(bianmaanniu==1)//如果编码按钮没有按下,就是调温功能
    {
     if(wendujiaqiang==0&&xiumiankaiguan==0&&shijian2>250)//如果是正常加热模式并且时间2大于250ms(不是休眠,关机,温度加强)
      shedingwendu=shedingwendu+canshu1;//步进加
     if(shedingwendu>450)//最高允许450度
      shedingwendu=450;
     if(xiumiankaiguan==1||wendujiaqiang==1)//如果是休眠,温度加强,关机模式就清零时间2
      shijian2=0;
     huancun=shedingwendu;//显示改变后的设定温度
     huancunkaiguan=1;//打开缓存开关(用于延时显示设定温度1.5秒)
     huancunjishu=0;//重新开始缓存计数
     if(xiumiankaiguan||guanjikaiguan)//如果是休眠模式或关机模式
      fengmingleixing=2;//蜂鸣类型2
     tuichuyiqie();//退出关机,休眠,温度加强
    }
  }
if(e==1&&f==1&&encodera==0&&encoderb==1)//和前一次状态比较确定为左旋
  {
   if(t12wendu!=500)//如果不是没插T12
    fengmingleixing=1;//蜂鸣类型1
   if(bianmaanniu==1)//如果编码按钮没有按下,就是调温功能
    {
     if(wendujiaqiang==0&&xiumiankaiguan==0&&shijian2>250)//如果是正常加热模式并且时间2大于250ms(不是休眠,关机,温度加强)
      shedingwendu=shedingwendu-canshu1;//步进减
     if(shedingwendu<200)//最低允许200度
      shedingwendu=200;
     if(xiumiankaiguan==1||wendujiaqiang==1)//如果是休眠,温度加强,关机模式就清零时间2
      shijian2=0;
     huancun=shedingwendu;//显示改变后的设定温度
     huancunkaiguan=1;//打开缓存开关(用于延时显示设定温度1.5秒)
     huancunjishu=0;//重新开始缓存计数
     if(xiumiankaiguan||guanjikaiguan)//如果是休眠模式或关机模式
      fengmingleixing=2;//蜂鸣类型2
     tuichuyiqie();//退出关机,休眠,温度加强
    }
  }
if(moshixuanze==2&&t12wendu!=500)//如果是稍微长按,进入关机模式
  {
   moshixuanze=0;//清除按下模式
   tuichujiaqiang();//退出温度加强
   xiumiankaiguan=1;//休眠
   guanjikaiguan=1;//关机
  }
if(moshixuanze==3&&t12wendu!=500&&!guanjikaiguan)//如果是长按,进入设置模式
  {
   tuichuyiqie();//退出关机,休眠等模式
   shezhimoshi=1;//进入参数设置模式
   ganggangkaiji=1;//认为是刚刚开机
   moshixuanze=0;//清零按下模式
   jinzhicaozuo=1;//禁止操作编码器
  }
if(!xiumiankaiguan&&t12wendu!=500)//如果不是休眠状态
  {
   if(moshixuanze==1)//如果是短按
    {
     wendujiaqiang=~wendujiaqiang;//改变温度加强状态
     moshixuanze=0;//清零按下模式
    }
    wendujiaqiangjishukaiguan=wendujiaqiang;//开始温度加强计时
  }
else//如果是休眠状态
  {
   if(moshixuanze==1)//如果是短按
    {
     tuichuyiqie();//退出关机,休眠,温度加强
     moshixuanze=0;//清零按下模式
    }
  }
}
/********************************编码器函数2(设置模式调用)******************************/
void bianmaqi2(void)
{
if(e==1&&f==1&&encodera==1&&encoderb==0&&jinzhicaozuo==0)//和前一次状态比较确定为右旋
  {
   fengmingleixing=1;//蜂鸣类型1
   if(jiaozhun.a<480)//调节温度校准参数
    jiaozhun.a++;
    huancun=jiaozhun.a;//刷新显示
  }
if(e==1&&f==1&&encodera==0&&encoderb==1&&jinzhicaozuo==0)//和前一次状态比较确定为左旋
  {
   fengmingleixing=1;//蜂鸣类型1
   if(jiaozhun.a>400)//调节温度校准参数
    jiaozhun.a--;
   huancun=jiaozhun.a;//刷新显示
  }
if(moshixuanze==3)//如果是长按,就保存数据并退出设置模式
  {
   moshixuanze=0;//清零按下模式
   baocunshuju();//保存数据
   shezhimoshi=0;//退出设置模式
  }
}
/********************************定时器0初始化函数*******************************************/
void timer0init(void)//定时器0初始化程序,24MHz频率下,每1ms中断一次
{
TMOD=0x00;//定时模式,16位自动重装
TH0=0xf8; //计时1ms
TL0=0x2f;
ET0=1;//开启定时器0中断
TR0=1;//启动定时器0
}
/********************************定时器0中断函数********************************************/
void timer0(void) interrupt 1//定时0中断函数,用于检测旋转编码器,掉电存储等操作(仅用于正常工作模式)
{
bit m;//用于屏幕闪烁(百位,十位,个位)
unsigned char buchang2;//加热补偿(减小稳态误差)
unsigned char b;//用于产生1秒时间
unsigned char k;//用于数码管扫描
unsigned char baiwei,shiwei,gewei;//定义百位,十位,个位
unsigned int g;//用于计算百位,十位,个位
signed int a;//a为实际应该设定的温度
signed int wencha;//wencha为设定温度和实际温度的差值
if(jiluguanji&&!guanjikaiguan)//如果刚刚从关机模式唤醒
  flag2=0;//允许下次到达设定温度时蜂鸣
jiluguanji=guanjikaiguan;//记录上次是否为关机状态
/********************************显示函数***********************************/
k++;
if(k==3)//三位数码管
  k=0;
g=huancun;//要显示的数据赋值给g
baiwei=g/100;//计算百位
g=g%100;
shiwei=g/10;//计算十位
g=g%10;
gewei=g;//计算个位
if(guanjikaiguan==1&&shezhimoshi==0)//关机显示OFF
  {
   baiwei=0;
   shiwei=12;
   gewei=12;
  }
if(t12wendu==500&&shezhimoshi==0)//不插T12显示ERR
  {
   baiwei=11;
   shiwei=13;
   gewei=13;
  }
if(k==0)//扫描百位
  {
   gw=1;
   xianshigonggong(duanma[baiwei]);//显示百位
   if(shijian3>0)//震动开关状态改变时,延时显示百位小数点
    dot=1;
   bw=0;//打开百位
   if(shezhixianshijishukaiguan&&m==1)//显示校准温度350°是闪烁屏幕
    bw=1;
  }
if(k==1)//扫描十位
  {
   bw=1;
   xianshigonggong(duanma[shiwei]);//显示十位
   if(wendujiaqiang==1&&zhouqijishu>99)//如果是温度加强模式,十位小数点闪烁
    dot=1;
   if(shezhimoshi&&!jinzhicaozuo)
    dot=1;    
   sw=0;//打开十位
   if(shezhixianshijishukaiguan&&m==1)//显示校准温度350°是闪烁屏幕
    sw=1;
  }
if(k==2)//扫描个位
  {
   sw=1;
   xianshigonggong(duanma[gewei]);//显示个位
   if((xiumiankaiguan==1&&guanjikaiguan==0)&&zhouqijishu>99)//如果是休眠状态,个位小数点闪烁
    dot=1;
   gw=0;//打开个位
   if(shezhixianshijishukaiguan&&m==1)//显示校准温度350°是闪烁屏幕
    gw=1;
  }
/******************************************************************************/
diaodiancunchu();//掉电存储函数
zhendongxiumian();//震动休眠函数
anxiamoshi();//确定按下模式
if(shezhimoshi)//设置模式下
  shezhihanshu();//调用设置函数
else//加热模式下
  bianmaqi1();//调用编码器1函数
bianmaqizhuangtai();//记录编码器状态
if(moshijishukaiguan==1)//如果允许按下时间计数
  moshijishu++;//就开始计数
if(xiumiankaiguan==0&&shijian2<255)//如果不是休眠模式(即转动了编码器从休眠模式唤醒了),时间2计时
  shijian2++;
zhouqijishu++;//加热周期计数
if(jiareshu>192)//最多加热192ms
  jiareshu=192;
t12=0;//不加热
if(zhouqijishu<=jiareshu&&guanjikaiguan==0&&t12wendu!=500)//如果当前计数小于等于加热数并且不是关机模式
  t12=1;//就加热
if(zhouqijishu==200)//每到200毫秒
  {
   zhouqijishu=0;//重新开始加热周期计数
   m=!m;
   if(shezhixianshijishukaiguan==1)//如果允许设置显示计数,就开始计数
    shezhixianshijishu++;
   if(huancunkaiguan==1)//延时显示计数
    huancunjishu++;
   if(huancunjishu==8)//设定温度延时显示1.6秒
    {
     huancunkaiguan=0;//如果达到了1.6秒,关闭缓存开关
     huancunjishu=0;//停止缓存计数
     huancun=t12wendu;//由显示设定温度改为显示t12温度
    }
   b++;//用于产生1秒时间
   if(b==5)//每到1秒
    {
     b=0;
     shijian4=1;//
     if(wendujiaqiangjishukaiguan==1)//温度加强计数
      {
       wendujiaqiangjishu++;
       fengmingleixing=4;//蜂鸣类型4
      }
     if(wendujiaqiangjishu==canshu6)//如果到达设定的温度加强时间
      {
       tuichujiaqiang();//退出温度加强模式
       fengmingleixing=3;//蜂鸣类型3
       fengmingcishu=1;//重复次数1次
      }
     if((xiumianjishukaiguan==1||ganggangkaiji==1)&&t12wendu!=500)//休眠计数
      {
       if(!wendujiaqiang&&!shezhimoshi)//如果不是温度加强模式,且不是设置模式
        xiumianjishu++;//就计数
       else//否则
        xiumianjishu=0;//不计数
      }
     if(xiumianjishu==canshu2*60&&canshu2!=0)//如果达到设定时间就休眠
      {
       xiumian();//进入休眠模式
       fengmingleixing=2;
      }
     if(guanjijishukaiguan==1)//关机计数
      guanjijishu++;
     if(guanjijishu==canshu3*60&&canshu3!=0)//如果关机计数达到了设定的时间
      {
       fengmingleixing=2;//蜂鸣类型2
       guanjikaiguan=1;//进入关机状态
       guanjijishukaiguan=0;//停止关机计数
       guanjijishu=0;//清零关机计数
      }
    }
   adc();//检测电压,计算温度
   if(!flag2&&(t12wendu>=shedingwendu-3)&&(t12wendu<shedingwendu+3)&&!xiumiankaiguan&&!shezhimoshi)//如果到达设定温度
    {
     fengmingleixing=3;//蜂鸣类型3
     fengmingcishu=1;//蜂鸣重复次数1次
     flag2=1;//禁止蜂鸣
    }
   a=shedingwendu;//直接为设定温度
   if(wendujiaqiang==1)//如果是温度加强模式,温度增加canshu5度
    a=shedingwendu+canshu5;
   if(xiumiankaiguan==1)//如果是休眠模式,温度设定为canshu7度
    a=canshu7;
   if(shezhimoshi)//设置模式下
    a=350;//校准温度为350度
   if(a>480)//如果实际设定温度超过480度
    a=480;//就设为480度    
   //////////////////////////以下为加热算法(请自行理解,不作注释)//////////////////////
   wencha=a-t12wendu;
   if(wencha>1&&wencha<60&&buchang2<190)
    buchang2++;
   if(wencha<2&&buchang2>0)
    buchang2--;
   if(wencha<-1||guanjikaiguan==1)
    buchang2=0;
   jiareshu=196;
   if(wencha<60&&wencha>=10)
    jiareshu=20+wencha*3+buchang2*3;
   if(wencha<10&&wencha>=5)
    jiareshu=wencha*5+buchang2*2;
   if(wencha<5&&wencha>=0)
    jiareshu=(a-140)/8+wencha*7+buchang2;
   if(wencha<0&&wencha>=-2)
    jiareshu=(a-150)/16;
   if(wencha<-2)
    jiareshu=0;    
  }
}
/********************************设置模式函数*******************************************/
void shezhihanshu(void) //定时器1中断仅用于参数设置模式
{
bianmaqi2();//调用编码器2函数
if(ganggangkaiji==1)//如果刚刚开机
  {
   huancun=350;//显示校准温度350度
   ganggangkaiji=0;//已经开机
   shezhixianshijishukaiguan=1;//允许设置显示计数
  }
if(shezhixianshijishu==15)//如果计数到规定的3s
  {
   shezhixianshijishukaiguan=0;//停止设置显示计数
   shezhixianshijishu=0;//清零计数
   jinzhicaozuo=0;//此时允许操作编码器
   huancun=jiaozhun.a;//刷新显示
  }
}

/*********************************校验函数*************************************************/
void jiaoyanhanshu(void)
{
xindizhi=0x200;//准备读写第二扇区数据
duqushezhishuju();//读取第二扇区数据
xindizhi=0;//准备读写第一扇区数据
if(jiaoyan==0x55)//如果第二扇区数据校验正确
  baocunshuju();//把数据写入到第一扇区
else //如果第二扇区数据校验错误
  {
   duqushezhishuju();//读取第一扇区数据
   if(jiaoyan!=0x55)//如果第一扇区数据校验错误
    {
     jiaozhun.a=420;
     baocunshuju();//写入到第一扇区
    }
  }
}
/********************************主函数*****************************************************/
void main(void)//主函数
{
P1M1=0x3f;//P1除P1.6,P1.7为推挽模式外,均为输入模式
P1M0=0xc0;
P1ASF=0x07;//设置P1相应ADC转换的I/O口为ADC输入模式
P2M0=0xff;//P2均为推挽模式
P3M0=0xf0;//P3.4,P3.5,P3.6,P3.7为推挽模式,其余为输入模式
P3M1=0x0f;
ADC_CONTR=0xe0;//打开ADC电源
speaker=0;//关闭蜂鸣器
speaker2=0;//关闭蜂鸣器
while(adcdianyuan()<4850);//等待电源电压上升(防止极端情况单片机死机)
jiaoyanhanshu();//校验EEPROM存储的数据
if(jiaozhun.a>480||jiaozhun.a<400)//如果温度校准参数超出范围
  jiaozhun.a=425;//设为默认值
shedingwendu=Byte_Read(0x02ff)+200;//读取上次关机时保存的设定温度
if(shedingwendu>450)//如果读取的设定温度超出范围
  shedingwendu=300;//就设为300度
IE=0x88;//打开定时器0中断,关闭定时器1中断
timer0init();//初始化定时器0
bianmaqizhuangtai();//记录编码器状态
g=zhendongkaiguan;//记录震动开关状态
fengmingleixing=2;//蜂鸣类型2
while(1)
{
  if(fengmingleixing==0)//蜂鸣0
   {
    speaker=0;
    speaker2=0;
   }
  else if(fengmingleixing==1)//蜂鸣1
   {
    fengmingleixing=0;
    speaker=1;
    speaker2=1;
    delay_ms(12);
    speaker=0;
    speaker2=0;
   }
  else if(fengmingleixing==2)//蜂鸣2
   {
    fengmingleixing=0;
    speaker=1;
    speaker2=1;
    delay_ms(300);
    speaker=0;
    speaker2=0;
   }
  else if(fengmingleixing==3)//蜂鸣3
   {
    fengmingleixing=0;
    flag=1;
    for(m=0;m<fengmingcishu;m++)
     {
      if(flag)
       {
           speaker=1;
        speaker2=1;
        delay_ms(100);
        speaker=0;
        speaker2=0;
        delay_ms(100);
        speaker=1;
        speaker2=1;
        delay_ms(100);
        speaker=0;
        speaker2=0;
        delay_ms(1000);
       }
     }
    fengmingcishu=1;
    flag=0;
   }
  else if(fengmingleixing==4)//蜂鸣4
   {
    fengmingleixing=0;
       speaker=1;
    speaker2=1;
    delay_ms(10);
    speaker=0;
    speaker2=0;
    delay_ms(1500);
   }
  else if(fengmingleixing==5)//蜂鸣5
   {
    fengmingleixing=0;
       speaker=1;
    speaker2=1;
    delay_ms(100);
    speaker=0;
    speaker2=0;
    delay_ms(1000);
   }
}
}
本帖最近打赏记录:共16条打赏M币+54专家+1
白日梦夏雪 M币 +3 - 2015-08-05
hu2011q M币 +3 優秀文章   又来放毒了,还在用白板白光,快忍不住了。 2015-08-05
zkele M币 +3 優秀文章,,,,,,原創內容,,,强烈支持! 2015-07-18
keye M币 +3 謝謝分享谢谢分享谢谢分享 2015-07-05
xxdz12345 M币 +3 我再加 。。。 2015-07-02
大海航标 M币 +3 原創內容 2015-07-02
数码家园 M币 +3 謝謝分享 2015-07-02
lmnwanan M币 +3 金大侠怎么又闲了?还有这代码这么长估计我打下来都不容易,简直膜拜啊 2015-07-02
杨雪飞 M币 +3 这代码,如果不用复制粘贴,抄下来也不是简单的事,感谢分享 2015-07-02
zlgmo M币 +5 注释写的很详细啊,谢谢分享! 2015-07-01
12
离线水银灯

发帖
1929
M币
2269
专家
2
粉丝
67
只看该作者 2楼 发表于: 2015-07-01
谢谢分享。还不开始折腾
离线benli

发帖
33437
M币
4803
专家
85
粉丝
445
只看该作者 3楼 发表于: 2015-07-01
这个是什么版本的?硬件似乎跟以前的不同了,发个电路图吧
离线wc5095928

发帖
13943
M币
8805
专家
10
粉丝
1188
只看该作者 4楼 发表于: 2015-07-01
楼主貌似喜欢折腾单片机啊
离线worldlyguest

发帖
1152
M币
4582
专家
4
粉丝
27
只看该作者 5楼 发表于: 2015-07-01
優秀文章,好,很好,顶楼主
离线zlgmo

发帖
49648
M币
7812
专家
3
粉丝
68
只看该作者 6楼 发表于: 2015-07-01
注释写的很详细啊,谢谢分享!
离线fsss007

发帖
668
M币
6505
专家
2
粉丝
45
只看该作者 7楼 发表于: 2015-07-01
谢谢分享,我的焊接好都要好久了也没利用上,原因是用着高频烙铁及WELLERWSD81感觉好用了。
离线lf1286

发帖
3579
M币
523
专家
0
粉丝
19
只看该作者 8楼 发表于: 2015-07-01
很好,帮顶了。
离线jialishoushi

发帖
347
M币
82
专家
2
粉丝
33
只看该作者 9楼 发表于: 2015-07-01
虽然我玩不转  但很欣赏楼主的奉献精神
快速回复
限80 字节
温馨提示:欢迎交流讨论,请勿发布纯表情、纯引用等灌水帖子;以免被删除
 
上一个 下一个