找回密码
 立即注册

QQ登录

只需一步,快速开始

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

基于单片机温度设计源程序

[复制链接]
跳转到指定楼层
楼主
ID:672377 发表于 2019-12-24 14:12 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
//摘要:温度控制器系统(温度显示精确到0.1度)
//调温调节范围设定在35-65度
//共计5种模式:
//模式0:温度实时值显示(前1位数码管显示模式,后2位显示实时温度值,精确到0.1C
//模式1:目标温度设定(35-65 度)
//模式2: PID 参数中的P参数调节模式(0.0-50.0)
//模式3: PID参数中的I参数调节模式(0.0-50.0)
//模式4: PID参数中的D参数调节模式(0.0-50.0)
//数码管第一位显示模式值,后三位显示参数值
//按MODE键显示对应模式,按UP,DOWN修改参数,按ENT键返回模式0即显示实时温度值

#include "STC12C5A60S2.h"
#include "table.h"
#define AD CHANNEL 0

#define uchar unsigned char
#define uint unsigned int

#define THCO 0xf8 //11.0592MHZ 晶振
#define TLCO 0xcb //定时 2ms时间常数值



unsigned char Data_Buffer[4]= {1,2,3,4};
uchar                    code
Duan[ 17]= {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71 ,0x76};
sbit P24=P2^4;  //四 个数码管的位码口定义
sbit P25=P2^5;
sbit P26=P2^6;
sbit P27=P2^7;
sbit warm=P3^4;
sbit Mode_key=P2^0;
sbit UP_key=P2^1;
sbit DOWN_key=P2^2;
sbit ENT_key=P3^2;


void AD_init();
unsigned int AD_Sample(unsigned char channel);
void Buffer_fresh();

bit kuaisu=0; //按 键快速处理
unsigned char V_mode=0; //0-4
unsigned int canshu[5]= {0,450,110,50,10;//均放大10倍
//模式0:温度实时值显示(前1位数码管显示模式,后2位显示实时温度值,精确到0.1C
//模式1:目标温度设定(35-65 度)
//模式2: PID参数中的P参数调节模式(0.0-50.0)
//模式3: PID参数中的I参数调节模式(0.0-50.0)
//模式4: PID参数中的D参数调节模式(0.0-50.0)
unsigned int maxcanshu[5]= {0,700,500,500,500};
unsigned int mincanshu[5]= {0,300,1,1,1};

bit ADflag=0;
bit PIDflag=0;
bit Disp_flag=0;
/*---------------------------------------------
      温度计算,放大10倍
---------------------------------------------*/

unsigned int ADtempreture(void)
{
      unsigned int da=0,max,min,mid;

        unsigned int V;
        float t,t1j;

                v=AD_ Sample(AD_ CHANNEL);
                t=v;
                t=v*4.83///4.883=5000/1024 ;
                t1=t/1000;       //t1为电压值
                t1=(5000-t)/t1;
                v=(unsigned int)t1*10;    // 计算得电阻值

                da=v;

                max=97; min=0;

         while(1)//查表求出温度值
            {
               mid=(max +min)/2;
               if(Table[mid]<da)             max-mid;
               else                                   min=mid;
               if(max-min)<=1)              break;
              }
             if(max-min)da-min* 10;         //温度值放大10倍
             else
             {
                j=(Table[min]-Table[max])/10;
                j=(Table[min]-da)j;
               da=j;
               da= 10*min+da;
                 }
         return da;

}
unsigned char pid_val_mid=0;
void PIDcompute()
{
   /*-------------------------------------------------
根据设定及采集值进行计算PID调节,计算出PID——VAL——MID 的值
--------------------------------------------------*/
static int SumError-0,PrevError-0,L astError-=0;
int dError-0,Error=0;
double j=0.0,i;

                Error =canshu[1]-cansbu[0];
                if(Error> 10){pid val mid-25s;returm;}
                else if(Errort 10<0){pid _val mid-0;return;}
                SumError +=Error;
                dError- Error-LastError;
                PrevError-LastError;
                LastError-Error;

//               j=canshu[2]*Error + canshu[3]*SumError + canshu[4]*dError;   //放大100倍

                 i=canshu[2];
                 j=Error*i;
                 i=canshu[3];
                 j=j+SumError*i;
                 i=canshu[4];
                 j=j+dError*i;

              if(j>0) j=j/10;     //PID参数放大了10倍,所以要減小10倍

              if(j> 255)pid _val mid= 255;       //全幵
              else ifj<0)pid val mid-0;           //全关
              else pid _val _mid=j;                   //计算值
}

/******************** ******/
void main(void)   //主程序
{
  bit x: -0,y=0;;

  TMOD =0x11;    //没置定肘器0工作模式,16位汁数模式
  TH0=THCO;
  TL0=TLCO;
  TR0=1;             //启动计时器
  ET0=1;            //使能定时器中断
  EA=l;            //幵总中断
CCON=0;         //清标志
CL=0;               //清计数器
CH=0;
CMOD=0x08;                    //PCA时钟为SYSCLK
PCAPWM1=0X0;

CCAP1H=CCAP1L=0xff;   //pwm0 output 50% duty cycle脉宽值越低输出越大DA
CCAPM1=0X42;              //PCA module-0 work in 8-bit PWM mode
CR= 1;                            //PCA timer start run

AD_init();

      while(1)
      {
          if(Disp_ flag==1)
                       { Disp_ flag=0;Bufer_ fresh0;}
          if(ADflag==1)
                       {canshu[0]=ADtempreture0;ADflag =0;
                       if(V_ mode= -0)Disp_ flag=1;}
           if(PIDflag==1)
                      {PIDflag=0;PIDcompute0;CCAP1H=CCAP1L= 255-pid_ val mid;}
           if(Mode_ key== =1)x=0;
             else if(x= =0)
             {x=1;
             V_mode++;Disp_ flag= l;
             if(V_ mode>4)V_ mode=0;
            }
             if(ENT_ key==1)y=0;            //按ENT键观察实时温度
             else if(y==0)
            {y=1;
             Disp_ flag=l;
             V_ mode=0;
             }
             if(canshu[0] > 500)||canshu[0]<350)
             {
             P3 = 0x00;
             }
             else
            {
             P3 = 0XFF;
             }
      }
}
void AD_ init();
{
  P1M0=P1M0&(~(1<<AD_ CHANNEL));     //P10 设为AD转换功以能
  PIM1=P1M1|(1<<AD_ CHANNEL);
  P1ASF=1<<AD_ CHANNEL;                      //通道选择

  AUXRI|=0x04;
  ADC_ _CONTR=0x80;                          //打开A/D转换器电源
}
unsigned int AD_ Sample(unsigned char channel)
{
         unsigned int temp;
         ADC_ CONTR=0x88|channel;                         //选择AD当前通道,并启动转换
         while((ADC_ CONTR&0x10)==0);                 //等待AD转换结束
         ADC_ _CONTR =0x80; //清除转 换结束标志
         temp (ADC_ RES&0x03)*256+ADC_ RESL;
         return  temp;
}
void timer0) interrupt 1                                    //定时 器中断服务子程序
{
      static unsigned int count=0,count1 =0,keytime =0;     //软计时变量定义
      static unsigned char Bit=0;                                   //静态变量,退出程序后,值保留

      TH0=THCO;
      TL0=TLCO;

      Bit++;
      if(Bit>=4)Bit=0;
      P2|=0xf0;                                                           //先关位码
      P0=Duan[Data_ _Buffer[Bit];
      if(Bit== 2|Bit==0)P0|=0X80;
      switch(Bit)                                                         //送位码
       {
           case 0: P24=0;break;
           case 1: P25=0;break;
           case 2: P26=0;break;
           case 3: P27=0;break;
        }
        count++;
        if(count>=100)                                           //200ms更新采集一次温度,并做一次 PID
       {
           count=0;
           ADflag=l;
        }
         count1++;
         if(count1>=400)                                                  //800ms做一次PID

        {
           count1=0;
           PIDflag=1;
         }
         if(UP_ key-=0|DOWN_ key==0)&&V_ mode!=0)
            {
                   if(+ +keytime >30)
                   {
                       keytime=0;
                       if(UP_ key==0)
            {canshu[V_ mode]++;if(canshu[V_ mode]>maxcanshu[V_ mode])canshu[V_ mode]- mincanshu[V_ mode];Disp_ flag=1;}

                       else if(DOWN_ key--0)

            {if(canshu[V_ mode] =mincanshu[V_ mode])canshu[V_ mode]=maxcanshu[V mode],canshu[V_ mode]--;Disp_ flag=1;}
                                 }
}

else (keytime=0;)}
}
void Buffer_ fresh()
{                Data_ Buffer[0]=V_ mode;
                 Data_ Buffer[ l]=canshu[V_ mode]/100%10;
                 Data Buffer[2]=canshu[V_ mode]/10%10;
                 Data_ Buffer[3]= canshu[V_ mode]%10;
}











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

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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