//P0.4:Tx
//P0.5:Rx
# include & ltc 8051f 310 . h & gt;//SFR聲明
# include & ltstdio.h & gt//標準I/O定義文件
# include & ltmath.h & gt//數學庫文件
# include & ltIntrins.h & gt
# include & ltabsacc.h & gt
無符號int j,I;
char a = 0;
無符號整數t = 0;
//sbit led=p0^2;
//P0.0(PWM0):給定左輪速度。
sbit vls=p0^4;//P0.4(GPIO):給左輪方向。
sbit vlf=p0^6;//P0.6(T0):反饋左輪轉速。
sbit dlf=p1^0;//P1.0(GPIO):反饋左輪方向。
//P0.2(PWM0):給定合適的輪速。
sbit vrs=p0^5;//P0.5(GPIO):給出正確的車輪方向。
sbit vrf=p0^7;//P0.7(T0):反饋右輪轉速。
sbit drf=p1^1;//P1.1(GPIO):反饋右輪方向。
int ol//左輪給定值
int len
int len_1,len _ 2;
int lyn_1,Lyn _ 2;
int vl1,vl2//反饋左輪速度值(采樣周期內的方波數)
int lfz//操作後分配給PWM的值
int lyn,lynn
int lun=0,LUN _ 1 = 0;//偏差校正值是校正後的PWM輸出。
國際倫普,魯尼,隆德;//PID校正值
int或;//右輪給定值
int ren
int ren_1,ren _ 2;
int ryn_1,ryn _ 2;
int vr1,vr2//反饋右輪轉速值(采樣周期內的方波數)
int rfz//操作後分配給PWM的值
int ryn,rynn
int run=0,run _ 1 = 0;//偏差校正值是校正後的PWM輸出。
int runp,runi,rund//PID校正值
浮點kp = 2.0//比例系數1.8
float kd = 0.2//微分系數0.4
浮動lki//積分系數
void Pio _ init(void);
void sys _ init(void);
void t 01 _ init(void);
void time 3 _ INT(void);
void PID(void);
void中斷_ init(void);
void delay(無符號int x);
void PWM 1 _ 1(void);
無效總管(無效)
{
PCA0MD & amp= ~ 0x40//關閉
Pio _ init();//P11為測距輸入。
sys _ init();
t 01 _ init();
PWM 1 _ 1();
time 3 _ INT();
中斷_初始化();
vls = 1;VRS = 0;
while(1)
{
ol = 50
or = 50
延時(1000);
ol = 100;
or = 100;
延時(1000);
ol =-50;
or = 50
延時(1000);
}
}
無效PID(無效)
{
/* * * * * * * * * * * *左輪PID調節* * * * * * * * * * * * * *
if(dlf==1)
{
Lyn =(vl2 * 256+VL 1);//dlf為左輪反饋方向,0表示前進vl=TL0。
}
其他
{
Lyn =-(vl2 * 256+VL 1);//dlf=1表示向後,速度應該是負的。
}
len = ol-Lyn;//誤差=給定速度-反饋速度(采樣周期內的方波數)
if(ABS(len)& lt;8)//30
{
lki = 1.4;//確定//ki值1.4
}
其他
{
lki = 0.05//積分系數:如果|給定值-反饋值|過大。
}//可以不引入積分,或者引入壹個小0.05。
lunp = KP *(len-len _ 1);//比例校正
魯尼= lki * len//積分校正
Lund = KD *(len-2 * len _ 1+len _ 2);//差分校正
LUN = lunp+魯尼+Lund+LUN _ 1;//總校正
* * * * * * * * * * * *新舊數據更新* * * * * * * * * * * * * * * * * * * *
len _ 2 = len _ 1;
len _ 1 = len;//len:當前采樣周期內的速度偏差;Len_1:上壹個采樣周期的速度偏差。
LUN _ 1 = LUN;//lun:當前采樣周期獲得的PWM校正值;Lun_1:在上壹個采樣周期獲得的PWM校正值。
* * * * * * * * * * * *新舊數據更新* * * * * * * * * * * * * * * * * * * *
if(LUN & gt;255)
{
lun = 255//正速度
}
如果(lun & lt-255)
{
LUN =-255;//負速度
}
如果(lun & lt0)
{
vls = 1;
PCA 0 cph 0 =-LUN;
}
if(LUN & gt;=0)
{
vls = 0;
PCA0CPH0 = lun
}
/* * * * * * * * * * * *右輪PID調節* * * * * * * * * * * * * * * *
if(drf==0)
{
ryn =(vr2 * 256+VR 1);//drf為右輪反饋方向,0表示前進vl=TL0。
}
其他
{
ryn =-(vr2 * 256+VR 1);//dlf=1表示向後,速度應該是負的。
}
ren = or-ryn;//誤差=給定速度-反饋速度(采樣周期內的方波數)
if(ABS(ren)& lt;8)//30
{
lki = 1.4;//確定//ki值1.4
}
其他
{
lki = 0.05//積分系數:如果|給定值-反饋值|過大。
}//可以不引入積分,或者引入壹個小0.05。
runp = KP *(ren-ren _ 1);//比例校正
runi = lki * ren//積分校正
rund = KD *(ren-2 * ren _ 1+ren _ 2);//差分校正
run = runp+runi+rund+run _ 1;//總校正
* * * * * * * * * * * *新舊數據更新* * * * * * * * * * * * * * * * * * * *
ren _ 2 = ren _ 1;
ren _ 1 = ren;//len:當前采樣周期內的速度偏差;Len_1:上壹個采樣周期的速度偏差。
run _ 1 =運行;//lun:當前采樣周期獲得的PWM校正值;Lun_1:在上壹個采樣周期獲得的PWM校正值。
* * * * * * * * * * * *新舊數據更新* * * * * * * * * * * * * * * * * * * *
if(run & gt;255)
{
run = 255//正速度
}
if(運行& lt-255)
{
run =-255;//負速度
}
if(運行& lt0)
{
VRS = 1;
PCA 0 cph 1 =-run;
}
if(run & gt;=0)
{
VRS = 0;
PCA 0 cph 1 =運行;
}
//因為這裏的PCA0CPH0越大,對應的電機轉速越低,所以需要降低255。
}
void pio_init(void)
{
XBR0 = 0x00//0000 0001
xbr 1 = 0x 72;//當0111010時,T0T1可以弱拉起來連接腳踝P06、P07 CEX0、CEX1,連接腳踝P00、P01。
P0MDIN = 0xff//模擬(0);號碼(1)1111011。
P0MDOUT = 0xc3//開漏(0);推拉式(1)111 111
P0SKIP = 0x3c//0011 1100
p 1 mdin = 0x ff;//1111 1111
p 1m dout = 0x fc;//
p 1 skip = 0x 00;//1111 1111
}
void sys _ init(void)//12 MHz
{
OSCICL = 0x43
OSCICN = 0xc2
CLKSEL = 0x00
}
void PWM 1 _ 1(void)//PWM初始化
{
PCA0MD = 0x08//PCA時鐘除以12。
PCA0CPL0 = 200//左輪
PCA 0 CPM 0 = 0x 42;//將左輪設置為8位PWM輸出。
PCA0CPH0 = 200
PCA 0 CPL 1 = 200;//平衡校正
PCA 0 CPM 1 = 0x 42;//設置為8位PWM輸出。
PCA 0 cph 1 = 200;
PCA0CN = 0x40//允許PCA工作
}
void t01_init(void)
{
TCON = 0x 50;//計數器1,2允許
TMOD = 0x 55;//定時器1和2采用16位計數功能。
CKCON = 0x00
th 1 = 0x 00;//用來采集左輪的速度。
TL 1 = 0x 00;
TH0 = 0x00//用於采集右輪的速度。
TL0 = 0x00
}
void TIME3_INT(void)
{
TMR3CN = 0x00//定時器3自動過載16位。
CKCON & amp= ~ 0x40
TMR3RLL = 0xff
TMR3RLH = 0xd7
TMR3L = 0xff
TMR3H = 0xd7
TMR3CN | = 0x04
}
Voidt3 _ ISR()中斷14//定時器3中斷服務程序。
{
//led = ~ led;
EA = 0;
TCON & amp;= ~ 0x50//關閉計數器0,1
VL 1 = TL0;//取左輪速度值
vl2 = TH0
VR 1 = TL 1;//取正確的輪速值。
vr2 = th 1;
th 1 = 0x 00;
TL 1 = 0x 00;
TH0 = 0x00
TL0 = 0x00
PID();//PID處理
TMR3CN & amp= ~ 0x80//清除中斷標誌。
TCON | = 0x 50;//重新啟動計數器0,1。
EA = 1;
}
void中斷_初始化(void)
{ IE = 0x80
IP = 0x00
eie 1 | = 0x 80;
EIP 1 | = 0x 80;
}
Void delay(unsigned int m) //延遲程序
{
for(I = 0;我& lt2000;i++)
{
for(j = 0;j & ltm;j++){ _ nop _();_ nop _();}
}
}