內含程序,原理圖和參考文件
溫度設定部分 設定部分主要是鍵盤輸入,此部分主要由三個按鍵組成,PLAS為加,SUBS為減,START為開始。當系統啟動時,默認設定溫度為30℃,當按下PLAS時設置水溫增加,按下SUBS時設置水溫減小,當按下START時為開始加熱。 此部分按鍵為常開按鈕,當不觸發時為斷開狀態,按鍵按下之后與地連接,故為低電平,單片機讀取按鍵數據為低電平時有效。 仿真說明 由于單片機端口的驅動能力有限,所以令其低電平觸發光電耦合器,故當P1.5口輸出低電平時電熱絲加熱。 當設定溫度與實際溫度之差大于10℃時屬于粗調,即令電熱絲持續加熱,無PWM控制;當設定溫度與實際溫度之差小于10℃時屬于微調,即電熱絲加熱時受PWM控制。 仿真結果 對各溫度仿真結果如下: (1)實際溫度19℃,設定溫度30℃ 當差值大于10℃時,輸出為低電平,電熱絲持續加熱,如圖5.1所示:
0.png (95.4 KB, 下載次數: 128)
下載附件
2017-5-7 16:07 上傳
(2)實際溫度21℃,設定溫度30℃當差值小于10℃,控制算法開始起作用,由低電平部分控制加熱,如圖5.2所示:
0.png (99.87 KB, 下載次數: 142)
下載附件
2017-5-7 16:07 上傳
(3)實際溫度24℃,設定溫度30℃當差值逐漸縮小,低電平時間減少,電熱絲功率降低,如圖5.3所示:
0.png (98.78 KB, 下載次數: 120)
下載附件
2017-5-7 16:08 上傳
(4)實際溫度28℃,設定溫度30℃當差值逐漸縮小,低電平時間減少,電熱絲功率降低,如圖5.4所示:
0.png (99.66 KB, 下載次數: 130)
下載附件
2017-5-7 16:08 上傳
(5)實際溫度32℃,設定溫度30℃當設定溫度小于實際溫度時,PWM輸出高電平,電熱絲不工作,如圖5.5所示:
0.png (92.93 KB, 下載次數: 126)
下載附件
2017-5-7 16:09 上傳
1.1 結論(1)當設定溫度與實際溫度之差小于10℃時,P1.5輸出PWM方波控制電熱絲加熱功率,以達到精確調溫的目的。(2)當差值大于10℃時,電熱絲持續加熱,使其盡快進入到PWM調節階段(3)當設定溫度小于實際溫度,說明溫度已超調,故電熱絲不工作,使其降溫。
0.png (30.72 KB, 下載次數: 152)
下載附件
2017-5-7 16:06 上傳
0.png (61.18 KB, 下載次數: 121)
下載附件
2017-5-7 16:06 上傳
- //包含的頭文件
- #include<REG51.H>
- #include<math.h>
- #include<INTRINS.H>
- #include<string.h>
- //定義宏定義
- #define CIRCLE 100
- #define uchar unsigned char
- #define uint unsigned int;
- struct PID {
- unsigned int SetPoint; // 設定目標 Desired Value
- unsigned int Proportion; // 比例常數 Proportional Const
- unsigned int Integral; // 積分常數 Integral Const
- unsigned int Derivative; // 微分常數 Derivative Const
- unsigned int LastError; // Error[-1]
- unsigned int PrevError; // Error[-2]
- unsigned int SumError; // Sums of Errors
- };
- struct PID spid; // PID Control Structure
- unsigned int rout; // PID Response (Output)
- unsigned int rin; // PID Feedback (Input)
- typedef unsigned char BYTE;
- typedef unsigned int WORD;
- typedef bit BOOL ;
- sbit key1=P3^2; //定義按鍵位置
- sbit key2=P3^3;
- sbit key3=P3^4;
- sbit rs = P1^0;
- sbit rw = P1^1;
- sbit ep = P1^2;
- sbit pwm=P1^5; //PWM輸出端設置為P1.5輸出
- sbit DQ=P1^3;//ds18b20 信號引腳即DQ
- sfr dataled=0x80;//顯示數據端口 即P2口為段選碼輸入口
- uchar temp;//溫度變量
- unsigned char set_temper=30;
- unsigned char high_time;
- unsigned int s;
- uchar flag_get,count,num,counter; //溫度讀取標志位、中斷次數變量t0中斷次數以讀取溫度值, t1中斷次數以控制周期和PWM的占空比
- char const table[]={100,80,70,60,50,40,30,20,0};//高電平時間查表
- uchar
- code
- tab[]={0x28,0xEB,0x32,0xA2,0xE1,0xA4,0x24,0xEA,0x20,0xA0,0x60,0x25,0x3C,0x23,0x34,
- 0x74,0xF7,0xFF};//,0x88,0x83,0xC6,0xA1,0x86,0x8E};//共陽led顯示段碼115段碼表
- uchar shi,ge,danwei,dang,dang_dis; // 定義溫度十位、個位、攝氏度單位、及檔位變量名稱,及顯示檔位的查表變量
-
- void delay1(uchar MS);// 延時函數
- unsigned char ReadTemperature(void);//讀溫度子函數
- void Init_DS18B20(void);// DS18B20初始化
- unsigned char ReadOneChar(void);//讀字節子函數
- void WriteOneChar(unsigned char dat);//寫字節子函數
- void delay(unsigned int i);//延時
- //void del(unsigned int);
- void drive_moto();//由P1低四位輸出控制信號
- void initial();
- unsigned int TempBuffer[5];
- BYTE code dis1[] = {"Temperature:"};
- BYTE code dis2[] = {"Set_Temper:"};
- BYTE code dis3[] = {"0123456789"};
- BYTE code dis4[] = 0xdf;
- BYTE code dis5[] = {"C"};
- //定義函數
- void delay2(BYTE ms)
- {
- BYTE i;
- while(ms--)
- {
- for(i = 0; i< 250; i++)
- {
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- }
- }
- }
- // 測試LCD忙碌狀態
- BOOL lcd_bz()
- {
- BOOL result;
- rs = 0;
- rw = 1;
- ep = 1;
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- result = (BOOL)(P0 & 0x80);
- ep = 0;
- return result;
- }
- // 寫入指令數據到LCD
- void lcd_wcmd(BYTE cmd)
- {
- while(lcd_bz());
- rs = 0;
- rw = 0;
- ep = 0;
- _nop_();
- _nop_();
- P0 = cmd;
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- ep = 1;
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- ep = 0;
- }
- //設定顯示位置
- void lcd_pos(BYTE pos)
- {
- lcd_wcmd(pos | 0x80);
- }
- //寫入字符顯示數據到LCD
- void lcd_wdat(BYTE dat)
- {
- while(lcd_bz());
- rs = 1;
- rw = 0;
- ep = 0;
- P0 = dat;
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- ep = 1;
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- ep = 0;
- }
- //LCD初始化設定
- void lcd_init()
- {
- lcd_wcmd(0x38); //
- delay2(1);
- lcd_wcmd(0x0c); //
- delay2(1);
- lcd_wcmd(0x06); //
- delay2(1);
- lcd_wcmd(0x01); //清除LCD的顯示內容
- delay2(1);
- }
- //初始化相應的寄存器
- void initial()
- {
- EA=1;
- TMOD=0x11;//定時器設置皆工作在16定時計數器模式
- TH0=0xef;//T0賦初值
- TL0=0xf0;
- TH1=(65536-1000)/256;//T1賦初值
- TL1=(65536-1000)%256;
- ET1=1;
- ET0=1;
- TR0=1;
- TR1=1;
- P2=0xff;
- count=0;
- counter=0;//pwm占空比控制變量
- //IP=0x08; //T1優先級高于T0 ,后來證明此語句是多余的因為當加入此句后反/////而PWM調速和溫度檢測都變得有點不穩定
- }
- //延時函數
- void delay(unsigned int i)
- {
- while(i--);
- }
-
- //18b20初始化函數檢測總線上是否有從屬器件DS的存在若存在則通訊成功
- void Init_DS18B20(void)
- {
- unsigned char x=0;
- DQ = 1; //DQ復位
- delay(8); //稍做延時
- DQ = 0; //單片機將DQ拉低
- delay(80); //延時 大于 480us
- DQ = 1; //拉高總線
- delay(10);
- x=DQ; //稍做延時后 如果x=0則初始化成功 x=1則初始化失敗因為DQ復位成功的回答信號即存在信號是低電平
- delay(5);
- }
- //讀一個字節ROM
- unsigned char ReadOneChar(void)
- {
- unsigned char i=0;
- unsigned char dat = 0;
- for (i=8;i>0;i--)
- {
- DQ = 0; // 給脈沖信號
- dat>>=1;
- DQ = 1; // 給脈沖信號
- if(DQ)
- dat|=0x80;//
- delay(5);
- }
- return(dat);
- }
-
- //寫一個字節
- void WriteOneChar(unsigned char dat)
- {
- unsigned char i=0;
- for (i=8; i>0; i--)
- {
- DQ = 0;
- DQ = dat&0x01;
- delay(5);
- DQ = 1;
- dat>>=1;
- }
- delay(5);
- }
- //讀取溫度
- unsigned char ReadTemperature(void)
- {
- unsigned char a=0;
- unsigned char b=0;
- unsigned char t=0;
-
- Init_DS18B20();// 復位
- WriteOneChar(0xCC); // 跳過讀序號列號的操作
- WriteOneChar(0x44); // 啟動溫度轉換
- delay(100);
- Init_DS18B20(); //每次操作前都要進行復位
- WriteOneChar(0xCC); //跳過讀序號列號的操作
- WriteOneChar(0xBE); //讀取溫度寄存器等共可讀9個寄存器 前兩個就是溫度
- a=ReadOneChar();
- b=ReadOneChar();
- s=(unsigned int)(a&0x0f);
- b<<=4;//取高字節的第四位因為高四位為符號位1111為負0000為正
- b+=(a&0xf0)>>4;//忽略小數位取a的高四位與b的相加就是此時所測得到整數溫度值
- t=b;
- return(t);//返回溫度值給這個函數
- }
- //顯示函數
- void printf()
- {
- BYTE i;
- delay2(10);
- lcd_pos(0x00); // 設置顯示位置為第一行的第5個字符
- i = 0;
- while(dis1[i] != '\0')
- {
- lcd_wdat(dis1[i]);
- i++;
- }
- lcd_pos(0x40); // 設置顯示位置為第二行第二個字符
- i = 0;
- while(dis2[i] != '\0')
- {
- lcd_wdat(dis2[i]); // 顯示字符
- i++;
- }
- TempBuffer[0]=temp/10; //十位
- TempBuffer[1]=temp%10; //個位
- lcd_pos(0x0c);
- lcd_wdat(dis3[TempBuffer[0]]); //測試溫度十位
- lcd_pos(0x0d);
- lcd_wdat(dis3[TempBuffer[1]]); //測試溫度個位
- lcd_pos(0x0e);
- lcd_wdat(dis4[0]);
- lcd_pos(0x0f);
- lcd_wdat(dis5[0]);
-
- TempBuffer[2]=set_temper/10; //十位
- TempBuffer[3]=set_temper%10; //個位
- lcd_pos(0x4c);
- lcd_wdat(dis3[TempBuffer[2]]); //設置溫度十位
- lcd_pos(0x4d);
- lcd_wdat(dis3[TempBuffer[3]]); //設置溫度個位
- lcd_pos(0x4e);
- lcd_wdat(dis4[0]);
- lcd_pos(0x4f);
- lcd_wdat(dis5[0]);
- }
- //鍵盤輸入函數
- void keyscan()
- {
- if(key1==0)
- {
- delay(200);
- if(key1==0)
- {
- set_temper++;
- }
- }
-
- if(key2==0)
- {
- delay(200);
- if(key2==0)
- {
- set_temper--;
- }
- }
- // //開始按鍵
- // if(key3==0)
- // {
- // delay(300);
- // if(key3==0)
- // {
- // TR1=1;
- // }
- // }
- }
- //T1定時中斷服務程序
- void into(void) interrupt 3
- {
-
- TH1=(65536-1000)/256;//初值重裝
- TL1=(65536-1000)%256;
- counter++;
- if(counter>CIRCLE)
- {
- counter=0;////限定周期為T=100X0.01ms=10ms
- }
- if(counter<=high_time)//取得查表參數以調節pwm的占空比
- pwm=1;//PWM高電平
- else
- pwm=0;
- }
- //設定占空比函數
- void compare_temper()
- {
- char shi=0,ge=0;
- if(set_temper>temp)
- {
- //當設置溫度與實際溫度大于10度時
- if(set_temper-temp>=10)
- {
- //進入死循環
- while(1)
- {
- TR1=0; //關閉定時器 從而關閉PWM波
- pwm=0; //輸出低電平
- temp=ReadTemperature(); //讀取溫度傳感器的值
- shi=temp/10; //分離出十位
- ge=temp%10; //分離出個位
- lcd_pos(0x0c); //設置顯示位置
- lcd_wdat(0x30+shi); //在指定位置顯示十位
- lcd_pos(0x0d); //設置顯示位置
- lcd_wdat(0x30+ge); //在指定位置顯示各位
- if(set_temper-temp<10) //如果溫度差值低于10度
- {
- TR1=1; //打開定時器 開pwm波
- break; //跳出循環
- }
- }
- }
- else
- {
- //打開定時器
- TR1=1;
- //根據差值調整PWM波
- if (set_temper-temp==9)
- high_time=10;
- if (set_temper-temp==8)
- high_time=20;
- if (set_temper-temp==7)
- high_time=30;
- if (set_temper-temp==6)
- high_time=40;
- if (set_temper-temp==5)
- high_time=50;
- if (set_temper-temp==4)
- high_time=60;
- if (set_temper-temp==3)
- high_time=70;
- if (set_temper-temp==2)
- high_time=80;
- if (set_temper-temp==1)
- high_time=90;
- }
- }
- else if(set_temper<temp)
- {
- //關閉定時器
- pwm=1;
- TR1=0;
- }
- }
- main()
- {
- initial();// 初始化個變量及定時器的初值開中斷等
- lcd_init(); // 初始化LCD
- while(1)
- {
- //比較函數
- compare_temper();
- //輸出函數
- printf();
- //讀取溫度函數
-
- …………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼
0.png (51.56 KB, 下載次數: 138)
下載附件
2017-5-7 16:06 上傳
下載:
電阻爐溫度控制系統.zip
(421.63 KB, 下載次數: 372)
2017-5-7 09:25 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|