找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4202|回复: 1
打印 上一主题 下一主题
收起左侧

STC单片机关于PID控制气压的算法,led数据码显示

[复制链接]
跳转到指定楼层
楼主
STC单片机做了一个关于PID控制气压的算法,led数据码显示


单片机源程序如下:

  1. #include "config.h"
  2. #include <math.h>
  3. #define ADC_POWER   0x80            
  4. #define ADC_FLAG    0x10            
  5. #define ADC_START   0x08           
  6. #define ADC_SPEEDLL 0x00         
  7. #define ADC_SPEEDL  0x20           
  8. #define ADC_SPEEDH  0x40         
  9. #define ADC_SPEEDHH 0x60

  10. unsigned char idata RsBuf[MAC_RX_BUF];
  11. unsigned char data guc_RsPoint=0;
  12. //unsigned char xdata Time0L1;
  13. //unsigned char xdata Time0H1;
  14. unsigned char xdata led_step=0;

  15. unsigned char xdata led_show1;
  16. unsigned char xdata led_show2;
  17. unsigned char xdata led_show3;
  18. unsigned char xdata led_show4;
  19. unsigned int xdata Time_Show=0;

  20. unsigned int xdata TimeMotor=0;
  21. unsigned int xdata PwmBitVat=0;
  22. //unsigned short xdata ADC_VAL[3];
  23. //unsigned char xdata ADC_ch=0;

  24. bit led_dian1;
  25. bit led_dian2;
  26. bit led_dian3;
  27. bit led_dian4;
  28. bit RsOver=0;

  29. typedef struct _pid_t
  30. {
  31.         float SetSpeed;//定义设定值
  32.         float ActualSpeed;//定义实际值
  33.         float err;//定义偏差值
  34.         float err_last;//定义上一个偏差值
  35.         float Kp,Ki,Kd;//定义比例、积分、微分系数
  36.         float voltage;//定义电压值(控制执行器的变量)
  37.         float integral;//定义积分值
  38.         float umax;
  39.         float umin;
  40. } pid_t;



  41. unsigned char code ledTab[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x27,0x7f,0x6f};


  42. void PID_init(pid_t *npid)
  43. {
  44.         npid->SetSpeed=0.0;
  45.         npid->ActualSpeed=0.0;
  46.         npid->err=0.0;
  47.         npid->err_last=0.0;
  48.         npid->voltage=0.0;
  49.         npid->integral=0.0;
  50.         npid->Kp=0.2;
  51.         npid->Ki=0.015;
  52.         npid->Kd=0.2;
  53.        
  54.         npid->umax=127;
  55.         npid->umin=-127;
  56. }

  57. float PID_realize(pid_t *npid ,float speed,float ActualSpeed)
  58. {
  59.         float index;
  60.         npid->SetSpeed=speed;
  61.         npid->ActualSpeed=ActualSpeed;
  62.         npid->err=npid->SetSpeed-npid->ActualSpeed;
  63.         if(npid->voltage>npid->umax)
  64.         {
  65.                 if(abs(npid->err)>200)//变积分过程
  66.                 {
  67.                         index=0.0;
  68.                 }
  69.                 else if(abs(npid->err)<180)
  70.                 {
  71.                         index=1.0;
  72.                         if(npid->err<0)
  73.                         {
  74.                                 npid->integral+=npid->err;
  75.                         }
  76.                 }
  77.                 else
  78.                 {
  79.                         index=(200-abs(npid->err))/20;
  80.                         if(npid->err<0)
  81.                         {
  82.                                 npid->integral+=npid->err;
  83.                         }
  84.                 }
  85.         }
  86.         else if(npid->voltage<npid->umin)
  87.         {
  88.                 if(abs(npid->err)>200)//变积分过程
  89.                 {
  90.                         index=0.0;
  91.                 }
  92.                 else if(abs(npid->err)<180)
  93.                 {
  94.                         index=1.0;
  95.                         if(npid->err>0)
  96.                         {
  97.                                 npid->integral+=npid->err;
  98.                         }
  99.                 }
  100.                 else
  101.                 {
  102.                         index=(200-abs(npid->err))/20;
  103.                         if(npid->err>0)
  104.                         {
  105.                                 npid->integral+=npid->err;
  106.                         }
  107.                 }
  108.         }
  109.         else
  110.         {
  111.                 if(abs(npid->err)>200)//变积分过程
  112.                 {
  113.                         index=0.0;
  114.                 }
  115.                 else if(abs(npid->err)<180)
  116.                 {
  117.                         index=1.0;
  118.                         npid->integral+=npid->err;
  119.                 }
  120.                 else
  121.                 {
  122.                         index=(200-abs(npid->err))/20;
  123.                         npid->integral+=npid->err;
  124.                 }
  125.         }
  126.         npid->voltage=npid->Kp*npid->err+index*npid->Ki*npid->integral+npid->Kd*(npid->err-npid->err_last);
  127.         npid->err_last=npid->err;
  128.         return npid->voltage;
  129. }


  130. void Delay_n_ms(unsigned int dly)
  131. {
  132.         unsigned int        j;
  133.         do
  134.         {
  135.                 j = MAIN_Fosc / 13000;        //延时1ms, 主程序在此节拍下运行
  136.                 while(--j)        ;
  137.         }while(--dly);
  138. }
  139. void InitUart(void)
  140. {
  141.         SCON = 0x50;//工作在串口模式
  142.         T2L = (65536 - (MAIN_Fosc/4/BAUD)); //设置波特率为重新装值
  143.         T2H = (65536 - (MAIN_Fosc/4/BAUD))>>8;
  144.         AUXR |= 0x14; //启用定时器T2为1T模式, 并启用定时器2
  145.         AUXR |= 0x01; //选择定时器2为串口1的波特率发生器
  146.         ES = 1; //使能串口1为中断
  147. }
  148. void InitTime0(void)
  149. {
  150. //        #if 0
  151. //        AUXR |=  (1<<7);        // Timer0 set as 1T mode
  152. //        TMOD = 0x01; //16位,
  153. //        //Timer0_16bit();
  154. //        Time0L1=(65536-(MAIN_Fosc/1000000)*(TIME0_us1))%256;
  155. //        Time0H1=(65536-(MAIN_Fosc/1000000)*(TIME0_us1))/256;
  156. //        TL0=Time0L1;
  157. //        TH0=Time0H1;
  158. //        #endif
  159.         T0_Load_us_12T(TIME0_us1);
  160.         ET0 = 1;                //Timer0 Interrupt Enable
  161.         PT0 = 1;                //高优先级
  162.         TR0 = 1;                //Timer0 Run
  163. }
  164. // ADC初始化函数
  165. void ADC_Init(void)
  166. {
  167. //        ADC_ch=0;
  168. //        P1ASF=0x30;//设置P1为ADC
  169. //        //P1ASF|=(1<<4)|(1<<5);
  170. //        ADC_RES=0; // 清除结果寄存器
  171. //        ADC_CONTR=ADC_POWER|ADC_SPEEDLL|ADC_START|4;
  172. //        Delay_n_ms(20);
  173. //        EADC=1;// EADC=1 允许ADC中断
  174.        
  175. //查询方式
  176.         P1ASF=0x30;//设置P1为ADC
  177.         ADC_RES=0;
  178.         ADC_RESL=0;
  179.         ADC_CONTR=ADC_POWER|ADC_SPEEDLL;
  180.         Delay_n_ms(20);
  181. }

  182. void SendTxdBuf(unsigned char ASC)                                                        //发送-个ASCII
  183. {
  184.         ES     =   0;  //关闭串口中断
  185.         SBUF   =   ASC;
  186.         while(TI ==0); //
  187.         TI     =   0;  //
  188.         ES     =   1;  //允许串口中断
  189. }
  190. void Rs_Do(void) interrupt 4 using 1                                                                 //  通讯中断接收程序
  191. {
  192.         unsigned char data luc_temp;
  193.         if(RI==1)
  194.         {
  195.                 RI=0;
  196.                 luc_temp = SBUF;
  197.                 if(guc_RsPoint>=MAC_RX_BUF)
  198.                         guc_RsPoint=0;       
  199.                 if(luc_temp==0x0d)
  200.                 {
  201.                         RsBuf[guc_RsPoint] = 0x0d;
  202.                         guc_RsPoint = 0;
  203.                         RsOver = 1;
  204.                 }
  205.                 else
  206.                 {
  207.                         RsBuf[guc_RsPoint++]=luc_temp;
  208.                 }
  209.         }
  210. }


  211. void ledTime()
  212. {
  213.         switch(led_step)
  214.         {
  215.                 case 0:
  216.                         DIG1=1;
  217.                         DIG2=0;
  218.                         DIG3=0;
  219.                         DIG4=0;
  220.                         P2=ledTab[led_show1];
  221.                         led_di=led_dian1;
  222.                         led_step=1;
  223.                         break;
  224.                 case 1:
  225.                         DIG1=0;
  226.                         DIG2=1;
  227.                         DIG3=0;
  228.                         DIG4=0;
  229.                         P2=ledTab[led_show2];
  230.                         led_di=led_dian2;
  231.                         led_step=2;
  232.                         break;
  233.                 case 2:
  234.                         DIG1=0;
  235.                         DIG2=0;
  236.                         DIG3=1;
  237.                         DIG4=0;
  238.                         P2=ledTab[led_show3];
  239.                         led_di=led_dian3;
  240.                         led_step=3;
  241.                         break;
  242.                 case 3:
  243.                         DIG1=0;
  244.                         DIG2=0;
  245.                         DIG3=0;
  246.                         DIG4=1;
  247.                         P2=ledTab[led_show4];
  248.                         led_di=led_dian4;
  249.                         led_step=0;
  250.                         break;
  251.         }
  252. }

  253. void Time0Interrupt(void) interrupt 1 using 3
  254. {
  255.         //TR0=0;
  256.         ledTime();
  257.         if(Time_Show>0)
  258.                 Time_Show--;
  259.        
  260.         if(PwmBitVat>TimeMotor)
  261.         {
  262.                 MOTOR1=1;
  263.         }
  264.         else
  265.         {
  266.                 MOTOR1=0;//低电平打开电机
  267.         }
  268.         if(PwmBitVat++>256)
  269.         {
  270.                 PwmBitVat=0;
  271.         }
  272.         //TL0=Time0L1;
  273.         //TH0=Time0H1;
  274.         //TR0=1;
  275. }

  276. //void ADC_ISR() interrupt 5
  277. //{
  278. //        ADC_CONTR &= ~ADC_FLAG;
  279. //        switch(ADC_ch)
  280. //        {
  281. //                case 0:
  282. //                        ADC_ch=1;
  283. //                        ADC_VAL[0]=(ADC_RES<<2)|(ADC_RESL&0x03);
  284. //               
  285. //                        ADC_CONTR = ADC_POWER | ADC_SPEEDLL | 5 | ADC_START;
  286. //                break;
  287. //                case 1:
  288. //                        ADC_ch=0;
  289. //                        ADC_VAL[1]=(ADC_RES<<2)|(ADC_RESL&0x03);
  290. //               
  291. //                        ADC_CONTR = ADC_POWER | ADC_SPEEDLL | 4 | ADC_START;
  292. //                break;
  293. //        }
  294. //}

  295. void led_showP(float fshowPa)
  296. {
  297.         static float tmp_showPa=-1;
  298.         float tmp_show=fshowPa;
  299.         float temp_dian;
  300.         unsigned char shorteger,shordian;
  301.         if(fshowPa==tmp_showPa)
  302.                 return;
  303.         tmp_showPa=fshowPa;
  304.        
  305.         shorteger=(unsigned char)abs((int)fshowPa);
  306.         temp_dian=tmp_show-(float)shorteger;
  307.        
  308.         led_show1=shorteger/10;
  309.         led_show2=shorteger%10;
  310.         led_dian1=0;
  311.         led_dian2=1;
  312.        
  313.         //小数点后两位
  314.         shordian=(unsigned char)(temp_dian*100.0);
  315.         led_show3=shordian/10;
  316.         led_show4=shordian%10;
  317.         led_dian3=0;
  318.         led_dian4=0;
  319. }

  320. unsigned short GetADCResult(unsigned char ch)
  321. {
  322.         ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ch | ADC_START;
  323.         while(!(ADC_CONTR&ADC_FLAG));
  324.         ADC_CONTR &= ~ADC_FLAG;
  325.        
  326.         return (ADC_RES<<2)|(ADC_RESL&0x03);
  327. }

  328. //-20-0 0.5=4.5(102.4-921.6)
  329. void main(void)
  330. {
  331.         unsigned short xdata sensorV;
  332.         unsigned short xdata RtV;
  333.         unsigned char xdata TimeShowRt=0;
  334.         float xdata Actual;
  335.         float xdata tmp_TimeMotor;
  336.         float xdata SetSpeed;
  337.         char xdata tmp_SetSpeed=-128;
  338.         float xdata getSpeed;
  339.         pid_t xdata gpid;
  340.         //GPIO1
  341.         PP1(0);//输出
  342.         PP1(1);//输出
  343.         PP1(2);//输出
  344.         PP1(3);//输出
  345.         RP1(4);//输入
  346.         RP1(5);//输入
  347.         //GPIO2
  348.         PP2(0);//输出
  349.         PP2(1);//输出
  350.         PP2(2);//输出
  351.         PP2(3);//输出
  352.         PP2(4);//输出
  353.         PP2(5);//输出
  354.         PP2(6);//输出
  355.         PP2(7);//输出
  356.         //GPIO3
  357.         PP3(2);//输出
  358.         PP3(3);//输出
  359.         PP3(4);//输出
  360.         PP3(5);//输出
  361.         RP3(6);//输入
  362.         PP3(7);//输出
  363.         InitUart();
  364.         InitTime0();
  365.         ADC_Init();
  366.         EA = 1;                // 打开总中断
  367.         SendTxdBuf(0x89);
  368.         RtV=GetADCResult(4);
  369.         SetSpeed=0.019531*RtV-20.0;
  370.         tmp_SetSpeed=(char)SetSpeed;
  371.         PID_init(&gpid);
  372.         gpid.Kp=0.4;//作用是加快系统的响应速度,提高系统的调节精度,副作用是会导致超调;
  373.         gpid.Ki=0.2;//作用是消除稳态误差,副作用是导致积分饱和现象
  374.         gpid.Kd=0.2;//作用是改善系统的动态性能,副作用是延长系统的调节时间

  375. ……………………

  376. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码

所有资料51hei提供下载:
软件.rar (112.24 KB, 下载次数: 70)



分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏2 分享淘帖 顶1 踩
回复

使用道具 举报

沙发
ID:798112 发表于 2023-10-10 22:55 | 只看该作者
学习pid
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表