1、基于Atmega16的温度测控系统PID算法/编译器:AVRStudio头文件部分:#include #define uchar unsigned char#define uchar unsigned char #define uint unsigned intvoid convert(float data); void init_1820(void); void write_1820(uchar x); uchar read_1820(void);float read_temperature(void);char key_scan();int lcd_bz();void lcd_wcmd(u
2、char cmd);void lcd_pos(uchar pos);void lcd_wdat(uchar dat); void lcd_wstr(unsigned char pos,unsigned char *q);void lcd_init();void avr_init();void delay(int us);void delayl(int ms);void delay1(int ms);按键程序#include#includeheadfile.h/.按键.char key_scan() int temp=0,temp1,temp2; char key; DDRA=0xf0; POR
3、TA&=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) case 0xee:key=/;break;/7 case 0xde:key=*;break;/8 case 0xbe:key=-;break;/9 case 0x7e:key=+;break;/+ ca
4、se 0xed:key=.;break;/4 case 0xdd:key=9;break;/5 case 0xbd:key=6;break;/6 case 0x7d:key=3;break;/- case 0xeb:key=;break;/1 case 0xdb:key=8;break;/2 case 0xbb:key=5;break;/3 case 0x7b:key=2;break;/* case 0xe7:key=0;break;/0 case 0xd7:key=7;break;/. case 0xb7:key=4;break;/= case 0x77:key=1;break;/ defa
5、ult :key=0;break; return key;1602显示程序#include /#include#define ep_1 (PORTB|=0x04)#define ep_0 (PORTB&=0x04)#define rs_1 (PORTB|=0x01)#define rs_0 (PORTB&=0x01)#define rw_1 (PORTB|=0x02)#define rw_0 (PORTB&=0x02)#define uchar unsigned char #define uint unsigned int/.LCD./. 测试LCD忙碌状态.int lcd_bz() DDRC
6、&=0x80; int result=0; rs_0; rw_1; ep_1; result =(result|(PINC & 0x80); ep_0; DDRC=0xff; return result; /. 写入指令数据到LCD.void lcd_wcmd(uchar cmd) while(lcd_bz(); rs_0; rw_0; ep_0; PORTC= cmd; ep_1; ep_0; delay(5);/.设定显示位置.void lcd_pos(uchar pos) lcd_wcmd(pos | 0x80);delay(5);/.写入字符显示数据到LCD.void lcd_wdat
7、(uchar dat) while(lcd_bz(); rs_1; rw_0; ep_0; PORTC=dat; ep_1; ep_0; /.写入字符显示数组到LCD.void lcd_wstr(unsigned char pos,unsigned char *q) /lcd_wcmd(0x01); /清屏 /delay(10); unsigned char i=0x00; lcd_pos(pos); while(*q!=0) lcd_wdat(*q); q+; i+; if(i=(0x0F-pos+1) lcd_pos(0x40); delay(10); /*/.LCD初始化设定.void
8、lcd_init() lcd_wcmd(0x38); /function set delay(10); lcd_wcmd(0x38); /function set delay(10); lcd_wcmd(0x0c); /display on/off delay(10); lcd_wcmd(0x06); /entry mode set delay(10); lcd_wcmd(0x01); /清除LCD的显示内容 delay(10);/.avr初始化./void avr_init() DDRC=0xFF; DDRB=0x07; 18b20程序#include #define uchar unsig
9、ned char#define uchar unsigned char #define uint unsigned int/-/.convert:data display.void convert(float data) /实数在液晶上显示 int i=0; int data1=(int)data; uchar array15=0,array25=0; lcd_wcmd(0x01); / lcd_wcmd(0x00); lcd_pos(0x0B); / if(data1=0) array10=0; lcd_wdat(48); / delay1(5); else while(data1!=0)
10、array1i=data1%10; data1=data1/10; i+; for(-i;i=0;i-) lcd_wdat(array1i+48); / delay1(5); /显示小数点前面 lcd_wdat(0x2E); /显示小数点 for(i=0;i2;i+) /显示小数部分前两位 data=data*10; array2i=(int)data)%10; lcd_wdat(array2i+48); /delay1(5); /.18B20.void init_1820(void) int Flag_1820Error; uchar i; uint j=0; PORTD|=(17);/PO
11、RTC|=(17); /1 PORTD&=(17);/PORTC&=(17); /0 for(i=0;i8;i+)delay(180);/delay_60us();/480us以上 PORTD|=(17);/PORTC|=(17); /1 DDRD&=(17);/DDRC&=(17); /PINC7 is INPUT delay(40);/delay_15us(); /1560us delay(40);/delay_15us(); Flag_1820Error=0; while(PIND&(17)/while(PINC&(1=18000)Flag_1820Error=1;break; DDRD
12、|=(17);/DDRC|=(17); /PORTC7 is OUTPUT PORTD|=(17);/PORTC|=(17); /1 for(i=0;i4;i+)delay(180);/delay_60us(); /240us /*/*/void write_1820(uchar x) uchar m; for(m=0;m8;m+) if(x&(1m) /写数据,从低位开始 PORTD&=(17);/PORTC&=(17);delay_5us(); /0,5us PORTD|=(17);/PORTC|=(17); /write1 delay(40);/delay_15us(); /1545us
13、 delay(40);/delay_15us(); delay(40);/delay_15us(); else PORTD&=(17);/PORTC&=(17);delay_15us();/0,15us delay(40);/delay_15us(); /write0 delay(40); /delay_15us(); /1545us delay(40);/delay_15us(); PORTD|=(17);/PORTC|=(17); /1 PORTD|=(17);/ PORTC|=(17); /1 /*/uchar read_1820(void) uchar temp,k,n; temp=0
14、; for(n=0;n8;n+) PORTD&=(17);/PORTC&=(17); /0 delay(13);/delay_5us(); PORTD|=(17);/PORTC|=(17); /1 delay(13);/delay_5us(); DDRD&=(17);/DDRC&=(17); /PINC7 is INPUT k=(PIND&(17);/k=(PINC&(17); /读数据,从低位开始 if(k) temp|=(1n); /read1 else temp&=(1n); /read0 delay(40);/delay_15us(); /45us delay(40);/delay_1
15、5us(); delay(40);/delay_15us(); DDRD|=(17);/DDRC|=(17); /PORTC7 is OUTPUT return (temp); /*/float read_temperature(void) float temp;/ uchar teml=0,temh=0; unsigned long t=0; init_1820(); /复位18b20 write_1820(0xcc); / 发出转换命令 write_1820(0x44); /Delay_nms(100); init_1820(); write_1820(0xcc); /发出读命令 writ
16、e_1820(0xbe); teml=read_1820(); /读数据byte1 temh=read_1820(); /byte2 t=temh; t=t8; t=t|teml; temp=t*0.0625*260/286; return(temp); /*if(temh&0xf8)sign=0; else sign=1; if(sign=0)temh=255-temh;teml=255-teml; temh=temh4; teml=teml&0x0f; teml=(teml*10)/16; tempval=temh;e0=tempval/100; tempval=temh;e1=(temp
17、val/10)%10; tempval=temh;e2=tempval%10; tempval=teml;e3=tempval;*/ Main程序 #include#includeheadfile.h#include#include#include#include#includeunsigned char key5; /按键数组float keyvalue; /按键值float actual; /温度值unsigned int flag=0;/判断按键标志unsigned char dis1=SET;unsigned char dis2=NOW;unsigned char dis3=00:00
18、;unsigned int h=0; /定时1S计时10000次unsigned count=0; /计算动态时间float PWM=0;float PWM1=0;float Error1; /误差unsigned int maxminflag=0;/判断达到动态平衡标志unsigned char time7;/存储动态时间struct PIDfloat SetPoint; / 设定目标 Desired Valuefloat Proportion; / 比例常数 Proportional Constfloat Integral; / 积分常数 Integral Constfloat Deriv
19、ative; / 微分常数 Derivative Constfloat LastError; / Error11float PrevError; / Error12;struct PID spid; / PID Control Structurestruct PID *pp;/*PID 结构体初始化*/void PIDInit (struct PID *pp) memset(pp,0,sizeof(struct PID);/*PID 参数设置*/void setPID(float a,float b,float c)pp-Proportion=a;pp-Integral=b;pp-Deriva
20、tive=c;/*PID 计算部分*/float PIDCalc( struct PID *pp, float NextPoint )float dError;unsigned int a;Error1 = pp-SetPoint-NextPoint; / 当前偏差 if(fabs(Error1)Proportion*(Error1-pp-LastError) +a*pp-Integral*pp-LastError +a*pp-Derivative*(Error1-2*pp-LastError+pp-PrevError);/*dError=pp-Proportion*Error1 -pp-In
21、tegral*pp-LastError +pp-Derivative*pp-PrevError;if(fabs(Error1)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 占空比设置/*/void setPWM(float dError) if(fabs(Erro
22、r1)10)PWM+=4*dError; else PWM+=6*dError; /PWM+=6*dError; PWM1=1023-PWM; if(PWM11020)PWM1=1020; OCR1BH=(int)(PWM1/256); OCR1BL=(int)PWM1%256;void factor(void) /确认按键值 unsigned char tmp; int i=0; int temp1,temp2; flag=0; float key1=0,key2=0; while(!flag) while(!(tmp=key_scan(); if(tmp=*) flag=1; else if(tmp=)flag=2; else keyi=tmp; lcd_pos(0x03+i); lcd_wdat(keyi); i+; keyi=0; keyvalue=(key0-48)*10+(key1-48)+(key3-48)*0.1+(key4-48)*0.01+0.5;/0.5是矫正 /* for(i=0;i=0&temp1=0;i-) key1=key1+(keyi-48)*pow(10,temp1-1-i);/10(temp1-1-i) for(i=temp1+1;iSetPoint=keyvalue;/*从DS18B20 获得实际温度值并设置显示位置*
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1