找回密码
 立即注册

QQ登录

只需一步,快速开始

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

求大神指导下,利用AT89C52和DS18B20设计的水温控制系统,请帮忙看下程序的错误部分。

[复制链接]
跳转到指定楼层
楼主
ID:100338 发表于 2015-12-24 15:51 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
# include<REG52.h>
# include<stdio.h>
# include<intrins.h>
sbit DQ   = P1^4;   // 定义DS18B20 的数据口
sbit SET  = P1^0;     // 定义报警值的控制开关
sbit BEEP = P1^3;
unsigned char TAP[10] =   // 共阳极, 不带点
{ 0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8,0x80, 0x90, } ;
unsigned char TAP2[10] =   // 共阳极, 带点
{ 0x40, 0x79, 0x24, 0x30, 0x19, 0x12, 0x02, 0x78,0x00, 0x10, } ;
// 定义一个存放转换后温度值的数组, 温度值为字符型(ASCII码),小数点后保留2位
unsigned char str[10] ;
unsigned char data con=0x00;
// 延时子程序, 延时( 10* D+ 3) us
void delay_10us( unsigned char D)
{     unsigned char i;
    for (i=0;i<D;i++)
    {     _nop_( ) ;     // 空操作, 一个指令周期
          _nop_( ) ;
    }
}
//1ms延时函数
delay1ms(int t)
{
int i,j;
for (i=0;i<t;i++)
for (j=0;j<120;j++)
;
}
// DS18B20 初始化
void INIT(void)
{     DQ = 0;
    delay_10us(50) ;   // 等待500  s
    DQ = 1;   // 释放18B20 数据线。
    delay_10us(9) ;   // 等待90  s
    while ( ! DQ) ;     // 等待18B20 准备好
}
// 读DS18B20 的程序
unsigned char READ(void)
{     unsigned char i,j;
    unsigned char D = 0;
  for ( i=0; i<8; i++ )   // 读8 位数据
    { D=D>>1;   // 先读数据低位
      DQ = 0;
      _nop_( ) ;
      DQ = 1;   // 释放18B20 数据线
      for ( j=1; j<9; j++ )
      {   _nop_( ) ; }
    if(DQ)
D += 0x80;    // 如果数据线上是 1 , D 最高位为 1 , 否则为 0
    delay_10us (6) ;   
      }
      return D; // 返回值为D, 即读出的一个字节数据。
}  
// 写DS18B20 的程序
void WRITE( unsigned char D)
    { unsigned char i;
    for ( i=0; i<8; i++ )  
    { DQ = 0;   
      if ( D&0x01)   
   DQ = 1;  
      else           
   DQ = 0;
      delay_10us(8) ;            
      DQ = 1;            
      D = D>>1; // 右移一位, 准备写下一位
    }
}
// 显示程序( str 数组内元素是ASCII码, 所以要减去48)
void display(void)
{     unsigned char i;
    unsigned char j=100;
    while( j-- )
  {
        for ( i=0; i<255; i++ )
        {
    P0 = ~TAP[str[0]-48] ;  
          P2 = ~0x01;
        }
  P2 = ~0x00;
        for ( i=0; i<255; i++ )
        { P0 = ~TAP2[str[1]-48] ;
          P2 = ~0x02;
  }
  P2 = ~0x00;
for ( i=0; i<255; i++ )
        { P0 = ~TAP[str[3]-48] ;  
          P2 = ~0x04;
        }
  P2 = ~0x00;
        for ( i=0; i<255; i++ )
        { P0 = ~TAP[str[4]-48] ;  
          P2 = ~0x08;
        }
  P2 = ~0x00;
    }
}
//蜂鸣器控制
void Alarm(unsigned char t)
{
  unsigned char i,j;
for(i=0;i<200;i++)
{
   BEEP= ~BEEP;
  for(j=0;j<t;j++);
}
}
// 主程序
void main( )
  { unsigned char warning= 25;
  unsigned char TMP_H = 0;
  unsigned char TMP_L = 0;
  short     TMP= 0; // 短整型数据
  float     TMP_F= 0; // 浮点型数据
// P1_0= 0;   // 开机时测试温度超限警报LED 灯
  while(1)
    {
if (SET==0)
{
delay1ms(10);   //按键去抖
  while (SET==0);
  con++;
  if (con>=2)
  con=0;
}
if(con)   // 报警值确定
{
      if( P1^1==0)
{
   //delay1ms(10);  //按键去抖
   //while( P1_1==0);
   warning++; // 增加上限
   }
      else
   if( P1^2==0)
   {
   //delay1ms(10);  //按键去抖
  //while( P1_2==0);
   warning--; // 减小上限
   }
      else     
   warning+= 0;
      str[ 0] = warning / 10+ 48;
      str[ 1] = warning%10+ 48;
      str[ 3] = 48;
      str[ 4] = 48;
      display( ) ;
      delay_10us( 5) ;
      }
    INIT( ) ;   // 初始化DS18B20
    WRITE( 0xCC) ; // 跳过ROM 配置
    WRITE( 0x44) ;   // 开始转换温度
    display( ) ;   // 默认至少等待750 ms, 用于温度转换
    INIT( ) ;     // 初始化DS18B20
    WRITE( 0xCC) ; // 跳过ROM 配置
    WRITE( 0xBE) ;   // 准备读取温度值
    TMP_L= READ( ) ;   // 读取温度值的低8 位
    TMP_H = READ( ) ;   // 读取温度值的高4 位
    TMP=TMP_H ;
    TMP=( TMP<<8) | TMP_L;  // 高位左移8 位与低位相或( 加) 赋值于T MP
    TMP_F= TMP *0.0625; // 计算温度值
    sprintf( str , "%.2f" , TMP_F) ;
// 将浮点数转换成字符型, 存入str 数组
    if( TMP_F>= warning )
{
P1^5 = 0;
P1^6 = 1;
P1^7 = 1;
Alarm(90);
Alarm(120);
}
// 如果温度值大于等于报警值, 报警
else   
{
P1^5 = 1;
P1^6 = 0;
P1^7 = 0;
}
}
}
//PID控制部分
#define FiltA  0.1;             //PID输出的滤波系数(0.0-1.0)
#define FiltB  0.9               // PID输出的滤波系数(1-FilterA)
#define Kp    1.75             //PID控制器的比例系数
#define Ki    0.00125           //PID控制器的积分系数
#define Kd    3.0              //PID控制器的微分系数
#define Emax  0.1              //误差积分上限
float Err[4] [2];
float InteR[4] [2];
float OnMs[4] [2];
/*
function:      unsigned char pid(unsigned char i,unsigned char j,unsigned char k,unsigned char l)
description:    this function for pid control
parameter:     i:-->channel
                j:-->time
                   k:-->set temprature
                      l:-->actual temprature
return:         adjust_time-->adjust time
*/
void pid (unsigned char ch,float refval)
{
   Float DiscE,Tmpr;
   Err[ch][1]=refval-GetTmp(GetData7705(ch+l));                       //e(k)
   
   If(Err[ch] [1]>=Emax) InteE[ch] [1]=InteE[ch] [1]=InteE[ch] [0]+Err[ch] [1];
    else                  InteE[ch] [l]= InteE[ch] [0];
   DiscE=Err [ch] [1]-Err[ch] [0];
   Tmpr=Kp*Err[ch] [1]+Ki*InteE[ch] [1]+Kd*DiscE;
   OnMs[ch] [1]=GetOnMs(FiltA*OnMs[ch] [0]+FiltB*Tmpr);
   Err[ch] [0]=Err [ch] [1];
   InteE[ch] [0]=InteE[ch] [1];
OnMs[ch] [0]= OnMs[ch] [1];
}
/*
function:       float GetOnMs(float OnTime)
description:     output control time
parameter:      none
return:         ftmp
*/
float GetOnMs(float OnTime)
{
   float ftmp;
   if(OnTime<=0)    ftmp=0;
   else if(OnTime>=100)   ftmp=100;
   else             ftmp=OnTime;
   return(ftmp);
}

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

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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