PID恒溫控制出現可以加熱,但是不能關閉加熱,大佬們幫忙看下是啥問題?是數據符號類型不一致嗎?**********************************************************************************************************************//*********************************************************************************************************************/#define INT_TIME 1000 //定時時間,單位為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產生中斷{ TH0 = TH_VAL; TL0 = TL_VAL; count++; if(count>=10) //10ms { cnt++; //計數 count=0; } // P03 = ~P03;}void Timer0_Init(void){ TMOD = (TMOD&0xFC)|0x01; //模式選擇: 定時器0,模式1。 TH0 = TH_VAL; //高8位裝初值 TL0 = TL_VAL; //低8位裝初值 TR0 = 1; //定時器0使能 ET0 = 1; //定時器0中斷使能 EA = 1;// PT0 = 1; //設置定時器0中斷優先級為高優先級 }/***********************************************************************************函數名稱: ADC_Init 功能描述: 初始化ADC寄存器(設置ADC時鐘、設置采樣時間、選擇ADC參考電壓)輸入參數: 無返 回 值: 無***********************************************************************************/void ADC_Init(void){// ADCON = AST(0) | ADIE(0) | HTME(7) | ADCALE(1) | VSEL(ADC_REF_INNER); //設置ADC參考電壓為內部1.5V ADCON = AST(0) | ADIE(0) | HTME(7) | ADCALE(0) | VSEL(ADC_REF_VDD); //設置ADC參考電壓為VDD ADCFGL = ACKD(7); P06F = P06_ADC8_SETTING; //設置P0.6為ADC引腳功能}/***********************************************************************************函數名稱: Get_AdcValue 功能描述: 獲取ADC轉換數值輸入參數: channel ADC通道號返 回 值: ADC值***********************************************************************************/unsigned int Get_AdcValue(unsigned char channel){ unsigned int AD_Value; ADCFGL = (ADCFGL&0xE0) | ADCHS(channel); //選擇ADC通道 ADCON |= AST(1); //啟動ADC轉換 while(!(ADCON & ADIF)); //等待ADC轉換完成 ADCON |= ADIF; //清除ADC中斷標志 AD_Value = ADCDH*256 + ADCDL; //讀取AD值 AD_Value >>= 4; return AD_Value;}/*********************************************************************************************************************/struct _pid{ float Set_WD; //設定值 float Actual_WD; //實際值 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; //設置溫度值void PID_Realize(){ //PID控制 unsigned int index; if(temp==40){temp_adc=1419;} //100K熱敏電阻40度溫度值時對應的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) //加熱函數{ if(cnt<PWM){P07=1;} //加熱, if(cnt>PWM){P07=0;} //關閉加熱 if(cnt>100){cnt=0;}}/*********************************************************************************************************************/void System_Init(void){ LVDCON = 0xE0; //開啟LVD,設置為低電壓復位模式,檢測電壓為2.7V #ifdef SYSCLK_8MHZ CKDIV = 0; //系統時鐘上電默認為IRCH的二分頻(4MHz),運行8MHz,則CKDIV設置為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(); //定時器初始化 ADC_Init(); //初始化ADC PID_INIT(); //PID初始化 while(1) { AD_Value = Get_AdcValue(ADC_CH8); //獲取溫度值 PID_Realize(); //PID運算 hot(PWM_OUT);//控制加熱 }}
|