找回密码
 立即注册

QQ登录

只需一步,快速开始

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

51单片机温度PID控制程序有问题 仿真数值不变

[复制链接]
跳转到指定楼层
楼主
电路原理图如下:


系统元件清单
1.    9*15万用板
2.    AT89C51
3.    40P IC座
4.    温度传感器
5.    语音芯片
6.    104电容
7.    5v喇叭
8.    12M晶振
9.    22uF电容
10.    30P瓷片电容    *2
11.    有源蜂鸣器
12.    103  10k排阻
13.    10k电阻
14.    2.4k电阻
15.    1k电阻*2
16.    红色Led灯
17.    8550三极管
18.    轻触按键*3
19.    Lcd1602液晶
20.    16p排母
21.    16p插针
22.    自锁开关
23.    导线若干
24.    焊锡若干
25.    dc插头
26.    usb供电线



单片机源程序如下:
  1. #include<reg52.h>
  2. #include <intrins.h>
  3. #define uchar unsigned char        //宏定义
  4. #define uint unsigned int
  5. sbit DQ = P3^7;  
  6. sbit k1=P3^2;
  7. sbit k2=P3^3;
  8. sbit k3=P3^4;
  9. sbit k=P3^5;
  10. sbit beep=P2^3;
  11. sbit P10=P1^0;
  12. uchar temp_value,num,t,s1num;                          //温度值
  13. uchar htemp=33,ltemp=15;                    //温度上下线初始化
  14. bit yyp=1,lalarm=0,yy=1;
  15. unsigned char TL=0,TH=0,TD=0,TN=0,count;
  16. int key_delay=0;
  17. const int key_count=400;
  18. /***********1602液晶显示部分子程序****************/
  19. sbit rs=P2^6;//LCD数据/命令选择端(H/L)
  20. sbit en=P2^7;//LCD使能控制
  21. uchar code table[]={"The temp  system"};//液晶固定显示部分
  22. uchar code table1[]={" Temp:          "};
  23. uchar code table2[]={" Set the temp:  "};
  24. uchar code table3[]={"H:   C    L:   C"};
  25. /*************************************************/
  26. void delay(uint x) //毫秒级延时函数
  27. {
  28.   uint i,j;
  29.   for(i=x;i>0;i--)
  30.      for(j=110;j>0;j--);
  31. }
  32. void delay1(uchar i)
  33. {
  34.     uchar j=100;
  35.     for(i;i>0;i--)
  36.       for(j;j>0;j--)
  37.         {;}
  38. }
  39. void di()
  40. {
  41.     beep=0;
  42.     delay(100);
  43.     beep=1;
  44. }
  45. void write_com(uchar com)
  46. {
  47.     rs=0;//命令
  48.     P0=com;
  49.     delay(5);
  50.     en=1;
  51.     delay(5);
  52.     en=0;
  53. }
  54. void write_date(uchar date)
  55. {
  56.     rs=1;//数据
  57.     P0=date;
  58.     delay(5);
  59.     en=1;
  60.     delay(5);
  61.     en=0;
  62. }
  63. void init1602()             //上电后液晶显示初始化函数
  64. {
  65.     write_com(0x38);    //设置工作方式
  66.     write_com(0x0c);    //设置光标
  67.     write_com(0x06);    //设置输入方式
  68.     write_com(0x01);    //清屏
  69.     write_com(0x80);
  70.     for(num=0;num<16;num++)
  71.     {
  72.         write_date(table[num]);
  73.     }
  74.     write_com(0x80+0x40);
  75.     for(num=0;num<16;num++)
  76.     {
  77.         write_date(table1[num]);
  78.     }
  79. }
  80. void init16021()        //设置温度上下限显示初始化函数
  81. {
  82.     write_com(0x80);
  83.     for(num=0;num<16;num++)
  84.     {
  85.         write_date(table2[num]);
  86.     }
  87.     write_com(0x80+0x40);
  88.     for(num=0;num<16;num++)
  89.     {
  90.         write_date(table3[num]);
  91.     }
  92.     write_com(0x80+0x40+4);
  93.     write_date(0xdf);
  94.     write_com(0x80+0x40+14);
  95.     write_date(0xdf);
  96.    
  97. }
  98. /////////////////////////////////
  99. /***********ds18b20子程序*************************/

  100. /***********ds18b20延迟子函数(晶振12MHz )*******/

  101. void delay_18B20(unsigned int i)
  102. {
  103.     while(i--);
  104. }

  105. /**********ds18b20初始化函数**********************/

  106. void Init_DS18B20(void)
  107. {
  108.      unsigned char x=0;
  109.      DQ = 1;                                  //DQ复位
  110.      delay_18B20(8);                          //稍做延时
  111.      DQ = 0;                                  //单片机将DQ拉低
  112.      delay_18B20(80);                         //精确延时 大于 480us
  113.      DQ = 1;                                  //拉高总线
  114.      delay_18B20(14);
  115.      x=DQ;                                    //稍做延时后 如果x=0则初始化成功 x=1则初始化失败
  116.      delay_18B20(20);
  117. }

  118. /***********ds18b20读一个字节**************/  

  119. unsigned char ReadOneChar(void)
  120. {
  121.     uchar i=0;
  122.     uchar dat = 0;
  123.     for (i=8;i>0;i--)
  124.      {
  125.           DQ = 0;                             // 给脉冲信号
  126.           dat>>=1;
  127.           DQ = 1;                             // 给脉冲信号
  128.           if(DQ)
  129.           dat|=0x80;
  130.           delay_18B20(4);
  131.      }
  132.      return(dat);
  133. }

  134. /*************ds18b20写一个字节****************/  

  135. void WriteOneChar(uchar dat)
  136. {
  137.      unsigned char i=0;
  138.      for (i=8; i>0; i--)
  139.      {
  140.           DQ = 0;
  141.          DQ = dat&0x01;
  142.         delay_18B20(5);
  143.          DQ = 1;
  144.         dat>>=1;
  145. }
  146. }

  147. /**************读取ds18b20当前温度************/

  148. void ReadTemp()
  149. {
  150.    

  151.     Init_DS18B20();
  152.     WriteOneChar(0xCC);        // 跳过读序号列号的操作
  153.     WriteOneChar(0x44);     // 启动温度转换

  154.     delay_18B20(100);       // this message is wery important

  155.     Init_DS18B20();
  156.     WriteOneChar(0xCC);     //跳过读序号列号的操作
  157.     WriteOneChar(0xBE);     //读取温度寄存器等(共可读9个寄存器) 前两个就是温度

  158.     TL=ReadOneChar();    //先读的是温度值低位
  159.     TH=ReadOneChar();    //接着读的是温度值高位
  160.     TN=TH*16+TL/16;         //实际温度值=(TH*256+TL)/16,即:TH*16+TL/16
  161.                                             //这样得出的是温度的整数部分,小数部分被丢弃了
  162.                        
  163.     TD=(TL%16)*10/16;       //计算温度的小数部分,将余数乘以10再除以16取整,
  164.                                             //这样得到的是温度小数部分的第一位数字(保留1位小数)
  165. }
  166. void write_wendu(uchar add,uchar date)
  167. {
  168.     uchar shi,ge;
  169.     shi=date/10;
  170.     ge=date%10;
  171.     write_com(0x80+0x40+add);
  172.     write_date(0x30+shi);
  173.     write_date(0x30+ge);
  174.     write_date('.');          //小数点

  175. }
  176. void write_wendu2(uchar add,uchar date)
  177. {
  178.      write_com(0x80+0x40+add);    //写显示地址
  179.     write_date(0x30+date);     //将小数部分的第一位数字字符常量写入LCD
  180.     write_date(0xdf);
  181.     write_date('C');
  182.     delay(50);          //延时1ms给硬件一点反应时间
  183. }
  184. void write_htemp(uchar add,uchar date)
  185. {
  186.     uchar shi,ge;
  187.     shi=date/10;
  188.     ge=date%10;
  189.     write_com(0x80+0x40+add);
  190.     write_date(0x30+shi);
  191.     write_date(0x30+ge);
  192. }

  193. void write_ltemp(uchar add,uchar date)
  194. {
  195.     uchar shi,ge;
  196.     shi=date/10;
  197.     ge=date%10;
  198.     write_com(0x80+0x40+add);
  199.     write_date(0x30+shi);
  200.     write_date(0x30+ge);   
  201. }
  202. /****按键扫描******/
  203. void keyscan()
  204. {
  205.     if(k1==0)
  206.     {
  207.         delay(10);
  208.         if(k1==0)
  209.         {
  210.             s1num++;TR0=1;                              //开定时器0
  211.             while(!k1);            //等待按键释放
  212.             yyp=0;
  213.             di();            
  214.             switch(s1num)
  215.             {
  216.                 case 1:    init16021();                  //设置温度上下限初始化
  217.                         
  218.                
  219.                         write_htemp(2,htemp);
  220.                         write_ltemp(12,ltemp);
  221.                         write_com(0x80+0x40+3);
  222.                         write_com(0x0f);            //打开光标
  223.                         break;
  224.                 case 2:    write_com(0x80+0x40+13);
  225.                         break;
  226.                 case 3:    s1num=0;
  227.                         write_com(0x0c);            //关闭光标
  228.                         yyp=1;
  229.                         init1602();                    //上电后显示初始化
  230.                         break;
  231.             }        
  232.         }
  233.     }
  234.     if(s1num!=0)
  235.     {
  236.         if(k2==0)
  237.         {
  238.             delay(10);
  239.             if(k2==0)
  240.             {
  241.                 do
  242.                 {
  243.                 delay1(10);
  244.                     }
  245.                 while((!k2)&(key_delay++<key_count));        //等待按键释放
  246.                 TR0=0;                              //关定时器0
  247.                 di();
  248.                 switch(s1num)
  249.                 {
  250.                     case 1: htemp++;
  251.                             if(htemp==50)htemp=20;
  252.                             write_htemp(2,htemp);
  253.                             write_com(0x80+0x40+3);   
  254.                         
  255.                             break;
  256.                     case 2: ltemp++;
  257.                             if(ltemp==30)ltemp=5;
  258.                             write_ltemp(12,ltemp);
  259.                             write_com(0x80+0x40+13);
  260.                         
  261.                             break;
  262.                 }
  263.             }
  264.         }
  265.         if(k3==0)
  266.         {
  267.             delay(10);
  268.             if(k3==0)
  269.             {
  270.                  do
  271.                 {
  272.                 delay1(10);
  273.                 }
  274.                 while((!k3)&(key_delay++<key_count));    //等待按键释放
  275.                 TR0=0;                              //关定时器0
  276.                 di();
  277.                 switch(s1num)
  278.                 {
  279.                     case 1: htemp--;
  280.                             if(htemp==0)htemp=50;
  281.                             write_htemp(2,htemp);
  282.                             write_com(0x80+0x40+3);
  283.                         
  284.                             break;
  285.                     case 2: ltemp--;
  286.                             if(ltemp==0)ltemp=30;
  287.                             write_ltemp(12,ltemp);
  288.                             write_com(0x80+0x40+13);
  289.                         
  290.                             break;
  291.                 }
  292.             }
  293.         }
  294.     }
  295. }
  296. void baojing()
  297. {
  298.             if((TN>htemp)||(TN<ltemp))        //温度高于设置最大温度或低于设置最小温度
  299.             {
  300.                 lalarm=1;
  301.             }
  302.             else
  303.             {
  304.                 lalarm=0;
  305.             
  306.               
  307.             }
  308.             if(lalarm==1)
  309.             {
  310.                     di();
  311.                     delay(100);
  312.                     di();
  313.                     delay(100);
  314.             }        
  315. }
  316. void  time0()
  317. {
  318.     TMOD=0x01;         //设置定时器0和1工作方式为1(0001 0001)
  319.     TH0=(65536-50000)/256;      //装定时器初值
  320.     TL0=(65536-50000)%256;
  321.     EA=1;                            //开总中断
  322.     ET0=1;                              //开定时器0中断
  323.     TR0=0;                              //关闭定时器0
  324. }

  325. //语音播报程序
  326. sbit MUSIC_REST =P2^2;//语音芯片复位脚                    
  327. sbit MUSIC_DATA =P2^1;//语音芯片脉冲识别
  328. sbit bus =P2^0;       //语音芯片工作状态识别信号  
  329. uchar bbh,xm1,xm2,xm0;

  330. void delay_us(unsigned int us)
  331. {
  332.     while(us--)
  333.     {
  334.         _nop_();
  335.         _nop_();
  336.         _nop_();
  337.         _nop_();
  338.     }
  339. }
  340. void Music(unsigned char music_count)
  341. {
  342.     MUSIC_REST=1;
  343.     delay_us(200);
  344.     MUSIC_REST=0;
  345.     delay_us(200);

  346.     while(music_count>0)
  347.     {
  348.         MUSIC_DATA=1;
  349.         delay_us(100);
  350.         MUSIC_DATA=0;
  351.         delay_us(100);
  352.         music_count--;
  353.     }
  354. }

  355. void Msc()
  356. {
  357.     if((xm0+xm1+xm2)!=0)           //当超出测量范围时不进行播报
  358.     {
  359.         Music(21);                    //播报:“温度”
  360.         while(!bus);
  361.         if(xm0==0)
  362.         {
  363.                   Music(2);             //播报:“十位数具体值”      0
  364.             while(!bus);   
  365.         }               
  366.            else Music(xm0+2);             //播报:“十位数具体值”
  367.         while(!bus);
  368.         Music(12);                //播报:+
  369.         while(!bus);

  370.         if((xm1+xm2)!=0)
  371.         {                  
  372.             Music(xm1+2);                //播报:“十分位的具体值”
  373.             while(!bus);

  374.             Music(14);                    //播报:“点”
  375.             while(!bus);
  376.                                 
  377.             Music(xm2+2);                //播报:“百分位的具体值”
  378.             while(!bus);               
  379.             Music(29);                //播报:“度”
  380.             while(!bus);
  381.         }
  382.         else
  383.         {
  384.             Music(29);                //播报:“度”
  385.             while(!bus);   
  386.         }
  387.     }      
  388. }

  389. void main()
  390. {

  391.     time0();
  392.     init1602();   
  393. P10 = 0;   
  394.             di();
  395.                     delay(100);
  396.     while(1)
  397.     {  
  398.         keyscan();  
  399.           if(yyp==1)
  400.         {
  401.             keyscan();
  402.             ReadTemp();                  //开启温度采集程序
  403.             write_wendu(6,TN);          //显示温度整数
  404.             write_wendu2(9,TD);          //显示温度小数
  405.             baojing();                                //报警函数        
  406.             if(TN<=htemp)
  407.                
  408.                 P10 = 1;
  409.         else
  410.             {
  411.                         Music(23);                //播报:“欢迎”
  412.     while(!bus);
  413.                 P10 = 0;
  414.             }
  415.             xm0=TN /10 ;
  416.             xm1=TN%10;
  417.             xm2=TD;
  418.         }
  419.           while(!k)
  420.           {
  421.               bbh=1;
  422.           }
  423.           if(bbh==1)                    //bb=1调用一次播报程序
  424.            {
  425.                 bbh=0;
  426.                 Msc();
  427.             }                     

  428.     }
  429. }
  430. void timer0() interrupt 1 //定时器0中断服务程序
  431. {
  432.     TH0=(65536-50000)/256;      //再次装定时器初值
  433.     TL0=(65536-50000)%256;
  434.     count++;
  435.     if(count>=200)    //20次50毫秒为1秒       5秒
  436.     {
  437.                 count=0;
  438.                 s1num=0;
  439.                 write_com(0x0c);            //关闭光标
  440.                 yyp=1;
  441.                 init1602();                    //上电后显示初始化
  442.                 TR0=0;                              //关闭定时器0
  443.     }
  444.    
  445.    
  446.    
  447. }
复制代码

所有资料51hei附件下载:
温度报警+语音播报.7z (188.75 KB, 下载次数: 11)
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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