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

QQ登錄

只需一步,快速開(kāi)始

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

一個(gè)MS83f系列單片機(jī)的多功能程序(自適應(yīng)模糊PID算法)

  [復(fù)制鏈接]
ID:391730 發(fā)表于 2019-2-14 20:12 | 顯示全部樓層 |閱讀模式
  這個(gè)程序NB在哪兒呢,在用了自適應(yīng)模糊PID算法,不過(guò)主函數(shù)中我把整個(gè)結(jié)構(gòu)去除了,因?yàn)樽龅捻?xiàng)目屬于公司的,但是保留了所有功能函數(shù),可以直接使用功能。另外要說(shuō)一句,最好用14引腳的同款芯片來(lái)實(shí)現(xiàn)功能,因?yàn)閺?fù)用編程器引腳會(huì)經(jīng)常在寫入程序時(shí)報(bào)錯(cuò)。

單片機(jī)源程序:
  1. /*                ----------------
  2. *  VDD----------|1(VDD)   (GND)8|------------GND
  3. *  RED--------- |2(RA6)   (PA0)7|------------GREEN
  4. *  PWM3--------|3(PC3)   (PA1)6|------------AD2
  5. *  AD6-----------|4(PC2)   (PC4)5|------------PWM4
  6. *                 ----------------
  7. */
  8. /*程序說(shuō)明:ADC轉(zhuǎn)換,通過(guò)ADC測(cè)量實(shí)現(xiàn)燈的轉(zhuǎn)變,通過(guò)ADC測(cè)量,對(duì)輸出mcu引腳頻率以及占空比進(jìn)行控制,從而達(dá)到控制輸出電流電壓*/
  9. /*timer0 用的是1:256分頻,timer0增1周期為32us,中斷一次耗時(shí)32us*255=8.16ms*/
  10. /*自設(shè)的pwm~pa6采用系統(tǒng)時(shí)鐘的80分頻,即一個(gè)pwm周期為0.125us*80=10us,由軟件方法實(shí)現(xiàn)設(shè)定,PA6的震動(dòng)頻率是80的整倍數(shù),占空比自調(diào)(必須由中斷計(jì)時(shí))*/
  11. /*為降低定時(shí)器中斷產(chǎn)生的難度,暫時(shí)將pwm周期設(shè)置為20us,由__delay_us()函數(shù)來(lái)完成。*/
  12. /* 注意:本程序所有的占空比是小數(shù)表示,不是用百分?jǐn)?shù)表示*/
  13. #include "syscfg.h"
  14. #include "MS83Fxx02.h"
  15. #include<stdio.h>


  16. #define _XTAL_FREQ                 32000000  //內(nèi)部晶振頻率為16M
  17. //時(shí)鐘周期與機(jī)器周期為1:1,2T模式下,2個(gè)機(jī)器周期為一個(gè)指令周期,當(dāng)前系統(tǒng)指令周期為0.125us,



  18. //******************************
  19. #define red_on     PA6=0;
  20. #define red_off    PA6=1;
  21. #define green_on   PA0=0;
  22. #define green_off  PA0=1;
  23. //*****************************//
  24. #define shutled {red_off;green_off;} //所有的燈熄滅
  25. #define openled {red_on;green_on;} //所有燈打開(kāi)
  26. #define TMR0_VALUE_INIT       5;//1個(gè)timer0中斷是(255-5)*0.125us*256=8ms,1250個(gè)timer0中斷是1s
  27. #define delay_num  500;   //大量延時(shí)用的默認(rèn)毫秒值
  28. unsigned int interrupt_time=0;          //timer0中斷次數(shù)
  29. float adc_avg_num=0, VCC=0.0;     //ADC轉(zhuǎn)換出來(lái)的數(shù)值

  30. /*-------------------模糊自適應(yīng)pid-------------------*/
  31. #define IS_Kp 1
  32. #define IS_Ki 2
  33. #define IS_Kd 3

  34. #define NL   -3
  35. #define NM   -2
  36. #define NS         -1
  37. #define ZE         0
  38. #define PS         1
  39. #define PM         2
  40. #define PL         3



  41. static const float fuzzyRuleKp[7][7]={
  42.         PL,        PL,        PM,        PM,        PS,        PS,        ZE,
  43.         PL,        PL,        PM,        PM,        PS,        ZE,        ZE,
  44.         PM,        PM,        PM,        PS,        ZE,        NS,        NM,
  45.         PM,        PS,        PS,        ZE,        NS,        NM,        NM,
  46.         PS,        PS,        ZE,        NS,        NS,        NM,        NM,
  47.         ZE,        ZE,        NS,        NM,        NM,        NM,        NL,
  48.         ZE,        NS,        NS,        NM,        NM,        NL,        NL
  49. };

  50. static const float fuzzyRuleKi[7][7]={
  51.         NL,        NL,        NL,        NM,        NM,        ZE,        ZE,
  52.         NL,        NL,        NM,        NM,        NS,        ZE,        ZE,
  53.         NM,        NM,        NS,        NS,        ZE,        PS,        PS,
  54.         NM,        NS,        NS,        ZE,        PS,        PS,        PM,
  55.         NS,        NS,        ZE,        PS,        PS,        PM,        PM,
  56.         ZE,        ZE,        PS,        PM,        PM,        PL,        PL,
  57.         ZE,        ZE,        PS,        PM,        PL,        PL,        PL
  58. };

  59. static const float fuzzyRuleKd[7][7]={
  60.         PS,        PS,        ZE,        ZE,        ZE,        PL,        PL,
  61.         NS,        NS,        NS,        NS,        ZE,        NS,        PM,
  62.         NL,        NL,        NM,        NS,        ZE,        PS,        PM,
  63.         NL,        NM,        NM,        NS,        ZE,        PS,        PM,

  64.         NL,        NM,        NS,        NS,        ZE,        PS,        PS,
  65.         NM,        NS,        NS,        NS,        ZE,        PS,        PS,
  66.         PS,        ZE,        ZE,        ZE,        ZE,        PL,        PL
  67. };

  68. typedef struct{
  69.         float Kp;
  70.         float Ki;
  71.         float Kd;
  72. }PID;

  73. PID fuzzy(float e,float ec);//e 誤差,ec誤差變化率
  74. float speed_pid(float s_tar,float s_cur);//在目標(biāo)值會(huì)多次改變的情況下,建議在函數(shù)內(nèi)部初始pid參數(shù)而不是作為形參

  75. /*-------------------------------模糊自適應(yīng)pid結(jié)束---------------------------------*/



  76. void Delay_xms(unsigned int);//不精準(zhǔn)的毫秒延時(shí)
  77. void Delay_xus(unsigned int);//不精準(zhǔn)的微妙延時(shí)
  78. void colck_init(void);//所有時(shí)鐘初始化
  79. void interrupt_init(void);//中斷模塊初始化
  80. void io_init(void);//所有io初始化
  81. void adc_init(void);//adc模塊初始化
  82. void pwm_colck_init(void);//pwm初始化,IO端口將在set_pwm中設(shè)置,本函數(shù)主要初始化的是相關(guān)時(shí)鐘配置
  83. void shutdown_pwmall(void);//關(guān)閉所有PWM,同時(shí)使P1C和P1B引腳狀態(tài)固定pc4=1;pc3=0;
  84. unsigned int start_tran_adc(void);//官方給定的ADC程序
  85. unsigned int start_tran_adc2(void);//專門用來(lái)測(cè)量電流值大小
  86. unsigned int start_tran_adc_vcc(void);//用來(lái)測(cè)量VCC電壓
  87. void set_pwm_frequence(unsigned int, float);//設(shè)置PA6端口周期和占空比,調(diào)用_delay_us()函數(shù)完成,如果用定時(shí)器中斷,則基準(zhǔn)頻率可以最高提升到8M,
  88. void set_duty(float duty);//占空比操作封裝
  89. void set_cycle(unsigned int cycle);//周期操作封裝
  90. void set_pwm1(float duty,unsigned int cycle);//系統(tǒng)pc3引腳的pwm設(shè)置,//PWM周期 Tpwm=(PR2+1)*4*Tsys*預(yù)分頻
  91. void set_pwm2(float duty,unsigned int cycle);//系統(tǒng)pc4引腳的pwm設(shè)置
  92. void set_half_bridge(float duty,unsigned int cycle);//系統(tǒng)pc3,pc3組成的半橋pwm設(shè)置
  93. void controlpwm_calc(float expecte_volate,float expecte_current);//輸入預(yù)期電流電壓,該程序自動(dòng)調(diào)控,設(shè)置占空比和頻率
  94. void controlpwm_fruzy_pid(float expecte_voltage,float expecte_current);//自適應(yīng)模糊PID控制算法




  95. float avg_adc_value(unsigned int frequency);//平均多次采樣數(shù)據(jù),采樣次數(shù)由frequency 確定
  96. void act_led(float);//根據(jù)adc轉(zhuǎn)化的值處理燈閃爍狀態(tài)
  97. void breathe_led(unsigned int,float);//呼吸燈程序


  98. void system_check(void);//系統(tǒng)閃燈自檢

  99. /*********************************************main*****************************************************************************/

  100. int main()
  101. {

  102.     colck_init();
  103.         interrupt_init();
  104.     io_init();
  105.     adc_init();

  106. system_check();

  107. INTCON=0B10000000;




  108.   // while(ADC_time>1250)//1250*8ms=10秒,每10秒啟動(dòng)一次檢測(cè)
  109.         while (1)
  110.         {

  111.                     {
  112.                 VCC=12*start_tran_adc_vcc()/1023;
  113.                 act_led(VCC);
  114.                   interrupt_time=0;

  115.                    }



  116.         }

  117. }
  118. /*********************************************************************************************************************/







  119. void colck_init(void)//中心頻率16M,2T模式,看門狗禁用,定時(shí)器0中斷
  120. {
  121.     //UCFG0
  122. ////////關(guān)鍵數(shù)據(jù)//////////////
  123.     OPTION=0B00000111;//time0定時(shí)器,PORTA上拉使能,下降沿中斷,內(nèi)部時(shí)鐘,預(yù)分頻器給timer0使用,timer0 256分頻
  124.     OSCCON=0B11110101;//低頻,256Khz,timer0每一指令周期加1,16M系統(tǒng)時(shí)鐘focs
  125.     WDTCON=0B00010110;//看門狗時(shí)鐘源32khz,65565分頻,溢出周期為32khz/65535,軟件關(guān)閉看門狗(sbit<0>)
  126.     ADCON1=0B01010000;//ADC選擇內(nèi)部時(shí)鐘16分頻(ADC采樣頻率為16M/16=1M)

  127. ////////關(guān)鍵數(shù)據(jù)//////////////*


  128.     //T1CON=0B10000101;//time1定時(shí)器,高電平有效,1:1分頻,內(nèi)部時(shí)鐘
  129.     //T2CON&=0B11111000;//time2定時(shí)器關(guān)閉
  130.     /*全局中斷及time1中斷在此設(shè)置*/




  131. }

  132. void interrupt_init(void)//關(guān)閉比較器中斷,禁止ADC中斷
  133. {
  134.         INTCON=0B10100000;//全局中斷使能,TIMER0中斷使能
  135.         PIE1 = 0b00000000;
  136.         PIE2 = 0b00000000;
  137.         PIR1 = 0b00000000;
  138.         PIR2 = 0b00000000;
  139.         IOCA=0B00000000;
  140. }



  141. void io_init(void)
  142. {
  143.      //GPIO 設(shè)置為輸出時(shí),弱上拉會(huì)自動(dòng)關(guān)斷,此點(diǎn)可作為測(cè)試關(guān)鍵點(diǎn)
  144.     CMCON0=0B00000111;//關(guān)閉PA6引腳的比較模式
  145.     MSCKCON=0B00000000;



  146.      TRISA=0B00000000;//全部porta引腳配置為輸出
  147.       TRISC=0B00000100;//除PC2配置為AN6輸入外,其他全部配置為輸出
  148.       PORTA=0B00000000;//初始化porta端口,全部低電平
  149.       PORTC=0B00000000;//初始化portc端口,全部低電平
  150.       ANSEL=0B01000000;//除AN6通道為模擬輸入外,其他全部設(shè)置為數(shù)字IO

  151.        WPUA=0B00000000;//全部弱上拉使能
  152.        WPUC=0B00000000;//全部允許弱上拉
  153.         WPD=0B00000000;//pc2,PA4,PC1,PC3都設(shè)置為下拉
  154. }




  155. void adc_init(void)
  156. {
  157.    // ADCON0=0B10111000;//右對(duì)齊,內(nèi)部2v參考電壓,AN6模擬通道,轉(zhuǎn)換完成,禁止ADC開(kāi)始(sbit<0>)
  158.     ADCON0=0B11011000;//參考3v,sbit<6:5> 10 3v,01 2v,00 VCC
  159.     ADCON1=0B01100000;//ADC采樣時(shí)間初始化,初始化為系統(tǒng)時(shí)鐘的64分頻
  160.         //ADCON0=0B10111100;//1/4VDD an7
  161. }






  162. float avg_adc_value(unsigned int frequency)//平均多次轉(zhuǎn)換結(jié)果,使轉(zhuǎn)換結(jié)果更穩(wěn)定
  163. {

  164.         float temp=0,Value_tmp=0,Value_min=1000000,Value_max=-100000;
  165.         if(0==frequency){frequency=1;}
  166.         else if(frequency<10)
  167.     {
  168.         for(int T=0;T<frequency;T++)
  169.          {
  170.         temp=(6*(start_tran_adc())/1023);//3V參考電壓
  171.         Value_tmp+=temp;
  172.          }
  173.         Value_tmp=(Value_tmp/frequency);
  174.     }

  175.     else
  176.         {for(int T=0;T<frequency;T++)
  177.          {
  178.         temp=(6*(start_tran_adc())/1023);
  179.         Value_tmp+=temp;
  180.         if(temp>Value_max) {Value_max=temp;}
  181.         if(temp<Value_min) {Value_min=temp;}
  182.          }
  183.         Value_tmp=Value_tmp-(Value_max+Value_min);

  184.         Value_tmp=(Value_tmp/(frequency-2));
  185.         }
  186. return Value_tmp;
  187. }




  188. void act_led(float tmp)//根據(jù)adc轉(zhuǎn)換的平均結(jié)果控制閃燈
  189. {


  190.     if(tmp>=4.16)//大于4.16v充滿,綠燈常亮
  191.     {
  192.         red_off;
  193.         green_on;
  194.     }
  195.   else if(tmp>4.0&&tmp<4.08)//3.0v~4.08v補(bǔ)足充電,綠燈閃
  196.     {
  197.         red_off;
  198.         green_on;__delay_ms(200);green_off;__delay_ms(200);


  199.     }
  200.   else if(tmp=4.0){breathe_led();}
  201.     else if(tmp>=3.0&&tmp<4.0)//3.0v~4.0v快充階段,紅綠燈交替閃
  202.     {
  203.          red_off;green_on;
  204.        __delay_ms(100);
  205.          red_on;green_off;
  206.        __delay_ms(100);


  207.     }
  208.    else if(tmp>=0.5&&tmp<3.0)//預(yù)充階段,紅燈閃爍
  209.     {
  210.             green_off;
  211.             red_on;__delay_ms(200);
  212.             red_off;__delay_ms(200);
  213.     }
  214.    else //故障,紅燈常亮
  215.     {
  216.         green_off;
  217.         red_on;

  218.     }

  219. }




  220. void interrupt ISR(void){
  221.         if(T0IE&&T0IF){
  222.                 T0IF=0;
  223.                 TMR0=TMR0_VALUE_INIT;//賦初值
  224.                 interrupt_time++;//系統(tǒng)指令周期0.125us*256分頻* TMR0是8位256=0.125*256*256=8.192ms
  225.         }
  226. }
  227. /////////////////////////////////////////////


  228. void set_pwm_frequence(unsigned int circle,float Duty)//分辨率1us,輸入單位100us
  229. {

  230.     PA6=1;
  231.     Delay_xus(circle*Duty*100);
  232.     PA6=0;
  233.     Delay_xus(circle*(1-Duty)*100);

  234. }

  235. void breathe_led(unsigned int freqs,float dutys)
  236. {
  237.     freqs=100000/freqs;
  238.     green_on;red_off;
  239.     Delay_xus((freqs*dutys));
  240.     green_off;red_on;
  241.     Delay_xus((freqs*(1-dutys)));

  242. }




  243. ///////////////////////////////////////////////breathe of led test  function ///////////





  244. void Delay_xms(unsigned int integerA){

  245.         for(unsigned int i=0;i<integerA;i++){
  246.                 __delay_ms(1);
  247.         }
  248. }

  249. void Delay_xus(unsigned int integerB){

  250.         for (unsigned int x=0;x<integerB;x++){
  251.                 __delay_us(1);
  252.         }
  253. }



  254. PID fuzzy(float e,float ec)//e 誤差,ec誤差變化率
  255. {

  256.      float etemp,ectemp;
  257.      float eLefttemp,ecLefttemp;
  258.      float eRighttemp ,ecRighttemp;

  259.      int eLeftIndex,ecLeftIndex;
  260.      int eRightIndex,ecRightIndex;
  261.      PID      fuzzy_PID;
  262.      etemp = e > 3.0 ? 0.0 : (e < - 3.0 ? 0.0 : (e >= 0.0 ? (e >= 2.0 ? 2.5: (e >= 1.0 ? 1.5 : 0.5)) : (e >= -1.0 ? -0.5 : (e >= -2.0 ? -1.5 : (e >= -3.0 ? -2.5 : 0.0) ))));

  263.      eLeftIndex = (int)e;
  264.      eRightIndex = eLeftIndex;
  265.      eLeftIndex = (int)((etemp-0.5) + 3);        //[-3,3] -> [0,6]
  266.      eRightIndex = (int)((etemp+0.5) + 3);

  267.      eLefttemp =etemp == 0.0 ? 0.0:((etemp+0.5)-e);
  268.      eRighttemp=etemp == 0.0 ? 0.0:( e-(etemp-0.5));

  269.      ectemp = ec > 3.0 ? 0.0 : (ec < - 3.0 ? 0.0 : (ec >= 0.0 ? (ec >= 2.0 ? 2.5: (ec >= 1.0 ? 1.5 : 0.5)) : (ec >= -1.0 ? -0.5 : (ec >= -2.0 ? -1.5 : (ec >= -3.0 ? -2.5 : 0.0) ))));

  270.      ecLeftIndex = (int)((ectemp-0.5) + 3);        //[-3,3] -> [0,6]
  271.      ecRightIndex = (int)((ectemp+0.5) + 3);

  272.      ecLefttemp =ectemp == 0.0 ? 0.0:((ectemp+0.5)-ec);
  273.      ecRighttemp=ectemp == 0.0 ? 0.0:( ec-(ectemp-0.5));

  274. ///////*************************************反模糊*************************************//////




  275.         fuzzy_PID.Kp = (eLefttemp * ecLefttemp *  fuzzyRuleKp[ecLeftIndex][eLeftIndex]
  276.                                         + eLefttemp * ecRighttemp * fuzzyRuleKp[ecRightIndex][eLeftIndex]
  277.                                         + eRighttemp * ecLefttemp * fuzzyRuleKp[ecLeftIndex][eRightIndex]
  278.                                         + eRighttemp * ecRighttemp * fuzzyRuleKp[ecRightIndex][eRightIndex]);

  279.         fuzzy_PID.Ki =   (eLefttemp * ecLefttemp * fuzzyRuleKi[ecLeftIndex][eLeftIndex]
  280.                                         + eLefttemp * ecRighttemp * fuzzyRuleKi[ecRightIndex][eLeftIndex]
  281.                                         + eRighttemp * ecLefttemp * fuzzyRuleKi[ecLeftIndex][eRightIndex]
  282.                                         + eRighttemp * ecRighttemp * fuzzyRuleKi[ecRightIndex][eRightIndex]);

  283.         fuzzy_PID.Kd = (eLefttemp * ecLefttemp *    fuzzyRuleKd[ecLeftIndex][eLeftIndex]
  284.                                         + eLefttemp * ecRighttemp * fuzzyRuleKd[ecRightIndex][eLeftIndex]
  285.                                         + eRighttemp * ecLefttemp * fuzzyRuleKd[ecLeftIndex][eRightIndex]
  286.                                         + eRighttemp * ecRighttemp * fuzzyRuleKd[ecRightIndex][eRightIndex]);
  287. return fuzzy_PID;

  288. }


  289. float speed_pid(float s_tar,float s_cur)//在目標(biāo)值會(huì)多次改變的情況下,建議在函數(shù)內(nèi)部初始pid參數(shù)而不是作為形參
  290. {
  291.         float tar = 0,cur = 0;      //目標(biāo)值 , 實(shí)際值
  292.         tar=s_tar;s_cur=cur;
  293.     static PID pid= {1, 0, 0};      //賦予初值kp,ki,kd
  294.         static float sumE = 0;                   //累加偏差
  295.         static float lastE = 0;

  296.         PID OUT = {0, 0, 0};
  297.         float e = -1,ec = -2.6;



  298.         e = tar - cur;             //目標(biāo)值 - 實(shí)際值
  299.         ec = e - lastE;            //誤差變化率
  300.         sumE += e;
  301.         lastE = e;
  302.         OUT = fuzzy(e, ec);      //模糊控制調(diào)整  kp,ki,kd

  303.         return (pid.Kp+OUT.Kp)*e + (pid.Kd+OUT.Kd)*ec + (pid.Ki+OUT.Ki)*sumE;
  304. }
  305. /////////////////////////////
  306. void pwm_colck_init(void)
  307. {
  308.     TMR2IF = 0;  //中斷標(biāo)志位清零
  309.         T2CON = 0B00000100;//timer2預(yù)分頻比<1,0> 00 1:1  與系統(tǒng)時(shí)鐘1:1

  310. }
  311. void shutdown_pwmall(void)
  312. {
  313.     ECCPAS=0B00000001;
  314. }
  315. unsigned int start_tran_adc(void)
  316. {
  317.             unsigned int TempADCBuffer=0;
  318.             TRISC=0B00000100;//除PC2配置為AN6輸入外,其他全部配置為輸出
  319.         ANSEL=0B01000000;//配置an6信號(hào)為模擬信號(hào)
  320.         ADCON0 = 0b11011001;                        //右對(duì)齊,ADC使能,AN6通道,3V參考電壓
  321.         __delay_us(20);
  322.         GO_DONE=1;   //開(kāi)始轉(zhuǎn)換
  323.         while(GO_DONE==1) ;        //等待轉(zhuǎn)換完成
  324.         TempADCBuffer = ADRESH;
  325.         TempADCBuffer = (TempADCBuffer<<8)|ADRESL;
  326.         asm("nop");
  327.         ADON = 0;
  328.       ANSEL=0B00000000;//關(guān)閉模擬輸入an6
  329.       TRISC=0B00000000;//關(guān)閉AN6,防止影響另一路adc
  330.         return(TempADCBuffer);
  331. }

  332. unsigned int start_tran_adc2(void)
  333. {
  334.             unsigned int TempADCBuffer=0;
  335.             TRISA=0B00000010;//除PA1配置為AN1輸入外,其他全部配置為輸出
  336.         ANSEL=0B00000010;


  337.         ADCON0= 0b10100101;                        //右對(duì)齊,ADC使能,選擇AN1通道,2V參考電壓,AN1通道,pa1口
  338.         __delay_us(20);
  339.         GO_DONE=1;   //開(kāi)始轉(zhuǎn)換
  340.         while(GO_DONE==1) ;        //等待轉(zhuǎn)換完成
  341.         TempADCBuffer = ADRESH;
  342.         TempADCBuffer = (TempADCBuffer<<8)|ADRESL;
  343.         asm("nop");
  344.         ADON = 0;
  345.       ANSEL=0B00000000;//關(guān)閉模擬輸入an1
  346.       TRISA=0B00000000;//關(guān)閉AN1,防止影響另一路adc
  347.         return(TempADCBuffer);
  348. }
  349. unsigned int start_tran_adc_vcc(void)
  350. {
  351.     unsigned int TempADCBuffer=0;
  352.             TRISA=0B00000000;//全部配置為輸出
  353.         ANSEL=0B10000000;//配置an7信號(hào)為模擬信號(hào)
  354.         //ADCON0= 0b10111101;                        //右對(duì)齊,ADC使能,采集內(nèi)部1/4VCC通道信號(hào),2V參考
  355.         ADCON0= 0b11011101;  //3v參考
  356.         __delay_us(20);
  357.         GO_DONE=1;   //開(kāi)始轉(zhuǎn)換
  358.         while(GO_DONE==1) ;        //等待轉(zhuǎn)換完成
  359.         TempADCBuffer = ADRESH;
  360.         TempADCBuffer = (TempADCBuffer<<8)|ADRESL;
  361.         asm("nop");
  362.         ADON = 0;
  363.       ANSEL=0B00000000;//關(guān)閉模擬輸入an1
  364.       TRISA=0B00000000;//關(guān)閉AN1,防止影響另一路adc
  365.         return(TempADCBuffer);
  366. }
  367. void set_duty(float duty)
  368. {
  369.      unsigned int t_duty=0;
  370.         /********************************占空比操作******************************/
  371.         t_duty=duty*(4*(PR2+1));//占空比是10位,高8位放在CCR1L,低2位被放在CCP1CON 的DC1B<1:0>中,所以為了封裝進(jìn)行了以下一系列操作
  372.         CCPR1L=t_duty>>2;
  373.         t_duty=t_duty-CCPR1L;
  374.         t_duty=t_duty<<4;
  375.         CCP1CON=t_duty|CCP1CON;
  376.         /********************************占空比操作完畢******************************/

  377. }
  378. void set_cycle(unsigned int cycle)
  379. { unsigned int timer2_prescaler=0;

  380.     /********************************PWM周期操作******************************/
  381.     timer2_prescaler=T2CON;
  382.     timer2_prescaler&=0b01111000;
  383.     timer2_prescaler=timer2_prescaler>>3;
  384.         PR2 = (cycle*4/timer2_prescaler-1);
  385.         /********************************PWM周期操作完畢******************************/
  386. }
  387. void set_pwm1(float duty,unsigned int cycle)  //Tpwm=(PR2+1)*4*Tsys*預(yù)分頻 ,pwm周期cycle單位是1us
  388. {



  389.     TRISC3 = 1;


  390.     set_duty(duty);set_cycle(cycle);
  391.     CCP1CON|=0B00001101;
  392.         CCP1CON&=0b00111101; //PWM模式,單輸出,P1C高電平有效,P1B低電平有效
  393.         TMR2IF = 0;
  394.         T2CON = 0B00000100;
  395.         while(TMR2IF==0)  ;
  396.         TRISC3 = 0;
  397. }

  398. void set_pwm2(float duty,unsigned int cycle)  //Tpwm=(PR2+1)*4*Tsys*預(yù)分頻 ,pwm周期cycle單位是1us
  399. {



  400.     TRISC4 = 1;

  401.     set_duty(duty);set_cycle(cycle);
  402.     CCP1CON|=0B00001101;
  403.         CCP1CON&=0b00111101; //PWM模式,單輸出,P1C高電平有效,P1B低電平有效
  404.         TMR2IF = 0;
  405.         T2CON = 0B00000100;
  406.         while(TMR2IF==0)  ;
  407.         TRISC4= 0;
  408. }

  409. void set_half_bridge(float duty,unsigned int cycle)
  410. {

  411.     TRISC4 = 1;TRISC3=1;
  412.     set_duty(duty);set_cycle(cycle);

  413.     CCP1CON|=0B00001101;
  414.         CCP1CON&=0b00111101; //PWM模式,單輸出,P1C高電平有效,P1B低電平有效
  415.         TMR2IF = 0;
  416.         T2CON = 0B00000100;
  417.         while(TMR2IF==0)  ;
  418.         TRISC4= 0;TRISC3=0;
  419. }

  420. /*以下程序?yàn)榭刂扑惴?///控制算法1
  421. void controlpwm_calc(float expecte_voltage,float expecte_current)//根據(jù)公式計(jì)算的算法1
  422. {
  423.     float duty_temp=0.0 , cycle_temp=0.0;
  424.     VCC=8*start_tran_adc_vcc()*1023;//10bit adc,2V參考電壓,采集1/4 vcc電壓
  425.     duty_temp=expecte_voltage/VCC;
  426.     cycle_temp=1.2*expecte_current/(VCC*(1-duty_temp));

  427.     set_half_bridge(duty_temp,cycle_temp);

  428. }
  429. void controlpwm_fruzy_pid(float expecte_voltage,float expecte_current)//模糊自適應(yīng)pid
  430. {
  431.     float duty_temp=0.0 ,pid_temp=0.0, s_cur=0,s_vol=0;
  432.     unsigned int cycle_temp=0;
  433.     VCC=8*start_tran_adc_vcc()/1023;
  434.     s_vol=9*start_tran_adc()/1023;
  435.     s_cur=4*start_tran_adc2()/5115;
  436.     pid_temp=speed_pid(expecte_voltage,s_vol);
  437.   duty_temp=pid_temp/VCC;//s_vol 是調(diào)整輸出電壓的數(shù)據(jù)
  438.   cycle_temp=1.2*VCC*speed_pid( expecte_current,s_cur)/(1-duty_temp);//s_cur 是調(diào)整電流的數(shù)據(jù),由另一路ADC完成
  439.   set_half_bridge(duty_temp,cycle_temp);
  440. }

  441. void system_check(void)
  442. {

  443. for(char i=0;i<3;i++)
  444. {
  445.   red_on;green_on;Delay_xms(i*100);
  446.   green_off;red_off;Delay_xms((4-i)*100);
  447. }

  448. }
復(fù)制代碼

評(píng)分

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

查看全部評(píng)分

回復(fù)

使用道具 舉報(bào)

ID:490693 發(fā)表于 2019-3-14 14:31 | 顯示全部樓層
樓主,你這個(gè)自適應(yīng)模糊PID算法能適應(yīng)所有PID方面的應(yīng)用嗎?譬如:溫度控制,電機(jī)控制,氣壓控制等。謝謝!
回復(fù)

使用道具 舉報(bào)

ID:147106 發(fā)表于 2019-3-25 13:55 | 顯示全部樓層
支持一下樓主,不錯(cuò)的資料
回復(fù)

使用道具 舉報(bào)

ID:391730 發(fā)表于 2019-4-10 11:23 | 顯示全部樓層
ljl76 發(fā)表于 2019-3-14 14:31
樓主,你這個(gè)自適應(yīng)模糊PID算法能適應(yīng)所有PID方面的應(yīng)用嗎?譬如:溫度控制,電機(jī)控制,氣壓控制等。謝謝!

是的,但是實(shí)際的項(xiàng)目還需要根據(jù)硬件來(lái)調(diào)整代碼,PID這部分你可以把他當(dāng)成一個(gè)函數(shù)用,已經(jīng)封裝的很好了。
回復(fù)

使用道具 舉報(bào)

ID:473043 發(fā)表于 2019-11-19 15:20 | 顯示全部樓層
float speed_pid(float s_tar,float s_cur)//在目標(biāo)值會(huì)多次改變的情況下,建議在函數(shù)內(nèi)部初始pid參數(shù)而不是作為形參
{
        float tar = 0,cur = 0;      //目標(biāo)值 , 實(shí)際值
        tar=s_tar;s_cur=cur;

樓主,這里s_cur和cur是不是反了?
回復(fù)

使用道具 舉報(bào)

ID:391730 發(fā)表于 2019-12-9 19:21 | 顯示全部樓層
ljl76 發(fā)表于 2019-3-14 14:31
樓主,你這個(gè)自適應(yīng)模糊PID算法能適應(yīng)所有PID方面的應(yīng)用嗎?譬如:溫度控制,電機(jī)控制,氣壓控制等。謝謝!

是的,但是要看你單片機(jī)有沒(méi)有那么大的運(yùn)行空間
回復(fù)

使用道具 舉報(bào)

ID:391730 發(fā)表于 2019-12-9 19:23 | 顯示全部樓層
1808399267 發(fā)表于 2019-11-19 15:20
float speed_pid(float s_tar,float s_cur)//在目標(biāo)值會(huì)多次改變的情況下,建議在函數(shù)內(nèi)部初始pid參數(shù)而不 ...

哦,是的,謝謝糾正,改一下就好了。
回復(fù)

使用道具 舉報(bào)

ID:71535 發(fā)表于 2020-1-9 22:35 | 顯示全部樓層
你好看過(guò)這篇自適應(yīng)模糊PID算法,想嘗試下在編譯時(shí)我將controlpwm_fruzy_pid函數(shù)放在main下面位置
                    {
                VCC=12*start_tran_adc_vcc()/1023;
                act_led(VCC);
controlpwm_fruzy_pid(3,1);//編譯器報(bào)錯(cuò):no space for auto / param _fuzzyS1772
                  interrupt_time=0;
                   }
請(qǐng)問(wèn)下是哪里出問(wèn)題?
回復(fù)

使用道具 舉報(bào)

ID:618513 發(fā)表于 2020-1-16 14:52 | 顯示全部樓層
樓主你這直接拿來(lái)用就ok了嗎/??
回復(fù)

使用道具 舉報(bào)

ID:284717 發(fā)表于 2020-2-16 14:51 | 顯示全部樓層
支持一下樓主
回復(fù)

使用道具 舉報(bào)

ID:140370 發(fā)表于 2020-7-28 00:18 | 顯示全部樓層
樓主,都是浮點(diǎn),32位單片機(jī)才能跑吧
回復(fù)

使用道具 舉報(bào)

ID:76841 發(fā)表于 2023-1-31 10:21 | 顯示全部樓層
查詢表是怎么來(lái)的
回復(fù)

使用道具 舉報(bào)

ID:1086732 發(fā)表于 2023-7-1 09:38 | 顯示全部樓層
太好了,感謝樓主
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

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

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

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