![]() |
發(fā)布時間: 2021-6-8 22:12
正文摘要:Proteus P8.11\Proteus 8 Professional\Tools\MAKE\RunTool.exe" --good-exits=0,1 --executable=C51.exe "..\main.c" ROM(D512K) BROWSE DEBUG CODE OBJECTEXTEND PREPRINT OBJECT("main.OBJ" ... |
#include "STC15Fxxxx.h" #include "button.h" #include "LCD1602.h" #include<absacc.h> #define uchar unsigned char //#define OSC 18432000L //#define BAUD 9600 //#define URMD 0 #define ADC_POWER 0x80 #define ADC_FLAG 0x10 #define ADC_START 0x08 #define ADC_SPEEDLL 0x00 #define ADC_SPEEDL 0x20 #define ADC_SPEEDH 0x40 #define ADC_SPEEDHH 0x60 #define TIMS 65236 #define uchar unsigned char #define uint unsigned int #define ADC_7 XBYTE[0x0600] //定義模數(shù)轉(zhuǎn)換IO地址 #define DAC_1 XBYTE[0x0640] //最小拍參數(shù) sbit str = P1^7; //定義A/D啟動信號 sbit DIN0 = P1^0; //聲明同步信號 uint data time; //聲明變量,用于定時 uchar data t0_h,t0_l; //用于存儲定時器0的初值 int TK=100; //聲明采樣周期變量,//采樣周期=TK*10ms int TC; //TK的變量 float KK0=0.5435; //系數(shù)kk0 float KK1=-0.2000; //系數(shù)kk1 float KK2=0; //系數(shù)kk2 float KK3=0; //系數(shù)kk3 float PP1=0.7170; //系數(shù)pp1 float PP2=0; //系數(shù)pp2 float PP3=0; //系數(shù)pp3 char UK; //當前時刻的D/A輸出 char EK; //當前時刻的偏差 char UK_1,UK_2,UK_3,EK_1,EK_2,EK_3;//前3次采樣時刻的控制量和偏差 //標志位 bit flag=0; unsigned int intr2; unsigned char intr; bit adc_flag; uchar state=1; //初始最小拍控制狀態(tài) #define da_cs P15 #define led P17 bit key_flag; float Err=0,D_Err=0; float Last_Err=0,Prev_Err=0; int limit=0; float vol_set,vol_sample=0,temp_sample,dac=0; int temp_set=60; uchar key_table[]={0,0,0}; float uk0=0; uint ad_data=0; //bit adc_rd=0; void timer_0() interrupt 1 { if(++intr == 10) //1ms?′DDò?′? { intr = 0; key_flag = 1; //10ms判鍵 } if(++intr2 == 600) //1ms?′DDò?′? { //P47=!P47; intr2 = 0; adc_flag=1; //1s adc2é?ù??ê±ê±???? } //display(temp_set,temp_sample); } void Timer0() interrupt 1 using 1 { str = !str; //產(chǎn)生A/D啟動信號 TH0 = t0_h; //重新裝入初值 TL0 = t0_l; } void adc_int() interrupt 5 { ADC_CONTR &=!ADC_FLAG; //if (adc_rd==1){ ad_data=ADC_RES*4+ADC_RESL; // } if (adc_rd==0) {adc_rd=1;} } float zuixiaopai( ) { TMOD = 0x01; time = 10; //定時10ms t0_h = (65536-500*time)/256; //計算定時器0初值 t0_l = (65536-500*time)%256; t0_l = t0_l+20; //修正因初值重裝而引起的定時誤差 TH0 = t0_h; TL0 = t0_l; IT1 = 1; //邊沿觸發(fā)中斷 EX1 = 1; //開外部中斷1 ET0 = 1; //開定時中斷0 TR0 = 1; //啟動定時器 TC = 1; DAC_1= 0x80; //D/A清零 UK=UK_1=UK_2=UK_3=0; EK=EK_1=EK_2=EK_3=0; EA = 1; return(UK); //開總中斷 while(1); } void int1() interrupt 2 using 2 { float i,j; DIN0 = 1; //讀取輸入前,先輸出高電平 if(DIN0) //判同步信號到否 { UK=UK_1=UK_2=UK_3=0; EK=EK_1=EK_2=EK_3=0; DAC_1 =0x80; //D/A輸出零 TC=1; } else { TC--; //判采樣周期到否 if(TC==0) { EK = ADC_7-128; //采樣當前的偏差值,并計算偏差的變化量 i=EK*KK0; //計算i=EK*KK0+EK_1*KK1+EK_2*KK2+EK_3*KK3) i=i+EK_1*KK1; i=i+EK_2*KK2; i=i+EK_3*KK3; j=UK_1*PP1; //計算j=UK_1*PP1+UK_2*PP2+UK_3*PP3 j=j+UK_2*PP2; j=j+UK_3*PP3; i=i-j; //i-j if(i>0) //判控制量是否溢出,溢出賦極值 { if(i>=127) UK=127; else UK=(char)i; } else { if(i<-128) UK=-128; else UK=(char)i; } DAC_1=UK+128; //D/A輸出控制量 UK_3=UK_2; //控制量遞推 UK_2=UK_1; UK_1=UK; EK_3=EK_2; //偏差遞退 EK_2=EK_1; EK_1=EK; TC=TK; //采樣周期變量恢復 } } } void main() { unsigned char key_temp; unsigned char ch=0; //AD2é?ùí¨μà uchar i=0; P3=0; P0M0 = 0x00; P0M1 = 0x00; P1M0 = 0x01; P1M1 = 0x01; P2M0 = 0x00; P2M1 = 0x00; P3M0 = 0x00; P3M1 = 0x00; P4M0 = 0x00; P4M1 = 0x00; P5M0 = 0x00; P5M1 = 0x00; P6M0 = 0x00; P6M1 = 0x00; P7M0 = 0x00; P7M1 = 0x00; CLK_DIV=0x03; lcd_init(); display_init(); led=1; TL0=TIMS; TH0=TIMS>>8; AUXR&=0x3F; AUXR1=0X08; TMOD=0x00; TR0 = 1; ET0 = 1; EA = 1; EADC=1; P1ASF=0xFF; ADC_RES=0; temp_sample=vol_sample*16+20; //設置換算溫度初始值,對應0-5V,采樣溫度范圍20-100°C ADC_CONTR =ADC_POWER |ADC_SPEEDLL | ADC_START | ch; //for(i=0;i<10000;i++); //ADC_CONTR &=!ADC_FLAG; da_cs=0; //D/A初始值 while(1) { if(key_flag) //10ms掃描鍵盤1次 { key_flag = 0; key_temp = read_key(); } switch (state) //狀態(tài)切換 { case 1: //PID控制 if (adc_flag==1) { ADC_CONTR=ADC_POWER |ADC_SPEEDLL | ADC_START | ch; // ad_data=0 adc_flag=0; vol_set=(temp_set-20)/16.0; //溫控設定范圍20-100度,AD 0-5V vol_sample=(float)(ad_data)*5/1024; //采樣數(shù)字量0-1023換算成電壓值0-5V temp_sample=vol_sample*16+20; //換算成溫度 Err = vol_set - vol_sample; uk0 = zuixiaopai( ); //調(diào)用最小拍 dac+=(uk0/5*256*5/12); limit=round(dac); if(limit<0) limit=0; if(limit>255) limit=255; P3=limit; } display(temp_set,temp_sample); if (key_temp==10) //設置鍵按下 { state=2; led=0; //設置指示燈亮 } break; case 2: //設置給定溫度 if (key_temp>=0&&key_temp<=9) //數(shù)字鍵按下 {key_table[i++]=key_temp; //按位記錄按鍵設定值 if (i==3) i=0;} else if (key_temp==11) { led=1; Err=0; D_Err=0; state=1; break; } //led=0; temp_set=key_table[0]*100+key_table[1]*10+key_table[2]; //組合成溫度設定值 display(temp_set,temp_sample); break; } } } |
Powered by 單片機教程網(wǎng)