|
在另一位大佬貼出來的程序的基礎(chǔ)上改的,各部分程序的作用也都理解了但是燒錄到單片機(jī)后電機(jī)就是不會(huì)調(diào)速 自己一直看不出有啥問題,請大佬們幫忙看看
單片機(jī)源程序如下:
- #include<reg51.h>
- #include "intrins.h"
- #include <LCD1602.H>
- #define uchar unsigned char
- #define uint unsigned int
- #define GPIO_KEY P2
- sbit PWM=P1^3;
- uchar speed1[4]={"000"};//設(shè)定轉(zhuǎn)速
- uchar speed2[3]={"000"};//占空比
- uchar speed[]={"000"}; //當(dāng)前轉(zhuǎn)速
- uchar KeyValue=0; //鍵值
- uint AA,count=0,flag;
- float pid_p=0.003,pid_i=0.003,pid_d=0.002; //PID三個(gè)參數(shù)初值
- uint SpeedSet=50,CurrentSpeed; //設(shè)定轉(zhuǎn)速 當(dāng)前轉(zhuǎn)速
- unsigned char pid_val_mid; //pid_val_mid脈沖寬度
- unsigned int lastError=0; //之前誤差初始為0
- long int sumError=0; //偏差積累初始為0
-
- void delay1(unsigned int i)
- {
- unsigned int j;
- for(;i>0;i--)
- for(j=0;j<333;j++)
- {;}
- }
- /********************* 鍵盤掃描*************/
- void KeyDown(void)
- {
- GPIO_KEY=0x0f; //設(shè)置按鍵觸點(diǎn)初始值為0;0000 1111
- delay1(10);
- if(GPIO_KEY!=0x0f) //判斷按鍵是否按下
- {
- delay1(10); //延時(shí)消抖
- if(GPIO_KEY!=0x0f) //再次判斷按鍵是否按下,低電平有效
- {
- GPIO_KEY=0X0F;
- delay1(10);
- //測試列
- switch(GPIO_KEY)
- {
- case(0X07): KeyValue=0;break;//0000 0111
- case(0X0b): KeyValue=1;break;//0000 1011
- case(0X0d): KeyValue=2;break;//0000 1101
- case(0X0e): KeyValue=3;break;//0000 1110
- }
- //測試行
- GPIO_KEY=0XF0;//設(shè)置按鍵觸點(diǎn)初始值為1;1111 0000
- delay1(10);
- switch(GPIO_KEY)
- { //鍵盤表:
- case(0X70): KeyValue=KeyValue+0;break;//0111 0000 0 1 2 3
- case(0Xb0): KeyValue=KeyValue+4;break;//1011 0000 4 5 6 7
- case(0Xd0): KeyValue=KeyValue+8;break;//1101 0000 8 9 a b
- case(0Xe0): KeyValue=KeyValue+12;break;//1110 0000 c d e f
- }
- }
- }
- }
- void timer()
- {
- TMOD=0x11;//定時(shí)器0工作方式1.16位定時(shí),定時(shí)器1工作方式1,16位定時(shí);
- TH0=0x4c;//11.0592mhz下的50ms初值 (65535-50000)/256 12mhz是0x3c
- TL0=0x00;// (65535-50000)%256 0xb0
- TH1=0xfc;//11.0592mhz下的1msPWM控制
- TL1=0x66;
- TR1=1; //定時(shí)器1啟動(dòng)位,該位由軟件清零
- ET1=1; //定時(shí)器T1溢出中斷允許
- IT0=1; //外部中斷下降沿觸發(fā)
- TR0=1; //定時(shí)器0啟動(dòng)位,該位由軟件清零
- ET0=1; //定時(shí)器T0溢出中斷允許
- EX0=1; //外部中斷0中斷允許
- EA=1; //CPU全局中斷開放
- }
- /***********************lcd顯示*************/
- void display()
- {
- speed[0]=CurrentSpeed/100+0x30; //當(dāng)前轉(zhuǎn)速
- speed[1]=CurrentSpeed/10%10+0x30;//0x30對應(yīng)ASCII的數(shù)值0
- speed[2]=CurrentSpeed%10+0x30;
- speed1[0]=SpeedSet/100+0x30;//設(shè)定轉(zhuǎn)速
- speed1[1]=SpeedSet/10%10+0x30;
- speed1[2]=SpeedSet%10+0x30;
- speed2[0]=pid_val_mid/100+0x30;//占空比
- speed2[1]=pid_val_mid/10%10+0x30;
- speed2[2]=pid_val_mid%10+0x30;
- LCD_ShowString(1,1,"SET:"); //設(shè)定速度
- LCD_ShowNum(1,5,speed1,3);
- LCD_ShowString(1,8,"R/MIN");
- LCD_ShowString(2,1,"NOW:"); //當(dāng)前速度
- LCD_ShowNum(2,5,speed,3);
- LCD_ShowString(2,8,"R/MIN");
-
- }
- /************************電機(jī)控制*************/
- void keyKZ()
- {
- if(KeyValue==7)//c設(shè)定速度加10
- SpeedSet+=10;
- if(KeyValue==15)//d設(shè)定速度減10
- SpeedSet-=10;
- if(KeyValue==3)//e設(shè)定速度加1
- SpeedSet+=1;
- if(KeyValue==11)//f設(shè)定速度減1
- SpeedSet-=1;
- KeyValue=0;
- }
- /************************PID控制算法*************/
- unsigned int PID()
- {
- int dError=0,Error=0,B;
- Error=SpeedSet-CurrentSpeed;//當(dāng)前誤差
- sumError=Error+sumError;//誤差積累
- dError=Error-lastError;//誤差偏差
- lastError=Error;
- B=pid_p*Error+pid_i*sumError+pid_d*dError;//三個(gè)參數(shù)計(jì)算
-
- if(B>100) pid_val_mid=100;
- if(B<0) pid_val_mid=0;
- if(B>=0&&B<=100)
- pid_val_mid=B;
- return(0);
- }
- void Timer0_isr() interrupt 1 //定時(shí)器0中斷
- {
- AA++;
- TH0=0x4b; //重裝50ms
- TL0=0xfe;
- if(AA==20) //1s
- {
- CurrentSpeed=count/96*60;//一分鐘的轉(zhuǎn)速:count/96(96線編碼器)得出1s內(nèi)圈數(shù)也就是r/s,圈數(shù)*60得到r/min
- count=0;
- AA=0;
- PID();
- }
- }
- void key_int() interrupt 0 //外部中斷0 P3.2口接a相
- {
- count++; //a相脈沖計(jì)數(shù)
- }
- void Timer1() interrupt 3 //定時(shí)器1中斷
- {
- static int c=0; //static靜態(tài)變量,只有第一次會(huì)賦值
- TH1=0xfc; //重新賦值1mspwm,也就是每間隔1ms中斷一次
- TL1=0x66;
- c++; //每次定時(shí)器溢出加1
- if(c<=pid_val_mid) PWM=1; //當(dāng)中斷次數(shù)小于設(shè)定的脈寬給高電平,
- if(c>pid_val_mid) PWM=0; //等到了設(shè)定脈寬值就變?yōu)榈碗娖?br />
- if(c>=100) c=0; //一個(gè)周期分為100段高低電平,大于100就是下一個(gè)周期
- }
- void main()
- {
- timer(); //定時(shí)器初始化
- LCD_Init();//LCD初始化
- while(1)
- {
- KeyDown(); //鍵盤掃描
- keyKZ(); //鍵盤控制
- display();//顯示LCD
- }
- }
復(fù)制代碼
|
|