久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 4340|回復: 5
打印 上一主題 下一主題
收起左側

stm32單片機PID溫控系統源程序 18b20,硬件驗證通過

  [復制鏈接]
跳轉到指定樓層
樓主
引腳說明:
//定義MCU與LCD的接口
/*******************************
*D4---->PB8
*D5---->PB5
*D6---->PB6
*D7---->PB7
*RS---->PA8
*RW---->PA11
*EN---->PA12

LCD1602
VCC---->5V
GND---->GND
VO----->接對比度調節滑動變阻器- -->GND
LED+ -->5v
LED- -->GND

PWM輸出(12703半導體制冷片)
4A電機pwm驅動芯片
*制冷IN1---->PB10
*加熱IN2---->PB11

18B20數字溫度傳感器
18B20OUT---->PB9
按鍵

KEY1---->PB12
KEY1---->PB13
KEY1---->PB14

AT24C16
1(A0)---->GND
2(A1)---->GND
3(A2)---->GND
4(GND)---->GND
4(SDA)---->PC13---->4.7K(R)---->VCC
6(SCL)---->PC14---->4.7K(R)---->VCC
7(WP)---->GND---->104(C)---->VCC
8(VCC)---->VCC

功能說明:通過18B20檢測溫度,通過pwm輸出來調節控溫,未進行精準pid調試,恒溫時間大約在5min左右。
2021.8.25 :基本程序編寫完成。
2021.8.26:修改程序,既可以制熱也可以制冷。
2021.8.27:加入24c16用于存儲設定溫度和模式,優化lcd顯示。

制作出來的實物圖如下:


單片機源程序如下:
  1. #include "incrementpid.h"
  2. #include "usart.h"
  3. //增量式PID
  4. PID pid;
  5. u8 T_mode=1;//制冷(1)制熱(0)模式切換
  6. void PIDParament_Init()  //
  7. {
  8.     pid.choose_model = MODEL_PID;//調節模式
  9.     pid.T=500;                //采樣周期,定時器使用1ms,則最小執行PID的周期為500ms
  10.     pid.set =25;            //用戶設定值,攝氏度
  11.     pid.Kp=0.6;                //比例系數
  12.     pid.Ti=100.0;                //微分系數常數ms
  13.     pid.Td=20.0;                //積分時間常數ms
  14.     pid.OUT0=0;                //一個維持的輸出
  15.     pid.pwmcycle = 1999;    //PWM的周期
  16. }

  17.    
  18. void pid_calc()  //增量式PID調節函數
  19. {
  20.   float dk1;float dk2;
  21.   float t1,t2,t3;
  22.    
  23.     if(pid.Tdata < (pid.T))  //最小計算周期未到
  24.      {
  25.             return ;
  26.      }
  27.     pid.Tdata = 0;
  28.    
  29.     pid.En=pid.set-pid.curr;  //本次誤差
  30.     dk1=pid.En-pid.En_1;   //本次偏差與上次偏差之差
  31.     dk2=pid.En-2*pid.En_1+pid.En_2;
  32.    
  33.    t1=pid.Kp*dk1;                            //比例
  34.    
  35.     t2=(pid.Kp*pid.T)/pid.Ti;      //積分
  36.     t2=t2*pid.En;
  37.    
  38.     t3=(pid.Kp*pid.Td)/pid.T;        //微分
  39.     t3=t3*dk2;
  40.    
  41.     switch(pid.choose_model)
  42.      {
  43.          case MODEL_P:     pid.Dout= t1;           printf("使用P運算\r\n") ;
  44.              break;
  45.          
  46.          case MODEL_PI:  pid.Dout= t1+t2;          printf("使用PI運算\r\n") ;
  47.              break;
  48.                  
  49.          case MODEL_PID: pid.Dout= t1+t2+t3;       printf("使用PID運算\r\n") ;
  50.              break;
  51.      }
  52.          
  53.    
  54.      
  55.   
  56. if(T_mode==0)//制熱PID調節
  57. {        
  58.         pid.currpwm+=pid.Dout;  //本次應該輸出的PWM
  59.     printf("PID算得的OUT:\t%d\r\n",(int)pid.currpwm) ;
  60.          
  61.         /*判斷算出的數是否符合控制要求*/
  62.     if(pid.currpwm>pid.pwmcycle)            //算出的值取值,肯定是在0-pid.pwmcycle之間,不然的話PWM怎么輸出
  63.     {
  64.       pid.currpwm=pid.pwmcycle;
  65.     }
  66.     if(pid.currpwm<0)
  67.     {
  68.      pid.currpwm=0;
  69.     }
  70.         TIM_SetCompare4(TIM2,pid.currpwm);        //pwm輸出函數
  71.         TIM_SetCompare3(TIM2,0);        //pwm輸出函數
  72.     printf("實際輸出使用的OUT:\t%d\r\n",(int)pid.currpwm) ;
  73. }
  74. else if(T_mode==1)//制冷PID調節
  75. {          
  76.           pid.currpwm+=pid.Dout;  //本次應該輸出的PWM
  77.          
  78.       printf("PID算得的OUT:\t%d\r\n",(int)pid.currpwm) ;
  79.          
  80.          
  81.     if(-pid.currpwm>pid.pwmcycle)//算出的值取值,肯定是在0-pid.pwmcycle之間,不然的話PWM怎么輸出
  82.     {
  83.         pid.currpwm=-pid.pwmcycle; //pwm最大寬度       
  84.      
  85.     }
  86.     if(pid.currpwm>0)//當前的pwm寬度
  87.     {
  88.         pid.currpwm=0;       
  89.      
  90.     }
  91.         TIM_SetCompare3(TIM2,-pid.currpwm);        //pwm輸出函數
  92.     TIM_SetCompare4(TIM2,0);
  93.     printf("實際輸出使用的OUT:\t%d\r\n",(int)pid.currpwm) ;
  94. }
  95.        
  96.     pid.En_2=pid.En_1;
  97.     pid.En_1=pid.En;
  98. }
復制代碼

  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include <math.h>

  5. #include "sys.h"
  6. #include "delay.h"
  7. #include "usart.h"
  8. #include "ds18b20.h"
  9. #include "LCD1602.h"
  10. #include "pwmout.h"
  11. #include "key.h"
  12. #include "timer3.h"
  13. #include "incrementpid.h"
  14. #include "24cxx.h"

  15. //float TM1;//存儲溫度值
  16. //s8 set_temp=30;//設定溫度

  17. uint8_t ucDs18b20Id[8];//存儲18b20數據
  18. u8 i;//循環讀取18b20ID次數
  19. u8 a,b,c=0;//lcd循環顯示
  20. u16 pwmval23=0,pwmval24=0;//占空比調節
  21. u8 cle_pwm1,cle_pwm2;//清除pwm顯示
  22. int main(void)
  23. {               
  24. delay_init();                     //延時函數初始化          
  25. NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //設置NVIC中斷分組2:2位搶占優先級,2位響應優先級
  26. uart_init(9600);         //串口初始化為9600
  27. LCD_init();//lcd1206初始化       
  28. PWM_Out_Init();        // 定時器輸出pwm初始化       
  29. KEY_Input_Init();//GPIO IN初始化       
  30. TIM3_Init(999,71); ////TIM2 1ms中斷       
  31. PIDParament_Init() ;//增量式PID初始化       
  32. AT24CXX_Init();//初始化IIC接口       
  33.        
  34.        
  35. TIM_SetCompare3(TIM2,0);        //pwm輸出函數
  36. TIM_SetCompare4(TIM2,0);        //pwm輸出函數               
  37.        
  38. LCD_set_xy(1,2);//寫位置       
  39. LCD_write_data('T');        //寫數據
  40. LCD_write_data('E');        //寫數據
  41. LCD_write_data('M');        //寫數據
  42. LCD_write_data('P');        //寫數據
  43. LCD_write_data(':');        //寫數據
  44. LCD_set_xy(1,1);//寫位置       
  45. LCD_write_data('P');        //寫數據
  46. LCD_write_data('W');        //寫數據
  47. LCD_write_data('M');        //寫數據
  48. LCD_write_data(':');        //寫數據               

  49. while( DS18B20_Init() )        //DS18B20初始化
  50. {       
  51. printf("no ds18b20 exit\r\n");//初始化DS18B20,不初始化就等待這里?
  52. delay_ms(500);       
  53. break;               
  54. }

  55. DS18B20_ReadId(ucDs18b20Id); //讀取18b20的ID
  56. //LCD_write_cmd(0x0f);//寫命令       

  57.          for(i = 0;i < 8;i ++)  
  58.     {  
  59.      printf("DS18B20[%d] ID:%d \r\n ",i,ucDs18b20Id[i]); //讀取18b20的ID      
  60.     }  
  61.        
  62. while(AT24CXX_Check())//檢測不到24c02
  63.         {
  64.                 printf("檢測不到24cXX\r\n") ;
  65.                 delay_ms(1000);
  66.                 break;       
  67.         }
  68.        
  69. pid.set=AT24CXX_ReadOneByte_minus(0);//設定溫度數據讀取,在AT24CXX指定地址讀出一個數據
  70. T_mode=AT24CXX_ReadOneByte(4);//模式數據讀取,在AT24CXX指定地址讀出一個數據
  71.        
  72.         while(1)
  73.                 {
  74. /************************溫度設定*****************************************/
  75.                        
  76.                 if( KEY_Scan(0,KEY1)){pid.set++;AT24CXX_WriteOneByte_minus(0,pid.set);/*在AT24CXX指定地址寫入一個數據*/}
  77.                 if( pid.set>125)pid.set=125;       
  78.                        
  79.                 if( KEY_Scan(0,KEY2)){T_mode=!T_mode;AT24CXX_WriteOneByte(4,T_mode);/*在AT24CXX指定地址寫入一個數據*/}//制冷制熱模式切換
  80.                        
  81.                 if( KEY_Scan(0,KEY3)){pid.set--;AT24CXX_WriteOneByte_minus(0,pid.set);/*在AT24CXX指定地址寫入一個數據*/}
  82.                 if( pid.set<-55)pid.set=-55;       
  83. /********************pwm輸出**********************************************/       
  84.                        
  85.         pid_calc() ;//增量式PID調節函數
  86.                        
  87. /*********************制冷制熱模式顯示****************************/               
  88.                 LCD_set_xy(16,1);//寫位置
  89.                 if(T_mode==1)//制冷           
  90.                         {
  91.                         LCD_write_data('L');        //寫數據       
  92.                         cle_pwm1=1;
  93.                                
  94.                         }                       
  95.                 else//制熱
  96.                    {
  97.                         LCD_write_data('H');        //寫數據
  98.                         cle_pwm2=1;                  
  99.                    }       
  100.                   
  101.                  if(cle_pwm1&&cle_pwm2)
  102.                  {
  103.                         LCD_set_xy(5,1);//寫位置
  104.                         LCD_write_data(' ');        //寫數據       
  105.                         LCD_write_data('0');        //寫數據       
  106.                         LCD_write_data('0');        //寫數據       
  107.                         LCD_write_data('0');        //寫數據       
  108.                         LCD_write_data('0');        //寫數據
  109.                         cle_pwm1=0;       
  110.                         cle_pwm2=0;                         
  111.                  }
  112. /*********************pwm輸出顯示在lcd1602上****************************/
  113.                
  114.                 //if(pid.currpwm<0)//制冷
  115.             if(T_mode==1)//制冷
  116.                 {       
  117.                 pwmval23=-pid.currpwm;
  118.                 memset(Data_Partition,0x30,sizeof(Data_Partition));//初始化數組               
  119.                 conversion(pwmval23);//將數據拆分方便寫入lcd1602               
  120.                 LCD_set_xy(5,1);//寫位置
  121.                 LCD_write_data('-');        //寫數據       
  122.                 LCD_write_data(Data_Partition[3]);        //寫數據       
  123.                 LCD_write_data(Data_Partition[2]);        //寫數據       
  124.                 LCD_write_data(Data_Partition[1]);        //寫數據       
  125.                 LCD_write_data(Data_Partition[0]);        //寫數據
  126.                                
  127.                 }
  128.                
  129.                 //else if(pid.currpwm>0)//制熱
  130.                 else if(T_mode==0)//制冷
  131.                 {                       
  132.                 pwmval24=pid.currpwm;       
  133.                 memset(Data_Partition,0x30,sizeof(Data_Partition));//初始化數組0x30 LCD的字符0       
  134.                 conversion(pwmval24);//將數據拆分方便寫入lcd1602
  135.                 LCD_set_xy(5,1);//寫位置
  136.                 LCD_write_data('+');        //寫數據       
  137.                 LCD_write_data(Data_Partition[3]);        //寫數據       
  138.                 LCD_write_data(Data_Partition[2]);        //寫數據       
  139.                 LCD_write_data(Data_Partition[1]);        //寫數據       
  140.                 LCD_write_data(Data_Partition[0]);        //寫數據
  141.                
  142.                 }
  143.                                                        
  144. /*****************設定溫度顯示在lcd1602上********************************/       
  145.                        
  146.                         if(pid.set>=0)        //lcd1602顯示設定溫度                       
  147.                   {
  148.                    b=Data_Line(pid.set);//獲取顯示數據位數       
  149.                    conversion(pid.set);//將數據拆分方便寫入lcd1602          
  150.                           
  151.                    LCD_set_xy(13,2);//寫位置  
  152.                    LCD_write_data(' ');        //清除“-”        號                 
  153.                   
  154.                         LCD_set_xy(14,2);//寫位置                       
  155.                         for(a=0;a<b+1;a++)        //清空顯示數據
  156.                         {
  157.                         LCD_write_data(' ');        //寫數據       
  158.                         }
  159.                        
  160.                         LCD_set_xy(14,2);//寫位置                       
  161.                         for(a=0;a<b;a++)        //整數部分顯示,不限長度
  162.                         {
  163.                         LCD_write_data(Data_Partition[b-a-1]);        //寫數據                                
  164.                         }
  165.                   }
  166.                   
  167. /****************************************************************/                          
  168.                   else if(pid.set<0)        //lcd1602顯示設定溫度                       
  169.                   {
  170.                    b=Data_Line(-pid.set);//獲取顯示數據位數       
  171.                    conversion(-pid.set);//將數據拆分方便寫入lcd1602  
  172.                           
  173.            LCD_set_xy(13,2);//寫位置  
  174.                    LCD_write_data('-');        //顯示“-” 號   
  175.                          
  176.                         LCD_set_xy(14,2);//寫位置                       
  177.                         for(a=0;a<b+1;a++)        //清空顯示數據
  178.                     {
  179.                         LCD_write_data(' ');        //寫數據       
  180.             }  
  181.                        
  182.                         LCD_set_xy(14,2);//寫位置       
  183.                         for(a=0;a<b;a++)        //整數部分顯示,不限長度
  184.                     {
  185.                         LCD_write_data(Data_Partition[b-a-1]);        //寫數據                                
  186.             }
  187.                        
  188.                   }
  189.                   
  190. /**************************溫度顯示在lcd1602*****************************************/                  
  191.                  

  192.                  pid.curr=DS18B20_GetTemp_MatchRom ( ucDs18b20Id ); //讀取18b20溫度數據         
  193.                  if(pid.curr>=0)        //lcd1602顯示溫度                       
  194.                 {
  195.                
  196.                 b=Data_Line(pid.curr*100);//獲取顯示數據位數       
  197.                 conversion(pid.curr*100);//將數據拆分方便寫入lcd1602       

  198. //                        LCD_set_xy(6,2);//寫位置       
  199. //                        for(a=0;a<b+2;a++)        //清空顯示數據
  200. //                    {
  201. //                        LCD_write_data(' ');        //寫數據       
  202. //                        }
  203.                        
  204.                         LCD_set_xy(6,2);//寫位置       
  205.                         for(a=0;a<b-2;a++)        //整數部分顯示,不限長度
  206.                     {
  207.                         LCD_write_data(Data_Partition[b-a-1]);        //寫數據                
  208.             }
  209.                         if(pid.curr<1)       
  210.                         {
  211.                         LCD_write_data('0');        //寫數據                       
  212.                         }
  213.                         LCD_write_data('.');        //寫數據                       
  214.                        
  215.             for(a=2;a>0;a--)        //小數部分顯示
  216.                     {
  217.                         LCD_write_data(Data_Partition[a-1]);        //寫數據                
  218.             }       
  219.                 }
  220. /******************************************************************************/               
  221.                 else if(pid.curr<0)        //lcd1602顯示溫度
  222.                 {
  223. ……………………

  224. …………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼

代碼工程51hei附件下載:
PID控制-STM32F103C8T6 控溫.7z (210.66 KB, 下載次數: 217)

評分

參與人數 1黑幣 +80 收起 理由
admin + 80 共享資料的黑幣獎勵!

查看全部評分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏12 分享淘帖 頂1 踩
回復

使用道具 舉報

沙發
ID:144730 發表于 2021-8-28 11:16 | 只看該作者
按鈕作用:從左到右,溫度-,模式切換(制冷/制熱),溫度+
回復

使用道具 舉報

板凳
ID:144730 發表于 2021-8-28 11:18 | 只看該作者
圖片未完全顯示,詳細請點擊圖片
回復

使用道具 舉報

地板
ID:144730 發表于 2021-8-30 08:36 | 只看該作者
18b20輸出引腳接4.7k電阻后接vcc
回復

使用道具 舉報

5#
ID:339860 發表于 2023-5-31 15:10 | 只看該作者
剛好學到,下載看看
回復

使用道具 舉報

6#
ID:1096092 發表于 2023-10-16 12:10 | 只看該作者
2479408246 發表于 2021-8-30 08:36
18b20輸出引腳接4.7k電阻后接vcc

兄弟你還在嗎,想請教請教你
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 一本色道久久综合亚洲精品高清 | 国产色网站 | 天天av天天好逼 | 天天弄| 国产精品伦理一区 | 精品久久久久久久久久久久 | 国产一级片91 | 国产精品高清在线 | 国产乱码精品一区二区三区中文 | 久久不卡区 | 亚洲成人av在线播放 | 日本一区二区三区四区 | 国产精品久久久亚洲 | 蜜桃在线视频 | 亚洲综合第一页 | 国产美女在线精品免费 | 日本在线观看网址 | 亚洲看片 | 国产aaaaav久久久一区二区 | 日韩一区二区三区精品 | 国产综合精品一区二区三区 | 91精品久久久久久久久中文字幕 | 国产高清视频在线观看 | 911精品美国片911久久久 | 精品一区二区久久久久久久网站 | 99精品欧美一区二区三区综合在线 | 中文字幕一级 | 91精品久久久久久久久久 | 日日摸日日碰夜夜爽2015电影 | 久久午夜剧场 | 久久大陆 | 成人国产一区二区三区精品麻豆 | 亚洲成人精品一区二区 | 国产99久久精品一区二区永久免费 | 欧美一区在线视频 | 日本高清视频在线播放 | 精品一区二区三区四区 | 日韩欧美三级在线 | 亚洲一区国产精品 | 欧美性一区二区三区 | 成人av网站在线观看 |