求助論壇大神,為什么我學習改寫別人的PID溫控源碼代碼,其中PWM 和temp_PID.SetPoint 總是不對,用串口調試的結果總是不對。
輸出結果: PWM:100 PWM:12288 PWM_P: 設置溫度:30 實?飾露?2619 temp_s:3000 temp_PID.SetPoint:
按理說我用了這樣的 PWM應該在0到100之間temp_PID.SetPoint:應該是3000才對可是輸出為什么不是,實在查不出原因,請大神指正。
引腳分配 lcd lcddata: P0
lcd_e: P2^7
lcd_rs: P2^6
lcd_rw: P2^5
設置按鍵 limit_choise: P //溫度上下限選擇按鍵
increase_temperature P //增加溫度限值按鍵
reduce_temperature P //減少溫度限值按鍵
蜂鳴器報警 warning P
溫度傳感器 temperature_sensor P
制熱 heatting P
制冷 refrigerating P
LED顯示 normal P //正常溫度指示燈
high_temperature P //高溫指示燈
low_temperature P //低溫指示燈
單片機源程序如下:
- /*******************************************************************************
- * 包含頭文件
- *******************************************************************************/
- #include <main.h>
- /*******************************************************************************
- * 變量聲明
- *******************************************************************************/
- uint PWM=0;
- uint PWM_P;//PWM_P 功率占比顯示
- uchar time_value=0;
- uchar time_heatting=0;
- uint temp_m=0; //實際溫度
- uint up_limit_temp=30;
- uint temp_s; //設置溫度*100
- PID temp_PID;
- uchar massage[]=0;
- /*******************************************************************************
- * 函數名 : void main()
- * 函數功能 : 主函數
- * 輸入 : 無
- * 輸出 : 無
- *******************************************************************************/
- void main()//主函數
- {
- init();//初始化函數
-
- temp_PID.Proportion =150; // 設置 PID 系數
- temp_PID.Integral =5;
- temp_PID.Derivative =2;
- while(1)
- {
- temp_s = up_limit_temp*100;
- temp_PID.SetPoint = temp_s;
- if(time_value==10) //讀取溫度
- {
- temp_m=get_temp(Ds18b20ReadTemp());
- }
- if(time_value==50)
- {
- if(temp_s-temp_m>=100)
- {
- PWM=100;
- }
- else
- {
- PWM = pid_calc(&temp_PID,temp_m);
- if( PWM>=100 ) PWM=100;
- else if(PWM<=1) PWM=1;
- }
- }
- if(time_value==60) //顯示溫度
- {
- display_real_temp(temp_m);
- }
- if(time_value==70)
- {
- send_string(" PWM:");
- DtoA(PWM,massage);
- send_string(massage);
- /*
- PWM_P = PWM;
-
- LcdWriteCom(0x80+0X40+0x0C);
- LcdWriteData('0'+PWM_P/100);
- LcdWriteCom(0x80+0X40+0x0D);
- LcdWriteData('0'+PWM_P%100/10);
- LcdWriteCom(0x80+0X40+0x0E);
- LcdWriteData('0'+PWM_P%10);
-
- */
- send_string(" PWM:");
- DtoA(PWM,massage);
- send_string(massage);
-
- send_string(" PWM_P:");
- DtoA(PWM_P,massage);
- send_string(massage);
-
- send_string(" 設置溫度:");
- DtoA(up_limit_temp,massage);
- send_string(massage);
-
- send_string(" 實際溫度:");
- DtoA(temp_m,massage);
- send_string(massage);
- send_string(" temp_s:");
- DtoA(temp_s,massage);
- send_string(massage);
-
- send_string(" temp_PID.SetPoint:");
- DtoA(temp_PID.SetPoint,massage);
- send_string(massage);
- send_string("\n");
- }
- if(time_value>=100) //指令執行時間,一個單位時間是10ms
- {
- time_value=0;
- }
- if(time_heatting >= 500) time_heatting = 0;
- if(time_heatting <= PWM*5)
- {
- heatting=1;
- }
- else
- {
- heatting=0;
- }
- }
- }
- /*******************************************************************************
- * 函數名 : void init()
- * 函數功能 : 初始化函數
- * 輸入 : 無
- * 輸出 : 無
- *******************************************************************************/
- void init()//初始化函數
- {
- uint i,j;
- Ds18b20Init();//Ds18b20初始化
- //heatting=0;//不制熱
-
- IT0Init();
- IT1Init();
- InitUart0();
- InitTimer0();//定時器初始化
- pid_init (&temp_PID);//PID初始化
-
- LcdInit();//LCD初始化函數
-
- LcdWriteCom(0x80);//第一行顯示
- j=strlen(num1);
- for(i=0; i<j; i++)
- {
- LcdWriteData(num1[i]);
- delay_ms(1);
- }
- LcdWriteCom(0x80+0x40);//第二行顯示
- j=strlen(num2);
- for(i=0; i<j; i++)
- {
- LcdWriteData(num2[i]);
- delay_ms(1);
- }
- LcdWriteCom(0x04); //關閉寫一個指針加1
- }
- /*******************************************************************************
- * 函數名 : uint get_temp(uint temp)
- * 函數功能 : 計算溫度函數
- * 輸入 : 溫度
- * 輸出 : 溫度
- *******************************************************************************/
- uint get_temp(uint temp)//計算溫度函數
- {
- float tp;
-
- tp=temp;//因為數據處理有小數點所以將溫度賦給一個浮點型變量
- //如果溫度是正的那么,那么正數的原碼就是補碼它本身
- temp=tp*0.0625*100+0.5;
- //留兩個小數點就*100,+0.5是四舍五入,因為C語言浮點數轉換為整型的時候把小數點
- //后面的數自動去掉,不管是否大于0.5,而+0.5之后大于0.5的就是進1了,小于0.5的就
- //算加上0.5,還是在小數點后面。
- return temp;
- }
- /*******************************************************************************
- * 函數名 : void display_real_temp(uint temp)
- * 函數功能 : 實時溫度顯示函數
- * 輸入 : 溫度
- * 輸出 : 無
- *******************************************************************************/
- void display_real_temp(uint temp)//實時溫度顯示函數
- {
- uchar datas[] = {0, 0, 0, 0}; //定義數組
- datas[0] = temp % 10000 / 1000;
- datas[1] = temp % 1000 / 100;
- datas[2] = temp % 100 / 10;
- datas[3] = temp % 10;
-
- LcdWriteCom(0x80+0x0a); //寫地址 80表示初始地址
- LcdWriteData('0'+datas[0]); //十位
- LcdWriteCom(0x80+0x0b); //寫地址 80表示初始地址
- LcdWriteData('0'+datas[1]); //個位
- LcdWriteCom(0x80+0x0d); //寫地址 80表示初始地址
- LcdWriteData('0'+datas[2]); //顯示小數點
- LcdWriteCom(0x80+0x0e); //寫地址 80表示初始地址
- LcdWriteData('0'+datas[3]); //顯示小數點
- }
- /*******************************************************************************
- * 函數名 : void InitTimer0(void)
- * 函數功能 : 定時器初始化函數
- * 輸入 : 無
- * 輸出 : 無
- *******************************************************************************/
- void InitTimer0(void)
- {
- TMOD &= 0xF0;
- TMOD |= 0x01;//設置定時模式1
- TH0 = 0xD8;
- TL0 = 0xF0;
- EA = 1;
- ET0 = 1;
- TR0 = 1;
- }
- /*******************************************************************************
- * 函數名 : void Timer0Interrupt(void) interrupt 1
- * 函數功能 : 定時器中斷函數
- * 輸入 : 無
- * 輸出 : 無
- *******************************************************************************/
- void Timer0Interrupt(void) interrupt 1
- {
- TH0 = 0xD8;
- TL0 = 0xF0;
-
- time_value++; //功能計數值+1
- time_heatting++; //加熱計數值+1
- }
- /*******************************************************************************
- * 函數名 : void INIT0(void) interrupt 0
- * 函數功能 : 外部中斷0執行函數
- * 輸入 : 無
- * 輸出 : 無
- *******************************************************************************/
- void INIT0(void) interrupt 0
- {
-
- delay_ms(5);
- if (increase_temperature == 0)
- {
- while(increase_temperature == 0);
- if(up_limit_temp<=110)
- {
- up_limit_temp=up_limit_temp+5;
- LcdWriteCom(0x80+0X40+0x03);
- LcdWriteData('0'+up_limit_temp%1000/100);
- LcdWriteCom(0x80+0X40+0x04);
- LcdWriteData('0'+up_limit_temp%100/10);
- LcdWriteCom(0x80+0X40+0x05);
- LcdWriteData('0'+up_limit_temp%10);
- }
- }
- }
- /*******************************************************************************
- * 函數名 : void INIT1(void) interrupt 2
- * 函數功能 : 外部中斷1執行函數
- * 輸入 : 無
- * 輸出 : 無
- *******************************************************************************/
- void INIT1(void) interrupt 2
- {
-
- delay_ms(5);
- if (reduce_temperature == 0)
- {
- while(reduce_temperature == 0);
- if(up_limit_temp>=20)
- {
- up_limit_temp=up_limit_temp-5;
- LcdWriteCom(0x80+0X40+0x03);
- LcdWriteData('0'+up_limit_temp%1000/100);
- LcdWriteCom(0x80+0X40+0x04);
- LcdWriteData('0'+up_limit_temp%100/10);
- LcdWriteCom(0x80+0X40+0x05);
- LcdWriteData('0'+up_limit_temp%10);
- }
- }
-
- }
- /*******************************************************************************
- * 函數名 : void IT0Init(void)
- * 函數功能 : 外部中斷0初始化
- * 輸入 : 無
- * 輸出 : 無
- *******************************************************************************/
- void IT0Init(void)
- {
- IT0 = 0;//0為電平,1為下降沿
- EX0 = 1;//外部中斷1
- }
- /*******************************************************************************
- * 函數名 : void IT1Init(void)
- * 函數功能 : 外部中斷1初始化
- * 輸入 : 無
- * 輸出 : 無
- *******************************************************************************/
- void IT1Init(void)
- {
- IT1 = 0;//0為電平,1為下降沿
- EX1 = 1;//外部中斷0
- }
- /*******************************************************************************
- * 函數名 : void InitUart0(void)
- * 函數功能 : 串口中斷初始化
- * 輸入 : 無
- * 輸出 : 無
- *******************************************************************************/
- void InitUart0(void)
- {//設計波特率:4800bps;實際波特率:4464bps
- TMOD&=0x0F;
- TMOD|=0x20;
- SCON=0x50;
- PCON|=0x80;
- TH1 = 0xF3;
- TL1 = 0xF3;
- ES = 1; //使能串口中斷 ,無論是TI/RI出現,只要中斷打開,單片機就進入中斷函數。
- TR1 = 1;
- //ET1 = 0;//禁止T1中斷
- }
- /*******************************************************************************
- * 函數名 : void IT1Init(void)
- * 函數功能 : 串口中斷函數
- * 輸入 : 無
- * 輸出 : 無
- *******************************************************************************/
- void Usart() interrupt 4
- {
- //uchar receiveData;
- //receiveData=SBUF;//出去接收到的數據
- RI = 0;//清除接收中斷標志位
-
- //SBUF=receiveData;//將接收到的數據放入到發送寄存器
- //while(!TI); //等待發送數據完成
- //TI=0; //清除發送完成標志
- //massage[0]=0;
-
- }
- /*******************************************************************************
- * 函數名 : void send_byte(uchar by)
- * 函數功能 : 串口發送字節函數
- * 輸入 : 無
- * 輸出 : 無
- *******************************************************************************/
- void send_byte(uchar by)
- {
- SBUF = by;
- while(!TI);//當寫下這句的時候,就不要在中斷函數里面在寫TI = 0;這句了,不然進入中斷函數將TI清零之后,程序就會一直卡在這里
- TI = 0; //在這里將TI清零
- }
- /*發送一個字符串*/
- /*******************************************************************************
- * 函數名 : void send_string(uchar *p)
- * 函數功能 : 串口發送字符串函數
- * 輸入 : 無
- * 輸出 : 無
- *******************************************************************************/
- void send_string(uchar *p)
- {
- while(*p!= '\0')
- {
-
- send_byte(*p);
- p++;
- }
- }
- /*******************************************************************************
- * 函數名 : void DtoA(unsigned long dat, unsigned char* buffer)
- * 函數功能 : 串口發送字符串函數
- * 輸入 : 無
- * 輸出 : 無
- *******************************************************************************/
-
- void DtoA(uint dat, unsigned char* buffer)
- {
- uint tmp = 0;
- char length = 0;
- tmp = dat;
- while(tmp != 0)//求出數字的實際長度
- {
- tmp = tmp/10;
- length++;
- }
- buffer[length] = '\0';//長度數為字符串截止位
- length--;
- while(length >= 0)//數字的低位放入數組的高位
- {
- tmp = dat%10;
- buffer[length--] = 0x30|tmp;
- dat = dat/10;
- }
- }
復制代碼 全部資料51hei下載地址:
PID恒溫控制器.zip
(113.68 KB, 下載次數: 20)
2019-3-27 16:34 上傳
點擊文件名下載附件
|