程序用的是同站一個大佬的這個的代碼
- #include <reg51.h>
- #include<stdio.h>
- #define uchar unsigned char
- #define uint unsigned int
- sbit qidong=P3^2;//啟動鍵
- sbit tingzhi=P1^4;//停止鍵
- sbit fangxiang=P1^5;//轉向鍵
- sbit AddSpeed=P1^6;//加速鍵
- sbit SubSpeed=P1^7;//減速鍵
- sbit RS = P0^7;//LCD1602數據命令選擇端口
- sbit RW = P0^6;//LCD1602讀寫選擇端口
- sbit EN = P0^5;//LCD1602使能端口
- sbit IN2=P1^1;//L298輸入端2
- sbit IN1=P1^0;//L298輸入端1
- sbit PWM_FC=P1^2;//L298使能端口
- uchar aa[]={'T','a','r','g','e','t',' ',' ',' ',' ',' ','r','/','s','e','c'};//目標轉速:Target r/sec
- uchar cc[]={'A','c','t','u','a','l',' ',' ',' ',' ',' ','r','/','s','e','c'};//實測轉速: Actual r/sec
- uchar displayflag;//顯示標志位變量
- uint SetSpeed=1000;//聲明設定速度變量
- uint ActualSpeed=0;//聲明實際速度變量
- int e ,e1 ,e2 ;//聲明當前偏差值變量、之后偏差值變量、再后偏差值變量
- int out=0;//PID調節后輸出偏差值變量
- uint cnt=0;//定時器1中斷次數變量
- uint Inpluse=0;//聲明脈沖計數變量、
- uint PWMTime=100;//聲明脈沖寬度時間變量
- float uk ,uk1 ,duk ;//聲明目前總偏差值變量、之后偏差值總變量、偏差值總變量
- float Kp=0.36,Ki=0.05,Kd=0.016;//pid控制系數p=0.1,i=0.05,d=0.016。
- void delay(uchar x)
- {
- uint i,j;
- for(i=x;i>0;i--)
- for(j=50;j>0;j--);
- }
- void DelayUs2x(unsigned char t)
- {
- while(--t);
- }
- void DelayMs(unsigned char t)
- {
- while(t--)
- {
- DelayUs2x(245);
- DelayUs2x(245);
- }
- }
- void write_com(uchar com)//寫命令
- {
- RS=0;
- RW=0;
- P2=com;
- DelayMs(5);
- EN=1;
- DelayMs(5);
- EN=0;
- }
- void write_data(uchar date)//寫一個字符
- {
- RS=1;
- RW=0;
- P2=date;
- DelayMs(5);
- EN=1;
- DelayMs(5);
- EN=0;
- }
- void init()//初始化
- {
- write_com(0x38);
- write_com(0x0c);
- write_com(0x06);
- write_com(0x01);
- }
- void LCD_Write_String(uchar x,uchar y,uchar *s)//寫字符串
- {
- if (y == 0)
- {
- write_com(0x80 + x);
- }
- else
- {
- write_com(0xC0 + x);
- }
- while (*s)
- {
- write_data( *s);
- s++;
- }
- }
- void PIDControl()//pid偏差計算
- {
- e=SetSpeed-ActualSpeed;//計算當前偏差值變量
- duk=(Kp*(e-e1)+Ki*e+Kd*(e-2*e1+e2));//PID連續系統離散化增量型PID算法,算出總偏差值變量。
- uk=duk+uk1;//計算偏差值總變量加上之后偏差值總變量之和賦給目前總偏差值變量
- out=(int)uk;//強制類型轉化為整數型的目前總偏差值變量賦給PID調節后輸出偏差值變量
- if(out>100)//判斷PID調節后輸出偏差值變量是否大于100
- {
- out=100;//PID調節后輸出偏差值變量為100
- }
- else if(out<0)//判斷PID調節后輸出偏差值變量是否小于0
- {
- out=0;//PID調節后輸出偏差值變量為0
- }
- uk1=uk;//目前總偏差值變量賦給之后偏差值總變量
- e2=e1;//之前偏差值變量賦給之后偏差值變量
- e1=e;//當前偏差值變量賦給之前偏差值變量
- PWMTime=out;//PID調節后輸出偏差值變量賦給脈沖寬度時間變量
- }
- void PWMOUT()
- {
- if(cnt<PWMTime)//判斷定時器1中斷次數變量是否小于脈沖寬度時間變量
- {
- PWM_FC=1;//脈沖寬度輸入端口輸出高電平
- }
- else
- {
- PWM_FC=0;//脈沖寬度輸入端口輸出低電平
- }
- if(cnt>100)//判斷定時器1中斷次數變量是否大于100
- cnt=0;//定時器1中斷次數變量歸0
- }
- void SystemInit()//定時器0定時器1外部中斷0初始化函數
- {
- TMOD=0X21;//定時器0方式1,定時器1方式2。
- TH0=0xf8;//初裝定時器0高八位寄存器定時數值
- TL0=0x50 ;//初裝定時器0低八位寄存器定時數值,即2毫秒。
- TH1=0xC0;//初裝定時器1高八位寄存器定時數值
- TL1=0XC0;//初裝定時器1低八位寄存器定時數值,即16毫秒。
- EA=1;//開總中斷
- EX0=1;//開外部中斷0
- IT0=1;//外部中斷0下降沿觸發
- ET0=1;//開定時器0中斷允許
- ET1=1;//開定時器1中斷允許
- TR0=1;//開定時器0中斷
- TR1=1;//開定時器1中斷
- e =0;//偏差值變量為0
- e1=0;//之后偏差值變量為0
- e2=0;//再后偏差值變量為0
- IN1=1;
- IN2=1;
- }
- void SpeedSet()//設定速度函數
- {
- if(qidong==0)
- {
- delay(10);
- if(qidong==0)
- {
- IN1=0;
- IN2=1;
- while(qidong==1);
- }
- }
- if(tingzhi==0)
- {
- delay(10);
- if(tingzhi==0)
- {
- IN1=1;
- IN2=1;
- EN=1;
- while(tingzhi==1);
- }
- }
- if(fangxiang==0)
- {
- delay(10);
- if(fangxiang==0)
- {
- IN1=~IN1;
- IN2=~IN2;
- while(fangxiang==1);
- }
- }
- if(AddSpeed==0)//判斷加速鍵是否按下
- {
- delay(10);//延時
- if(AddSpeed==0)//再次判斷加速鍵是否按下
- {
- SetSpeed+=100;//設定速度變量每次加100
- if(SetSpeed>1000)//判斷設定速度變量是否大于3500
- {
- SetSpeed=1000;//設定速度變量歸為3500
- }
- }
- }
- if(SubSpeed==0)//判斷減速鍵是否按下
- {
- delay(10);//延時
- if(SubSpeed==0)//再次判斷減速鍵是否按下
- {
- SetSpeed-=100;//設定速度變量每次減100
- if(SetSpeed<0)//判斷設定速度變量是否小于0
- SetSpeed=0;//設定速度變量歸0
- }
- }
- aa[7]=SetSpeed/1000+'0';
- aa[8]=SetSpeed/100%10+'0';
- aa[9]=SetSpeed/10%10+'0';
- aa[10]=SetSpeed%10+'0';
- LCD_Write_String(0,0,aa);
- }
- /**************主函數************/
- void main()
- {
- SystemInit();
- init();
- LCD_Write_String(0,0,aa);
- displayflag=1;
- while(1)
- {
- SpeedSet();
- if(displayflag==1)
- {
- displayflag=0;
- cc[7]=ActualSpeed/1000+'0';
- cc[8]=ActualSpeed/100%10+'0';
- cc[9]=ActualSpeed/10%10+'0';
- cc[10]=ActualSpeed%10+'0';
- LCD_Write_String(0,1,cc);
- }
- }
- }
- void int0() interrupt 0//外部中斷0函數
- {
- Inpluse++;//脈沖計數變量加加
- }
- void Timer0() interrupt 1//定時器0中斷服務函數
- {
- static uint time=0;//轉速測量周期變量
- TH0=0xf8;//重裝定時器0高八位寄存器計數值
- TL0=0x50 ;//重裝定時器0低八位寄存器計數值,即2毫秒。
- time++;//轉速測量周期變量加加
- if(time>500)//判斷轉速測量周期變量是否大于500,等于500就是500x2毫秒=1000毫秒,也就是1s。
- {
- time=0;//轉速測量周期變量歸0
- displayflag=1;//顯示標志位變量置1
- ActualSpeed=Inpluse;//脈沖計數變量表示實際速度變量
- Inpluse=0;//脈沖計數變量歸0
- PIDControl();//PID控制函數
- }
- PWMOUT();
- }
- void Timer1() interrupt 3//定時器1中斷服務函數
- {
- cnt++;//定時器1中斷次數變量
- }
復制代碼 |