找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開始

搜索
查看: 12584|回復(fù): 4
收起左側(cè)

51單片機(jī)的PID溫控(熱得快)設(shè)計(jì)與調(diào)試資料

  [復(fù)制鏈接]
ID:341661 發(fā)表于 2018-5-30 20:57 | 顯示全部樓層 |閱讀模式
《自動(dòng)控制原理》課程設(shè)計(jì)
目錄

1. 系統(tǒng)設(shè)計(jì)方案3
1.1方案一3
1.2 方案二3
1.3方案三3
1.4方案的比較和確定3
2.系統(tǒng)硬件部分設(shè)計(jì)3
2.1 系統(tǒng)硬件電路圖3
2.1.1 單片機(jī)AT89C524
2.1.2單片機(jī)與LCD通信連接4
2.1.3 其他電路模塊及總電路5
3系統(tǒng)軟件部分5
3.1系統(tǒng)的主流程圖如下5
4.溫度控制系統(tǒng)PID調(diào)節(jié)6
4.1 PID控制傳遞函數(shù)6
4.2 PID參數(shù)調(diào)節(jié)方法6
4.3 PID參數(shù)設(shè)定6
5.實(shí)驗(yàn)與調(diào)試7
6.總論8
附    錄8
參 考 文 獻(xiàn)24


  • 系統(tǒng)設(shè)計(jì)方案

1.1方案一

          選用鉑電阻溫度傳感器。此類溫度傳感器線性度、穩(wěn)定性等方面性能都很好,但其成本較高。

1.2 方案二

          采用熱敏電阻。選用此類元器件有價(jià)格便宜的優(yōu)點(diǎn),但由于熱敏電阻的非線性特性會(huì)影響系統(tǒng)的精度。

1.3方案三

采用DS18B20溫度傳感器。DS18B20是DALLAS公司生產(chǎn)的一線式數(shù)字溫度傳感器,具有3引腳封裝形式;溫度測(cè)量范圍為-55℃~+125℃,可編程為9位~12位A/D轉(zhuǎn)換精度,測(cè)溫分辨率可達(dá)0.0625℃,被測(cè)溫度用符號(hào)擴(kuò)展的16位數(shù)字量方式串行輸出遠(yuǎn)端引入

     1.4方案的比較和確定

比較以上三種方案,方案三具有具有體積小、質(zhì)量輕、線形度好、性能穩(wěn)定等優(yōu)點(diǎn)其各方面特性都滿足此系統(tǒng)的設(shè)計(jì)要求的優(yōu)點(diǎn),因此選用方案三。

  • 系統(tǒng)硬件部分設(shè)計(jì)

硬件設(shè)計(jì)包含DS18B20模塊,1602液晶顯示模塊,繼電器模塊,鍵盤輸入模塊和聲光報(bào)警模塊,DS18B20可以被編程,所以箭頭是雙向的,CPU(89C52)首先寫入命令給DS18B20,然后DS18B20開始轉(zhuǎn)換數(shù)據(jù),轉(zhuǎn)換后通89C52來(lái)處理數(shù)據(jù)。數(shù)據(jù)處理后的結(jié)果就顯示到1602液晶上。

2.1系統(tǒng)硬件電路圖

2.1.1 單片機(jī)STC89C52

2.1.2單片機(jī)與LCD通信連接

2.1.3 其他電路模塊及總電路

  • 系統(tǒng)軟件部分

軟件設(shè)計(jì)的部分采用分層模塊化設(shè)計(jì),主要有鍵盤掃描、按鍵處理程序、數(shù)碼管顯示程序、繼電器控制程序、溫度信號(hào)處理程序、超溫報(bào)警程序。另外以 AT89C52 單片機(jī)為控制核心。利用PID 控制算法提高了水溫的控制精度使用PID 控制算法實(shí)施自動(dòng)控制系統(tǒng)具有控制參數(shù)精度高、反映速度快和穩(wěn)定性好的特點(diǎn)。

3.1系統(tǒng)的主流程圖如下


4.溫度控制系統(tǒng)PID調(diào)節(jié)

4.1 PID控制傳遞函數(shù)

     通過(guò)熱電偶采集的被測(cè)溫度偏離所希望的給定值時(shí),PID控制可根據(jù)測(cè)量信號(hào)與給定值的偏差進(jìn)行比例(P)、積分(I)、微分(D)運(yùn)算,從而輸出某個(gè)適當(dāng)?shù)目刂菩盘?hào)給執(zhí)行機(jī)構(gòu),促使測(cè)量值恢復(fù)到給定值,達(dá)到自動(dòng)控制的效果。

4.2 PID參數(shù)調(diào)節(jié)方法及參數(shù)設(shè)定

  PID模塊的溫度控制精度主要受P、I、D這三個(gè)參數(shù)影響。其中P代表比例,I代表積分,D代表微分。
  比例運(yùn)算(P)
  比例控制是建立與設(shè)定值(SV)相關(guān)的一種運(yùn)算,并根據(jù)偏差在求得運(yùn)算值(控制輸出量)。如果當(dāng)前值(PV)小,運(yùn)算值為100%。如果當(dāng)前值在比例帶內(nèi),運(yùn)算值根據(jù)偏差比例求得并逐漸減小直到SV和PV匹配(即,直到偏差為0),此時(shí)運(yùn)算值回復(fù)到先前值(前饋運(yùn)算)。若出現(xiàn)靜差(殘余偏差),可用減小P方法減小殘余偏差。如果P太小,反而會(huì)出現(xiàn)振蕩。
  積分運(yùn)算(I)
  將積分與比例運(yùn)算相結(jié)合,隨著調(diào)節(jié)時(shí)間延續(xù)可減小靜差。積分強(qiáng)度用積分時(shí)間表示,積分時(shí)間相當(dāng)于積分運(yùn)算值到比例運(yùn)算值在階躍偏差響應(yīng)下達(dá)到的作用所需要的時(shí)間。積分時(shí)間越小,積分運(yùn)算的校正時(shí)間越強(qiáng)。但如果積分時(shí)間值太小,校正作用太強(qiáng)會(huì)出現(xiàn)振蕩。
  微分運(yùn)算(D)
  比例和積分運(yùn)算都校正控制結(jié)果,所以不可避免地會(huì)產(chǎn)生響應(yīng)延時(shí)現(xiàn)象。微分運(yùn)算可彌補(bǔ)這些缺陷。在一個(gè)突發(fā)的干擾響應(yīng)中,微分運(yùn)算提供了一個(gè)很大的運(yùn)算值,以恢復(fù)原始狀態(tài)。微分運(yùn)算采用一個(gè)正比于偏差變化率(微分系數(shù))的運(yùn)算值校正控制。微分運(yùn)算的強(qiáng)度由微分時(shí)間表示,微分時(shí)間相當(dāng)于微分運(yùn)算值達(dá)到比例運(yùn)算值在階躍偏差響應(yīng)下達(dá)到的作用所需的時(shí)間。微分時(shí)間值越大,微分運(yùn)算的校正強(qiáng)度越強(qiáng)。


5.實(shí)驗(yàn)與調(diào)試

              用繼電器模塊來(lái)控制200W“熱得快”來(lái)對(duì)1升水進(jìn)行加熱,用鍵盤設(shè)定需要加熱溫度值,觀察1602所顯示的穩(wěn)定水溫和環(huán)境溫度降低時(shí)溫度控制的靜態(tài)誤差。多次調(diào)試并合設(shè)定PID參數(shù)來(lái)完善系統(tǒng)。
              實(shí)物圖:

6.總論

首先,通過(guò)本次應(yīng)用系統(tǒng)設(shè)計(jì),在很大程度上提高了我們的獨(dú)立思考能力和專業(yè)知識(shí)相信在接下來(lái)的日子我們能在已有的基礎(chǔ)上做得更好。我們所設(shè)計(jì)的該系統(tǒng)主要根據(jù)目前省能源的發(fā)展趨勢(shì)和國(guó)內(nèi)實(shí)際的應(yīng)用特點(diǎn)和要求,采用了自動(dòng)化的結(jié)構(gòu)形式,實(shí)現(xiàn)對(duì)水溫的自動(dòng)檢測(cè)和控制。該系統(tǒng)的主要特點(diǎn)是:

1)適用性強(qiáng),用戶只需對(duì)界面參數(shù)進(jìn)行設(shè)置并啟動(dòng)系統(tǒng)正常運(yùn)行便可滿足不同用戶水溫的要求,實(shí)現(xiàn)對(duì)水溫的實(shí)時(shí)監(jiān)控。避免了電力力資源的浪費(fèi),節(jié)省了能源。

2)將單片機(jī)以及溫度傳感器引入對(duì)水溫的分析和處理中,單片機(jī)控制決策無(wú)需建立被控對(duì)象的數(shù)學(xué)模型,系統(tǒng)的適應(yīng)性強(qiáng),適合對(duì)非線性、時(shí)變、滯后系統(tǒng)的控制對(duì)水溫控制系統(tǒng)進(jìn)行控制。 3)系統(tǒng)成本低廉,操作非常簡(jiǎn)單,可擴(kuò)展性強(qiáng),只要稍加改變,即可增加其他使用功能。

通過(guò)對(duì)本設(shè)計(jì)的思考,更加加深了我們對(duì)單片機(jī)的認(rèn)識(shí),熟練了對(duì)單片機(jī)的控制,更對(duì)當(dāng)前的溫度傳感器有了更深刻的認(rèn)識(shí)與了解,但是由于此系統(tǒng)依賴溫度傳感器,因而對(duì)溫度傳感器的穩(wěn)定性,線性等諸多方面有著嚴(yán)格的要求,但是傳感器的性能越好,相對(duì)而言其價(jià)格也就越高,因而在此設(shè)計(jì)中,溫度傳感器覺的還是存在遺憾,由于溫度計(jì)的使用溫度有限所以水溫不能達(dá)到90℃以上。最后由于時(shí)間緊迫,本設(shè)計(jì)還有諸多地方需要改進(jìn),我們會(huì)在接下來(lái)的時(shí)間里繼續(xù)完善該設(shè)計(jì),以期做的更好。

附錄:

部分程序:

//main.c:
  1. #include<reg51.h>
  2. #include"lcd.h"
  3. #include"temp.h"
  4. #include"pid.h"

  5. sbit c1=P2^6;
  6. sbit c2=P2^7;
  7. sbit beep=P1^3;

  8. sbit K3=P3^2;
  9. sbit K4=P3^3;

  10. void IntConfiguration();
  11. void Delay(unsigned int n);
  12. unsigned char KeyValue=0;

  13. extern float set_temper;


  14. /*******************************************************************************
  15. * 函數(shù)名         : main
  16. * 函數(shù)功能                               : 主函數(shù)
  17. * 輸入           : 無(wú)
  18. * 輸出                       : 無(wú)
  19. *******************************************************************************/

  20. void main()
  21. {
  22.               extern struct PID spid; // PID Control Structure
  23.             
  24.               LcdInit();
  25.               IntConfiguration();
  26.             
  27.               PIDInit ( &spid );
  28.               spid.Proportion = 10; // Set PID Coefficients
  29.               spid.Integral = 8;
  30.               spid.Derivative =6;
  31.               spid.SetPoint = 100; // Set PID Setpoint
  32.             
  33.               beep=1;
  34.             
  35.               TMOD=0x21;
  36.               TH0=0x2f;
  37.               TL0=0x40;
  38.               //PCON=0X80;                                          //波特率加倍
  39.               //TH1=0XF3;                                                        //計(jì)數(shù)器初始值設(shè)置,注意波特率是4800的
  40.               //TL1=0XF3;
  41.               EA=1;
  42.               ET0=1;
  43.               //ES=1;
  44.               TR0=1;
  45.               TR1=1;

  46.               c1=0;
  47.               c2=0;
  48.             
  49.               P1=0XFF;
  50.             
  51.               while(1)
  52.               {
  53.                             LcdDisplay(Ds18b20ReadTemp());
  54.                             LcdDisplay2(set_temper);
  55. //                            LcdDisplay3(realtmp);
  56. /*                            if((set_temper-realtmp)<1&&(realtmper-set_temp)<1)
  57.                             {
  58.                                           beep=0;
  59.                             }
  60.                             else
  61.                                           beep=1;              */
  62.                             compare_temper();
  63. //                            SBUF=Ds18b20ReadTemp();
  64. //                            Delay1ms(1);//1s鐘刷一次
  65.               }
  66. }


  67. void IntConfiguration()
  68. {
  69.               //設(shè)置INT0
  70.               IT0=1;//跳變沿出發(fā)方式(下降沿)
  71.               EX0=1;//打開INT0的中斷允許。
  72.               //設(shè)置INT1
  73.               IT1=1;
  74.               EX1=1;
  75.             
  76.               EA=1;//打開總中斷            
  77. }
  78. /*******************************************************************************
  79. * 函數(shù)名         : Delay(unsigned int n)
  80. * 函數(shù)功能                               : 延時(shí)
  81. * 輸入           : n
  82. * 輸出                       : 無(wú)
  83. *******************************************************************************/

  84. void Delay(unsigned int n)   //延時(shí)50us誤差 0us
  85. {
  86.     unsigned char a,b;
  87.                             for(;n>0;n--)
  88.                             {
  89.                   for(b=1;b>0;b--)
  90.         for(a=22;a>0;a--);
  91.                             }
  92. }
  93. /*******************************************************************************
  94. * 函數(shù)名         : Int0()              interrupt 0
  95. * 函數(shù)功能                               : 外部中斷0的中斷函數(shù)
  96. * 輸入           : 無(wú)
  97. * 輸出                       : 無(wú)
  98. *******************************************************************************/

  99. void Int0()              interrupt 0                            //外部中斷0的中斷函數(shù)
  100. {
  101.               Delay(1);              //延時(shí)消抖
  102.               if(K3==0)
  103.               {
  104.                             while(K3==0);
  105.                             set_temper++;
  106.               }
  107.               if(set_temper>60.00)
  108.                             set_temper=60.00;
  109. }
  110. /*******************************************************************************
  111. * 函數(shù)名         : Int1() interrupt 2
  112. * 函數(shù)功能                               : 外部中斷1的中斷函數(shù)
  113. * 輸入           : 無(wú)
  114. * 輸出                       : 無(wú)
  115. *******************************************************************************/

  116. void Int1() interrupt 2                            //外部中斷1的中斷函數(shù)
  117. {
  118.               Delay(1);                            //延時(shí)消抖
  119.               if(K4==0)
  120.               {
  121.                             while(K4==0);
  122.                             set_temper--;
  123.               }
  124.               if(set_temper<40.00)
  125.                             set_temper=40.00;            
  126. }



  127. //pid.c
  128. #include"pid.h"
  129. #include"temp.h"

  130. struct PID spid; // PID Control Structure

  131. unsigned int rout; // PID Response (Output)
  132. unsigned int rin; // PID Feedback (Input)



  133. int i=0,j=0,flag2=0,tem=0;

  134. sbit output=P1^6;


  135. unsigned char flag,flag_1=0;
  136. unsigned char high_time,low_time,count=0;//占空比調(diào)節(jié)參數(shù)
  137. float set_temper=40;



  138. void PIDInit (struct PID *pp)
  139. {
  140.               high_time=50;
  141.               low_time=50;
  142.               memset ( pp,0,sizeof(struct PID));
  143.             
  144. }
  145. /*====================================================================================================
  146. PID計(jì)算部分
  147. =====================================================================================================*/
  148. unsigned int PIDCalc( struct PID *pp, unsigned int NextPoint )
  149. {
  150. unsigned int dError,Error;
  151. Error = pp->SetPoint - NextPoint; // 偏差
  152. pp->SumError += Error; // 積分
  153. dError = pp->LastError - pp->PrevError; // 當(dāng)前微分
  154. pp->PrevError = pp->LastError;
  155. pp->LastError = Error;
  156. return (pp->Proportion * Error//比例
  157. + pp->Integral * pp->SumError  //積分項(xiàng)
  158. + pp->Derivative * dError); //   微分項(xiàng)
  159. }
  160. /***********************************************************
  161. 溫度比較處理子程序
  162. ***********************************************************/
  163. void compare_temper()
  164. {
  165. unsigned char i;
  166. extern float realtmp;
  167. extern unsigned int s;

  168. if(set_temper>realtmp)
  169. {
  170. if(set_temper-realtmp>1)
  171. {
  172. high_time=100;
  173. low_time=0;
  174. //P1=0XFF;
  175. //mod1=0;
  176. }
  177. else
  178. {
  179. //P1=0XFF;
  180. //mod2=0;
  181. for(i=0;i<10;i++)
  182. { Ds18b20ReadTemp();
  183. rin = s; // Read Input
  184. rout = PIDCalc ( &spid,rin ); // Perform PID Interation
  185. }

  186. if (high_time<=100)
  187. high_time=(unsigned char)(rout/800);
  188. else
  189. high_time=100;
  190. low_time= (100-high_time);
  191. }
  192. }
  193. else if(set_temper<=realtmp)
  194. {
  195. if(realtmp-set_temper>0)
  196. {
  197. //P1=0XFF;
  198. //mod3=0;
  199. high_time=0;
  200. low_time=100;
  201. //mod2=0;
  202. }
  203. else
  204. {
  205. //P1=0XFF;
  206. //mod4=0;
  207. for(i=0;i<10;i++)
  208. { Ds18b20ReadTemp();
  209. rin = s; // Read Input
  210. rout = PIDCalc ( &spid,rin ); // Perform PID Interation
  211. }
  212. if (high_time<100)
  213. high_time=(unsigned char)(rout/10000);
  214. else
  215. high_time=0;
  216. low_time= (100-high_time);
  217. }
  218. }
  219. // else
  220. // {}
  221. }
  222. /*****************************************************
  223. T0中斷服務(wù)子程序,用于控制電平的翻轉(zhuǎn) ,40us*100=4ms周期
  224. ******************************************************/
  225. void serve_T0() interrupt 1 using 1
  226. {
  227. j++;
  228. if(++count<=(high_time))
  229. {
  230.               output=1;
  231.               i++;
  232. }
  233. else if(count<=100)
  234. {
  235. output=0;
  236. }
  237. else
  238. count=0;
  239. if(j==1000)
  240.               {j=0;flag2=1;tem=i;i=0; }
  241. TH0=0x2f;
  242. TL0=0xe0;
  243. }
  244. /*****************************************************
  245. 串行口中斷服務(wù)程序,用于上位機(jī)通訊
  246. ******************************************************/
  247. void serve_sio() interrupt 4
  248. {              
  249. /*              EA=0;
  250. //                            flag2=0;
  251.                             while(!TI);                                          //等待發(fā)送數(shù)據(jù)完成
  252.                             TI=0;
  253.                             EA=1;  */
  254. }



  255. //temp.c
  256. #include"temp.h"

  257. int temp=0;
  258. unsigned int s;
  259. //float set_temp=27.00;
  260. /*******************************************************************************
  261. * 函數(shù)名         : Delay1ms
  262. * 函數(shù)功能                               : 延時(shí)函數(shù)
  263. * 輸入           : 無(wú)
  264. * 輸出                       : 無(wú)
  265. *******************************************************************************/

  266. void Delay1ms(unsigned int y)
  267. {
  268.               unsigned int x;
  269.               for(y;y>0;y--)
  270.                             for(x=110;x>0;x--);
  271. }
  272. /*******************************************************************************
  273. * 函數(shù)名         : Ds18b20Init
  274. * 函數(shù)功能                               : 初始化
  275. * 輸入           : 無(wú)
  276. * 輸出                       : 初始化成功返回1,失敗返回0
  277. *******************************************************************************/

  278. unsigned char Ds18b20Init()
  279. {
  280.               unsigned int i;
  281.               DSPORT=0;                                          //將總線拉低480us~960us
  282.               i=70;            
  283.               while(i--);//延時(shí)642us
  284.               DSPORT=1;                                          //然后拉高總線,如果DS18B20做出反應(yīng)會(huì)將在15us~60us后總線拉低
  285.               i=0;
  286.               while(DSPORT)              //等待DS18B20拉低總線
  287.               {
  288.                             i++;
  289.                             if(i>5000)//等待>5MS
  290.                                           return 0;//初始化失敗            
  291.               }
  292.               return 1;//初始化成功
  293. }

  294. /*******************************************************************************
  295. * 函數(shù)名         : Ds18b20WriteByte
  296. * 函數(shù)功能                               : 向18B20寫入一個(gè)字節(jié)
  297. * 輸入           : com
  298. * 輸出                       : 無(wú)
  299. *******************************************************************************/

  300. void Ds18b20WriteByte(unsigned char dat)
  301. {
  302.               unsigned int i,j;
  303.               for(j=0;j<8;j++)
  304.               {
  305.                             DSPORT=0;                                          //每寫入一位數(shù)據(jù)之前先把總線拉低1us
  306.                             i++;
  307.                             DSPORT=dat&0x01; //然后寫入一個(gè)數(shù)據(jù),從最低位開始
  308.                             i=6;
  309.                             while(i--); //延時(shí)68us,持續(xù)時(shí)間最少60us
  310.                             DSPORT=1;              //然后釋放總線,至少1us給總線恢復(fù)時(shí)間才能接著寫入第二個(gè)數(shù)值
  311.                             dat>>=1;
  312.               }
  313. }
  314. /*******************************************************************************
  315. * 函數(shù)名         : Ds18b20ReadByte
  316. * 函數(shù)功能                               : 讀取一個(gè)字節(jié)
  317. * 輸入           : com
  318. * 輸出                       : 無(wú)
  319. *******************************************************************************/


  320. unsigned char Ds18b20ReadByte()
  321. {
  322.               unsigned char byte,bi;
  323.               unsigned int i,j;            
  324.               for(j=8;j>0;j--)
  325.               {
  326.                             DSPORT=0;//先將總線拉低1us
  327.                             i++;
  328.                             DSPORT=1;//然后釋放總線
  329.                             i++;
  330.                             i++;//延時(shí)6us等待數(shù)據(jù)穩(wěn)定
  331.                             bi=DSPORT;              //讀取數(shù)據(jù),從最低位開始讀取
  332.                             /*將byte左移一位,然后與上右移7位后的bi,注意移動(dòng)之后移掉那位補(bǔ)0。*/
  333.                             byte=(byte>>1)|(bi<<7);                                                                                    
  334.                             i=4;                            //讀取完之后等待48us再接著讀取下一個(gè)數(shù)
  335.                             while(i--);
  336.               }                                                      
  337.               return byte;
  338. }
  339. /*******************************************************************************
  340. * 函數(shù)名         : Ds18b20ChangTemp
  341. * 函數(shù)功能                               : 讓18b20開始轉(zhuǎn)換溫度
  342. * 輸入           : com
  343. * 輸出                       : 無(wú)
  344. *******************************************************************************/

  345. void  Ds18b20ChangTemp()
  346. {
  347.               Ds18b20Init();
  348.               Delay1ms(1);
  349.               Ds18b20WriteByte(0xcc);                            //跳過(guò)ROM操作命令                           
  350.               Ds18b20WriteByte(0x44);                //溫度轉(zhuǎn)換命令
  351.               Delay1ms(100);
  352. }
  353. /*******************************************************************************
  354. * 函數(shù)名         : Ds18b20ReadTempCom
  355. * 函數(shù)功能                               : 發(fā)送讀取溫度命令
  356. * 輸入           : com
  357. * 輸出                       : 無(wú)
  358. *******************************************************************************/

  359. void  Ds18b20ReadTempCom()
  360. {            

  361.               Ds18b20Init();
  362.               Delay1ms(1);
  363.               Ds18b20WriteByte(0xcc);              //跳過(guò)ROM操作命令
  364.               Ds18b20WriteByte(0xbe);              //發(fā)送讀取溫度命令
  365. }
  366. /*******************************************************************************
  367. * 函數(shù)名         : Ds18b20ReadTemp
  368. * 函數(shù)功能                               : 讀取溫度
  369. * 輸入           : com
  370. * 輸出                       : 無(wú)
  371. *******************************************************************************/

  372. int Ds18b20ReadTemp()
  373. {
  374.               unsigned char tmh,tml;
  375.               Ds18b20ChangTemp();                                                        //先寫入轉(zhuǎn)換命令
  376.               Ds18b20ReadTempCom();                                          //然后等待轉(zhuǎn)換完后發(fā)送讀取溫度命令
  377.               tml=Ds18b20ReadByte();                            //讀取溫度值共16位,先讀低字節(jié)
  378.               tmh=Ds18b20ReadByte();                            //再讀高字節(jié)
  379.               temp=tmh;
  380.               temp<<=8;
  381.               temp|=tml;
  382.               s=(unsigned int)(tml&0x0f);
  383.               s=(s*100)/16;
  384.               return temp;
  385. }



  386. //LCD.c
  387. #include"lcd.h"
  388. /*******************************************************************************
  389. * 函數(shù)名         : Delay1us
  390. * 函數(shù)功能                               : 延時(shí)函數(shù),延時(shí)1us
  391. * 輸入           : a
  392. * 輸出                       : 無(wú)
  393. *******************************************************************************/
  394. float realtmp=0;

  395. void Delay1us(unsigned int a)
  396. {
  397.               unsigned int b,c;
  398.               for(c=a;c>0;c--)
  399.                             for(b=110;b>0;b--);
  400. }
  401. /*******************************************************************************
  402. * 函數(shù)名         : LcdWriteCom
  403. * 函數(shù)功能                               : 向LCD寫入一個(gè)字節(jié)的命令
  404. * 輸入           : com
  405. * 輸出                       : 無(wú)
  406. *******************************************************************************/

  407. void LcdWriteCom(unsigned char com)                //寫入命令
  408. {
  409.               RS=0;
  410.               RW=0;
  411.               GPIO_LCD=com;
  412.               Delay1us(10);
  413.               LCDE=1;
  414.               Delay1us(10);
  415.               LCDE=0;
  416. }
  417. /*******************************************************************************
  418. * 函數(shù)名         : LcdWriteData
  419. * 函數(shù)功能                               : 向LCD寫入一個(gè)字節(jié)的數(shù)據(jù)
  420. * 輸入           : dat
  421. * 輸出                       : 無(wú)
  422. *******************************************************************************/                              
  423.                               
  424. void LcdWriteData(unsigned char dat)                                          //寫入數(shù)據(jù)
  425. {
  426.               RS=1;
  427.               RW=0;
  428.               GPIO_LCD=dat;
  429.               Delay1us(10);
  430.               LCDE=1;
  431.               Delay1us(10);
  432.               LCDE=0;
  433. }
  434. /*******************************************************************************
  435. * 函數(shù)名         : LcdInit()
  436. * 函數(shù)功能                               : 初始化LCD屏
  437. * 輸入           : 無(wú)
  438. * 輸出                       : 無(wú)
  439. *******************************************************************************/                              

  440. void LcdInit()                                                                                      //LCD初始化子程序
  441. {
  442.               LcdWriteCom(0x38);  //開顯示
  443.               LcdWriteCom(0x0c);  //開顯示不顯示光標(biāo)
  444.               LcdWriteCom(0x06);  //寫一個(gè)指針加1
  445.               LcdWriteCom(0x01);  //清屏
  446.               LcdWriteCom(0x80);  //設(shè)置數(shù)據(jù)指針起點(diǎn)
  447. }

  448. void LcdDisplay(int temp)               //lcd顯示
  449. {

  450.   unsigned char datas[] = {0, 0, 0, 0, 0}; //定義數(shù)組
  451.               float tp;
  452.                                           //初始化LCD
  453.               if(temp< 0)                                                        //當(dāng)溫度值為負(fù)數(shù)
  454.   {
  455.                 LcdWriteCom(0x80);                            //寫地址 80表示初始地址
  456.     LcdWriteData('-');                              //顯示負(fù)
  457.                             //因?yàn)樽x取的溫度是實(shí)際溫度的補(bǔ)碼,所以減1,再取反求出原碼
  458.                             temp=temp-1;
  459.                             temp=~temp;
  460.                             tp=temp;
  461.                             temp=tp*0.0625*100+0.5;            
  462.                             //留兩個(gè)小數(shù)點(diǎn)就*100,+0.5是四舍五入,因?yàn)镃語(yǔ)言浮點(diǎn)數(shù)轉(zhuǎn)換為整型的時(shí)候把小數(shù)點(diǎn)
  463.                             //后面的數(shù)自動(dòng)去掉,不管是否大于0.5,而+0.5之后大于0.5的就是進(jìn)1了,小于0.5的就
  464.                             //算加上0.5,還是在小數(shù)點(diǎn)后面。

  465.   }
  466.   else
  467.   {                                         
  468.                 LcdWriteCom(0x80);                            //寫地址 80表示初始地址
  469.     LcdWriteData('+');                             //顯示正
  470.                             tp=temp;//因?yàn)閿?shù)據(jù)處理有小數(shù)點(diǎn)所以將溫度賦給一個(gè)浮點(diǎn)型變量
  471.                             //如果溫度是正的那么,那么正數(shù)的原碼就是補(bǔ)碼它本身
  472.                             temp=tp*0.0625*100+0.5;            
  473.                             //留兩個(gè)小數(shù)點(diǎn)就*100,+0.5是四舍五入,因?yàn)镃語(yǔ)言浮點(diǎn)數(shù)轉(zhuǎn)換為整型的時(shí)候把小數(shù)點(diǎn)
  474.                             //后面的數(shù)自動(dòng)去掉,不管是否大于0.5,而+0.5之后大于0.5的就是進(jìn)1了,小于0.5的就
  475.                             //算加上0.5,還是在小數(shù)點(diǎn)后面。
  476.                             realtmp=(float)temp/100;
  477.   }
  478.               datas[0] = temp / 10000;
  479.   datas[1] = temp % 10000 / 1000;
  480.   datas[2] = temp % 1000 / 100;
  481.   datas[3] = temp % 100 / 10;
  482.   datas[4] = temp % 10;

  483.               LcdWriteCom(0x82);                              //寫地址 80表示初始地址
  484.   LcdWriteData('0'+datas[0]); //百位


  485.   LcdWriteCom(0x83);                            //寫地址 80表示初始地址
  486.   LcdWriteData('0'+datas[1]); //十位

  487.               LcdWriteCom(0x84);                            //寫地址 80表示初始地址
  488.   LcdWriteData('0'+datas[2]); //個(gè)位

  489.               LcdWriteCom(0x85);                            //寫地址 80表示初始地址
  490.   LcdWriteData('.');                             //顯示 ‘.’

  491.               LcdWriteCom(0x86);                            //寫地址 80表示初始地址
  492.   LcdWriteData('0'+datas[3]); //顯示小數(shù)點(diǎn)

  493.               LcdWriteCom(0x87);                            //寫地址 80表示初始地址
  494.   LcdWriteData('0'+datas[4]); //顯示小數(shù)點(diǎn)

  495.               LcdWriteCom(0x88);                            //寫地址 80表示初始地址
  496.   LcdWriteData('C');  
  497. }

  498. void LcdDisplay2(float num)
  499. {
  500.               unsigned char datas[] = {0, 0, 0, 0, 0}; //定義數(shù)組
  501.               int temp;
  502. //              LcdInit();                                          //初始化LCD
  503.             
  504.                 LcdWriteCom(0xC0);                            //寫地址 80表示初始地址
  505.     LcdWriteData('+');                             //顯示正
  506.                             temp=num*100+0.5;            
  507.                             //留兩個(gè)小數(shù)點(diǎn)就*100,+0.5是四舍五入,因?yàn)镃語(yǔ)言浮點(diǎn)數(shù)轉(zhuǎn)換為整型的時(shí)候把小數(shù)點(diǎn)
  508.                             //后面的數(shù)自動(dòng)去掉,不管是否大于0.5,而+0.5之后大于0.5的就是進(jìn)1了,小于0.5的就
  509.                             //算加上0.5,還是在小數(shù)點(diǎn)后面。

  510.               datas[0] = temp / 10000;
  511.   datas[1] = temp % 10000 / 1000;
  512.   datas[2] = temp % 1000 / 100;
  513.   datas[3] = temp % 100 / 10;
  514.   datas[4] = temp % 10;

  515.               LcdWriteCom(0xC1);                              //寫地址 80表示初始地址
  516.   LcdWriteData('0'+datas[0]); //百位


  517.   LcdWriteCom(0xC2);                            //寫地址 80表示初始地址
  518.   LcdWriteData('0'+datas[1]); //十位

  519.               LcdWriteCom(0xC3);                            //寫地址 80表示初始地址
  520.   LcdWriteData('0'+datas[2]); //個(gè)位

  521.               LcdWriteCom(0xC4);                            //寫地址 80表示初始地址
  522.   LcdWriteData('.');                             //顯示 ‘.’

  523.               LcdWriteCom(0xC5);                            //寫地址 80表示初始地址
  524.   LcdWriteData('0'+datas[3]); //顯示小數(shù)點(diǎn)

  525.               LcdWriteCom(0xC6);                            //寫地址 80表示初始地址
  526.   LcdWriteData('0'+datas[4]); //顯示小數(shù)點(diǎn)

  527.               LcdWriteCom(0xC7);                            //寫地址 80表示初始地址
  528.   LcdWriteData('C');
  529. }

  530. void LcdDisplay3(float num)
  531. {
  532.               unsigned char datas[] = {0, 0, 0, 0, 0}; //定義數(shù)組
  533.               int temp;
  534. //              LcdInit();                                          //初始化LCD
  535.             
  536.                 LcdWriteCom(0xC8);                            //寫地址 80表示初始地址
  537.     LcdWriteData('+');                             //顯示正
  538.                             temp=num*100+0.5;            
  539.                             //留兩個(gè)小數(shù)點(diǎn)就*100,+0.5是四舍五入,因?yàn)镃語(yǔ)言浮點(diǎn)數(shù)轉(zhuǎn)換為整型的時(shí)候把小數(shù)點(diǎn)
  540.                             //后面的數(shù)自動(dòng)去掉,不管是否大于0.5,而+0.5之后大于0.5的就是進(jìn)1了,小于0.5的就
  541.                             //算加上0.5,還是在小數(shù)點(diǎn)后面。

  542.               datas[0] = temp / 10000;
  543.   datas[1] = temp % 10000 / 1000;
  544.   datas[2] = temp % 1000 / 100;
  545.   datas[3] = temp % 100 / 10;
  546.   datas[4] = temp % 10;

  547.               LcdWriteCom(0xC9);                              //寫地址 80表示初始地址
  548.   LcdWriteData('0'+datas[0]); //百位


  549.   LcdWriteCom(0xCA);                            //寫地址 80表示初始地址
  550.   LcdWriteData('0'+datas[1]); //十位

  551.               LcdWriteCom(0xCB);                            //寫地址 80表示初始地址
  552.   LcdWriteData('0'+datas[2]); //個(gè)位

  553.               LcdWriteCom(0xCC);                            //寫地址 80表示初始地址
  554.   LcdWriteData('.');                             //顯示 ‘.’

  555.               LcdWriteCom(0xCD);                            //寫地址 80表示初始地址
  556.   LcdWriteData('0'+datas[3]); //顯示小數(shù)點(diǎn)

  557.               LcdWriteCom(0xCE);                            //寫地址 80表示初始地址
  558.   LcdWriteData('0'+datas[4]); //顯示小數(shù)點(diǎn)

  559.               LcdWriteCom(0xCF);                            //寫地址 80表示初始地址
  560.   LcdWriteData('C');
  561. }
復(fù)制代碼

完整的Word格式文檔51黑下載地址:
基于51單片機(jī)的PID調(diào)溫(熱得快).doc (4.46 MB, 下載次數(shù): 279)



評(píng)分

參與人數(shù) 1黑幣 +50 收起 理由
admin + 50 共享資料的黑幣獎(jiǎng)勵(lì)!

查看全部評(píng)分

回復(fù)

使用道具 舉報(bào)

ID:403447 發(fā)表于 2019-10-18 19:05 | 顯示全部樓層
正有學(xué)習(xí)PID算法,下了,謝謝樓主分享。
回復(fù)

使用道具 舉報(bào)

ID:782863 發(fā)表于 2020-6-25 16:07 | 顯示全部樓層
謝謝樓主,正在做設(shè)計(jì),很有幫助
回復(fù)

使用道具 舉報(bào)

ID:917064 發(fā)表于 2021-5-7 16:18 | 顯示全部樓層
謝謝樓主,這個(gè)對(duì)我?guī)椭艽蟆?/td>
回復(fù)

使用道具 舉報(bào)

ID:462629 發(fā)表于 2021-12-28 10:05 | 顯示全部樓層
能提供一下電路原理圖,源碼嗎
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表