找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 12112|回复: 29
打印 上一主题 下一主题
收起左侧

单片机PID算法MAX6675热电偶温控项目源程序与电路图+PCB

  [复制链接]
跳转到指定楼层
楼主
ID:280052 发表于 2018-3-13 19:56 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本附件包含51单片机上面实现PID温控项目的所有程序电路原理及其仿真
Altium Designer画的原理图和PCB图如下:(51hei附件中可下载工程文件)


单片机源程序如下:
  1. #include<intrins.h>
  2. #include<stdlib.h>//包含 rand() 这样的随机函数

  3. #include "STC12C5A60S2.h"
  4. #include "zcy.h"
  5. #include "s_12864.h"



  6. ////////////////////////////////////////////////////////
  7. //全局变量

  8. volatile long time0_temp1 = 0;
  9. volatile long time0_temp2 = 0;

  10. volatile long global_sec = 0;

  11. int key_counter = 0 ;
  12. int led_flash_mode_index = 2 ;//led闪灯模式 1--8 从1开始 最多8种模式   ssssssssss

  13. volatile int time0_10ms_flag = 0;
  14. int time0_10ms_counter = 0;
  15. int led_active_flag = 0;

  16. typedef void (*led_fun_str)(void);//定义一个函数指针的数据类型
  17. //之后用该数据类型定义一个数组
  18. led_fun_str led_fun_bufffer[29+29];

  19. void (*led_flash_fun_str)(void);

  20. int led_index = 1;

  21. int k_off = 0;
  22. int k_on  = 0;

  23. uchar temp_random = 0;
  24. uchar now_temp_random = 0;
  25. uchar last_temp_random = 0;
  26. uchar temp_diff        = 0;

  27. uchar temp_buffer_random[29];

  28. int k_extern = 0;
  29. int loop_temp = 0;

  30. uchar temp_buffer_16_16_comm[32];//必须设计成全局变量才不会显示错乱
  31. uchar temp_buffer_8_16_comm[16];//必须设计成全局变量才不会显示错乱

  32. int refer_fun_flag = 0;
  33. int key_perss_counter  = 0;
  34. int key_once_active_flag = 0;//key动作一次
  35. int key_value = 0 ;

  36. float now_temp              = 0.0;
  37. long dis_now_temp           = 0;
  38. float wenkong_now_temp      = 0.0;//用于温度控制的当前温度

  39. volatile int global_sec_flag = 0;
  40. int temp_zero_below_flag = 1 ;//1说明是0及正温度  0说明是负温度

  41. char temp_dis_num_buffer[10];//必须定义成全局变量 否则出错 原因不详
  42. char *temp_str;

  43. uint them = 0;
  44. int  ds_18b20_reset_ok_flag = 0;

  45. //pid
  46. float           SV_value           = 50.0; //设定温度值
  47. float           PV_value           = 0.0;  //用于参与计算的当前温度值
  48. volatile float  P_value            = 0.0;  //比例带 比如56.3代表56.3%  0.0--200.0
  49. int             I_value            = 0;  //积分时间  秒  0-3600
  50. int             D_value            = 0;   //微分时间  秒  0-900

  51. int comm_dis_once_flag    = 1; //初始为1
  52. volatile int special_dis_once_flag = 1; //初始为1
  53. int pid_tune_flag         = 0;//初始为0 即pid阶段 采用默认的值    1 为自整定过程

  54. int three_dot_dis_flag    = 0;

  55. float  Proportion  = 0.0;           //  比例常数 Proportional Const
  56. float  Integral    = 0.0;           //  积分常数 Integral Const        
  57. float  Derivative  = 0.0;           //  微分常数 Derivative Const
  58. float  LastError   = 0.0;           //  Error[-1]
  59. float  PrevError   = 0.0;           //  Error[-2]
  60. float  SumError    = 0.0;           //  Sums of Errors
  61. float  dError      = 0.0;
  62. float  Error       = 0.0;

  63. int   pid_result = 0;
  64. float T_Hight = 0.0;
  65. float T_LOW   = 100.0; //温度
  66. long TIME_Hight = 0;
  67. long TIME_LOW   = 0;        //具体的秒
  68. int pid_con_10ms_flag = 0;
  69. int pid_con_counter        = 0;

  70. float  KC = 1.0;  //临界比例系数  初始默认的值
  71. int    TC = 40;   //振荡周期      初始默认的值

  72. int temp_pid  =  0;//设定成全局变量  

  73. volatile int get_now_temp_flag   = 0;
  74. volatile int enable_pid_sec_flag = 0;
  75. volatile int pid_self_sec_flag   = 0;

  76. //uint pid_self_calc_buffer[200] _at_ 0xF000;        //0xffff 对应flash的最顶端

  77. int zero_across_counter = 0;
  78. int pid_self_first_status_flag = 0;

  79. long pid_self_time_sec = 0;

  80. float max_temp  = 0.0 ;  //初始温度等于0
  81. float min_temp  = 100.0 ;//初始温度等于100
  82. float sum_temp  = 0.0 ;  //初始温度等于0
  83. float aver_temp        = 0.0 ;

  84. int cool_ack_counter    = 0;
  85. int hot_ack_counter     = 0;
  86. int once_add_1_flag     = 0;

  87. float pid_self_calc_buffer[4];
  88. int k_pid_self_counter = 0;

  89. int enable_calc_min_max_flag = 0;
  90. int k_max_min = 0;
  91. int dis_tune_once_flag = 1;

  92. int k_cut_off_flag = 0;//断k偶标志
  93. long k_reou_value = 0;

  94. int soft_dis_flag = 1;
  95. int soft_counter  = 0;
  96. int soft_end_counter = 0;

  97. int pwm_con_time_flag = 0;

  98. //qqqqqqqqqqqqqq
  99. ////////////////////////////////////////////////////////
  100. //函数定义
  101. void SendByte(uchar Dbyte); //发送字节数据
  102. void write_cmd(uchar Cbyte);//写指令
  103. void write_data(uchar Dbyte);//写数据
  104. void PUTchar8x8(int row,int col,int count,uchar *put);
  105. void PUTchar8x16(int row,int col,int count,uchar *put);
  106. void PUTchar16x16(int row,int col,int count,uchar *put);//32个字节表示1个汉字
  107. void PUTchar24x24(int row,int col,int count,uchar *put);
  108. void PUTBMP(void);//图片
  109. void PUTREVERSEBMP(void);//图片反显
  110. void LcmClear(void);//清屏
  111. void LcmSet(void);//显示所有  即满屏都是黑色的
  112. void LcmInit(void);//初始化
  113. void ohengxian(void);//O横线程序
  114. void jihengxian(void);//奇横线程序
  115. void oshuxian(void);//O竖线程序
  116. void jishuxian(void);//奇竖线程序
  117. void dianxian(void);//点显示程序 满屏都是点
  118. void zifu8x16xian(void);//可以显示数字及英文
  119. void zifu16x16xian(void);//可以显示特定的汉字
  120. void lcd_dis_position_16_16(int line,int column,uchar zifu_16_16[2]);// 1行 1列 具体的字符
  121. void lcd_dis_position_8_16(int line,int column,uchar zifu_8_16);// 1行 1列 具体的字符
  122. void lcd_s_12864_dis_8_16_str(int dis_line,int start_position,char *dis_str);//显示一行的8*16的字符
  123. void ds_18b20_DelayXus(int n);
  124. void ds_18b20_init(void);//DS18B20的初始化
  125. uchar ds_18b20_read_date(void);  //读一个字节
  126. void ds_18b20_write_date(uchar date);//写一个字节
  127. float read_18b20_temp(void);//读出18b20的温度值 实际温度值返回 同时改变temp_zero_below_flag的值 如果是0 说明是0度以下
  128. void key_pro(void);
  129. void display_pro(void);
  130. void pid_pro(void);
  131. void dis_4_line_as_null(void);
  132. void dis_pid_self_value(void);
  133. float read_max6675_temper(void);// 利用max6675读k探头的温度 返回最终温度的1倍
  134. void PWM_clock(uchar clock);
  135. void PWM_start(uchar module,uchar mode);
  136. void set_pwm_value(uchar value);//0--255之间         value越大,占空比越高 输出电压也越大 40-->0.8v 237-->4.6v



  137. //hhhhhhhhhhhhhhhhhhhhhhhhhhh
  138. ////////////////////////////////////////////////////////
  139. //中断函数ttttttttttttttttttttttttttttt
  140. void tm0_isr(void) interrupt 1 using 1  //1ms
  141. {

  142. TL0 = 0x20;                //设置定时初值
  143. TH0 = 0xD1;                //设置定时初值
  144.         
  145. time0_temp1++;
  146. if(time0_temp1 % 2 == 0 )//2ms
  147.         {
  148.         
  149.         pid_con_10ms_flag = 1;
  150.         
  151.         }
  152. if(time0_temp1 >= 10 )//10ms
  153.         {
  154.         time0_temp1 = 0;
  155.         time0_10ms_flag = 1;
  156.         
  157.         }

  158. time0_temp2++;

  159. if(time0_temp2 % 200  == 0)//200ms
  160.         {
  161.         get_now_temp_flag   = 1;
  162.         }

  163. if(time0_temp2 % 200  == 0)//200ms
  164.         {
  165.         //get_now_temp_flag   = 1;
  166.         
  167.         pid_self_sec_flag   = 1;
  168.         
  169.         pwm_con_time_flag   = 1;
  170.         enable_pid_sec_flag = 1;
  171.         special_dis_once_flag = 1;
  172.         
  173.         }

  174. if(time0_temp2 >= 1000 )//1s         如果要想1000对应1s 那么中间不能有关中断的行为发生
  175.         {
  176.         time0_temp2 = 0;
  177.         global_sec++;
  178.         global_sec_flag = 1;
  179.         
  180.         three_dot_dis_flag  ^= 1;
  181.    
  182.         soft_dis_flag = 1;//软启动
  183.         
  184.         //ssr_con_1;delay_ms(10);ssr_con_0;//test
  185.         
  186.         }

  187. }


  188. void PCA_Intrrpt(void) interrupt 7 //pwm 的中断
  189. {
  190. if(CCF0) CCF0=0;
  191. if(CCF1) CCF1=0;   //软件清零
  192. if(CF)   CF=0;     //软件清零
  193. }



  194. ////////////////////////////////////////////////////////
  195. //函数

  196. void Timer0Init(void)                //1毫秒@12.000MHz  定时器0
  197. {
  198.         AUXR |= 0x80;        //定时器时钟1T模式
  199.         TMOD &= 0xF0;        //设置定时器模式
  200.         TMOD |= 0x01;        //设置定时器模式
  201.         TL0 = 0x20;                //设置定时初值
  202.         TH0 = 0xD1;                //设置定时初值
  203.         TF0 = 0;                //清除TF0标志
  204.         TR0 = 1;                //定时器0开始计时
  205.         ET0 = 1;        //enable timer0 interrupt   
  206. }


  207. void io_init(void)
  208. {

  209. P3M0 = 0x00 ;   //  0000  0000  
  210. P2M0 = 0xf0 ;   //  1111  0000  低四位为按键
  211. P1M0 = 0xff ;   //  1111  1111  强推挽输出          lcd 及 ssr驱动
  212. P0M0 = 0x00 ;   //  0000  0000  强推挽输出

  213. key_1_in;
  214. key_2_in;
  215. key_3_in;
  216. key_4_in;

  217. ssr_con_out;

  218. lcd_s_12864_cs_out;
  219. lcd_s_12864_reset_out;
  220. lcd_s_12864_rs_out;
  221. lcd_s_12864_sda_out;
  222. lcd_s_12864_sck_out;
  223. lcd_s_12864_light_out;

  224. lcd_s_12864_cs_0;
  225. lcd_s_12864_reset_0;
  226. lcd_s_12864_rs_0;
  227. lcd_s_12864_sda_0;
  228. lcd_s_12864_sck_0;
  229. lcd_s_12864_light_0;

  230. max6675_so_in;
  231. max6675_sck_out;
  232. max6675_cs1_out;
  233. cs1_1;

  234. pwm_con_out;
  235. pwm_con_0;

  236. }



  237. void power_on_event(void)//eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
  238. {
  239. int k;
  240. for( k = 0; k < 2; k++ )//闪灯2次
  241.         {
  242.         lcd_s_12864_light_0;
  243.         delay_ms(200);
  244.         lcd_s_12864_light_1;
  245.         delay_ms(200);
  246.         }

  247. //引用一下基本的函数 否则老是出现警告错误
  248. if( refer_fun_flag == 1 )//让refer_fun_flag永远为0 意思就是永远不实际引用这些函数
  249.         {
  250. //        PUTchar8x8(1,1,5,zifu8x8);
  251. //        PUTchar24x24(1,1,2,zifu24x24);
  252. //        PUTBMP();//图片
  253. //        PUTREVERSEBMP();//图片反显
  254. //        LcmClear();//清屏
  255. //        LcmSet();//显示所有  即满屏都是黑色的
  256. //        LcmInit();//初始化
  257. //        ohengxian();//O横线程序
  258. //        jihengxian();//奇横线程序
  259. //        oshuxian();//O竖线程序
  260. //        jishuxian();//奇竖线程序
  261. //        dianxian();//点显示程序 满屏都是点
  262. //        zifu8x16xian();//可以显示数字及英文
  263. //        zifu16x16xian();//可以显示特定的汉字
  264. //        lcd_dis_position_16_16(1,1,"郑");
  265. //        lcd_dis_position_8_16(1,1,'8');

  266.         }                                                               

  267. }


  268. //s_12864    lllllllllllllllllllllllllllllll
  269. void SendByte(uchar Dbyte) //发送字节数据
  270. {
  271. uchar i,TEMP;
  272. TEMP = Dbyte;
  273. for(i=0;i<8;i++)
  274.     {
  275.     lcd_s_12864_sck_0;
  276.     _nop_();        
  277.         _nop_();
  278.     if( TEMP & 0x80 )
  279.         {
  280.         lcd_s_12864_sda_1;
  281.         }
  282.     else
  283.         {
  284.         lcd_s_12864_sda_0;
  285.         }
  286.     lcd_s_12864_sck_1;
  287.     _nop_();        
  288.     _nop_();     
  289.     TEMP = TEMP<<1;
  290.     }
  291. }


  292. void write_cmd(uchar Cbyte )//写指令
  293. {
  294. lcd_s_12864_cs_0;
  295. lcd_s_12864_rs_0;
  296. SendByte(Cbyte);
  297. }


  298. void write_data(uchar Dbyte )//写数据
  299. {
  300. lcd_s_12864_cs_0;
  301. lcd_s_12864_rs_1;
  302. SendByte(Dbyte);
  303. }


  304. void PUTchar8x8(int row,int col,int count,uchar *put)
  305. {               
  306. uint X=0;
  307. int  j,i;
  308. write_cmd(0xb0+row);
  309. write_cmd(0x10+(8*col/16));               
  310. write_cmd(0x00+(8*col%16));
  311. for(j=0;j<count;j++)
  312.     {
  313.     for(i=0;i<8;i++)
  314.         {
  315.         write_data(put[X++]);
  316.         }
  317.     }        
  318. }


  319. void PUTchar8x16(int row,int col,int count,uchar *put)//row 0--3代表1--4行 col 0--15 代表1--16个起始位置  count 1--16 代表写入了几个字符  *put代表字符数组 16个字节代表一个8*16的字符
  320. {               
  321. uint X=0;
  322. int j,i;
  323. write_cmd(0xb0+row);
  324. write_cmd(0x10+(8*col/16));               
  325. write_cmd(0x00+(8*col%16));
  326. for(j=0;j<count;j++)
  327.     {
  328.     for(i=0;i<8;i++)
  329.         {
  330.         write_data(put[X++]);
  331.         }
  332.     write_cmd(0xb1+row);        
  333.     write_cmd(0x10+(8*col/16));               
  334.     write_cmd(0x00+(8*col%16));
  335.     for(i=0;i<8;i++)
  336.         {
  337.         write_data(put[X++]);
  338.         }
  339.     write_cmd(0xb0+row);
  340.     col=col+1;
  341.     }
  342. }


  343. void PUTchar16x16(int row,int col,int count,uchar *put)//32个字节表示1个汉字
  344. {               
  345. uint X=0;
  346. int j,i;
  347. write_cmd(0xb0+row);
  348. write_cmd(0x10+(8*col/16));               
  349. write_cmd(0x00+(8*col%16));
  350. for(j=0;j<count;j++)
  351.     {
  352.     for(i=0;i<16;i++)
  353.         {
  354.         write_data(put[X++]);
  355.         }
  356.     write_cmd(0xb1+row);        
  357.     write_cmd(0x10+(8*col/16));               
  358.     write_cmd(0x00+(8*col%16));
  359.     for(i=0;i<16;i++)
  360.         {
  361.         write_data(put[X++]);
  362.         }
  363.     write_cmd(0xb0+row);         
  364.     col=col+2;
  365.     }
  366. }


  367. void PUTchar24x24(int row,int col,int count,uchar *put)
  368. {               
  369. uint X=0;
  370. int j,i;
  371. write_cmd(0xb0+row);           //纵坐标
  372. write_cmd(0x10+(8*col/16));                 //横坐标
  373. write_cmd(0x00+(8*col%16));
  374. for(j=0;j<count;j++)
  375.     {
  376.     for(i=0;i<24;i++)
  377.         {
  378.         write_data(put[X++]);
  379.         }
  380.     write_cmd(0xb1+row);        
  381.     write_cmd(0x10+(8*col/16));               
  382.     write_cmd(0x00+(8*col%16));
  383.     for(i=0;i<24;i++)
  384.         {
  385.         write_data(put[X++]);
  386.         }
  387.     write_cmd(0xb2+row);        
  388.     write_cmd(0x10+(8*col/16));               
  389.     write_cmd(0x00+(8*col%16));
  390.     for(i=0;i<24;i++)
  391.         {
  392.         write_data(put[X++]);
  393.         }
  394.     write_cmd(0xb0+row);
  395.     col=col+3;
  396.     }
  397. }


  398. void PUTBMP(void)//图片
  399. {               
  400. uint X=0;
  401. int j,i;
  402. for(j=0;j<8;j++)
  403.     {
  404.     write_cmd(0xb0+j);
  405.     write_cmd(0x10);               
  406.     write_cmd(0x00);
  407.     for(i=0;i<128;i++)
  408.         {
  409.         write_data(bmp1[X++]);//bmp1为具体的图片数组
  410.         }
  411.     }        
  412. }


  413. void PUTREVERSEBMP(void)//图片反显
  414. {        
  415. uint X=0;
  416. int j,i;
  417. for(j=0;j<8;j++)
  418.     {
  419.     write_cmd(0xb0+j);
  420.     write_cmd(0x10);               
  421.     write_cmd(0x00);
  422.     for(i=0;i<128;i++)
  423.         {
  424.         write_data(~bmp1[X++]);
  425.         }
  426.     }        
  427. }


  428. void LcmClear(void)//清屏
  429. {         
  430. int x,y;
  431. for(y=0;y<8;y++)
  432.     {   
  433.     write_cmd(0xb0+y);
  434.     write_cmd(0x10);               
  435.     write_cmd(0x00);
  436.     for(x=0;x<132;x++)
  437.         {
  438.         write_data(0);
  439.         }
  440.     }        
  441. }


  442. void LcmSet(void)//显示所有  即满屏都是黑色的
  443. {         
  444. int x,y;
  445. for(y=0;y<8;y++)
  446.     {   
  447.     write_cmd(0xb0+y);
  448.     write_cmd(0x10);               
  449.     write_cmd(0x00);
  450.     for(x=0;x<132;x++)
  451.         {
  452.         write_data(0xff);
  453.         }
  454.     }        
  455. }


  456. void LcmInit(void)//初始化
  457. {        
  458. lcd_s_12864_cs_0;
  459. lcd_s_12864_reset_0;
  460. delay_ms(100);
  461. lcd_s_12864_reset_1;
  462. delay_ms(100);
  463. write_cmd(0xe2);//system reset
  464. delay_ms(10);
  465. write_cmd(0x24);//SET VLCD RESISTOR RATIO  0x20--0x27  可以调节对比对 之有 0x23 0x24 这2个值可以选择 0x24的对比度强  粗调
  466. write_cmd(0xa2);//BR=1/9
  467. write_cmd(0xa0);//set seg direction
  468. write_cmd(0xc8);//set com direction
  469. write_cmd(0x2f);//set power control
  470. write_cmd(0x40);//set scroll line
  471. write_cmd(0x81);//SET ELECTRONIC VOLUME
  472. write_cmd(0x1c);//set pm: 通过改变这里的数值来改变电压 //也可以调节对比度 从0x00 -- 0x3f 值越大对比度越大 细调

  473. //write_cmd(0xa6);//set inverse display           a6 off, a7 on  打开跟不打开没有任何影响
  474. //write_cmd(0xa4);//set all pixel on                      打开跟不打开没有任何影响
  475. write_cmd(0xaf);//set display enable
  476. LcmClear();     //先清屏
  477. }


  478. void ohengxian(void)//O横线程序
  479. {
  480. int x,y;
  481. for(y=0;y<8;y++)
  482.     {   
  483.     write_cmd(0xb0+y);
  484.     write_cmd(0x10);               
  485.     write_cmd(0x00);
  486.     for(x=0;x<128;x++)
  487.         {
  488.         write_data(0x55);
  489.         }
  490.     }         
  491. }


  492. void jihengxian(void)//奇横线程序
  493. {
  494. int x,y;
  495. for(y=0;y<8;y++)
  496.     {
  497.     write_cmd(0xb0+y);
  498.     write_cmd(0x10);               
  499.     write_cmd(0x00);
  500.     for(x=0;x<128;x++)
  501.         {
  502.         write_data(0xAA);
  503.         }
  504.     }         
  505. }


  506. void oshuxian(void)//O竖线程序
  507. {
  508. int x,y;
  509. for(y=0;y<8;y++)
  510.     {   
  511.     write_cmd(0xb0+y);
  512.     write_cmd(0x10);               
  513.     write_cmd(0x00);
  514.     for(x=0;x<128;x++)
  515.         {
  516.         if(x%2==0)
  517.             {
  518.             write_data(0xFF);
  519.             }
  520.         else
  521.             {
  522.             write_data(0);
  523.             }   
  524.         }
  525.     }         
  526. }


  527. void jishuxian(void)//奇竖线程序
  528. {
  529. int x,y;
  530. for(y=0;y<8;y++)
  531.     {   
  532.     write_cmd(0xb0+y);
  533.     write_cmd(0x10);               
  534.     write_cmd(0x00);
  535.     for(x=0;x<128;x++)
  536.         {
  537.         if(x%2==0)
  538.             {
  539.             write_data(0);
  540.             }
  541.         else
  542.             {
  543.             write_data(0xFF);
  544.             }
  545.         }
  546.     }         
  547. }


  548. void dianxian(void)//点显示程序 满屏都是点
  549. {
  550. int x,y;
  551. for(y=0;y<8;y++)
  552.     {   
  553.     write_cmd(0xb0+y);
  554.     write_cmd(0x10);               
  555.     write_cmd(0x00);
  556.     for(x=0;x<128;x++)
  557.         {
  558.         if(x%2==0)
  559.             {
  560.             write_data(0xAA);
  561.             }
  562.         else
  563.             {
  564.             write_data(0x55);
  565.             }
  566.         }
  567.     }         
  568. }


  569. void zifu8x16xian(void)//可以显示数字及英文
  570. {
  571. int k;
  572. for(k=0;k<4;k++)//代表显示4行
  573.     {
  574.     PUTchar8x16(2*k,0,16,zifu8x16);
  575.     }
  576. }


  577. void zifu16x16xian(void)//可以显示特定的汉字
  578. {
  579. int k;
  580. for(k=0;k<4;k++)
  581.     {
  582.     PUTchar16x16(2*k,0,16,zifu16x16);
  583.     }
  584. }


  585. //zzzzzzzzzzzzzzzzzzz
  586. void lcd_dis_position_16_16(int line,int column,uchar zifu_16_16[2])// 1行 1列 具体的字符
  587. {               
  588. uint X=0;
  589. int i;
  590. /////////////////////////////////////
  591. if     ( zifu_16_16 == "郑" ){for(i = 0; i < 32; ++i){temp_buffer_16_16_comm[i] = hanzi_16_16_001[i];}}
  592. else if( zifu_16_16 == "州" ){for(i = 0; i < 32; ++i){temp_buffer_16_16_comm[i] = hanzi_16_16_002[i];}}
  593. else if( zifu_16_16 == "迎" ){for(i = 0; i < 32; ++i){temp_buffer_16_16_comm[i] = hanzi_16_16_003[i];}}
  594. else if( zifu_16_16 == "之" ){for(i = 0; i < 32; ++i){temp_buffer_16_16_comm[i] = hanzi_16_16_004[i];}}
  595. else if( zifu_16_16 == "胜" ){for(i = 0; i < 32; ++i){temp_buffer_16_16_comm[i] = hanzi_16_16_005[i];}}
  596. else if( zifu_16_16 == "电" ){for(i = 0; i < 32; ++i){temp_buffer_16_16_comm[i] = hanzi_16_16_006[i];}}
  597. else if( zifu_16_16 == "子" ){for(i = 0; i < 32; ++i){temp_buffer_16_16_comm[i] = hanzi_16_16_007[i];}}
  598. else if( zifu_16_16 == "公" ){for(i = 0; i < 32; ++i){temp_buffer_16_16_comm[i] = hanzi_16_16_008[i];}}
  599. else if( zifu_16_16 == "司" ){for(i = 0; i < 32; ++i){temp_buffer_16_16_comm[i] = hanzi_16_16_009[i];}}

  600. else if( zifu_16_16 == "当" ){for(i = 0; i < 32; ++i){temp_buffer_16_16_comm[i] = hanzi_16_16_010[i];}}
  601. else if( zifu_16_16 == "前" ){for(i = 0; i < 32; ++i){temp_buffer_16_16_comm[i] = hanzi_16_16_011[i];}}
  602. else if( zifu_16_16 == "温" ){for(i = 0; i < 32; ++i){temp_buffer_16_16_comm[i] = hanzi_16_16_012[i];}}
  603. else if( zifu_16_16 == "度" ){for(i = 0; i < 32; ++i){temp_buffer_16_16_comm[i] = hanzi_16_16_013[i];}}

  604. else if( zifu_16_16 == "设" ){for(i = 0; i < 32; ++i){temp_buffer_16_16_comm[i] = hanzi_16_16_014[i];}}
  605. else if( zifu_16_16 == "定" ){for(i = 0; i < 32; ++i){temp_buffer_16_16_comm[i] = hanzi_16_16_015[i];}}

  606. else if( zifu_16_16 == "比" ){for(i = 0; i < 32; ++i){temp_buffer_16_16_comm[i] = hanzi_16_16_016[i];}}
  607. else if( zifu_16_16 == "例" ){for(i = 0; i < 32; ++i){temp_buffer_16_16_comm[i] = hanzi_16_16_017[i];}}
  608. else if( zifu_16_16 == "积" ){for(i = 0; i < 32; ++i){temp_buffer_16_16_comm[i] = hanzi_16_16_018[i];}}
  609. else if( zifu_16_16 == "分" ){for(i = 0; i < 32; ++i){temp_buffer_16_16_comm[i] = hanzi_16_16_019[i];}}
  610. else if( zifu_16_16 == "微" ){for(i = 0; i < 32; ++i){temp_buffer_16_16_comm[i] = hanzi_16_16_020[i];}}

  611. else if( zifu_16_16 == "自" ){for(i = 0; i < 32; ++i){temp_buffer_16_16_comm[i] = hanzi_16_16_021[i];}}
  612. else if( zifu_16_16 == "整" ){for(i = 0; i < 32; ++i){temp_buffer_16_16_comm[i] = hanzi_16_16_022[i];}}
  613. else if( zifu_16_16 == "定" ){for(i = 0; i < 32; ++i){temp_buffer_16_16_comm[i] = hanzi_16_16_023[i];}}
  614. else if( zifu_16_16 == "中" ){for(i = 0; i < 32; ++i){temp_buffer_16_16_comm[i] = hanzi_16_16_024[i];}}

  615. else if( zifu_16_16 == "软" ){for(i = 0; i < 32; ++i){temp_buffer_16_16_comm[i] = hanzi_16_16_025[i];}}
  616. else if( zifu_16_16 == "启" ){for(i = 0; i < 32; ++i){temp_buffer_16_16_comm[i] = hanzi_16_16_026[i];}}
  617. else if( zifu_16_16 == "动" ){for(i = 0; i < 32; ++i){temp_buffer_16_16_comm[i] = hanzi_16_16_027[i];}}

  618. /////////////////////////////////////
  619. write_cmd(0xb0+((line-1)*2));//第1行
  620. write_cmd(0x10+(8*(2*(column-1))/16));
  621. write_cmd(0x00+(8*(2*(column-1))%16));//起始位置
  622. for(i=0;i<16;i++)
  623.     {   
  624.     write_data(temp_buffer_16_16_comm[X++]);
  625.     }
  626. write_cmd(0xb1+((line-1)*2));        
  627. write_cmd(0x10+(8*(2*(column-1))/16));        
  628. write_cmd(0x00+(8*(2*(column-1))%16));
  629. for(i=0;i<16;i++)
  630.     {
  631.     write_data(temp_buffer_16_16_comm[X++]);
  632.     }
  633. write_cmd(0xb0+((line-1)*2));
  634. }


  635. void lcd_dis_position_8_16(int line,int column,uchar zifu_8_16)// 1行 1列 具体的字符
  636. {               
  637. uint X=0;
  638. int i;
  639. /////////////////////////////////////
  640. if     ( zifu_8_16 == '0' ){for(i = 0; i < 16; ++i){temp_buffer_8_16_comm[i] = zifu_8_16_001[i];}}
  641. else if( zifu_8_16 == '1' ){for(i = 0; i < 16; ++i){temp_buffer_8_16_comm[i] = zifu_8_16_002[i];}}
  642. else if( zifu_8_16 == '2' ){for(i = 0; i < 16; ++i){temp_buffer_8_16_comm[i] = zifu_8_16_003[i];}}
  643. else if( zifu_8_16 == '3' ){for(i = 0; i < 16; ++i){temp_buffer_8_16_comm[i] = zifu_8_16_004[i];}}
  644. else if( zifu_8_16 == '4' ){for(i = 0; i < 16; ++i){temp_buffer_8_16_comm[i] = zifu_8_16_005[i];}}
  645. else if( zifu_8_16 == '5' ){for(i = 0; i < 16; ++i){temp_buffer_8_16_comm[i] = zifu_8_16_006[i];}}
  646. else if( zifu_8_16 == '6' ){for(i = 0; i < 16; ++i){temp_buffer_8_16_comm[i] = zifu_8_16_007[i];}}
  647. else if( zifu_8_16 == '7' ){for(i = 0; i < 16; ++i){temp_buffer_8_16_comm[i] = zifu_8_16_008[i];}}
  648. else if( zifu_8_16 == '8' ){for(i = 0; i < 16; ++i){temp_buffer_8_16_comm[i] = zifu_8_16_009[i];}}
  649. else if( zifu_8_16 == '9' ){for(i = 0; i < 16; ++i){temp_buffer_8_16_comm[i] = zifu_8_16_010[i];}}
  650. else if( zifu_8_16 == ':' ){for(i = 0; i < 16; ++i){temp_buffer_8_16_comm[i] = zifu_8_16_011[i];}}
  651. else if( zifu_8_16 == '-' ){for(i = 0; i < 16; ++i){temp_buffer_8_16_comm[i] = zifu_8_16_012[i];}}
  652. else if( zifu_8_16 == '.' ){for(i = 0; i < 16; ++i){temp_buffer_8_16_comm[i] = zifu_8_16_013[i];}}
  653. else if( zifu_8_16 == '+' ){for(i = 0; i < 16; ++i){temp_buffer_8_16_comm[i] = zifu_8_16_014[i];}}

  654. else if( zifu_8_16 == '%' ){for(i = 0; i < 16; ++i){temp_buffer_8_16_comm[i] = zifu_8_16_015[i];}}
  655. else if( zifu_8_16 == 'S' ){for(i = 0; i < 16; ++i){temp_buffer_8_16_comm[i] = zifu_8_16_016[i];}}
  656. else if( zifu_8_16 == 'C' ){for(i = 0; i < 16; ++i){temp_buffer_8_16_comm[i] = zifu_8_16_017[i];}}

  657. else if( zifu_8_16 == 'P' ){for(i = 0; i < 16; ++i){temp_buffer_8_16_comm[i] = zifu_8_16_018[i];}}
  658. else if( zifu_8_16 == 'I' ){for(i = 0; i < 16; ++i){temp_buffer_8_16_comm[i] = zifu_8_16_019[i];}}
  659. else if( zifu_8_16 == 'D' ){for(i = 0; i < 16; ++i){temp_buffer_8_16_comm[i] = zifu_8_16_020[i];}}

  660. else if( zifu_8_16 == ' ' ){for(i = 0; i < 16; ++i){temp_buffer_8_16_comm[i] = zifu_8_16_021[i];}}

  661. /////////////////////////////////////
  662. write_cmd(0xb0+((line-1)*2));//第1行
  663. write_cmd(0x10+(8*(1*(column-1))/16));
  664. write_cmd(0x00+(8*(1*(column-1))%16));//起始位置
  665. for(i=0;i<8;i++)
  666.     {   
  667.     write_data(temp_buffer_8_16_comm[X++]);
  668.     }
  669. write_cmd(0xb1+((line-1)*2));        
  670. write_cmd(0x10+(8*(1*(column-1))/16));        
  671. write_cmd(0x00+(8*(1*(column-1))%16));
  672. for(i=0;i<8;i++)
  673.     {
  674.     write_data(temp_buffer_8_16_comm[X++]);
  675.     }
  676. write_cmd(0xb0+((line-1)*2));
  677. }


  678. char *convert_num_to_str(long num)//将数字转成字符串 最大显示21亿 第1位为0的话,则显示0
  679. {

  680. temp_dis_num_buffer[0] = ((num/1000000000)%10) + '0';
  681. temp_dis_num_buffer[1] = ((num/100000000)%10) + '0';
  682. temp_dis_num_buffer[2] = ((num/10000000)%10) + '0';
  683. temp_dis_num_buffer[3] = ((num/1000000)%10) + '0';
  684. temp_dis_num_buffer[4] = ((num/100000)%10) + '0';
  685. temp_dis_num_buffer[5] = ((num/10000)%10) + '0';
  686. temp_dis_num_buffer[6] = ((num/1000)%10) + '0';
  687. temp_dis_num_buffer[7] = ((num/100)%10) + '0';
  688. temp_dis_num_buffer[8] = ((num/10)%10) + '0';
  689. temp_dis_num_buffer[9] = ((num/1)%10) + '0';

  690. temp_str = temp_dis_num_buffer;

  691. return temp_str;
  692. }


  693. void lcd_s_12864_dis_8_16_str(int dis_line,int start_position,char *dis_str)//显示一行的8*16的字符
  694. {
  695. int temp_1=0;
  696. int i;
  697. char *temp_str;
  698. temp_str = dis_str;
  699. while(1)//求出长度
  700.     {
  701.     temp_1++;
  702.     if( *temp_str++ == '\0'  )
  703.         {
  704.         break;
  705.         }
  706.     }
  707. for(i = 0; i < (temp_1 - 1) ; ++i)
  708.     {
  709.     lcd_dis_position_8_16(dis_line,start_position + i , *dis_str++);
  710.     }
  711. }


  712. void dis_long_number(int dis_line,long dis_num)
  713. {

  714. lcd_dis_position_8_16(dis_line,0,((dis_num/1000000000)%10) + '0');
  715. lcd_dis_position_8_16(dis_line,1,((dis_num/100000000)%10) + '0');
  716. lcd_dis_position_8_16(dis_line,2,((dis_num/10000000)%10) + '0');
  717. lcd_dis_position_8_16(dis_line,3,((dis_num/1000000)%10) + '0');
  718. lcd_dis_position_8_16(dis_line,4,((dis_num/100000)%10) + '0');
  719. lcd_dis_position_8_16(dis_line,5,((dis_num/10000)%10) + '0');
  720. lcd_dis_position_8_16(dis_line,6,((dis_num/1000)%10) + '0');
  721. lcd_dis_position_8_16(dis_line,7,((dis_num/100)%10) + '0');
  722. lcd_dis_position_8_16(dis_line,8,((dis_num/10)%10) + '0');
  723. lcd_dis_position_8_16(dis_line,9,((dis_num/1)%10) + '0');

  724. }


  725. //key
  726. int key_scan(void)
  727. {
  728. int key_temp = 0;
  729. if(!(key_1_status))
  730.     {
  731.     delay_ms(10);
  732.     if(!(key_1_status))
  733.         {
  734.         key_perss_counter++;
  735.         if(( key_perss_counter > key_perss_long_max_num ) && ( key_perss_counter < key_perss_long_long_max_num ))
  736.             {
  737.             //lcd_s_12864_light_0;
  738.             //delay_ms(20);
  739.             //lcd_s_12864_light_1;//报警            
  740.             //delay_ms(20);
  741.             key_temp = 11;//长按
  742.             }
  743.         else if( key_perss_counter >= key_perss_long_long_max_num )
  744.             {
  745.             lcd_s_12864_light_0;
  746.             delay_ms(50);
  747.             lcd_s_12864_light_1;//报警            
  748.             delay_ms(50);
  749.             key_temp = 111;//超长按
  750.             }
  751.         else
  752.             {
  753.             if( key_once_active_flag == 1 )
  754.                 {
  755.                 key_once_active_flag = 0;
  756.                 //lcd_s_12864_light_0;
  757.                 //delay_ms(10);
  758.                 //lcd_s_12864_light_1;//报警
  759.                 key_temp = 1;//短按
  760.                 }               
  761.             }
  762.         }
  763.     }
  764. else if(!(key_2_status))
  765.     {
  766.     delay_ms(10);
  767.     if(!(key_2_status))
  768.         {
  769.         key_perss_counter++;
  770.         if(( key_perss_counter > key_perss_long_max_num ) && ( key_perss_counter < key_perss_long_long_max_num ))
  771.             {
  772.             //lcd_s_12864_light_0;
  773.             //delay_ms(20);
  774.             //lcd_s_12864_light_1;
  775.             //delay_ms(20);
  776.             key_temp = 22;//长按
  777.             }
  778.         else if( key_perss_counter >= key_perss_long_long_max_num )
  779.             {
  780.             lcd_s_12864_light_0;
  781.             delay_ms(50);
  782.             lcd_s_12864_light_1;
  783.             delay_ms(50);
  784.             key_temp = 222;//超长按
  785.             }
  786.         else
  787.             {
  788.             if( key_once_active_flag == 1 )
  789.                 {
  790.                 key_once_active_flag = 0;
  791.                 //lcd_s_12864_light_0;
  792.                 //delay_ms(10);
  793.                 //lcd_s_12864_light_1;
  794.                 key_temp = 2;//短按
  795.                 }               
  796.             }
  797.         }
  798.     }
  799. else if(!(key_3_status))
  800.     {
  801.     delay_ms(10);
  802.     if(!(key_3_status))
  803.         {
  804.         key_perss_counter++;
  805.         if(( key_perss_counter > key_perss_long_max_num ) && ( key_perss_counter < key_perss_long_long_max_num ))
  806.             {
  807.             //lcd_s_12864_light_0;
  808.             //delay_ms(20);
  809.             //lcd_s_12864_light_1;
  810.             //delay_ms(20);
  811.             //key_temp = 33;//长按
  812.             key_temp = 3;            
  813.                         }
  814.         else if( key_perss_counter >= key_perss_long_long_max_num )
  815.             {
  816.             lcd_s_12864_light_0;
  817.             delay_ms(50);
  818.             lcd_s_12864_light_1;
  819.             delay_ms(50);
  820.             key_temp = 333;//超长按
  821.             //key_temp = 3;            
  822.                         }
  823.         else
  824.             {
  825.             if( key_once_active_flag == 1 )
  826.                 {
  827.                 key_once_active_flag = 0;
  828.                 //lcd_s_12864_light_0;
  829.                 //delay_ms(10);
  830.                 //lcd_s_12864_light_1;
  831.                 key_temp = 3;//短按
  832.                 }               
  833.             }
  834.         }
  835.     }
  836. else if(!(key_4_status))
  837.     {
  838.     delay_ms(10);
  839.     if(!(key_4_status))
  840.         {
  841.         key_perss_counter++;
  842.         if(( key_perss_counter > key_perss_long_max_num ) && ( key_perss_counter < key_perss_long_long_max_num ))
  843.             {
  844.             //lcd_s_12864_light_0;
  845.             //delay_ms(20);
  846.             //lcd_s_12864_light_1;
  847.             //delay_ms(20);
  848.             //key_temp = 44;//长按
  849.             key_temp = 4;            
  850.                         }
  851.         else if( key_perss_counter >= key_perss_long_long_max_num )
  852.             {
  853.             lcd_s_12864_light_0;
  854.             delay_ms(50);
  855.             lcd_s_12864_light_1;
  856.             delay_ms(50);
  857.             key_temp = 444;//超长按
  858.             //key_temp = 4;
  859.                         }
  860.         else
  861.             {
  862.             if( key_once_active_flag == 1 )
  863.                 {
  864.                 key_once_active_flag = 0;
  865.                 //lcd_s_12864_light_0;
  866.                 //delay_ms(10);
  867.                 //lcd_s_12864_light_1;
  868.                 key_temp = 4;//短按
  869.                 }               
  870.             }
  871.         }
  872.     }
  873. else//没有任何key按动的时候
  874.     {
  875.     key_once_active_flag = 1;//允许再按时1次动作
  876.     key_perss_counter    = 0;
  877.     }
  878. return key_temp;
  879. }


  880. //DS18B20
  881. void ds_18b20_DelayXus(int n)
  882. {
  883. while (n--)
  884.         {
  885.         _nop_();
  886.         //_nop_();
  887.         }
  888. }


  889. void ds_18b20_init(void)//DS18B20的初始化
  890. {  
  891. EA = 0;//关中断
  892. DQ=1;
  893. ds_18b20_DelayXus(1);//1US
  894. DQ=0;
  895. ds_18b20_DelayXus(600);//600US
  896. DQ=1;
  897. ds_18b20_DelayXus(100);         //100US
  898. if(DQ==0)
  899.         {
  900.         ds_18b20_reset_ok_flag = 1;
  901.         ds_18b20_DelayXus(200);
  902.         DQ=1;
  903.         }
  904. if(DQ==1)//说明复位成功
  905.         {
  906.         ds_18b20_reset_ok_flag = 0;
  907.         ds_18b20_DelayXus(200);
  908.         DQ=1;
  909.         }
  910. EA = 1;//开中断
  911. }


  912. uchar ds_18b20_read_date(void)  //读一个字节
  913. {
  914. uchar temp,i;
  915. EA = 0;
  916. for( i=0;i<8;i++)
  917.         {
  918.         DQ=1;
  919.         ds_18b20_DelayXus(2);
  920.         DQ=0;
  921.         ds_18b20_DelayXus(3);
  922.         DQ=1;
  923.         ds_18b20_DelayXus(2);
  924.         temp>>=1;
  925.         if(DQ)
  926.                 {
  927.                 temp=temp|0x80;
  928.                 }
  929.         ds_18b20_DelayXus(50);
  930.         }
  931. EA = 1;
  932. return temp;
  933. }


  934. void ds_18b20_write_date(uchar date)//写一个字节
  935. {
  936. uchar i;
  937. //EA = 0;
  938. for( i=0 ;i<8;i++)
  939.         {
  940.         DQ=0;
  941.         ds_18b20_DelayXus(2);
  942.         DQ = date&0x01;
  943.         ds_18b20_DelayXus(50);//50us
  944.         DQ=1;
  945.         date>>=1;
  946.         }
  947. EA = 1;
  948. }


  949. float read_18b20_temp(void)//读出18b20的温度值 实际温度值返回 同时改变temp_zero_below_flag的值 如果是0 说明是0度以下
  950. {
  951. uchar themh=0;   
  952. uchar theml=0;
  953. uint temp_0 = 0;
  954. float temp_1;

  955. ds_18b20_init();
  956. if(ds_18b20_reset_ok_flag == 0)//检测传感器是否存在
  957.         {   
  958.         ds_18b20_write_date(0xcc);          //跳过ROM匹配
  959.         ds_18b20_write_date(0x44);          //发出温度转换命令
  960.         ds_18b20_DelayXus(1000);
  961.         }
  962. ds_18b20_init();
  963. if(ds_18b20_reset_ok_flag == 0)
  964.         {
  965.         ds_18b20_write_date(0x0cc);         //跳过ROM匹配
  966.         ds_18b20_write_date(0x0be);         //发出读温度命令
  967.         theml=ds_18b20_read_date() ;        //读出温度值并存放在 theml,themh
  968.         themh=ds_18b20_read_date() ;
  969.         }

  970. //temp_0 = themh*256 + theml;
  971. temp_0 = (themh<<8) | theml;  //2句作用一样

  972. if( temp_0 & 0xf000 ) //说明是 负温度
  973.     {
  974.     temp_0 =  (~temp_0)+ 1 ;//等于268  0000 0001 0000 1100 == 按位反 = 1111 1110 1111 0011 = fef3 = 65267 然后加1 = 65267+1 = 65268
  975.     //temp_0 = (65536 - temp_0) ;//负温度求补码  65268 + 268 = 65536  跟用这个办法计算出的值一样
  976.         temp_zero_below_flag = 0;
  977.         }
  978. else//为0 ,说明是 正温度
  979.     {
  980.     temp_zero_below_flag = 1;
  981.         }

  982. temp_1 = (float)(temp_0)*0.0625;

  983. return temp_1;
  984. }


  985. void dis_now_temp_test(void)//测试用 显示当前温度
  986. {
  987. if( global_sec_flag == 1 )//1秒1次
  988.         {
  989.         global_sec_flag = 0;
  990.         ssr_con_1;delay_ms(10);ssr_con_0;//test               
  991.         
  992.         now_temp = read_18b20_temp();
  993.         wenkong_now_temp = now_temp;
  994.     dis_now_temp = (long)(wenkong_now_temp*10);//*10是为了显示的需要
  995.         
  996.         //dis_now_temp = 396;//test
  997.         lcd_dis_position_16_16(1,1,"当");
  998.     lcd_dis_position_16_16(1,2,"前");
  999.     lcd_dis_position_16_16(1,3,"温");
  1000.     lcd_dis_position_16_16(1,4,"度");
  1001.    
  1002.         if (temp_zero_below_flag == 1)//正温度
  1003.                 {
  1004.                 lcd_dis_position_8_16(2,1, '+');
  1005.             lcd_dis_position_8_16(2,2, (dis_now_temp/100%10) + '0');
  1006.             lcd_dis_position_8_16(2,3, (dis_now_temp/10%10) + '0');
  1007.             lcd_dis_position_8_16(2,4, '.');
  1008.             lcd_dis_position_8_16(2,5, (dis_now_temp/1%10) + '0');
  1009.                 }
  1010.         else if (temp_zero_below_flag == 0)//负温度
  1011.                 {
  1012.                 lcd_dis_position_8_16(2,1, '-');
  1013.             lcd_dis_position_8_16(2,2, (dis_now_temp/100%10) + '0');
  1014.             lcd_dis_position_8_16(2,3, (dis_now_temp/10%10) + '0');
  1015.             lcd_dis_position_8_16(2,4, '.');
  1016.             lcd_dis_position_8_16(2,5, (dis_now_temp/1%10) + '0');
  1017.                 }
  1018.         }
  1019. }

  1020. //kkkkkkkkkkkkkkkkkkkk
  1021. void key_pro(void)
  1022. {
  1023. key_value = key_scan();
  1024. if     (key_value == 1)//A 作为 自整定 跟 pid 切换的开关
  1025.         {
  1026.         pid_tune_flag ^= 1;
  1027.         LcmClear();//清屏
  1028.         //清除最后一行的内容
  1029.         //dis_4_line_as_null();

  1030.         if(pid_tune_flag == 1)//自整定阶段
  1031.                 {
  1032.                
  1033.                 //记录此刻的状态 即设定温度是否 高于或等于 当前温度
  1034.                 if( SV_value >= PV_value )//设定温度 高于 或者 等于  当前温度  启动加热
  1035.                         {
  1036.                         pid_self_first_status_flag = 1;
  1037.                         once_add_1_flag = 0;
  1038.                         }
  1039.                 else//设定温度 低于 当前温度
  1040.                         {
  1041.                         pid_self_first_status_flag = 0;
  1042.                         once_add_1_flag = 1;
  1043.                         }
  1044.                
  1045.                 dis_tune_once_flag = 1;
  1046.                 zero_across_counter = 0;
  1047.                 pid_self_time_sec = 0;
  1048.                 pid_self_calc_buffer[0]=0.0;
  1049.         pid_self_calc_buffer[1]=0.0;
  1050.         pid_self_calc_buffer[2]=0.0;
  1051.         pid_self_calc_buffer[3]=0.0;        
  1052.                 k_pid_self_counter = 0;
  1053.                 enable_calc_min_max_flag = 0;
  1054.                 max_temp = 0.0 ;  //初始温度等于0
  1055.                 min_temp = 1024.0 ;//初始温度等于1024
  1056.                 sum_temp = 0.0 ;  //初始温度等于0
  1057.                 aver_temp = 0.0 ;
  1058.                 T_Hight  = 0.0;
  1059.                 T_LOW    = 1024.0; //温度
  1060.                 TIME_Hight = 0;
  1061.                 TIME_LOW   = 0;        //具体的0.2s
  1062.                
  1063.                 }
  1064.         else if(pid_tune_flag == 0)//pid阶段
  1065.                 {
  1066.                 comm_dis_once_flag    = 1;
  1067.                 special_dis_once_flag = 1;
  1068.                 }
  1069.         }
  1070. else if(key_value == 2)//B
  1071.         {
  1072.         
  1073.         }
  1074. else if((key_value == 3) || (key_value == 333))  //-  设定温度
  1075.         {
  1076.         special_dis_once_flag = 1;
  1077.         if(key_value == 3)
  1078.                 {
  1079.                 SV_value-=1.0;
  1080.                 }
  1081.         else
  1082.                 {
  1083.                 SV_value-=10.0;
  1084.                 }
  1085.         if(SV_value < 0.0)
  1086.                 {
  1087.                 SV_value = 999.9;
  1088.                 }
  1089.         }
  1090. else if((key_value == 4) || (key_value == 444)) //+
  1091.         {
  1092.         special_dis_once_flag = 1;
  1093.         if(key_value == 4)
  1094.                 {
  1095.                 SV_value+=1.0;
  1096.                 }
  1097.         else
  1098.                 {
  1099.                 SV_value+=10.0;
  1100.                 }
  1101.         if(SV_value > 999.9)
  1102.                 {
  1103.                 SV_value = 0.0;
  1104.                 }
  1105.         }

  1106. }        

  1107. //dddddddddddddddddddddd
  1108. void display_pro(void)
  1109. {
  1110. if( pid_tune_flag == 0 )//pid阶段
  1111.         {
  1112.         //第1行 当前温度
  1113.         //第2行 设定温度
  1114.         //第3行 显示pid 各参数的名字
  1115.         //第4行 显示pid 各参数的具体值
  1116.         if (comm_dis_once_flag == 1)//基本信息只显示一次
  1117.                 {
  1118.                 comm_dis_once_flag = 0;
  1119.                
  1120.                 lcd_dis_position_16_16(1,1,"当");
  1121.                 lcd_dis_position_16_16(1,2,"前");
  1122.                 lcd_dis_position_16_16(1,3,"温");
  1123.                 lcd_dis_position_16_16(1,4,"度");
  1124.                
  1125.                 lcd_dis_position_16_16(2,1,"设");
  1126.                 lcd_dis_position_16_16(2,2,"定");
  1127.                 lcd_dis_position_16_16(2,3,"温");
  1128.                 lcd_dis_position_16_16(2,4,"度");
  1129.                
  1130.                 lcd_dis_position_8_16(1,15,'C');
  1131.                 lcd_dis_position_8_16(2,15,'C');
  1132.                
  1133.                 lcd_dis_position_16_16(3,1,"比");
  1134.                 lcd_dis_position_16_16(3,2,"例");
  1135.                 lcd_dis_position_16_16(3,4,"积");
  1136.                 lcd_dis_position_16_16(3,5,"分");
  1137.                 lcd_dis_position_16_16(3,7,"微");
  1138.                 lcd_dis_position_16_16(3,8,"分");
  1139.                
  1140.                 }
  1141.         
  1142.         if (special_dis_once_flag == 1)//独立信息  0.2秒1次
  1143.                 {
  1144.                 special_dis_once_flag = 0;
  1145.                
  1146.                 //lcd_s_12864_light_1;delay_ms(10);lcd_s_12864_light_0;//test

  1147.                 //当前温度
  1148.                 lcd_dis_position_8_16(1,9, ((uint)(PV_value*10)/1000)%10 + '0');//百位
  1149.                 lcd_dis_position_8_16(1,10,((uint)(PV_value*10)/100)%10 + '0');
  1150.                 lcd_dis_position_8_16(1,11,((uint)(PV_value*10)/10)%10 + '0');
  1151.                 lcd_dis_position_8_16(1,12,'.');
  1152.                 lcd_dis_position_8_16(1,13,((uint)(PV_value*10)/1)%10 + '0');
  1153.         
  1154.                 //设定温度
  1155.                 lcd_dis_position_8_16(2,9, ((uint)(SV_value*10)/1000)%10 + '0');
  1156.                 lcd_dis_position_8_16(2,10,((uint)(SV_value*10)/100)%10 + '0');
  1157.                 lcd_dis_position_8_16(2,11,((uint)(SV_value*10)/10)%10 + '0');
  1158.                 lcd_dis_position_8_16(2,12,'.');
  1159.                 lcd_dis_position_8_16(2,13,((uint)(SV_value*10)/1)%10 + '0');
  1160.                
  1161.                 lcd_dis_position_8_16(4,6,'%');
  1162.                 lcd_dis_position_8_16(4,11,'S');
  1163.                 lcd_dis_position_8_16(4,16,'S');
  1164.         
  1165.                 if( pid_tune_flag == 1 )//如果启动了pid自整定 ,则显示 pid自整定中...
  1166.                         {
  1167.                         lcd_dis_position_8_16(4,1,'P');
  1168.                         lcd_dis_position_8_16(4,2,'I');
  1169.                         lcd_dis_position_8_16(4,3,'D');
  1170.                         
  1171.                         lcd_dis_position_16_16(4,3,"自");
  1172.                         lcd_dis_position_16_16(4,4,"整");
  1173.                         lcd_dis_position_16_16(4,5,"定");
  1174.                         lcd_dis_position_16_16(4,6,"中");
  1175.                         
  1176.                         if     ( three_dot_dis_flag == 1 )//显示不断闪烁的3个点 表示运算中
  1177.                                 {
  1178.                                 lcd_dis_position_8_16(4,14,'.');
  1179.                                 lcd_dis_position_8_16(4,15,'.');
  1180.                                 lcd_dis_position_8_16(4,16,'.');
  1181.                                 }
  1182.                         else if( three_dot_dis_flag == 0 )
  1183.                                 {
  1184.                                 lcd_dis_position_8_16(4,14,' ');
  1185.                                 lcd_dis_position_8_16(4,15,' ');
  1186.                                 lcd_dis_position_8_16(4,16,' ');
  1187.                                 }
  1188.                         }
  1189.                 else if( pid_tune_flag == 0 )//整定ok后 显示计算获得的pid值 正常pid控制的时候显示的内容
  1190.                         {
  1191.                         //比例 积分 微分
  1192.                         lcd_dis_position_8_16(4,1,((uint)(P_value*10)/1000)%10 + '0');
  1193.                         lcd_dis_position_8_16(4,2,((uint)(P_value*10)/100)%10 + '0');
  1194.                         lcd_dis_position_8_16(4,3,((uint)(P_value*10)/10)%10 + '0');
  1195.                         lcd_dis_position_8_16(4,4,'.');
  1196.                         lcd_dis_position_8_16(4,5,((uint)(P_value*10)/1)%10 + '0');
  1197.                         
  1198.                         lcd_dis_position_8_16(4,7,((I_value*1)/1000)%10 + '0');
  1199.                         lcd_dis_position_8_16(4,8,((I_value*1)/100)%10 + '0');
  1200.                         lcd_dis_position_8_16(4,9,((I_value*1)/10)%10 + '0');
  1201.                         lcd_dis_position_8_16(4,10,((I_value*1)/1)%10 + '0');
  1202.                         
  1203.                         lcd_dis_position_8_16(4,13,((D_value*1)/100)%10 + '0');
  1204.                         lcd_dis_position_8_16(4,14,((D_value*1)/10)%10 + '0');
  1205.                         lcd_dis_position_8_16(4,15,((D_value*1)/1)%10 + '0');
  1206.                         }
  1207.                 }        
  1208.         }
  1209. else if( pid_tune_flag == 1 )//自整定阶段
  1210.         {
  1211.         if(dis_tune_once_flag == 1)//显示一次  
  1212.                 {
  1213.                 dis_tune_once_flag = 0;
  1214.                 dis_pid_self_value();
  1215.                 }
  1216.         }
  1217. }


  1218. int pid_calc(float set_temp ,float now_temp )// pid计算  set_temp 为设定的温度  now_temp  代表实际输入的当前温度值  0 - 100的输出值
  1219. {
  1220. Error = set_temp - now_temp;                 // 偏差
  1221. if(( Error < max_value_error  ) && ( Error > (min_value_error)  ))//只有在一定的温差范围内才pid计算
  1222.     {   
  1223.     SumError += Error;
  1224.     dError    = LastError - PrevError;   // 当前微分
  1225.     PrevError = LastError;
  1226.     LastError = Error;
  1227.     temp_pid  =  (int)((Proportion * Error) + (Integral * SumError) + (Derivative * dError));   
  1228.     //temp_pid  =  (int)(temp_pid * 0.5) ;//输出比例控制
  1229.         }
  1230. else//只有开关作用
  1231.     {
  1232.     if( Error >= max_value_error )//远大于当前温度,加热
  1233.         {
  1234.         temp_pid = 100;
  1235.         //temp_pid = 80;
  1236.                 }
  1237.     else if( Error <= (min_value_error) )//远小于当前温度,不加热
  1238.         {
  1239.         temp_pid = 0;
  1240.         }
  1241.     }
  1242. if( temp_pid < 0 )
  1243.     {
  1244.     temp_pid = 0;
  1245.     }
  1246. else if( temp_pid > 100 )
  1247.     {
  1248.     temp_pid = 100;
  1249.     }
  1250. return temp_pid;
  1251. }


  1252. void pid_con(void)//由计算结果控制输出
  1253. {

  1254. //适用于 pwm
  1255. //每200ms根据结果改变一次输出电压的值
  1256. if( pwm_con_time_flag == 1)
  1257.         {
  1258.         pwm_con_time_flag = 0;
  1259.         
  1260.         //lcd_s_12864_light_1;delay_ms(10);lcd_s_12864_light_0;//test

  1261.         //set_pwm_value(40 + (uchar)(pid_result * (((float)(237-40))/100.0)) );
  1262.         set_pwm_value(40 + (uchar)(pid_result * 1.97) );//跟上面这句话等价
  1263.         
  1264.         }

  1265. }


  1266. void pid_pro(void)//pid 自整定及控制输出 ppppppppppppppppppppppppppppp
  1267. {
  1268. //每200ms获得一次温度
  1269. if( get_now_temp_flag == 1)//200ms秒获得一次温度
  1270.         {
  1271.         get_now_temp_flag = 0;
  1272.         
  1273.         //lcd_s_12864_light_1;delay_ms(10);lcd_s_12864_light_0;//test

  1274.         PV_value = read_max6675_temper();
  1275.         }

  1276. if     ( pid_tune_flag == 1 )//自整定阶段  完毕之后转成pid控制
  1277.         {
  1278.         //自整定ok后自动转为pid阶段
  1279.         //自整定失败的情况下 让基本参数恢复默认值

  1280.         if( pid_self_sec_flag == 1 )//自整定过程  0.2秒1次
  1281.                 {
  1282.                 pid_self_sec_flag = 0;
  1283.                 dis_tune_once_flag = 1;//0.2秒显示1次基本信息
  1284.                 //lcd_s_12864_light_0;delay_ms(10);lcd_s_12864_light_1;//test

  1285.                 pid_self_time_sec++;
  1286.                 if(pid_self_time_sec > (3600*3)) // 如果总的自整定时间大于了3/5=0.6个小时,则说明整定失败
  1287.                         {
  1288.                         pid_self_time_sec = 0;                        
  1289.                         //lcd_s_12864_light_0;delay_ms(10);lcd_s_12864_light_1;//test
  1290.                         LcmClear();//清屏
  1291.                         comm_dis_once_flag    = 1;
  1292.                         special_dis_once_flag = 1;
  1293.                         pid_tune_flag = 0;//那么将自动退出自整定过程 同时采用默认值  进入pid阶段
  1294.                         KC = 1.0;//临界比例系数  初始默认的值
  1295.                         TC = 40; //振荡周期    初始默认的值

  1296.                         }

  1297.                 if(( pid_self_first_status_flag == 1) || ( pid_self_first_status_flag == 0))//0 设定温度 低于 当前温度  //1设定温度 高于 或者 等于  当前温度  启动加热
  1298.                         {

  1299.                         //lcd_s_12864_light_0;delay_ms(10);lcd_s_12864_light_1;//test

  1300.                         //基本on/off控制
  1301.                         if( SV_value >= PV_value )//启动加热
  1302.                                 {
  1303.                                 cool_ack_counter = 0;
  1304.                                 hot_ack_counter++;
  1305.                                 if(hot_ack_counter > 3)//连续3次都是一样的结果 说明确定 SV_value >= PV_value
  1306.                                         {
  1307.                                        
  1308.                                         ssr_con_1;
  1309.                                         //pwm_con_1;//一旦pwm参与将不能通过操作io的形式控制该口线
  1310.                                         set_pwm_value(237);//全速加热

  1311.                                         if(once_add_1_flag == 0)
  1312.                                                 {
  1313.                                                 once_add_1_flag = 1;
  1314.                                                 zero_across_counter++;
  1315.                                                 
  1316.                                                 //lcd_s_12864_light_0;delay_ms(10);lcd_s_12864_light_1;//test
  1317.                                                 
  1318.                                                 if(zero_across_counter == 3 )
  1319.                                                         {
  1320.                                                         TIME_LOW = pid_self_time_sec - 3;//此时的时间不是最低温度对应的时间
  1321.                                                         }
  1322.                                                 }
  1323.                                         }
  1324.                                 }
  1325.                         else//当前温度 大于 设定温度 停止加热
  1326.                                 {
  1327.                                 
  1328.                                 //lcd_s_12864_light_0;delay_ms(10);lcd_s_12864_light_1;//test
  1329.                                                                
  1330.                                 hot_ack_counter = 0;
  1331.                                 cool_ack_counter++;
  1332.                                 if(cool_ack_counter > 3)
  1333.                                         {
  1334.                                         ssr_con_0;
  1335.                                         set_pwm_value(40);//不加热
  1336.                                         if(once_add_1_flag == 1)
  1337.                                                 {
  1338.                                                 once_add_1_flag = 0;
  1339.                                                 zero_across_counter++;
  1340.                                                 if(zero_across_counter == 3 )
  1341.                                                         {
  1342.                                                         TIME_LOW = pid_self_time_sec - 3;//此时的时间不是最低温度对应的时间
  1343.                                                         }
  1344.                                                 }
  1345.                                         }
  1346.                                 }

  1347.                         //最低温度 出现在 zero_across_counter = 3 的阶段
  1348.                         //最高温度 出现在 zero_across_counter = 4 的阶段
  1349.                         if((zero_across_counter == 3 ) || (zero_across_counter == 4 ))
  1350.                                 {                                
  1351.                                 pid_self_calc_buffer[k_pid_self_counter] = PV_value;
  1352.                                 k_pid_self_counter++;
  1353.                                 if(k_pid_self_counter > 3)//0--3 共4个元素
  1354.                                         {
  1355.                                         k_pid_self_counter = 0;
  1356.                                         enable_calc_min_max_flag = 1;
  1357.                                         }
  1358.                                 if(enable_calc_min_max_flag == 1)//只要有4个值,就可以计算了 后面来的值覆盖了前面的值
  1359.                                         {
  1360.                                         //去掉最小值 最大值 取剩下2个值的平均值
  1361.                                         sum_temp = 0.0;  //先清0
  1362.                                         min_temp = 1024.0;
  1363.                                         max_temp = 0.0;
  1364.                                                 
  1365.                                         for(k_max_min = 0; k_max_min < 4; k_max_min++ )
  1366.                                                 {                                                
  1367.                                                 if(pid_self_calc_buffer[k_max_min] <= min_temp)
  1368.                                                         {
  1369.                                                         min_temp = pid_self_calc_buffer[k_max_min];
  1370.                                                         }
  1371.                                                 if(pid_self_calc_buffer[k_max_min] >= max_temp)
  1372.                                                         {
  1373.                                                         max_temp = pid_self_calc_buffer[k_max_min];
  1374.                                                         }                                                
  1375.                                                 sum_temp = (sum_temp + pid_self_calc_buffer[k_max_min]);
  1376.                                                 }
  1377.                                         sum_temp =  sum_temp - min_temp - max_temp ;
  1378.                                        
  1379.                                        
  1380.                                         //pid_self_first_status_flag = 1 时 最低温度出现在3阶段
  1381.                                         //pid_self_first_status_flag = 0 时 最低温度出现在4阶段
  1382.                                         if(pid_self_first_status_flag == 1)
  1383.                                                 {
  1384.                                                 if(zero_across_counter == 3 )//最低温度
  1385.                                                         {
  1386.                                                         aver_temp = (sum_temp/2.0);                                       
  1387.                                                         if( aver_temp <= T_LOW )
  1388.                                                                 {
  1389.                                                                 T_LOW = aver_temp;
  1390.                                                                 }                                
  1391.                                                         }
  1392.                                                 else if(zero_across_counter == 4 )//最高温度
  1393.                                                         {
  1394.                                                         aver_temp = (sum_temp/2.0);
  1395.                                                         if( aver_temp >= T_Hight )
  1396.                                                                 {
  1397.                                                                 T_Hight = aver_temp;
  1398.                                                                 }
  1399.                                                         }
  1400.                                                 }
  1401.                                         else if(pid_self_first_status_flag == 0)
  1402.                                                 {
  1403.                                                 if(zero_across_counter == 4 )//最低温度
  1404.                                                         {
  1405.                                                         aver_temp = (sum_temp/2.0);                                       
  1406.                                                         if( aver_temp <= T_LOW )
  1407.                                                                 {
  1408.                                                                 T_LOW = aver_temp;
  1409.                                                                 }                                
  1410.                                                         }
  1411.                                                 else if(zero_across_counter == 3 )//最高温度
  1412.                                                         {
  1413.                                                         aver_temp = (sum_temp/2.0);
  1414.                                                         if( aver_temp >= T_Hight )
  1415.                                                                 {
  1416.                                                                 T_Hight = aver_temp;
  1417.                                                                 }
  1418.                                                         }
  1419.                                                 }
  1420.                                         }
  1421.                                 }
  1422.                         else if(zero_across_counter == 5 )//4次过0 则说明出现了振荡 整定成功
  1423.                                 {
  1424.                                 zero_across_counter = 0;                                
  1425.                                 pid_tune_flag = 0;//进入pid阶段
  1426.                                 //pid_tune_flag = 1;//test
  1427.                                 TIME_Hight = pid_self_time_sec - 3;//此时的时间不是最高温度对应的时间
  1428.                                 LcmClear();//清屏
  1429.                                 comm_dis_once_flag    = 1;
  1430.                                 special_dis_once_flag = 1;                                
  1431.                                 //dis_4_line_as_null();//清除最后一行的内容
  1432.                                 //计算 T_Hight T_LOW TIME_Hight TIME_LOW 这4个值
  1433.                                 //根据以上4个值  KC 与 TC 的值便会计算出来
  1434.                                 
  1435.                                 KC = 12.7/(T_Hight - T_LOW);
  1436.                                 KC = 5.0 * KC;//因为是0.2s一次 所以扩大5倍
  1437.                                 TC = 1 * (TIME_Hight - TIME_LOW);//如果记录了 最低温度 与 最高温度对应的时间 那么沿用这个公式:TC = 2 * (TIME_Hight - TIME_LOW);
  1438.                                 }
  1439.                         }
  1440.                 //显示具体的值  测试用
  1441.                 //dis_pid_self_value(); //test
  1442.                 }
  1443.         }
  1444. else if( pid_tune_flag == 0 )//pid 阶段  默认开机进入此阶段
  1445.         {
  1446.         //0 算出 临界增益 KC 及 振荡周期 TC
  1447.         // KC = (4*d)/(3.14*A)  ---> d = 5(输出幅值) ; A = 记录的温度最高值与最低值的差值的0.5倍 即:(T_Hight - T_LOW)*0.5
  1448.         // KC = (4*5)/(3.14*((T_Hight - T_LOW)*0.5)) = 40/3.14/(T_Hight - T_LOW) =  12.7/(T_Hight - T_LOW)
  1449.         // KC = 12.7/(T_Hight - T_LOW)
  1450.         // TC = 2 * (TIME_Hight - TIME_LOW) ---> 2 * ( 高点温度对应时间 - 低点温度对应时间 )
  1451.         // TC = 2 * (TIME_Hight - TIME_LOW)
  1452.         //1 算出 具体的比例系数 积分秒数 微分秒数
  1453.         //Proportion = 0.6*KC
  1454.         //I_value    = 0.5*TC
  1455.         //D_value    = 0.125*TC
  1456.         //2 算出具体的 比例带 积分系数 微分系数
  1457.         //P_value     = (1/Proportion)*100
  1458.         //Integral          = Proportion/I_value = (0.6*KC)/(0.5*TC)
  1459.         //Derivative  = Proportion*D_value = (0.6*KC)*(0.125*TC)  
  1460.         //3显示用的3个变量的值
  1461.         //P_value     = (1/Proportion)*100  百分比
  1462.         //I_value     = 0.5*TC                                秒
  1463.         //D_value     = 0.125*TC                        秒
  1464.         //4pid计算用的3个变量的值
  1465.         //Proportion  = 0.6*KC
  1466.         //Integral          = Proportion/I_value = (0.6*KC)/(0.5*TC)
  1467.         //Derivative  = Proportion*D_value = (0.6*KC)*(0.125*TC)  
  1468.         
  1469.         //KC = 21.4;//test
  1470.         //TC = 471;//test
  1471.         
  1472.         if(enable_pid_sec_flag == 1)//进入pid时,0.2秒计算1次
  1473.                 {
  1474.                 enable_pid_sec_flag = 0;
  1475.                
  1476.                 //lcd_s_12864_light_0;delay_ms(10);lcd_s_12864_light_1;//test

  1477.                 if(KC > 1666.0 )
  1478.                         {
  1479.                         KC = 1666.0;//对应 比例带为 0.1%
  1480.                         }
  1481.                 else if(KC < 0.5 )
  1482.                         {
  1483.                         KC = 0.5;//对应 比例带为 200.0%
  1484.                         }
  1485.                 if(TC > 7200 )
  1486.                         {
  1487.                         TC = 7200;
  1488.                         }
  1489.                 else if(TC < 8 )
  1490.                         {
  1491.                         TC = 8;
  1492.                         }
  1493.                
  1494.                 Proportion  = 0.6*KC;//先算 比例系数
  1495.                
  1496.                 P_value     = ((1/Proportion)*100);     //比例带  百分比
  1497.                 I_value     = (int)(0.5*TC);                        //积分    秒
  1498.                 D_value     = (int)(0.125*TC);                        //微分    秒
  1499.                 //限幅处理
  1500.                 if(P_value > 200.0)
  1501.                         {
  1502.                         P_value = 200.0;
  1503.                         }
  1504.                 else if(P_value < 0.0)
  1505.                         {
  1506.                         P_value = 0.0;
  1507.                         }
  1508.                 if(I_value > 3600)
  1509.                         {
  1510.                         I_value = 3600;
  1511.                         }
  1512.                 else if(I_value < 0)
  1513.                         {
  1514.                         I_value = 0;
  1515.                         }
  1516.                 if(D_value > 900)
  1517.                         {
  1518.                         D_value = 900;
  1519.                         }
  1520.                 else if(D_value < 0)
  1521.                         {
  1522.                         D_value = 0;
  1523.                         }
  1524.                
  1525.                 Proportion  = 0.6*KC;
  1526.                 Integral        = (0.6*KC)/(0.5*TC);
  1527.                 Derivative  = (0.6*KC)*(0.125*TC);
  1528.                
  1529.                 pid_result = pid_calc(SV_value,PV_value);
  1530.                 }
  1531.         
  1532.         pid_con();//根据上一步的结果控制输出
  1533.         
  1534.         }

  1535. }


  1536. void dis_4_line_as_null(void)
  1537.         {
  1538.         int kop;
  1539.         for(kop = 0; kop < 16; kop++ )
  1540.                 {
  1541.                 lcd_dis_position_8_16(4,kop + 1,' ');
  1542.                 }
  1543.         }


  1544. void dis_pid_self_value(void)//显示自整定阶段的基本信息
  1545. {
  1546. //显示基本信息如下
  1547. //zero_across_counter = 2;
  1548. //TIME_Hight          = 153;
  1549. //TIME_LOW                  = 27;  //1   行 + 当前温度
  1550. //T_Hight                      = 45.8;
  1551. //T_LOW                          = 25.6;//2   行 + 一组当中的温度最小值
  1552. //KC                              = 45.9;
  1553. //TC                              = 512; //3   行 + 一组当中的温度最大值
  1554. //pid_self_time_sec   = 2541;//4   行  + 温度平均值 + 温度总和


  1555. lcd_dis_position_8_16(1,1,zero_across_counter+'0');//过0的次数

  1556. lcd_dis_position_8_16(1,3,((TIME_Hight/1000)%10)+ '0');
  1557. lcd_dis_position_8_16(1,4,((TIME_Hight/100)%10)+ '0');
  1558. lcd_dis_position_8_16(1,5,((TIME_Hight/10)%10)+ '0');
  1559. lcd_dis_position_8_16(1,6,((TIME_Hight/1)%10)+ '0'); //温度高时的时间

  1560. lcd_dis_position_8_16(1,8,((TIME_LOW/1000)%10)+ '0');
  1561. lcd_dis_position_8_16(1,9,((TIME_LOW/100)%10)+ '0');
  1562. lcd_dis_position_8_16(1,10,((TIME_LOW/10)%10)+ '0');
  1563. lcd_dis_position_8_16(1,11,((TIME_LOW/1)%10)+ '0');//温度低时的时间

  1564. lcd_dis_position_8_16(1,12,((uint)(PV_value*10)/1000)%10 + '0');
  1565. lcd_dis_position_8_16(1,13,((uint)(PV_value*10)/100)%10 + '0');
  1566. lcd_dis_position_8_16(1,14,((uint)(PV_value*10)/10)%10 + '0');
  1567. lcd_dis_position_8_16(1,15,'.');
  1568. lcd_dis_position_8_16(1,16,((uint)(PV_value*10)/1)%10 + '0');//当前温度
  1569.         
  1570. lcd_dis_position_8_16(2,1,(((uint)(T_Hight*1)/1000)%10)+ '0');
  1571. lcd_dis_position_8_16(2,2,(((uint)(T_Hight*1)/100)%10)+ '0');
  1572. lcd_dis_position_8_16(2,3,(((uint)(T_Hight*1)/10)%10)+ '0');
  1573. lcd_dis_position_8_16(2,4,(((uint)(T_Hight*1)/1)%10)+ '0');//高温

  1574. lcd_dis_position_8_16(2,6,(((uint)(T_LOW*1)/1000)%10)+ '0');
  1575. lcd_dis_position_8_16(2,7,(((uint)(T_LOW*1)/100)%10)+ '0');
  1576. lcd_dis_position_8_16(2,8,(((uint)(T_LOW*1)/10)%10)+ '0');
  1577. lcd_dis_position_8_16(2,9,(((uint)(T_LOW*1)/1)%10)+ '0');//低温

  1578. lcd_dis_position_8_16(3,1,(((uint)(KC*1)/1000)%10)+ '0');
  1579. lcd_dis_position_8_16(3,2,(((uint)(KC*1)/100)%10)+ '0');
  1580. lcd_dis_position_8_16(3,3,(((uint)(KC*1)/10)%10)+ '0');
  1581. lcd_dis_position_8_16(3,4,(((uint)(KC*1)/1)%10)+ '0');//比例

  1582. lcd_dis_position_8_16(3,6,(((uint)(TC*1)/1000)%10)+ '0');
  1583. lcd_dis_position_8_16(3,7,(((uint)(TC*1)/100)%10)+ '0');
  1584. lcd_dis_position_8_16(3,8,(((uint)(TC*1)/10)%10)+ '0');
  1585. lcd_dis_position_8_16(3,9,(((uint)(TC*1)/1)%10)+ '0');//周期

  1586. lcd_dis_position_8_16(4,1,(((uint)(pid_self_time_sec*1)/1000)%10)+ '0');
  1587. lcd_dis_position_8_16(4,2,(((uint)(pid_self_time_sec*1)/100)%10)+ '0');
  1588. lcd_dis_position_8_16(4,3,(((uint)(pid_self_time_sec*1)/10)%10)+ '0');
  1589. lcd_dis_position_8_16(4,4,(((uint)(pid_self_time_sec*1)/1)%10)+ '0');//计时的时间 单位:0.2s

  1590. lcd_dis_position_8_16(4,6,(((uint)(aver_temp*1)/1000)%10)+ '0');
  1591. lcd_dis_position_8_16(4,7,(((uint)(aver_temp*1)/100)%10)+ '0');
  1592. lcd_dis_position_8_16(4,8,(((uint)(aver_temp*1)/10)%10)+ '0');
  1593. lcd_dis_position_8_16(4,9,(((uint)(aver_temp*1)/1)%10)+ '0');//平均温度

  1594. lcd_dis_position_8_16(4,11,(((uint)(sum_temp*1)/1000)%10)+ '0');
  1595. lcd_dis_position_8_16(4,12,(((uint)(sum_temp*1)/100)%10)+ '0');
  1596. lcd_dis_position_8_16(4,13,(((uint)(sum_temp*1)/10)%10)+ '0');
  1597. lcd_dis_position_8_16(4,14,(((uint)(sum_temp*1)/1)%10)+ '0');//温度和

  1598. lcd_dis_position_8_16(2,11,(((uint)(min_temp*1)/1000)%10)+ '0');
  1599. lcd_dis_position_8_16(2,12,(((uint)(min_temp*1)/100)%10)+ '0');
  1600. lcd_dis_position_8_16(2,13,(((uint)(min_temp*1)/10)%10)+ '0');
  1601. lcd_dis_position_8_16(2,14,(((uint)(min_temp*1)/1)%10)+ '0');//最小温度

  1602. lcd_dis_position_8_16(3,11,(((uint)(max_temp*1)/1000)%10)+ '0');
  1603. lcd_dis_position_8_16(3,12,(((uint)(max_temp*1)/100)%10)+ '0');
  1604. lcd_dis_position_8_16(3,13,(((uint)(max_temp*1)/10)%10)+ '0');
  1605. lcd_dis_position_8_16(3,14,(((uint)(max_temp*1)/1)%10)+ '0');//最大温度

  1606. }


  1607. //max6675
  1608. void max6675_delay(uint n)
  1609. {
  1610. while (n--)
  1611.         {
  1612.     _nop_();
  1613.     _nop_();
  1614.         }
  1615. }


  1616. float read_max6675_temper(void)// 利用max6675读k探头的温度 返回最终温度的1倍
  1617. {

  1618. uchar i=0;   
  1619. uint dat_temp=0;   
  1620. float dat_6675=0.0;   

  1621. //lcd_s_12864_light_1;delay_ms(10);lcd_s_12864_light_0;//test

  1622. cs1_0;
  1623. max6675_delay(10);
  1624. sck_0;
  1625. for(i=0;i<16;i++)   
  1626.         {                       
  1627.         sck_1;
  1628.         max6675_delay(10);      
  1629.         dat_temp = dat_temp<<1;   
  1630.         if(so_status)
  1631.                 {
  1632.                 dat_temp |= 0x01;   
  1633.                 }
  1634.         sck_0;
  1635.         max6675_delay(10);               
  1636.         }   
  1637. cs1_1;
  1638. max6675_delay(10);
  1639. sck_0;
  1640. k_cut_off_flag = (dat_temp>>2)&0x0001; //断偶标志 1的话,断开
  1641. dat_temp = dat_temp<<1;   
  1642. dat_temp = dat_temp>>4;//舍弃最高位及最低的3位 留下中间的12位 这12位中的后2位代表小数位

  1643. //dat_6675 = (float)((((float)(dat_temp & 0x0003)*0.25) +  (float)(dat_temp>>2))*1.0);//最终温度扩大1倍
  1644. dat_6675 = ((float)dat_temp) * 0.25;

  1645. return dat_6675;  
  1646. }


  1647. void k_test(void)
  1648. {
  1649. k_reou_value = (long)(read_max6675_temper()*100.0);
  1650. //k_reou_value = 321451;//test        
  1651. dis_long_number(1,k_reou_value);
  1652. delay_ms(200);//必须的间隔 否则不会更新
  1653. }


  1654. //pwm

  1655. //* CCAPOH = CCAPOL = 0XC0; //模块0输出 占空因数为25%
  1656. //* CCAPOH = CCAPOL = 0X80; //模块0输出 占空因数为50%
  1657. //* CCAPOH = CCAPOL = 0X40; //模块0输出 占空因数为75%


  1658. void PWM_clock(uchar clock)
  1659. {
  1660. CMOD |= (clock<<1);
  1661. CL = 0x00;
  1662. CH = 0x00;
  1663. }

  1664. void PWM_start(uchar module,uchar mode)
  1665. {
  1666. //CCAP0H = 0XC0;   //模块0初始输出 占空因数为25%
  1667. //CCAP0L = 0XC0;

  1668. CCAP0H = 0xff;  // 当为1时,低电平持续的时间为:1us  当为255的时候,低电平持续的时间为:255us  高电平持续的时间为:1us
  1669. //CCAP0L = 0Xff;//貌似没有作用

  1670. CCAP1H = 0XC0;   //模块1初始输出 占空因数为25%
  1671. CCAP1L = 0XC0;

  1672. if(module == 0)
  1673.         {
  1674.         switch(mode)
  1675.                 {
  1676.                 case 0: CCAPM0 = 0X42;break; //模块0设置为8位PWM输出,无中断   如果时钟源确定了,那么pwm的周期就确定了 因为是8位,所以,当送入256个脉冲后,归0 比如:时钟周期为1/12us,那么pwm周期是:(1/12) * 256 = 21.33us ---> 46.88khz
  1677.                 case 1: CCAPM0 = 0X53;break; //模块0设置为8位PWM输出,下降沿产生中断
  1678.                 case 2: CCAPM0 = 0X63;break; //模块0设置为8位PWM输出,上升沿产生中断
  1679.                 case 3: CCAPM0 = 0X73;break; //模块0设置为8位PWM输出,跳变沿产生中断
  1680.                 default: break;
  1681.                 }
  1682.         }
  1683. else
  1684.         if(module==1)
  1685.                 {
  1686.                         switch(mode)
  1687.                         {
  1688.                         case 0: CCAPM1 = 0X42;break; //模块1设置为8位PWM输出,无中断
  1689.                         case 1: CCAPM1 = 0X53;break; //模块1设置为8位PWM输出,下降沿产生中断
  1690.                         case 2: CCAPM1 = 0X63;break; //模块1设置为8位PWM输出,上升沿产生中断
  1691.                         case 3: CCAPM1 = 0X73;break; //模块1设置为8位PWM输出,跳变沿产生中断
  1692.                         default: break;
  1693.                         }
  1694.                 }
  1695.            else
  1696.             if(module==2)
  1697.                         {
  1698.                         switch(mode)
  1699.                                 {
  1700.                                 case 0: CCAPM0 = CCAPM1 = 0X42;break; //模块0和1设置为8位PWM输出,无中断
  1701.                                 case 1: CCAPM0 = CCAPM1 = 0X53;break; //模块0和1设置为8位PWM输出,下降沿产生中断
  1702.                                 case 2: CCAPM0 = CCAPM1 = 0X63;break; //模块0和1设置为8位PWM输出,上升沿产生中断
  1703.                                 case 3: CCAPM0 = CCAPM1 = 0X73;break; //模块0和1设置为8位PWM输出,跳变沿产生中断
  1704.                                 default: break;
  1705.                                 }
  1706.                         }
  1707. CR=1; //PCA计数器开始计数
  1708. }


  1709. void set_pwm_value(uchar value)//0--255之间         value越大,占空比越高 输出电压也越大 40-->0.8v 237-->4.6v
  1710. {
  1711. if (value > 255)
  1712.         {
  1713.         value = 255;
  1714.         }
  1715. CCAP0H = (255 - value);
  1716. CCAPM0 = 0x42;
  1717. CR = 1;
  1718. }


  1719. //函数结束hhhhhhhhhhhhhhhhh
  1720. ////////////////////////////////////////////////////////
  1721. //mmmmmmmmmmmmm

  1722. void main(void)
  1723. {
  1724.         
  1725.         delay_us(1);
  1726.         delay_ms(1);
  1727.         delay10us();

  1728.         io_init();
  1729.         Timer0Init();
  1730.         
  1731.         //pwm 初始化
  1732.         //如果用定时器0控制pwm频率的话,打开以下3句 同时做相应的设置
  1733.         //TMOD|=0x02;        // timer 0 mode 2: 8-Bit reload
  1734.         //TH0=0xff;
  1735.         //TR0=1;            
  1736.         PWM_clock(0);      // PCA/PWM时钟源为 2-->定时器0的溢出         0-->系统时钟频率(12M) fosc/12  这里决定pwm的频率 如果为系统时钟的(1/12)则pwm周期为:256us 频率为:3.91khz
  1737.         PWM_start(0,0);    // 模块0,设置为PWM输出,无中断

  1738.         LcmInit();
  1739.         
  1740.         power_on_event();//开机事件
  1741.         
  1742.         EA = 1;   //open global interrupt switch           

  1743. while(1)//软启动阶段
  1744.         {
  1745.         
  1746.         if (soft_dis_flag == 1)//1秒1次
  1747.                 {
  1748.                 soft_dis_flag = 0;
  1749.                
  1750.                 soft_counter ^= 1;
  1751.                 soft_end_counter++;
  1752.                
  1753.                 set_pwm_value(40 + 5 * soft_end_counter);//每一秒都递增一点  极弱功率加热

  1754.                 if (soft_counter == 1 )
  1755.                         {
  1756.                         lcd_dis_position_16_16(1,3,"软");
  1757.                         lcd_dis_position_16_16(1,4,"启");
  1758.                         lcd_dis_position_16_16(1,5,"动");
  1759.                         lcd_dis_position_16_16(1,6,"中");
  1760.                         
  1761.                         lcd_dis_position_8_16(2,5,'.');
  1762.                         lcd_dis_position_8_16(2,6,'.');
  1763.                         lcd_dis_position_8_16(2,7,'.');
  1764.                         lcd_dis_position_8_16(2,8,'.');
  1765.                         lcd_dis_position_8_16(2,9,'.');
  1766.                         lcd_dis_position_8_16(2,10,'.');
  1767.                         }
  1768.                 else
  1769.                         {
  1770.                         lcd_dis_position_16_16(1,3,"软");
  1771.                         lcd_dis_position_16_16(1,4,"启");
  1772.                         lcd_dis_position_16_16(1,5,"动");
  1773.                         lcd_dis_position_16_16(1,6,"中");
  1774.                         
  1775.                         lcd_dis_position_8_16(2,5,' ');
  1776.                         lcd_dis_position_8_16(2,6,' ');
  1777.                         lcd_dis_position_8_16(2,7,' ');
  1778.                         lcd_dis_position_8_16(2,8,' ');
  1779.                         lcd_dis_position_8_16(2,9,' ');
  1780.                         lcd_dis_position_8_16(2,10,' ');
  1781.                         }
  1782.                 }        
  1783.         
  1784.                
  1785.         if(soft_end_counter >= soft_sec_value)//N秒的软启动时间  可根据需要调整
  1786.                 {
  1787.                 set_pwm_value(0);//重新停止加热
  1788.                 LcmClear();     //清屏
  1789.                 break;
  1790.                 }
  1791.         }

  1792. while(1)
  1793.         {

  1794.            key_pro();
  1795.         pid_pro();
  1796.         display_pro();
  1797.         
  1798.         }        
  1799. }

  1800. /////////////////////////////////////////////////////////
  1801. //delay_ms(200);
  1802. //delay_us(100);
  1803. //delay10us();

  1804. //set_pwm_value(40);
  1805. //set_pwm_value(237);
  1806. //delay_ms(10);//过短的间隔将不起作用 输出电压一直为高 至少1ms

  1807. //pwm_con_1;
  1808. //delay_ms(20);
  1809. //pwm_con_0;
  1810. //delay_ms(20);

  1811. //ssr_con_1;
  1812. //lcd_s_12864_light_1;delay_ms(10);lcd_s_12864_light_0;//test
  1813. //ssr_con_1;delay_ms(10);ssr_con_0;//test
  1814. //lcd_dis_position_16_16(1,1,"郑");
  1815. //lcd_dis_position_8_16(1,3,'5');
  1816. //P1 ^= ssr_con;//test
  1817. //lcd_s_12864_dis_8_16_str(1,1,"784512");
  1818. //lcd_s_12864_dis_8_16_str(3,1,convert_num_to_str(4784597));
  1819. //for(k = 0; k < 16; k++ )
  1820. //        {
  1821. //        lcd_dis_position_8_16(4,k+1,' ');
  1822. //        }
  1823. //lcd_s_12864_light_0;delay_ms(10);lcd_s_12864_light_1;//test

  1824. //40---237 --- pwm

  1825. //1486
复制代码


所有资料51hei提供下载:
单片机程序 原理图.rar (2.96 MB, 下载次数: 548)


评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏27 分享淘帖 顶4 踩
回复

使用道具 举报

沙发
ID:356207 发表于 2018-6-25 09:23 | 只看该作者
比较有参考价值
回复

使用道具 举报

板凳
ID:337973 发表于 2018-10-6 17:48 | 只看该作者
有参考价值
回复

使用道具 举报

地板
ID:370606 发表于 2018-10-7 00:49 | 只看该作者
好东西,赞一个
回复

使用道具 举报

5#
ID:464768 发表于 2019-1-8 17:52 | 只看该作者
好东西,赞一个
回复

使用道具 举报

6#
ID:72649 发表于 2019-1-19 11:54 来自手机 | 只看该作者
能不能做出来
回复

使用道具 举报

7#
ID:412814 发表于 2019-3-3 20:42 | 只看该作者
谢谢楼主,挺好的资料、
回复

使用道具 举报

8#
ID:462629 发表于 2019-3-28 09:19 | 只看该作者
下一个参考一下,有没有C8051的
回复

使用道具 举报

9#
ID:17809 发表于 2019-5-2 22:47 | 只看该作者
谢谢分享
回复

使用道具 举报

10#
ID:387410 发表于 2019-5-10 07:45 来自手机 | 只看该作者
很不错,看一下
回复

使用道具 举报

11#
ID:477269 发表于 2019-6-7 07:48 | 只看该作者
谢谢楼主,挺不错的资料
回复

使用道具 举报

12#
ID:561156 发表于 2019-6-25 18:53 | 只看该作者
感谢楼主的分享,很有学习价值
回复

使用道具 举报

13#
ID:580853 发表于 2019-7-9 13:45 | 只看该作者
好东西,赞一个
回复

使用道具 举报

14#
ID:302158 发表于 2019-7-20 21:07 | 只看该作者
谢谢大佬分分享
回复

使用道具 举报

15#
ID:140370 发表于 2019-8-13 14:48 | 只看该作者
感谢分享,所有程序放在一个文件里一竿子到底,这风格辣眼睛。
回复

使用道具 举报

16#
ID:80689 发表于 2019-9-30 19:21 | 只看该作者
好东西,有参考价值!!
回复

使用道具 举报

17#
ID:245473 发表于 2019-10-20 15:03 | 只看该作者
有参考价值!好东西
回复

使用道具 举报

18#
ID:97678 发表于 2019-12-4 20:45 | 只看该作者
正在寻找资料,好好学习一下。谢谢
回复

使用道具 举报

19#
ID:267435 发表于 2020-1-19 16:08 | 只看该作者

正在寻找资料,好好学习一下。谢谢
回复

使用道具 举报

20#
ID:406947 发表于 2020-4-26 17:55 | 只看该作者
非常有价值,感谢分享
回复

使用道具 举报

21#
ID:140370 发表于 2020-6-14 04:26 | 只看该作者
多谢楼主分享,自整定部分看了好久没看懂,但算是很完整的PID自整定参考。
回复

使用道具 举报

22#
ID:695384 发表于 2020-6-14 20:26 | 只看该作者
听说这个MAX6675已经停产了,
我新的案子用MAX31855K
回复

使用道具 举报

23#
ID:695384 发表于 2020-6-14 20:29 | 只看该作者
MAX31855关键特性】
冷端补偿
14位、0.25°C分辨率
转换器的温度分辨率为0.25°C,
温度读数为-270°C 至+1800°C,
对于K型热电偶,在-200°C至+700°C温度范围内,保持±2°C精度。
提供K、J、N、T和E型热电偶器件版本
简单的SPI兼容接口(只读)
检测热电偶对GND或VCC短路
检测热电偶开路
应用
电器设备
汽车
HVAC
工业
中文资料 MAX31855 中英文对照数据手册.pdf (728.16 KB, 下载次数: 21)



回复

使用道具 举报

24#
ID:427869 发表于 2021-6-25 22:11 来自手机 | 只看该作者
感谢楼主的无私奉献
回复

使用道具 举报

25#
ID:28992 发表于 2021-6-27 21:37 | 只看该作者
thank u Sir!
回复

使用道具 举报

26#
ID:33455 发表于 2021-8-31 21:40 | 只看该作者
感谢楼主,最近想做个12864和da18b20的pid控制温度的带自整定功能,找了好久都没有找到可参考的例程
回复

使用道具 举报

27#
ID:866992 发表于 2021-12-7 18:22 来自手机 | 只看该作者
这个有做出来的吗?我下了程序,屏幕没显示
回复

使用道具 举报

28#
ID:462629 发表于 2021-12-28 10:25 | 只看该作者
这个可以实际工业上使用吗
回复

使用道具 举报

29#
ID:1104962 发表于 2023-12-19 14:45 | 只看该作者

谢谢楼主,挺不错的资料
回复

使用道具 举报

30#
ID:433219 发表于 2023-12-19 16:03 | 只看该作者
MAX6675 + K型,热电偶?  
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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