|
不足之處歡迎指出
單片機(jī)源程序如下:
- #include "pid.h"
- #include "stm32f10x.h"
- #define pwmout_0 GPIO_SetBits(GPIOB,GPIO_Pin_5)
- #define pwmout_1 GPIO_ResetBits(GPIOB,GPIO_Pin_5)
- PID pid;
- float DIY_Pulse=0;
- void PID_Init()
- {
- pid.sv=60;
- pid.Kp=20;
- pid.T=1;
- pid.Ti=50;
- pid.Td=0;
- pid.pwmcycle=1000;//pwm周期
- pid.OUT0=1;
-
-
- pid.T2=100;
- pid.jiao=100;
- pid.Kp2=20;
- pid.Ti2=0;
- pid.Td2=0;
- }
- void PIDOUT_Init()
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //使能PB,PE端口時(shí)鐘
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; //LED0-->PB.5 端口配置
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽輸出
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度為50MHz
- GPIO_Init(GPIOB, &GPIO_InitStructure); //根據(jù)設(shè)定參數(shù)初始化GPIOB.5
- GPIO_ResetBits(GPIOB,GPIO_Pin_6); //PB.5 輸出高
-
-
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7; //LED1-->PE.5 端口配置, 推挽輸出
- GPIO_Init(GPIOB, &GPIO_InitStructure); //推挽輸出 ,IO口速度為50MHz
- GPIO_SetBits(GPIOB,GPIO_Pin_7); //PE.5 輸出高
-
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; //LED1-->PE.5 端口配置, 推挽輸出
- GPIO_Init(GPIOB, &GPIO_InitStructure); //推挽輸出 ,IO口速度為50MHz
- GPIO_ResetBits(GPIOB,GPIO_Pin_8); //PE.5 輸出高
- }
- void PID_Calc() //PID計(jì)算
- {
- float DelEk;
- float ti,ki;
- float Iout;
- float Pout;
- float Dout;
- float td;
- float kd;
-
-
- if(pid.C10ms<(pid.T))//計(jì)算周期未到
- {
- return ;
- }
- pid.Ek=pid.sv-pid.pv;
- Pout=pid.Kp*pid.Ek; //比例輸出
- pid.SEK+=pid.Ek; //歷史偏差和
- DelEk=pid.Ek-pid.Ek_1; //相鄰兩次偏差差值
- ti=pid.T/pid.Ti;
- ki=ti*pid.Kp;
- Iout=pid.SEK*pid.Kp*ti; //積分輸出
- td=pid.Td/pid.T;
- kd=pid.Kp*td;
- Dout=DelEk*kd; //微分輸出
-
- pid.OUT=Pout+Iout+Dout+pid.OUT0;//本次輸出脈寬
-
- if(pid.OUT>pid.pwmcycle)
- {
- pid.OUT=pid.pwmcycle;
- }
- if(pid.OUT<0)
- {
- pid.OUT=0;
- }
- pid.Ek_1=pid.Ek;
-
- pid.pv=encoder;
- encoder=0;
-
- pid.C10ms=0;
- }
- void PID_Calc2() //PID計(jì)算
- {
- float DelEk;
- float ti,ki;
- float Iout;
- float Pout;
- float Dout;
- float td;
- float kd;
-
-
- if(pid.C100ms<(pid.T2))//計(jì)算周期未到
- {
- return ;
- }
- pid.Ek2=pid.jiao-pid.jpv;
- Pout=pid.Kp2*pid.Ek2; //比例輸出
- pid.SEK2+=pid.Ek2; //歷史偏差和
- DelEk=pid.Ek2-pid.Ek_12; //相鄰兩次偏差差值
- ti=pid.T2/pid.Ti2;
- ki=ti*pid.Kp2;
- Iout=pid.SEK2*pid.Kp2*ti; //積分輸出
- td=pid.Td2/pid.T2;
- kd=pid.Kp2*td;
- Dout=DelEk*kd; //微分輸出
-
- pid.OUT1=Pout+Iout+Dout+pid.OUT0;//本次輸出脈寬
-
- if(pid.OUT1>pid.pwmcycle)
- {
- pid.OUT1=pid.pwmcycle;
- }
- if(pid.OUT1<0)
- {
- pid.OUT1=0;
- }
- pid.Ek_12=pid.Ek2;
-
- pid.jpv=jiao;
-
-
- pid.C100ms=0;
- }
- int myabs(int a)
- {
- int temp;
- if(a<0) temp=-a;
- else temp=a;
- return temp;
- }
- //void XCHG_Pid(float Pulse)
- //{
- // TIM_OCInitTypeDef TIM_OCInitStructure;
- //
- // TIM_OCInitStructure.TIM_Pulse = Pulse;
- // TIM_OC2Init(TIM3, &TIM_OCInitStructure);
- //}
- void PID_out(void)
- {
- static u16 pw;
- pw++;
-
- // PID_Calc();
- if(pw>pid.pwmcycle)
- {
- pw=0;
- }
- // if(pid.OUT>0) AIN2=1, AIN1=0;
- // else AIN2=0, AIN1=1;
- if(pw<pid.OUT)
- {
- DIY_Pulse=DIY_Pulse-0.1;
- TIM3->CCR2=DIY_Pulse;
- //XCHG_Pid(DIY_Pulse);
- //pid.jiao++;
- //pwmout_0; //加?
- //PWM1=1;
- }
- else
- {
- DIY_Pulse=DIY_Pulse+0.1;
- TIM3->CCR2=DIY_Pulse;
- //XCHG_Pid(DIY_Pulse);
-
- // pwmout_1; //減速
- //pid.jiao--;
- //PWM1=0;
- }
- }
- void MiniBalance_PWM_Init(u16 arr,u16 psc)
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
- TIM_OCInitTypeDef TIM_OCInitStructure;
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);//
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE); //使能GPIO外設(shè)和AFIO復(fù)用功能模塊時(shí)鐘
-
- GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE); //Timer3部分重映射 TIM3_CH2->PB5
-
- //設(shè)置該引腳為復(fù)用輸出功能,輸出TIM2 CH1~ CH4的PWM脈沖波形
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //TIM_CH1 ~TIM_CH4
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //復(fù)用推挽輸出
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(GPIOB, &GPIO_InitStructure);
-
- TIM_TimeBaseStructure.TIM_Period = arr; //設(shè)置在下一個(gè)更新事件裝入活動(dòng)的自動(dòng)重裝載寄存器周期的值
- TIM_TimeBaseStructure.TIM_Prescaler =psc; //設(shè)置用來作為TIMx時(shí)鐘頻率除數(shù)的預(yù)分頻值 不分頻
- TIM_TimeBaseStructure.TIM_ClockDivision =TIM_CKD_DIV1 ; //設(shè)置時(shí)鐘分割:TDTS = Tck_tim
- TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上計(jì)數(shù)模式
- TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根據(jù)TIM_TimeBaseInitStruct中指定的參數(shù)初始化TIMx的時(shí)間基數(shù)單位
-
- TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //選擇定時(shí)器模式:TIM脈沖寬度調(diào)制模式1
- TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比較輸出使能
- TIM_OCInitStructure.TIM_Pulse =DIY_Pulse; //設(shè)置待裝入捕獲比較寄存器的脈沖值
- TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //輸出極性:TIM輸出比較極性高
-
- TIM_OC2Init(TIM3, &TIM_OCInitStructure); //根據(jù)TIM_OCInitStruct中指定的參數(shù)初始化外設(shè)TIMx
-
- // TIM_CtrlPWMOutputs(TIM2,ENABLE); //MOE 主輸出使能
-
- TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable); //CH2預(yù)裝載使能
-
- TIM_ARRPreloadConfig(TIM3, ENABLE); //使能TIMx在ARR上的預(yù)裝載寄存器
- // TIM_CtrlPWMOutputs(TIM3, ENABLE);
- TIM_Cmd(TIM3, ENABLE); //使能TIM2
-
- }
- //int transfer(int encoder)
- //{
- // int temp;
- // temp=encoder;
- // encoder=0; //清零是為了算速度 不清零則是算位置
- // return temp;
- //}
- void MiniBalance_EXTI_Init(void)
- {
- GPIO_InitTypeDef GPIO_InitStructure;
-
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//外部中斷,需要使能AFIO時(shí)鐘
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能GPIO端口時(shí)鐘
-
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; //端口配置
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //上拉輸入
- GPIO_Init(GPIOA, &GPIO_InitStructure); //根據(jù)設(shè)定參數(shù)初始化GPIO
-
- Exit_Init();
- }
- void Exit_Init(void)
- {
- EXTI_InitTypeDef EXTI_InitStructure;
- NVIC_InitTypeDef NVIC_InitStructure;
- /*====PA.11====*/
- GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource3);
-
- EXTI_InitStructure.EXTI_Line=EXTI_Line3;
- EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
- EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; /*上升沿觸發(fā)*/
- EXTI_InitStructure.EXTI_LineCmd = ENABLE;
- EXTI_Init(&EXTI_InitStructure); /*根據(jù)EXTI_InitStruct中指定的參數(shù)初始化外設(shè)EXTI寄存器*/
- NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQn;
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; /*搶占優(yōu)先級(jí)2, */
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01; /*子優(yōu)先級(jí)1*/
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; /*使能外部中斷通道*/
- NVIC_Init(&NVIC_InitStructure);
-
-
-
- }
- void EXTI3_IRQHandler()
- {
- if(SET == EXTI_GetITStatus(EXTI_Line3))//PB3 右后A相
- {
-
- // if(RB)
- // {
- encoder++;
- if(pid.OUT1>80) jiao++;
- else jiao--;
- // }
- // else encoder--;
-
- EXTI_ClearITPendingBit(EXTI_Line3);
- }
- }
復(fù)制代碼- #include "stm32f10x.h"
- #include "pid.h"
- #include "timer.h"
- #include "bsp_key.h"
- #include "bsp_ili9341_lcd.h"
- #include "bsp_spi_flash.h"
- #include "bsp_usart.h"
- #include "delay.h"
- #include <stdio.h>
- extern PID pid;
- static void LCD_Test(void);
- static void Delay ( __IO uint32_t nCount );
- void Printf_Charater(void) ;
- u32 encoder;
- u32 jiao;
- void LED_Init(void)
- {
-
- GPIO_InitTypeDef GPIO_InitStructure;
-
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE, ENABLE); //使能PB,PE端口時(shí)鐘
-
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //LED0-->PB.5 端口配置
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽輸出
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度為50MHz
- GPIO_Init(GPIOB, &GPIO_InitStructure); //根據(jù)設(shè)定參數(shù)初始化GPIOB.5
- GPIO_SetBits(GPIOB,GPIO_Pin_5); //PB.5 輸出高
- }
- int main(void)
- {
- delay_init(); //延時(shí)函數(shù)初始化
- LED_Init(); //LED端口初始化
- PID_Init();
- PIDOUT_Init();
- ILI9341_Init (); //LCD 初始化
- Key_GPIO_Config();
-
- TIM4_Int_Init(7199,0); //
- MiniBalance_PWM_Init(7199,0); //輸出PWM波
- MiniBalance_EXTI_Init();
- ILI9341_GramScan ( 6 );
- while(1)
- {
- LCD_Test();
- PID_Calc();
-
- if( Key_Scan(KEY1_GPIO_PORT,KEY1_GPIO_PIN) == KEY_ON )
- {
- pid.sv=pid.sv+10;
- }
- if( Key_Scan(KEY2_GPIO_PORT,KEY2_GPIO_PIN) == KEY_ON )
- {
- pid.sv=pid.sv-10;
- }
- if( KEY3==0 )
- {
- AIN1=1,AIN2=0;
-
- while(!KEY3);
- }
- if( KEY4==0 )
- {
- AIN1=0,AIN2=1;
- while(!KEY4);
- }
- if( KEY5==0 )
- {
- AIN1=0,AIN2=0;
- while(!KEY5);
- }
-
- if( KEY6==0 )
- {
- jiao=0;
- while(1)
- {
- pid.OUT=0;
- pid.sv=10;
- PID_Calc();
- PID_Calc2();
- LCD_Test();
- if(pid.OUT1>80)
- {
- AIN1=1,AIN2=0;
- }
- else
- AIN1=0,AIN2=1;
-
- if(pid.jpv==pid.jiao)
- {
- AIN1=0,AIN2=0;
- break;
- }
- }
- }
- }
- }
- void LCD_Test(void)
- {
- /*演示顯示變量*/
- char sv[100];
- char pv[100];
- char OUT[100];
- char jiao[100];
- char jpv[100];
- char OUT1[100];
- char disbuff[100];
-
- LCD_SetFont(&Font8x16);
- LCD_SetColors(RED,BLACK);
- ILI9341_Clear(0,0,LCD_X_LENGTH,LCD_Y_LENGTH); /* 清屏,顯示全黑 */
- /********顯示字符串示例*******/
- ILI9341_DispStringLine_EN_CH(LINE(0),"野火3.2寸LCD參數(shù):");
- ILI9341_DispStringLine_EN_CH(LINE(1),"分辨率:240x320 px");
- ILI9341_DispStringLine_EN_CH(LINE(2),"ILI9341液晶驅(qū)動(dòng)");
-
- /********顯示變量示例*******/
- LCD_SetFont(&Font16x24);
- LCD_SetTextColor(GREEN);
- /*使用c標(biāo)準(zhǔn)庫(kù)把變量轉(zhuǎn)化成字符串*/
- sprintf(sv,"設(shè)定速度: %f ",pid.sv);
- sprintf(pv,"實(shí)際速度 : %f ",pid.pv);
- sprintf(OUT,"pid輸出: %f ",pid.OUT);
- sprintf(jiao,"設(shè)定角度: %f ",pid.jiao);
- sprintf(jpv,"實(shí)際角度: %f ",pid.jpv);
- sprintf(OUT1,"pid輸出: %f ",pid.OUT1);
-
- LCD_ClearLine(LINE(4)); /* 清除單行文字 */
- LCD_ClearLine(LINE(5)); /* 清除單行文字 */
- LCD_ClearLine(LINE(6)); /* 清除單行文字 */
- LCD_ClearLine(LINE(7)); /* 清除單行文字 */
- LCD_ClearLine(LINE(8)); /* 清除單行文字 */
- LCD_ClearLine(LINE(9)); /* 清除單行文字 */
-
- /*然后顯示該字符串即可,其它變量也是這樣處理*/
- ILI9341_DispStringLine_EN_CH(LINE(4),sv);
- ILI9341_DispStringLine_EN_CH(LINE(5),pv);
- ILI9341_DispStringLine_EN_CH(LINE(6),OUT);
- ILI9341_DispStringLine_EN_CH(LINE(7),jiao);
- ILI9341_DispStringLine_EN_CH(LINE(8),jpv);
- ILI9341_DispStringLine_EN_CH(LINE(9),OUT1);
- }
復(fù)制代碼
所有資料51hei提供下載:
PID算法.7z
(227.61 KB, 下載次數(shù): 138)
2019-3-12 22:25 上傳
點(diǎn)擊文件名下載附件
下載積分: 黑幣 -5
|
|