找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 947|回复: 1
收起左侧

STC15F204EA T12数码管焊台移植STC15W408AS单片机问题

[复制链接]
ID:1039485 发表于 2022-8-29 11:47 | 显示全部楼层 |阅读模式
  1. /*****************STC15W408AS单片机旋转编码器版白光T12控制器代码(by金向维)***********************/
  2. #include "STC15W408AS.h"//单片机头文件,24MHz时钟频率
  3. #include "INTRINS.h"//头文件
  4. unsigned char code duanma[12]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40,0x73};//共阴数码管段码数据(0,1,2,3,4,5,6,7,8,9),倒数第二个是显示负号-的数据,倒数第一个是显示字母P的数据
  5. unsigned int code wendubiao[62]={924,959,996,1033,1071,1110,1150,1190,1232,1273,1315,1358,1401,1443,1487,1501,1574,1619,1663,1706,1751,1756,1776,1810,1853,1903,1958,2017,2078,2141,2204,2266,2327,2387,2444,2500,2554,2607,2657,2706,2738,2800,2844,2889,2931,2974,3016,3056,3098,3139,3179,3218,3257,3296,3333,3372,3408,3446,3484,3519,3554,3590};//根据NTC电阻随温度变化进而引起电压变化得出的数据,用来查表计算室温(进而对热电偶冷端补偿)
  6. unsigned char code moren[8]={150,100,43,10,3,5,30,0};//白光控制器的默认参数
  7. unsigned char canshu[7]={100,43,10,3,5,30,0};//部分参数,依次为:失调电压,热电偶数据,温度步进,休眠时间,关机时间,温度修正,唤醒方式
  8. sbit dot=P2^7;//数码管的小数点接P2.7
  9. sbit t12=P2^0;//T12通过P2.0控制
  10. sbit bw=P3^4;//数码管百位位选为P3.4
  11. sbit sw=P3^5;//数码管十位位选为P3.5
  12. sbit gw=P3^6;//数码管个位位选为P3.6
  13. sbit tihuan=P3^7;//数码管的a段本应该用P1.0控制,由于P1.0被用来控制T12,所以要用P3.7替代P1.0
  14. sbit encoderb=P1^4;//编码器的b脚接P1.4
  15. sbit encodera=P3^2;//编码器的a脚接P3.2
  16. sbit zhendongkaiguan=P5^5;//震动开关接P5.5
  17. sbit bianmaanniu=P3^3;//编码器的按键接P3.3
  18. sbit a7=P2^7;
  19. sbit a6=P2^6;
  20. sbit a5=P2^5;
  21. sbit a4=P2^4;
  22. sbit a3=P2^3;
  23. sbit a2=P2^2;
  24. sbit a1=P2^1;
  25. bit e=1,f=1,g,h=1;//e,f,h用来保存编码器上一次的状态,g用来保存震动开关上一次的状态
  26. bit huancunkaiguan=0;//用于改变设定温度后延时显示设定温度(而不是立刻显示t12温度)
  27. bit xiumiankaiguan=0;//定义休眠开关
  28. bit xiumianjishukaiguan=0;//定义休眠计数开关
  29. bit ganggangkaiji=1;//定义刚刚开机(用于确保刚开机未震动手柄能进入休眠状态,因为每次休眠计时是通过震动传感器状态改变触发的,而刚开机手柄没有震动所以要特殊处理)
  30. bit guanjikaiguan=0;//定义关机开关
  31. bit guanjijishukaiguan;//定义关机计数开关
  32. bit huifumoren=0;//是否恢复默认参数
  33. bit shezhimoshi=0;//设置模式还是正常工作模式
  34. bit shezhixianshijishukaiguan;//用于设置模式延时显示P01,P02等菜单项
  35. bit jinzhicaozuo=1;//用于设置模式下某时刻禁止编码器操作
  36. bit xianship;//用于设置模式下显示菜单P01,P02等的字母P
  37. bit wendujiaqiang;//温度加强开关
  38. bit wendujiaqiangjishukaiguan;//温度加强计数开关
  39. bit moshijishukaiguan;//编码器按下时间计数开关,用来判断长按还是短按
  40. signed char wenduxiuzheng;
  41. signed int huancun;//显示函数直接显示huancun,要显示一个数据将必须这个数据赋值给缓存(由于数码管只有三位,为了在显示三位数同时保持四位数的精度,所以实际显示的是数据除以10,支持显示负数.但是在参数设置模式下显示的是实际值,不除以10)
  42. signed int shiwen;//10倍实际室温,即实际室温乘以10(为了精确)(允许的室温范围为-11度至50度)
  43. signed int t12wendu;//T12烙铁头的实际温度(非热电偶的温差)(同样为10倍温度)
  44. signed int shedingwendu;//设定温度(范围200~450度)
  45. signed int wencha;//T12两个周期间的温差
  46. unsigned char zhouqijishu;//加热周期200ms计数
  47. unsigned char jinduzhi;//设置模式中设置到了P几(P00,P01,P02等等)
  48. unsigned char moshixuanze;//有效值0,1,2;短按编码器置2,长按置3
  49. unsigned int jiareshu;//每200ms加热周期内需要加热的次数(一次等于1ms,相当于加热占空比)
  50. unsigned int huancunjishu;//用于改变设定温度后保持显示设定温度一段时间再显示t12温度(而不是立刻显示t12温度)
  51. unsigned int baocunwendu;//用于进入休眠时保存退出休眠时恢复原来的设定温度
  52. unsigned int zengyi;//运算放大器增益
  53. unsigned int shezhixianshijishu;//设置模式中用于延时显示菜单项
  54. unsigned int moshijishu;//编码器按下时间计数,用来判断长按还是短按
  55. unsigned int shijian;
  56. unsigned long cankaodianya0,t12dianya,ntcdianya,dianyuandianya;//用于参考电压(ADC后的直接数据,未转换为mV),计算电源电压,热电偶经放大器放大后的电压和NTC电阻确定的室温电压(单位均为mV)
  57. unsigned long xiumianjishu;//等待多长时间进入休眠状态(单位ms)
  58. unsigned long guanjijishu;//等待多长时间进入关机状态(单位ms)
  59. unsigned long wendujiaqiangjishu;//多长时间退出温度加强模式(单位ms)

  60. /********************************EEPROM公共函数(1)************************************************/
  61. void gonggonghanshu(void)//所有的公共函数都是因为多次使用到了,而把它们整理起来再调用可以减小编译后的文件大小(迫不得已的做法,因为单片机的FLASH太小了,否则装不下程序)
  62. {
  63. IAP_TRIG = 0x5a;//发送5ah到触发寄存器
  64. IAP_TRIG = 0xa5;//发送a5h到触发寄存器
  65. _nop_();//延时
  66. IAP_CONTR = 0;//关闭IAP 功能
  67. IAP_CMD = 0;//清空命令寄存器
  68. IAP_TRIG = 0;//清空命令触发寄存器
  69. IAP_ADDRH = 0;//清空地址高位
  70. IAP_ADDRL = 0;//清空地址低位
  71. }

  72. /********************************字节读函数****************************************************/
  73. unsigned char Byte_Read(unsigned int add)
  74. {
  75. IAP_DATA = 0x00;//清空数据
  76. IAP_CONTR = 0x81;//打开IAP,设置操作等待时间
  77. IAP_CMD = 0x01;//字节读命令
  78. IAP_ADDRH = add>>8;//设置高8位地址
  79. IAP_ADDRL = add&0x00ff;//设置低8位地址
  80. gonggonghanshu();
  81. return (IAP_DATA);//返回读到的数据
  82. }

  83. /********************************字节编程函数************************************************/
  84. void Byte_Program(unsigned int add, unsigned char dat)
  85. {
  86. IAP_CONTR = 0x81;//打开IAP,设置操作等待时间
  87. IAP_CMD = 0x02;//字节编程命令
  88. IAP_ADDRH = add>>8;//设置高8位地址
  89. IAP_ADDRL = add&0x00ff;//设置低8位地址
  90. IAP_DATA = dat;//要编程的数据先送进IAP_DATA 寄存器
  91. gonggonghanshu();
  92. }

  93. /********************************扇区擦除函数************************************************/
  94. void Sector_Erase(unsigned int add)
  95. {
  96. IAP_CONTR = 0x81;//打开IAP,设置操作等待时间
  97. IAP_CMD = 0x03;//扇区擦除命令
  98. IAP_ADDRH = add>>8;//设置高8位地址
  99. IAP_ADDRL = add&0x00ff;//设置低8位地址
  100. gonggonghanshu();
  101. }

  102. /********************************1ms延时函数*************************************************/
  103. void delay_ms (unsigned int a)//24MHz时钟时的1毫秒延时函数
  104. {
  105. unsigned int b;
  106. while(a--)
  107. {
  108.   for(b=0;b<1200;b++);
  109. }
  110. }

  111. /********************************10us延时函数************************************************/
  112. void delay_10us (unsigned int a)//24MHz时钟时的10微秒延时函数
  113. {
  114. unsigned int b;
  115. while(a--)
  116. {
  117.   for(b=0;b<12;b++);
  118. }
  119. }

  120. /********************************数码管延时关断函数******************************************/
  121. void guanduan (void)//用于关断数码管的位选
  122. {
  123. delay_ms(1);//延时
  124. bw=1;//关断百位
  125. sw=1;//关断十位
  126. gw=1;//关断个位
  127. }

  128. /********************************公共函数10(显示)********************************************/
  129. void gonggonghanshu10(unsigned char a)
  130. {
  131. a7=a&0x80;
  132. a6=a&0x40;
  133. a5=a&0x20;
  134. a4=a&0x10;
  135. a3=a&0x08;
  136. a2=a&0x04;
  137. a1=a&0x02;
  138. tihuan=a&0x01;
  139. }

  140. /********************************显示函数****************************************************/
  141. void display(signed int a)//显示函数(显示实际数据除以10(参数设置模式除外),支持显示负数,负数显示方式为百位显示负号"-"十位和个位显示数据)
  142. {
  143.   unsigned char baiwei,shiwei,gewei,d;//定义百位,十位,个位,每次显示帧数
  144.   unsigned char f;//用于小数点闪烁
  145.   signed int c;//用于处理数字a
  146.   if(a<0)//如果a是负数
  147.    c=-a;//取a的相反数
  148.   else//否则
  149.    c=a;//就直接取a
  150.   if(guanjikaiguan==1&&shezhimoshi==0)//如果是关机状态
  151.    c=0;//就显示000
  152.   if(shezhimoshi==0)//如果是正常模式就显示数据的十分之一,如果是设置模式直接显示数据   
  153.    c=c/10;
  154.   baiwei=c/100;//计算百位
  155.   c=c%100;
  156.   shiwei=c/10;//计算十位
  157.   c=c%10;
  158.   gewei=c;//计算个位
  159.   for(d=0;d<20;d++)//显示部分,每次显示20个循环(20帧)
  160.   {
  161.    if(a<0)//如果a是负数,则百位显示负号
  162.         gonggonghanshu10(duanma[10]);
  163.    else if(shezhimoshi==1&&xianship==1)//在设置模式显示菜单项时,百位显示字母P
  164.         gonggonghanshu10(duanma[11]);
  165.    else//否则直接显示百位
  166.     gonggonghanshu10(duanma[baiwei]);//显示百位
  167.    if(shijian>6000&&f>1)//如果是温度加强模式,十位小数点闪烁
  168.     dot=1;
  169.    bw=0;//打开百位
  170.    guanduan();//延时关断百位

  171.    gonggonghanshu10(duanma[shiwei]);//显示十位
  172.    if(wendujiaqiang==1&&f>1)//如果是温度加强模式,十位小数点闪烁
  173.     dot=1;
  174.    sw=0;//打开十位
  175.    guanduan();//延时关断十位

  176.    gonggonghanshu10(duanma[gewei]);//显示个位
  177.    if((xiumiankaiguan==1&&guanjikaiguan==0)&&f>1)//如果是休眠状态,个位小数点闪烁
  178.         dot=1;
  179.    gw=0;//打开个位
  180.    guanduan();//延时关断个位
  181.    if(d==19)//用于确定小数点何时点亮(从而实现闪烁)
  182.     f++;
  183.    if(f==4)
  184.     f=0;
  185.   }
  186. }

  187. /********************************ADC公共函数**************************************************/
  188. void gonggonghanshu2(void)//此函数测量单片机电源电压
  189. {
  190. ADC_CONTR=0x88;//ADC_POWER, SPEED1, SPEED0, ADC_FLAG---ADC_START, CHS2, CHS1, CHS0
  191. delay_10us(5);//延时等待转换结束
  192. ADC_RESL=ADC_RESL&0x03;//取转换结果低八位中的低二位
  193. cankaodianya0=(ADC_RES*4+ADC_RESL);//把结果转换成十进制数据(10位ADC,最大值1024)
  194. dianyuandianya=2549760/cankaodianya0;//计算电源电压,单位mV
  195. }

  196. /********************************ADC测电压函数************************************************/
  197. void adc (void)//ADC函数,用于测量和计算各种电压
  198. {
  199. signed char a;//查NTC表用
  200. signed int b;//两次温度求平均值用
  201. gonggonghanshu2();//公共函数2(此函数功能是测量电源电压,单位mV)

  202. ADC_CONTR=0x89;//ADC_POWER, SPEED1, SPEED0, ADC_FLAG---ADC_START, CHS2, CHS1, CHS0 转换采用最低速度速,低速更精确(测量t12电压务必使用最低速度AD转换,实测高速误差大)
  203. delay_10us(5);
  204. ADC_RESL=ADC_RESL&0x03;
  205. t12dianya=(ADC_RES*4+ADC_RESL);
  206. t12dianya=2490*t12dianya/cankaodianya0;//计算t12电压,单位mV
  207.                                                                                                                        
  208. ADC_CONTR=0x8a;//ADC_POWER, SPEED1, SPEED0, ADC_FLAG---ADC_START, CHS2, CHS1, CHS0       
  209. delay_10us(5);
  210. ADC_RESL=ADC_RESL&0x03;
  211. ntcdianya=(ADC_RES*4+ADC_RESL);
  212. ntcdianya=2490*ntcdianya/cankaodianya0;//计算ntc电压,单位mV

  213. for(a=0;wendubiao[a]<ntcdianya;a++)//查表计算室温
  214.   {
  215.    if(a>=61)//如果超出表的范围就取允许的最高温度(50度)
  216.    break;//并且退出查表
  217.   }
  218. shiwen=(a-11)*10;//得出室温(实际室温乘以10)

  219. t12wendu=(t12dianya-canshu[0])*canshu[1]*10/zengyi+shiwen-wenduxiuzheng*10;//计算t12的实际温度
  220. if((t12wendu-b)>-2000&&(t12wendu-b)<2000)//如果两次温度相差不超过200度
  221.   t12wendu=(t12wendu+b)/2;//就两次温度求平均值
  222. if(t12wendu<shiwen)//如果t12温度小于室温
  223.   t12wendu=shiwen;//就取室温
  224. b=t12wendu;//记录上一次温度
  225. if(t12wendu>5000)//如果得出的温度超过500度,说明没有插入烙铁头或参数错误(因为烙铁头的温度不可能超过500度)
  226.   t12wendu=5000;//显示500作为错误指示(注意显示函数显示的是1/10,所以要显示500,需要赋值5000)
  227. if(huancunkaiguan==1)//如果缓存开关开,说明刚刚改变了设定温度
  228.   huancun=shedingwendu;//于是显示设定温度(而不是t12温度)
  229. else
  230.   huancun=t12wendu;//否则直接显示t12温度
  231. }

  232. /********************************定时器0初始化函数*******************************************/
  233. void timer0init (void)//定时器0初始化程序,24MHz频率下,每1ms中断一次
  234. {
  235. TMOD=0x00;//定时模式,16位自动重装
  236. TH0=0xf8; //计时1ms
  237. TL0=0x2f;
  238. ET0=1;//开启定时器0中断
  239. TR0=1;//启动定时器0
  240. }

  241. /********************************定时器1初始化函数*******************************************/
  242. void timer1init (void)//定时器0初始化程序,24MHz频率下,每1ms中断一次
  243. {
  244. TMOD=0x00;//定时模式,16位自动重装
  245. TH1=0xf8; //计时1ms
  246. TL1=0x2f;
  247. ET1=1;//开启定时器1中断
  248. TR1=1;//启动定时器1
  249. }

  250. /********************************恢复默认值函数********************************************/
  251. void morenzhi(void)//恢复控制器的默认参数
  252. {
  253. unsigned char a;
  254. Sector_Erase(0x0000);//擦除扇区
  255. for(a=0;a<9;a++)//一项一项的查表并存储参数
  256.   Byte_Program(a,moren[a]);
  257. }

  258. /********************************公共函数4(退出温度加强)************************************/
  259. void gonggonghanshu4(void)
  260. {
  261. wendujiaqiangjishukaiguan=0;//温度加强计数关闭
  262. wendujiaqiangjishu=0;//清零温度加强计数
  263. wendujiaqiang=0;//退出温度加强
  264. }

  265. /********************************公共函数3(编码器)******************************************/
  266. void gonggonghanshu3(void)
  267. {
  268. ganggangkaiji=0;//已经开机
  269. if(xiumiankaiguan==1)//如果原来在休眠状态
  270.   {
  271.    xiumiankaiguan=0;//停止休眠
  272.    shedingwendu=baocunwendu;//恢复休眠前的设定温度
  273.   }
  274. xiumianjishukaiguan=1;//允许新的一次休眠计时
  275. xiumianjishu=0;//从0开始计时
  276. guanjijishukaiguan=0;//停止关机计数
  277. guanjikaiguan=0;//退出关机状态
  278. gonggonghanshu4();//退出温度加强
  279. }

  280. /********************************公共函数6(记录编码器状态)**********************************/
  281. void gonggonghanshu6(void)
  282. {
  283. e=encodera;//记录编码器a脚此次状态
  284. f=encoderb;//记录编码器b脚此次状态
  285. h=bianmaanniu;//记录编码按钮此次状态
  286. }

  287. /********************************公共函数8(进入休眠)****************************************/
  288. void gonggonghanshu8(void)
  289. {
  290. ganggangkaiji=0;//已经开机
  291. baocunwendu=shedingwendu;//记录当前设定温度
  292. shedingwendu=2000;//设定休眠温度
  293. xiumiankaiguan=1;//进入休眠状态
  294. xiumianjishukaiguan=0;//停止休眠计数
  295. xiumianjishu=0;//清零休眠计数
  296. guanjijishukaiguan=1;//允许关机计数
  297. }
  298. /********************************公共函数9(确定按下模式)************************************/
  299. void gonggonghanshu9(void)
  300. {
  301. if(h==1&&bianmaanniu==0)//如果按下了编码器
  302.    moshijishukaiguan=1;//允许按下时间计数
  303. if(moshijishukaiguan==1)//如果允许按下时间计数
  304.   moshijishu++;//就开始计数
  305. if(moshijishukaiguan==1&&bianmaanniu==1)//如果在计数过程中编码器松开
  306.   {
  307.    moshijishukaiguan=0;//停止按下时间计数
  308.    if(moshijishu>1500)//
  309.     moshixuanze=3;
  310.    else if(moshijishu>300)//如果按下时间大于0.3秒
  311.     moshixuanze=2;//就是长按
  312.    else//否则
  313.     moshixuanze=1;//就是短按;
  314.    moshijishu=0;//清零计数
  315.   }
  316. }

  317. /********************************编码器函数(正常加热模式调用)********************************/
  318. void bianmaqi(void)
  319. {
  320. if(e==1&&f==1&&encodera==1&&encoderb==0)//和前一次状态比较确定为右旋
  321.   {
  322.    shedingwendu=shedingwendu+canshu[2]*10;//步进
  323.    if(shedingwendu>4500)//最高允许450度
  324.         shedingwendu=4500;
  325.    huancun=shedingwendu;//显示改变后的设定温度
  326.    huancunkaiguan=1;//打开缓存开关(用于延时显示设定温度1.5秒)
  327.    huancunjishu=0;//重新开始缓存计数
  328.    gonggonghanshu3();
  329.   }
  330. if(e==1&&f==1&&encodera==0&&encoderb==1)//和前一次状态比较确定为左旋
  331.   {
  332.    shedingwendu=shedingwendu-canshu[2]*10;//步进
  333.    if(shedingwendu<2000)//最低允许200度
  334.         shedingwendu=2000;
  335.    huancun=shedingwendu;//显示改变后的设定温度
  336.    huancunkaiguan=1;//打开缓存开关(用于延时显示设定温度1.5秒)
  337.    huancunjishu=0;//重新开始缓存计数
  338.    gonggonghanshu3();
  339.   }
  340. gonggonghanshu9();//确定按下模式
  341. if(moshixuanze==2)//如果是长按
  342.   {
  343.    gonggonghanshu8();//就进入休眠状态
  344.    moshixuanze=0;//清零按下模式
  345.   }
  346. if(moshixuanze==3)
  347.   {
  348.    jinduzhi=0;//进度值设为0
  349.    shezhimoshi=1;//进入参数设置模式
  350.    ET0=0;//关闭定时器0中断
  351.    TR0=0;//关闭定时器0
  352.    IE=0x82;//打开定时器1中断,关闭定时器0中断
  353.    timer1init();//初始化定时器1
  354.    ganggangkaiji=1;//认为是刚刚开机
  355.    moshixuanze=0;//清零模式选择
  356.   }
  357. if(xiumiankaiguan==0)//如果不是休眠状态
  358.   {
  359.    if(moshixuanze==1)//如果是短按
  360.         {
  361.      wendujiaqiang=~wendujiaqiang;//改变温度加强状态
  362.          moshixuanze=0;
  363.         }
  364.    if(wendujiaqiang==1)//如果温度加强打开
  365.     wendujiaqiangjishukaiguan=1;//开始温度加强计时
  366.   }
  367. else//如果是休眠状态
  368.   {
  369.    if(moshixuanze==1)//如果是短按
  370.     {
  371.          gonggonghanshu3();//退出温度加强模式
  372.      moshixuanze=0;//清零按下模式
  373.         }
  374.   }
  375. gonggonghanshu6();//记录编码器状态
  376. }

  377. /********************************读取设置数据函数******************************************/
  378. void duqushezhishuju(void)//读取控制器的参数
  379. {
  380. unsigned char a;
  381. zengyi=Byte_Read(0x0000);//读取增益原始参数
  382. zengyi=zengyi+100;//换算到正确的区间
  383. for(a=0;a<7;a++)//读取其他的参数值
  384.   {
  385.    canshu[a]=Byte_Read(a+1);
  386.   }
  387. wenduxiuzheng=canshu[5]-30;
  388. }

  389. /********************************保存数据函数**********************************************/
  390. void baocunshuju(void)//保存控制器数据到EEPROM
  391. {
  392. unsigned char a;
  393. Sector_Erase(0x0000);//擦除扇区
  394. Byte_Program(0x0000,(zengyi-100));//保存增益参数
  395. for(a=0;a<7;a++)//保存其他参数
  396.   {
  397.    Byte_Program(a+1,canshu[a]);
  398.   }
  399. }
  400. /********************************公共函数7(刷新菜单显示)*************************************/
  401. void gonggonghanshu7(void)
  402. {
  403. huancun=canshu[jinduzhi-2];
  404. if(jinduzhi==0)
  405.   huancun=huifumoren;
  406. if(jinduzhi==1)
  407.   huancun=zengyi;
  408. if(jinduzhi==7)
  409.   huancun=wenduxiuzheng;
  410. }

  411. /********************************公共函数11(退出设置模式,进入加热模式)**************************/
  412. void gonggonghanshu11(void)
  413. {
  414. shijian=0;
  415. moshixuanze=0;
  416. baocunshuju();//保存数据到EEPROM
  417. xianship=0;//所以百位不再显示字母P
  418. shezhimoshi=0;//退出设置模式
  419. ET1=0;//关闭定时器1
  420. TR1=0;
  421. IE=0x88;//关闭定时器1中断,开启定时器0中断
  422. timer0init();//初始化定时器0,进入正常工作模式!!!!!!!!!!!
  423. ganggangkaiji=1;//认为是刚刚开机
  424. xiumianjishukaiguan=1;//允许新的一次休眠计时
  425. xiumianjishu=0;//从0开始计时
  426. }

  427. /********************************编码器函数2(参数设置模式调用)******************************/
  428. void bianmaqi2(void)
  429. {
  430. gonggonghanshu9();//确定按下模式
  431. if(e==1&&f==1&&encodera==1&&encoderb==0&&jinzhicaozuo==0)//和前一次状态比较确定为右旋
  432.   {
  433.    if(jinduzhi==0)//菜单P00
  434.          huifumoren=1;
  435.    if(jinduzhi==1)//菜单P01
  436.         {
  437.          if(zengyi<350)
  438.           zengyi++;
  439.         }
  440.    if(jinduzhi==2)//菜单P02
  441.         {
  442.          if(canshu[0]<250)
  443.           canshu[0]=canshu[0]+2;
  444.         }
  445.    if(jinduzhi==3)//菜单P03
  446.         {
  447.          if(canshu[1]<50)
  448.           canshu[1]++;
  449.         }
  450.    if(jinduzhi==4)//菜单P04
  451.     {
  452.      if(canshu[2]==0)
  453.       canshu[2]=1;
  454.      else if(canshu[2]==1)
  455.       canshu[2]=2;
  456.      else if(canshu[2]==2)
  457.       canshu[2]=5;
  458.      else if(canshu[2]==5)
  459.       canshu[2]=10;
  460.     }
  461.    if(jinduzhi==5)//菜单P05
  462.     {
  463.          if(canshu[3]<60)
  464.           canshu[3]++;
  465.         }
  466.    if(jinduzhi==6)//菜单P06
  467.     {
  468.          if(canshu[4]<180)
  469.           {
  470.            if(canshu[4]<30)
  471.             canshu[4]++;
  472.            else
  473.             canshu[4]=canshu[4]+10;
  474.           }
  475.         }
  476.    if(jinduzhi==7)//菜单P07
  477.     {
  478.          if(wenduxiuzheng<30)
  479.           {
  480.            wenduxiuzheng++;
  481.            canshu[5]=wenduxiuzheng+30;
  482.           }
  483.         }
  484.    if(jinduzhi==8)//菜单P08
  485.         canshu[6]=1;
  486.    gonggonghanshu7();//刷新菜单显示
  487.    shijian=0;
  488.   }
  489. if(e==1&&f==1&&encodera==0&&encoderb==1&&jinzhicaozuo==0)//和前一次状态比较确定为左旋
  490.   {
  491.    if(jinduzhi==0)//同上,不再赘述
  492.          huifumoren=0;
  493.    if(jinduzhi==1)
  494.         {
  495.          if(zengyi>200)
  496.           zengyi--;
  497.         }
  498.    if(jinduzhi==2)
  499.         {
  500.          if(canshu[0]>=2)
  501.           canshu[0]=canshu[0]-2;
  502.         }
  503.    if(jinduzhi==3)
  504.         {
  505.          if(canshu[1]>30)
  506.           canshu[1]--;
  507.         }
  508.    if(jinduzhi==4)
  509.     {
  510.      if(canshu[2]==1)
  511.       canshu[2]=0;
  512.      else if(canshu[2]==2)
  513.       canshu[2]=1;
  514.      else if(canshu[2]==5)
  515.       canshu[2]=2;
  516.      else if(canshu[2]==10)
  517.       canshu[2]=5;
  518.     }
  519.    if(jinduzhi==5)
  520.     {
  521.          if(canshu[3]>0)
  522.           canshu[3]--;
  523.         }
  524.    if(jinduzhi==6)
  525.     {
  526.          if(canshu[4]>0)
  527.           {
  528.            if(canshu[4]<31)
  529.             canshu[4]--;
  530.            else
  531.             canshu[4]=canshu[4]-10;
  532.           }
  533.         }
  534.    if(jinduzhi==7)
  535.     {
  536.          if(wenduxiuzheng>-30)
  537.           {
  538.            wenduxiuzheng--;
  539.            canshu[5]=wenduxiuzheng+30;
  540.           }
  541.         }
  542.    if(jinduzhi==8)
  543.         canshu[6]=0;
  544.    gonggonghanshu7();//刷新菜单显示
  545.    shijian=0;
  546.   }
  547. if(shijian>8000)//如果超过设定时间
  548.   gonggonghanshu11();//自动退出参数设置模式,进入加热模式
  549. if(h==0&&bianmaanniu==1&&jinzhicaozuo==0)//如果按下编码按钮,并且此时允许操作编码器
  550.   {
  551.    if(jinduzhi==0&&huifumoren==1)//如果在P00菜单选择了恢复默认值
  552.         {
  553.          morenzhi();//就恢复默认值
  554.          duqushezhishuju();//并重新读取数据到RAM
  555.         }
  556.    jinduzhi++;//菜单数加一(即下一项菜单)
  557.    xianship=1;//百位显示字母P
  558.    huancun=jinduzhi;//显示新的菜单项(指P几菜单)
  559.    jinzhicaozuo=1;//由于菜单项要延迟显示1.5秒才显示菜单对应的参数,所以显示菜单项的时候禁止操作编码器改变参数
  560.    shezhixianshijishukaiguan=1;//允许开始新的延迟计数(1.5秒)
  561.    shezhixianshijishu=0;//从0开始计数
  562.    baocunshuju();//保存数据到EEPROM
  563.    if(jinduzhi==9||moshixuanze==3)//菜单项最大为P08,如果到了P09说明所有的菜单都设置完了
  564.         gonggonghanshu11();//退出参数设置模式,进入加热模式
  565.   }
  566. gonggonghanshu6();//记录编码器状态
  567. if(bianmaanniu==0)
  568.   shijian=0;
  569. }

  570. /********************************掉电存储函数*********************************************/
  571. void diaodiancunchu(void)//用于关机时存储温度数据,以便下次开机时恢复温度
  572. {
  573. gonggonghanshu2();//检测电源电压
  574. if(dianyuandianya<4850)//如果电源电压降低到4.85V说明掉电了
  575.   {
  576.    P2=0x00;//关闭数码管位选和t12(即停止显示,停止加热),节约电量
  577.    P3=0x70;//关闭替换脚,关闭位选脚,节约电量
  578.    if(xiumiankaiguan==1)//如果是休眠状态
  579.     shedingwendu=baocunwendu;//就恢复休眠前的温度
  580.    Sector_Erase(0x0200);//擦除扇区
  581.    Byte_Program(0x0200,(shedingwendu/10-200));//写入温度到EEPROM
  582.    delay_ms(40);//等待写入完毕
  583.    t12=1;//设定温度已经保存,于是加热t12以尽快耗尽电容电量,加速关机
  584.    delay_ms(1000);//最多加热1S
  585.   }
  586. }

  587. /********************************震动休眠函数**********************************************/
  588. void zhendongxiumian(void)
  589. {
  590. if(zhendongkaiguan!=g)//震动开关状态改变,说明晃动了手柄
  591.   {
  592.    ganggangkaiji=0;//已经开机
  593.    xiumianjishu=0;//清零休眠计数
  594.    xiumianjishukaiguan=1;//开始新的休眠计数
  595.    if((xiumiankaiguan==1&&guanjikaiguan==0)||(xiumiankaiguan==1&&guanjikaiguan==1&&canshu[6]==0))//
  596.     {
  597.          xiumiankaiguan=0;//停止休眠
  598.          shedingwendu=baocunwendu;//恢复原来的温度
  599.          xiumianjishukaiguan=1;//允许新一次休眠计数
  600.      xiumianjishu=0;//从0开始计数
  601.      guanjijishukaiguan=0;//停止关机计数
  602.      guanjikaiguan=0;//退出关机状态(如果原来是关机状态的话)
  603.         }
  604.   }
  605. g=zhendongkaiguan;//保存当前震动传感器状态(用于和下一次比较,以便确定是否震动了)
  606. }

  607. /********************************定时器0中断函数********************************************/
  608. void timer0(void) interrupt 1//定时0中断函数,用于检测旋转编码器,掉电存储等操作(仅用于正常工作模式)
  609. {
  610. unsigned int a,b;
  611. unsigned char buchang;
  612. diaodiancunchu();//调用掉电存储函数
  613. bianmaqi();//调用编码器函数
  614. zhendongxiumian();//调用震动休眠函数
  615. if(huancunkaiguan==1)//延时显示计数
  616.   huancunjishu++;
  617. if(xiumianjishukaiguan==1||ganggangkaiji==1)//休眠计数
  618.   {
  619.    if(wendujiaqiang==0)//如果不是温度加强模式
  620.     xiumianjishu++;//就计数
  621.    else//否则
  622.     xiumianjishu=1;//不计数
  623.   }
  624. if(guanjijishukaiguan==1||canshu[4]==0)//关机计数
  625.   guanjijishu++;
  626. if(wendujiaqiangjishukaiguan==1)//温度加强计数
  627.   wendujiaqiangjishu++;
  628. if(wendujiaqiangjishu==60000)//如果到达设定的温度加强时间(60s)
  629.   gonggonghanshu4();//退出温度加强模式
  630. if(xiumianjishu==canshu[3]*60000)//如果达到设定时间就休眠
  631.   gonggonghanshu8();//进入休眠模式

  632. if(guanjijishu==canshu[4]*60000)//如果关机计数达到了设定的时间
  633.   {
  634.    guanjikaiguan=1;//进入关机状态
  635.    guanjijishukaiguan=0;//停止关机计数
  636.    guanjijishu=0;//清零关机计数
  637.   }
  638. zhouqijishu++;//加热周期计数
  639. if(jiareshu>196)//最多加热196ms
  640.   jiareshu=196;
  641. if((zhouqijishu<=jiareshu)&&(guanjikaiguan==0))//如果当前计数小于等于加热数并且不是关机模式
  642.   t12=1;//就加热
  643. else//否则
  644.   t12=0;//不加热
  645. if(t12wendu==5000)//如果t12温度为500,说明没有插入烙铁头或参数严重错误
  646.   t12=0;//停止加热
  647. if(huancunjishu==1500)//设定温度延时显示1.5秒
  648.   {
  649.    huancunkaiguan=0;//如果达到了1.5秒,关闭缓存开关
  650.    huancunjishu=0;//停止缓存计数
  651.    huancun=t12wendu;//由显示设定温度改为显示t12温度
  652.   }
  653. if(zhouqijishu==200)//t12停止加热后2ms再检测温度(给电容留出放电时间,防止检测的温度偏高)
  654.   {
  655.    adc();//检测电压,计算温度
  656.    zhouqijishu=0;//重新开始加热周期计数
  657.    if(wendujiaqiang==1)
  658.     a=shedingwendu+515;
  659.    else
  660.     a=shedingwendu+15;
  661.    if(a>4515)
  662.     a=4515;        //////////////////////////以下为加热算法(请自行理解,不作注释)//////////////////////
  663.    if(t12wendu>a)
  664.     {
  665.          if(t12wendu-a<=20)
  666.           jiareshu=(t12wendu-a)/4+a/1000;
  667.          else
  668.           jiareshu=0;
  669.         }
  670.    if(t12wendu<=a)
  671.     {
  672.          wencha=a-t12wendu;
  673.          if(wencha>30)
  674.           {
  675.            buchang++;
  676.            if(buchang>150)
  677.             buchang=150;
  678.           }
  679.          else
  680.           buchang=0;
  681.          if(a-t12wendu>=300)
  682.           jiareshu=198;
  683.          else if(a-t12wendu>=200)
  684.           jiareshu=160;
  685.          else if(a-t12wendu>=150)
  686.           jiareshu=130;
  687.          else if(a-t12wendu>=100)
  688.           jiareshu=90+wencha/2+buchang;
  689.          else if(a-t12wendu>=50)
  690.           jiareshu=50+buchang*2;
  691.          else
  692.           jiareshu=shedingwendu/400+wencha*2/3+buchang;
  693.         }
  694.    }
  695.   if((b>t12wendu)&&(t12wendu<shedingwendu-30))
  696.    jiareshu=jiareshu+50;
  697.   b=t12wendu;
  698. }

  699. /********************************定时器1中断函数*******************************************/
  700. void timer1(void) interrupt 3//定时器1中断仅用于参数设置模式
  701. {
  702. shijian++;
  703. t12=0;
  704. bianmaqi2();//调用编码器2函数
  705. if(ganggangkaiji==1)//如果刚刚开机
  706.   {
  707.    xianship=1;//百位显示字母P
  708.    huancun=jinduzhi;//显示菜单P00(因为此时进度值为0)
  709.    ganggangkaiji=0;//已经开机
  710.    shezhixianshijishukaiguan=1;//允许设置显示计数
  711.   }
  712. if(shezhixianshijishukaiguan==1)//如果允许设置显示计数,就开始计数
  713.   shezhixianshijishu++;
  714. if(shezhixianshijishu==1500)//如果计数到规定的1.5s
  715.   {
  716.    xianship=0;//停止显示百位的字母P
  717.    shezhixianshijishukaiguan=0;//停止设置显示计数
  718.    shezhixianshijishu=0;//清零计数
  719.    jinzhicaozuo=0;//此时禁止操作编码器
  720.    huancun=canshu[jinduzhi-2];
  721.    if(jinduzhi==0)//显示当前菜单项对应的参数(P00的参数)
  722.     huancun=huifumoren;
  723.    if(jinduzhi==1)//同上,不再赘述
  724.     huancun=zengyi;
  725.    if(jinduzhi==7)
  726.     huancun=wenduxiuzheng;
  727.    jinzhicaozuo=0;//禁止编码器操作
  728.   }
  729. }

  730. /********************************主函数*****************************************************/
  731. void main (void)//主函数
  732. {
  733. P1M0=0x00;//P1除P1.0,P1.1,P1.2为输入模式外均为正常模式
  734. P1M1=0x07;
  735. P1ASF=0x07;//设置P1相应ADC转换的I/O口为ADC输入模式
  736. P2M0=0xff;//P2都是推挽模式
  737. P2M1=0x00;
  738. P3M0=0xf0;//P3.4,P3.5,P3.6,P3.7为推挽模式,P3.2,P3.3为输入模式,其余正常模式
  739. P3M1=0x06;
  740. ADC_CONTR=0xe0;//打开ADC电源
  741. shedingwendu=Byte_Read(0x0200);//读取上次关机时保存的设定温度
  742. shedingwendu=(shedingwendu+200)*10;
  743. if(shedingwendu>4500||shedingwendu<2000)//如果读取的设定温度超出范围
  744.   shedingwendu=3000;//就设为300度
  745. duqushezhishuju();//读取控制器的设置参数
  746. if(bianmaanniu==0)//如果开机时编码按钮是低电平(即按下了按钮)
  747.   {
  748.    shezhimoshi=1;//进入参数设置模式
  749.    IE=0x82;//打开定时器1中断,关闭定时器0中断
  750.    timer1init();//初始化定时器1
  751.   }
  752. else//如果开机时没有按下编码器按钮
  753.   {
  754.    shezhimoshi=0;//进入正常加热模式
  755.    IE=0x88;//打开定时器0中断,关闭定时器1中断
  756.    timer0init();//初始化定时器0
  757.   }
  758. while(1)
  759. {
  760.   display(huancun);//数码管显示数据
  761. }
  762. }
复制代码
以上为金大师STC15F204EA T12数码管焊台固件,本人小白。只知道改引脚P5.5,后来发现STC15W408AS没有定时器1,导致刷了程序导致T12无法正常工作,请教大佬们怎么把定时器1改成定时器2。
回复

使用道具 举报

ID:213173 发表于 2022-8-29 17:53 | 显示全部楼层
void Timer2Init(void)                //1毫秒@24.000MHz
{
        AUXR |= 0x04;                //定时器时钟1T模式
        T2L = 0x40;                //设置定时初始值
        T2H = 0xA2;                //设置定时初始值
        AUXR |= 0x10;                //定时器2开始计时
}

void timer2() interrupt 12
{
shijian++;
t12=0;
bianmaqi2();//调用编码器2函数
if(ganggangkaiji==1)//如果刚刚开机
  {
   xianship=1;//百位显示字母P
   huancun=jinduzhi;//显示菜单P00(因为此时进度值为0)
   ganggangkaiji=0;//已经开机
   shezhixianshijishukaiguan=1;//允许设置显示计数
  }
if(shezhixianshijishukaiguan==1)//如果允许设置显示计数,就开始计数
  shezhixianshijishu++;
if(shezhixianshijishu==1500)//如果计数到规定的1.5s
  {
   xianship=0;//停止显示百位的字母P
   shezhixianshijishukaiguan=0;//停止设置显示计数
   shezhixianshijishu=0;//清零计数
   jinzhicaozuo=0;//此时禁止操作编码器
   huancun=canshu[jinduzhi-2];
   if(jinduzhi==0)//显示当前菜单项对应的参数(P00的参数)
    huancun=huifumoren;
   if(jinduzhi==1)//同上,不再赘述
    huancun=zengyi;
   if(jinduzhi==7)
    huancun=wenduxiuzheng;
   jinzhicaozuo=0;//禁止编码器操作
  }
}
回复

使用道具 举报

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

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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