|
# 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);
}
|
|