|
PID恒溫控制出現(xiàn)可以加熱,但是不能關(guān)閉加熱,大佬們幫忙看下是啥問題?是數(shù)據(jù)符號類型不一致嗎?**********************************************************************************************************************//*********************************************************************************************************************/#define INT_TIME 1000 //定時(shí)時(shí)間,單位為us#define TH_VAL (unsigned char)((0x10000 - (INT_TIME*(FOSC/1000))/12000)>>8)#define TL_VAL (unsigned char)((0x10000 - (INT_TIME*(FOSC/1000))/12000))void TIMER0_ISR (void) interrupt 1 //每1ms產(chǎn)生中斷{ TH0 = TH_VAL; TL0 = TL_VAL; count++; if(count>=10) //10ms { cnt++; //計(jì)數(shù) count=0; } // P03 = ~P03;}void Timer0_Init(void){ TMOD = (TMOD&0xFC)|0x01; //模式選擇: 定時(shí)器0,模式1。 TH0 = TH_VAL; //高8位裝初值 TL0 = TL_VAL; //低8位裝初值 TR0 = 1; //定時(shí)器0使能 ET0 = 1; //定時(shí)器0中斷使能 EA = 1;// PT0 = 1; //設(shè)置定時(shí)器0中斷優(yōu)先級為高優(yōu)先級 }/***********************************************************************************函數(shù)名稱: ADC_Init 功能描述: 初始化ADC寄存器(設(shè)置ADC時(shí)鐘、設(shè)置采樣時(shí)間、選擇ADC參考電壓)輸入?yún)?shù): 無返 回 值: 無***********************************************************************************/void ADC_Init(void){// ADCON = AST(0) | ADIE(0) | HTME(7) | ADCALE(1) | VSEL(ADC_REF_INNER); //設(shè)置ADC參考電壓為內(nèi)部1.5V ADCON = AST(0) | ADIE(0) | HTME(7) | ADCALE(0) | VSEL(ADC_REF_VDD); //設(shè)置ADC參考電壓為VDD ADCFGL = ACKD(7); P06F = P06_ADC8_SETTING; //設(shè)置P0.6為ADC引腳功能}/***********************************************************************************函數(shù)名稱: Get_AdcValue 功能描述: 獲取ADC轉(zhuǎn)換數(shù)值輸入?yún)?shù): channel ADC通道號返 回 值: ADC值***********************************************************************************/unsigned int Get_AdcValue(unsigned char channel){ unsigned int AD_Value; ADCFGL = (ADCFGL&0xE0) | ADCHS(channel); //選擇ADC通道 ADCON |= AST(1); //啟動(dòng)ADC轉(zhuǎn)換 while(!(ADCON & ADIF)); //等待ADC轉(zhuǎn)換完成 ADCON |= ADIF; //清除ADC中斷標(biāo)志 AD_Value = ADCDH*256 + ADCDL; //讀取AD值 AD_Value >>= 4; return AD_Value;}/*********************************************************************************************************************/struct _pid{ float Set_WD; //設(shè)定值 float Actual_WD; //實(shí)際值 float err; //偏差 float err_last; //上一次偏差 float err_next; float Kp,Ki,Kd; float voltage; //電壓值 float integral; //積分值}pid;void PID_INIT(){ pid.Set_WD=0.0; pid.Actual_WD=0.0; pid.err=0.0; pid.err_last=0.0; pid.err_next=0.0; pid.voltage=0.0; pid.integral=0.0; pid.Kp=0.4; pid.Ki=0.5; pid.Kd=0.4;}unsigned int temp=40; //設(shè)置溫度值void PID_Realize(){ //PID控制 unsigned int index; if(temp==40){temp_adc=1419;} //100K熱敏電阻40度溫度值時(shí)對應(yīng)的ADC值 pid.Set_WD=temp_adc; pid.err=pid.Set_WD-AD_Value; if(pid.err>200 || pid.err<-200) { index=0; } else if(pid.err<100 || pid.err>-100) { index=1; pid.integral+=pid.err; } else { if(pid.err>0) { index=(200-pid.err)/100; pid.integral+=pid.err; } else { index=(200+pid.err)/100; pid.integral+=pid.err; } } pid.voltage=pid.Kp*pid.err + pid.Ki*pid.integral + pid.Kd*(pid.err-pid.err_last); pid.err_last=pid.err; PWM_OUT=pid.voltage*1.0; //賦值給PWM_OUT if(PWM_OUT>100){PWM_OUT=100;} }void hot(unsigned int PWM) //加熱函數(shù){ if(cnt<PWM){P07=1;} //加熱, if(cnt>PWM){P07=0;} //關(guān)閉加熱 if(cnt>100){cnt=0;}}/*********************************************************************************************************************/void System_Init(void){ LVDCON = 0xE0; //開啟LVD,設(shè)置為低電壓復(fù)位模式,檢測電壓為2.7V #ifdef SYSCLK_8MHZ CKDIV = 0; //系統(tǒng)時(shí)鐘上電默認(rèn)為IRCH的二分頻(4MHz),運(yùn)行8MHz,則CKDIV設(shè)置為0#endif #ifdef UART1_EN Uart1_Initial(UART1_BAUTRATE);#endif }void main(void){ P06F = INPUT | PU_EN; //ADC腳 P07F = OUTPUT | PU_EN; //加熱腳 P06=1; P07=0; System_Init(); EA = 1; //開全局中斷 Timer0_Init(); //定時(shí)器初始化 ADC_Init(); //初始化ADC PID_INIT(); //PID初始化 while(1) { AD_Value = Get_AdcValue(ADC_CH8); //獲取溫度值 PID_Realize(); //PID運(yùn)算 hot(PWM_OUT);//控制加熱 }}
|
|