基于Atmega16的温度测控系统PID算法.docx

上传人:b****6 文档编号:3309579 上传时间:2022-11-21 格式:DOCX 页数:20 大小:19.20KB
下载 相关 举报
基于Atmega16的温度测控系统PID算法.docx_第1页
第1页 / 共20页
基于Atmega16的温度测控系统PID算法.docx_第2页
第2页 / 共20页
基于Atmega16的温度测控系统PID算法.docx_第3页
第3页 / 共20页
基于Atmega16的温度测控系统PID算法.docx_第4页
第4页 / 共20页
基于Atmega16的温度测控系统PID算法.docx_第5页
第5页 / 共20页
点击查看更多>>
下载资源
资源描述

基于Atmega16的温度测控系统PID算法.docx

《基于Atmega16的温度测控系统PID算法.docx》由会员分享,可在线阅读,更多相关《基于Atmega16的温度测控系统PID算法.docx(20页珍藏版)》请在冰豆网上搜索。

基于Atmega16的温度测控系统PID算法.docx

基于Atmega16的温度测控系统PID算法

//编译器:

AVRStudio

头文件部分:

#include

#defineucharunsignedchar

#defineucharunsignedchar

#defineuintunsignedint

voidconvert(floatdata);

voidinit_1820(void);

voidwrite_1820(ucharx);

ucharread_1820(void);

floatread_temperature(void);

charkey_scan();

intlcd_bz();

voidlcd_wcmd(ucharcmd);

voidlcd_pos(ucharpos);

voidlcd_wdat(uchardat);

voidlcd_wstr(unsignedcharpos,unsignedchar*q);

voidlcd_init();

voidavr_init();

voiddelay(intus);

voiddelayl(intms);

voiddelay1(intms);

按键程序

#include

#include"headfile.h"

//............................按键.................................

charkey_scan()

{

inttemp=0,temp1,temp2;

charkey;

DDRA=0xf0;

PORTA&=0x0f;

delay1(3);

temp1=PINA&0x0f;

if(temp1!

=0x0f)

{

delay1(80);

temp1=PINA&0x0f;

if(temp1!

=0x0f)

{

DDRA=0x0f;

PORTA&=0xf0;

delay1(5);

temp2=PINA&0xf0;

if(temp2!

=0xf0)

{

temp=temp1+temp2;

}

}

}

switch(temp)

{

case0xee:

key='/';break;//7

case0xde:

key='*';break;//8

case0xbe:

key='-';break;//9

case0x7e:

key='+';break;//+

case0xed:

key='.';break;//4

case0xdd:

key='9';break;//5

case0xbd:

key='6';break;//6

case0x7d:

key='3';break;//-

case0xeb:

key='=';break;//1

case0xdb:

key='8';break;//2

case0xbb:

key='5';break;//3

case0x7b:

key='2';break;//*

case0xe7:

key='0';break;//0

case0xd7:

key='7';break;//.

case0xb7:

key='4';break;//=

case0x77:

key='1';break;///

default:

key=0;break;

}

returnkey;

}

1602显示程序

#include

//#include

#defineep_1(PORTB|=0x04)

#defineep_0(PORTB&=~0x04)

#definers_1(PORTB|=0x01)

#definers_0(PORTB&=~0x01)

#definerw_1(PORTB|=0x02)

#definerw_0(PORTB&=~0x02)

#defineucharunsignedchar

#defineuintunsignedint

//.....................LCD............................

//..............................测试LCD忙碌状态.........................................................................................................

intlcd_bz()

{

DDRC&=~0x80;

intresult=0;

rs_0;

rw_1;

ep_1;

result=(result||(PINC&0x80));

ep_0;

DDRC=0xff;

returnresult;

}

//.................................写入指令数据到LCD..............................................................................................................................

voidlcd_wcmd(ucharcmd)

{

while(lcd_bz());

rs_0;

rw_0;

ep_0;

PORTC=cmd;

ep_1;

ep_0;

delay(5);

}

//..........................设定显示位置........................................................................

voidlcd_pos(ucharpos)

{

lcd_wcmd(pos|0x80);

delay(5);

}

//...........................写入字符显示数据到LCD.........................................................

voidlcd_wdat(uchardat)

{

while(lcd_bz());

rs_1;

rw_0;

ep_0;

PORTC=dat;

ep_1;

ep_0;

}

//.........................写入字符显示数组到LCD.....................................

voidlcd_wstr(unsignedcharpos,unsignedchar*q)

{

//lcd_wcmd(0x01);//清屏

//delay(10);

unsignedchari=0x00;

lcd_pos(pos);

while(*q!

='\0')

{

lcd_wdat(*q);

q++;

i++;

if(i==(0x0F-pos+1))

lcd_pos(0x40);

delay(10);

}

}/**/

//........................LCD初始化设定.............................................

voidlcd_init()

{

lcd_wcmd(0x38);//functionset

delay(10);

lcd_wcmd(0x38);//functionset

delay(10);

lcd_wcmd(0x0c);//displayon/off

delay(10);

lcd_wcmd(0x06);//entrymodeset

delay(10);

lcd_wcmd(0x01);//清除LCD的显示内容

delay(10);

}

//........................avr初始化.................//

voidavr_init()

{

DDRC=0xFF;

DDRB=0x07;

}

18b20程序

#include

#defineucharunsignedchar

#defineucharunsignedchar

#defineuintunsignedint

//------------------------//

//.................convert:

datadisplay.............

voidconvert(floatdata)//实数在液晶上显示

{

inti=0;

intdata1=(int)data;

uchararray1[5]={0},array2[5]={0};

lcd_wcmd(0x01);

//lcd_wcmd(0x00);

lcd_pos(0x0B);

//

if(data1==0)

{

array1[0]=0;

lcd_wdat(48);

//delay1(5);

}

else

while(data1!

=0)

{

array1[i]=data1%10;

data1=data1/10;

i++;

}

for(--i;i>=0;i--)

{

lcd_wdat(array1[i]+48);

//delay1(5);

}//显示小数点前面

lcd_wdat(0x2E);//显示小数点

for(i=0;i<2;i++)//显示小数部分前两位

{

data=data*10;

array2[i]=((int)data)%10;

lcd_wdat(array2[i]+48);

//delay1(5);

}

}

//...................18B20......................

voidinit_1820(void)

{

intFlag_1820Error;

uchari;

uintj=0;

PORTD|=(1<<7);//PORTC|=(1<<7);//"1"

PORTD&=~(1<<7);//PORTC&=~(1<<7);//"0"

for(i=0;i<8;i++)delay(180);//delay_60us();//480us以上

PORTD|=(1<<7);//PORTC|=(1<<7);//"1"

DDRD&=~(1<<7);//DDRC&=~(1<<7);//"PINC7isINPUT"

delay(40);//delay_15us();//15~60us

delay(40);//delay_15us();

Flag_1820Error=0;

while(PIND&(1<<7))//while(PINC&(1<<7))

{delay(180);//delay_60us();

j++;

if(j>=18000){Flag_1820Error=1;break;}

}

DDRD|=(1<<7);//DDRC|=(1<<7);//PORTC7isOUTPUT

PORTD|=(1<<7);//PORTC|=(1<<7);//"1"

for(i=0;i<4;i++)delay(180);//delay_60us();//240us

}

/********************************/

/********************************/

voidwrite_1820(ucharx)

{

ucharm;

for(m=0;m<8;m++)

{

if(x&(1<

{

PORTD&=~(1<<7);//PORTC&=~(1<<7);delay_5us();//"0",5us

PORTD|=(1<<7);//PORTC|=(1<<7);//write"1"

delay(40);//delay_15us();//15~45us

delay(40);//delay_15us();

delay(40);//delay_15us();

}

else

{

PORTD&=~(1<<7);//PORTC&=~(1<<7);delay_15us();//"0",15us

delay(40);//delay_15us();//write"0"

delay(40);//delay_15us();//15~45us

delay(40);//delay_15us();

PORTD|=(1<<7);//PORTC|=(1<<7);//"1"

}

}

PORTD|=(1<<7);//PORTC|=(1<<7);//"1"

}

/*******************************/

ucharread_1820(void)

{

uchartemp,k,n;

temp=0;

for(n=0;n<8;n++)

{

PORTD&=~(1<<7);//PORTC&=~(1<<7);//"0"

delay(13);//delay_5us();

PORTD|=(1<<7);//PORTC|=(1<<7);//"1"

delay(13);//delay_5us();

DDRD&=~(1<<7);//DDRC&=~(1<<7);//"PINC7isINPUT"

k=(PIND&(1<<7));//k=(PINC&(1<<7));//读数据,从低位开始

if(k)

temp|=(1<

else

temp&=~(1<

delay(40);//delay_15us();//45us

delay(40);//delay_15us();

delay(40);//delay_15us();

DDRD|=(1<<7);//DDRC|=(1<<7);//PORTC7isOUTPUT

}

return(temp);

}

/*************************************/

floatread_temperature(void)

{

floattemp;////////////

ucharteml=0,temh=0;

unsignedlongt=0;

init_1820();//复位18b20

write_1820(0xcc);//发出转换命令

write_1820(0x44);

//Delay_nms(100);

init_1820();

write_1820(0xcc);//发出读命令

write_1820(0xbe);

teml=read_1820();//读数据byte1

temh=read_1820();//byte2

t=temh;

t=t<<8;

t=t|teml;

temp=t*0.0625*260/286;

return(temp);

/*if(temh&0xf8)sign=0;

elsesign=1;

if(sign==0){temh=255-temh;teml=255-teml;}

temh=temh<<4;

temh|=(teml&0xf0)>>4;

teml=teml&0x0f;

teml=(teml*10)/16;

tempval=temh;e[0]=tempval/100;

tempval=temh;e[1]=(tempval/10)%10;

tempval=temh;e[2]=tempval%10;

tempval=teml;e[3]=tempval;*/

}

Main程序

#include

#include"headfile.h"

#include

#include

#include

#include

#include

unsignedcharkey[5];//按键数组

floatkeyvalue;//按键值

floatactual;//温度值

unsignedintflag=0;//判断按键标志

unsignedchardis1[]={"SET"};

unsignedchardis2[]={"NOW"};

unsignedchardis3[]={"00:

00"};

unsignedinth=0;//定时1S计时10000次

unsignedcount=0;//计算动态时间

floatPWM=0;

floatPWM1=0;

floatError1;//误差

unsignedintmaxminflag=0;//判断达到动态平衡标志

unsignedchartime[7];//存储动态时间

structPID

{

floatSetPoint;//设定目标DesiredValue

floatProportion;//比例常数ProportionalConst

floatIntegral;//积分常数IntegralConst

floatDerivative;//微分常数DerivativeConst

floatLastError;//Error1[‐1]

floatPrevError;//Error1[‐2]

};

structPIDspid;//PIDControlStructure

structPID*pp;

/***************PID结构体初始化*****/

voidPIDInit(structPID*pp)

{

memset(pp,0,sizeof(structPID));

}

/*****************PID参数设置******************/

voidsetPID(floata,floatb,floatc)

{

pp->Proportion=a;

pp->Integral=b;

pp->Derivative=c;

}

/***********PID计算部分***************************//////////////

floatPIDCalc(structPID*pp,floatNextPoint)

{

floatdError;

unsignedinta;

Error1=pp->SetPoint-NextPoint;//当前偏差

if(fabs(Error1)<10)a=1;

elsea=0;

dError=pp->Proportion*(Error1-pp->LastError)

+a*pp->Integral*pp->LastError

+a*pp->Derivative*(Error1-2*pp->LastError+pp->PrevError);

/*dError=pp->Proportion*Error1

-pp->Integral*pp->LastError

+pp->Derivative*pp->PrevError;

if(fabs(Error1)<=14)

a=1;

else

a=0;

dError=pp->Proportion*(Error1-pp->LastError)+a*pp->Integral*pp->LastError+

pp->Derivative*(Error1-2*pp->LastError+pp->PrevError);*/

pp->PrevError=pp->LastError;

pp->LastError=Error1;

return(dError);//微分项

}

/*********************PWM占空比设置/**********************/////////

voidsetPWM(floatdError)

{

if(fabs(Error1)<10)PWM+=4*dError;

elsePWM+=6*dError;

//PWM+=6*dError;

PWM1=1023-PWM;

if(PWM1<10)PWM1=10;

elseif(PWM1>1020)PWM1=1020;

OCR1BH=(int)(PWM1/256);

OCR1BL=(int)PWM1%256;

}

voidfactor(void)//确认按键值

{

unsignedchartmp;

inti=0;

inttemp1,temp2;

flag=0;

floatkey1=0,key2=0;

while(!

flag)

{

while(!

(tmp=key_scan()));

if(tmp=='*')flag=1;

elseif(tmp=='=')flag=2;

else

{

key[i]=tmp;

lcd_pos(0x03+i);

lcd_wdat(key[i]);

i++;

}

}

key[i]='\0';

keyvalue=(key[0]-48)*10+(key[1]-48)+(key[3]-48)*0.1+(key[4]-48)*0.01+0.5;//0.5是矫正

/*for(i=0;i<5;i++)

{

if(key[i]=='.')temp1=i;if(key[i]=='\0')temp2=i;

}

//if(temp1>=0&&temp1<=4)

for(i=temp

else1-1;i>=0;i--)

key1=key1+(key[i]-48)*pow(10,temp1-1-i);//10^(temp1-1-i)

for(i=temp1+1;i

key2=key2+(key[i]-48)*pow(10,temp1-i);//10^(temp1-i)

keyvalue=key1+key2;*/

pp->SetPoint=keyvalue;

}

/************从DS18B20获得实际温度值并设置显示位置*************

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 小学教育 > 语文

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1