/*********************************************************** 写一位数据子程序
***********************************************************/ void write_bit(unsigned char bitval) {
EA=0;
DQ=0; /*拉低DQ以开始一个写时序*/ if(bitval==1) { _nop_();
DQ=1; /*如要写1,则将总线置高*/ }
delay(5); /*延时90us供DA18B20采样*/ DQ=1; /*释放DQ总线*/ _nop_(); _nop_(); EA=1; }
/*********************************************************** 写一字节数据子程序
***********************************************************/ void write_byte(unsigned char val) {
unsigned char i; unsigned char temp; EA=0; /*关中断*/ TR0=0;
for(i=0;i<8;i++) /*写一字节数据,一次写一位*/ {
temp=val>>i; /*移位操作,将本次要写的位移到最低位*/ temp=temp&1;
write_bit(temp); /*向总线写该位*/ }
delay(7); /*延时120us后*/ // TR0=1; EA=1; /*开中断*/ }
/*********************************************************** 读一位数据子程序
***********************************************************/ unsigned char read_bit() {
unsigned char i,value_bit; EA=0;
DQ=0; /*拉低DQ,开始读时序*/ _nop_(); _nop_();
DQ=1; /*释放总线*/ for(i=0;i<2;i++){} value_bit=DQ; EA=1;
return(value_bit); }
/*********************************************************** 读一字节数据子程序
***********************************************************/ unsigned char read_byte() {
unsigned char i,value=0; EA=0; for(i=0;i<8;i++) {
if(read_bit()) /*读一字节数据,一个时序中读一次,并作移位处理*/ value|=0x01<
delay(4); /*延时80us以完成此次都时序,之后再读下一数据*/ } EA=1; return(value); }
/*********************************************************** 复位子程序
***********************************************************/ unsigned char reset() {
unsigned char presence; EA=0;
DQ=0; /*拉低DQ总线开始复位*/ delay(30); /*保持低电平480us*/ DQ=1; /*释放总线*/
delay(3);
presence=DQ; /*获取应答信号*/
delay(28); /*延时以完成整个时序*/
EA=1;
return(presence); /*返回应答信号,有芯片应答返回0,无芯片则返回1*/ }
/*********************************************************** 获取温度子程序
***********************************************************/ void get_temper() {
unsigned char i,j; do
{
i=reset(); /*复位*/
}while(i!=0); /*1为无反馈信号*/ i=0xcc; /*发送设备定位命令*/ write_byte(i);
i=0x44; /*发送开始转换命令*/ write_byte(i); delay(180); /*延时*/ do
{
i=reset(); /*复位*/ }while(i!=0); i=0xcc; /*设备定位*/ write_byte(i);
i=0xbe; /*读出缓冲区内容*/ write_byte(i); j=read_byte(); i=read_byte(); i=(i<<4)&0x7f;
s=(unsigned int)(j&0x0f); s=(s*100)/16;
j=j>>4;
temper=i|j; /*获取的温度放在temper中*/ }
/*==================================================================================================== Initialize PID Structure
=====================================================================================================*/ void PIDInit (struct PID *pp) {
memset ( pp,0,sizeof(struct PID)); }
/*==================================================================================================== PID计算部分
=====================================================================================================*/
unsigned int PIDCalc( struct PID *pp, unsigned int NextPoint ) {
unsigned int dError,Error;
Error = pp->SetPoint - NextPoint; // 偏差 pp->SumError += Error; // 积分
dError = pp->LastError - pp->PrevError; // 当前微分 pp->PrevError = pp->LastError; pp->LastError = Error;
return (pp->Proportion * Error//比例 + pp->Integral * pp->SumError //积分项 + pp->Derivative * dError); // 微分项 }
/*********************************************************** 温度比较处理子程序
***********************************************************/ compare_temper() {
unsigned char i; if(set_temper>temper) {
if(set_temper-temper>1) {
high_time=100; low_time=0; } else {
for(i=0;i<10;i++) { get_temper(); rin = s; // Read Input
rout = PIDCalc ( &spid,rin ); // Perform PID Interation }
if (high_time<=100)
high_time=(unsigned char)(rout/800); else