?? 蹺蹺板平衡程序——最終華麗終結(jié)版.c
字號(hào):
#include<reg51.h>
#define uchar unsigned char
sbit p2_0=P2^0;
sbit p2_1=P2^1;
sbit p2_2=P2^2;
sbit p2_3=P2^3;
sbit p2_4=P2^4;
sbit p2_5=P2^5;
sbit p2_6=P2^6;
sbit p1_0=P1^0;
sbit p1_1=P1^1;
sbit p1_2=P1^2;
sbit p1_3=P1^3;
sbit p1_4=P1^4;
sbit p1_5=P1^5;
sbit p1_6=P1^6;
sbit p2_7=P2^7;
sbit p3_2=P3^2;
sbit p3_6=P3^6;
sbit p3_4=P3^4;
int a,b,l,setnumber=5,n,r,t,kk,i,m=0,tk,vt,st,yx,z,TC=1;
int phzt=0/*平衡狀態(tài)*/;dd=0/*等待時(shí)間*/;
char sec1,sec2,sec3,sec4,sd1=48,sd2=48,sd3=48,sd4=48,lc1,lc2,lc3,lc4;
float s,c=0.9742647;
double v;
sbit E_CLK =P1^6;//clock input 同步時(shí)鐘輸入端
sbit RW_SID=P1^7;//data input/output 入、輸出端
//串行發(fā)送一字節(jié)數(shù)據(jù)
void SendByte(unsigned char dat)
{ unsigned char i;
for(i=0;i<8;i++)
{ E_CLK=0;
if(dat&0x80)RW_SID=1;
else RW_SID=0;
E_CLK=1;
dat=dat<<1;
}
}
void SendCMD(unsigned char dat)
{ SendByte(0xF8);//11111,00,0 RW=0,RS=0 同步標(biāo)志
SendByte(dat&0xF0);//高四位
SendByte((dat&0x0F)<<4);//低四位
}
//寫顯示數(shù)據(jù)或單字節(jié)字符
void SendDat(unsigned char dat)
{ SendByte(0xFA);//11111,01,0 RW=0,RS=1
SendByte(dat&0xF0);//高四位
SendByte((dat&0x0F)<<4);//低四位
}
/* 寫漢字到LCD 指定的位置
x_add顯示RAM的地址
dat1/dat2顯示漢字編碼
*/
//初始化 LCM
void initlcm(void)
{ SendCMD(0x30);//功能設(shè)置,一次送8位數(shù)據(jù),基本指令集
SendCMD(0x0C);//0000,1100 整體顯示,游標(biāo)off,游標(biāo)位置off
SendCMD(0x01);//0000,0001 清DDRAM
SendCMD(0x02);//0000,0010 DDRAM地址歸位
SendCMD(0x80);//1000,0000 設(shè)定DDRAM 7位地址000,0000到地址計(jì)數(shù)器AC
}
void set_wenzi(void)
{ SendCMD(0x80);//1000,0001 設(shè)定DDRAM 7位地址000,0001到地址計(jì)數(shù)器AC.
SendDat(0xd0); //將ASCII碼調(diào)出來,顯示在液晶屏幕上.下同
SendDat(0xa1);//小
SendDat(0xb3);
SendDat(0xb5);//車
SendDat(0xd7);
SendDat(0xb4);//狀
SendDat(0xcc);
SendDat(0xac);//態(tài)
SendDat(0xa3);
SendDat(0xba);
SendCMD(0x90); //設(shè)置液晶屏的顯示地址,下同.
SendDat(0xca);
SendDat(0xb1);//時(shí)
SendDat(0xbc);
SendDat(0xe4); //間
SendDat(0x3a);
SendDat(sec4);
SendDat(sec3);
SendDat(sec2);
SendDat(0x2e);
SendDat(sec1);
SendDat(0x73);
SendCMD(0x88);
SendDat(0xcb);
SendDat(0xd9); //速
SendDat(0xb6);
SendDat(0xc8); //度
SendDat(0x3a); //:
SendDat(sd4);
SendDat(sd3);
SendDat(sd2);
SendDat(0x2e);
SendDat(sd1);
SendDat(0x63);
SendDat(0x6d);
SendDat(0x2f);
SendDat(0x73);
SendCMD(0x98);
SendDat(0xc2);
SendDat(0xb7); //路
SendDat(0xb3);
SendDat(0xcc); // 程
SendDat(0x3a);
SendDat(lc4);
SendDat(lc3);
SendDat(0x2e);
SendDat(lc2);
SendDat(lc1);
SendDat(0x6d);
}
xianshi()
{ set_wenzi(); //將想要設(shè)置的文字顯示在液晶屏幕上。
return;
}
void delay1ms(uchar t); //延時(shí)程序
void rightrun()
{ b=1;
p1_0=1;
p1_1=0;
p1_3=1;
p1_4=1;
a=2;
return;
}
void leftrun()
{
b=1;
p1_0=0;
p1_1=1;
p1_3=1;
p1_4=0;
a=1;
return;
}
void brightrun() //////////////
{ b=1;
p1_0=1;
p1_1=0;
p1_3=0;
p1_4=1;
a=2;
return;
}
void bleftrun()//////////////
{ b=1;
p1_0=0;
p1_1=1;
p1_3=1;
p1_4=1;
a=1;
return;
}
void forwordrun()
{ b=0;
p1_0=1;
p1_1=0;
p1_3=1;/**/
p1_4=0;/**/
a=3;
return;
}
void backrun()
{ b=0;
p1_0=0;
p1_1=1;
p1_3=0;/**/
p1_4=1;/**/
a=4;
return;
}
timer0() interrupt 1 using 1
{ TH0=0xFc;
TL0=0x18;
r++;
t++;
if(TC==1)
{ if(b==1)
{
if(m<setnumber)
{ p1_2=0;
p1_5=0;
}
else
{ p1_2=1;
p1_5=1;
}
if (m>=10)
m=0;
m++;
}
else if(b==0)
{ if(l<setnumber+1)
{ p1_2=0;
p1_5=0;
}
else
{ p1_2=1;
}
if (l>setnumber+1)
p1_5=1;
if (l>10)
l=0;
l++;
}
}
if(t==100)
{ if(phzt!=1&&phzt!=3)
tk++;
else
{ dd++;
p3_4=!p3_4;
}
if(dd==50)
{ if(phzt==1)
phzt=2;
if(phzt==3)
phzt=4; //打破平衡,準(zhǔn)備下蹺蹺板
p3_4=1;
tk=0; //重新計(jì)時(shí)
dd=0;
}
if (tk>=10000)
tk=0;
t=tk;
sec4=(t/1000)+0x30;
t=t%1000;
sec3=(t/100)+0x30;
t=t%100;
sec2=(t/10)+0x30;
t=t%10;
sec1=t+0x30;
t=0;
}
if(r==1000)
{ r=0;
v=n*c;
v=v*10;
vt=v;
if(vt>=10000)
vt=9999;
sd4=(vt/1000)+0x30;
vt=vt%1000;
sd3=(vt/100)+0x30;
vt=vt%100;
sd2=(vt/10)+0x30;
vt=vt%10;
sd1=vt+0x30;
n=0;
}
}
timer1() interrupt 3 using 2
{ n++;
s=s+c;
if(s>=10000)
s=0;
st=s;
lc4=(st/1000)+0x30;
st=st%1000;
lc3=(st/100)+0x30;
st=st%100;
lc2=(st/10)+0x30;
st=st%10;
lc1=st+0x30;
}
main()
{ int cs=0/*蹺蹺板翻的次數(shù)*/,fdd=6/*防抖動(dòng)系數(shù)*/;
int fx=0/*前一次運(yùn)動(dòng)方向,標(biāo)志*/,ph=0/*平衡的持久度*/;
int fy=0/*反應(yīng)時(shí)間*/,wt=0/*是否微調(diào),標(biāo)志*/,cf=1/*沖鋒標(biāo)志*/,cfsj=40,bc=0/*是否補(bǔ)償,標(biāo)志*/;
long qj=10/*前進(jìn)參數(shù)*/,ht=1/*后退參數(shù)*/,tz=0/*平衡狀態(tài)參數(shù)*/,bf=400/*步進(jìn)*/;
yx=0;/*是否運(yùn)行,標(biāo)志位*/
initlcm();
sec1=48;
sec2=48;
sec3=48;
sec4=48;
lc1=48;
lc2=48;
lc3=48;
lc4=48;
TMOD=0x61;
TH0=0xFC;
TL0=0x18;
TL1=-1;
TH1=-1;
IP=0x08;
EA=0;ET0=1;ET1=1;
TR0=1;TR1=1;
yx=1;
for(;;)
{ xianshi();
z=p3_2;
if(z==0)
{
yx++;
yx=(yx%2);
EA=yx;
TC=yx;
p1_2=!yx;
p1_5=!yx;
delay1ms(1000);
}
if(p3_6==0)
{ delay1ms(1000);
sec1=48;
sec2=48;
sec3=48;
sec4=48;
lc1=48;
lc2=48;
lc3=48;
lc4=48;
sd1=48;
sd2=48;
sd3=48;
sd4=48;
TH0=0xFC;
TL0=0x18;
TL1=-1;
TH1=-1;
yx=0;
tk=0;
s=0;
EA=0;
TC=1;
}
if(yx==1)
{
/////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
if((p2_5==0||phzt==2)&&phzt!=4)//后仰了
{ fy++;//反應(yīng)參數(shù)自加一
qj++;//前進(jìn)(后仰)參數(shù);
TC=1;//打開電機(jī)
if(cf||phzt==2)
{ //若在沖鋒,反應(yīng)參數(shù)到達(dá)20,自動(dòng)滿足前進(jìn)條件
qj=fdd*ht;
bc=1;
if(cf&&tk>=35)
setnumber=5;
if(cf&&tk>=45)
setnumber=4;
if(phzt==2)
if(p2_0&&p2_1&&p2_2)
phzt=3;
}
if(!cf&&fy>=200)//若沒有沖鋒,則反應(yīng)參數(shù)到200后,自動(dòng)對(duì)前進(jìn)后退參數(shù)置一,并且打開微調(diào)
{fy=0;
qj=1;
ht=1;
wt=1;
}
if(qj>=fdd*ht)//防平衡器抖動(dòng);
{ ph=0;//電機(jī)打開,平衡態(tài)系數(shù)置零
fx=2;//方向?yàn)榍?
for(i=0;i<=(bf)/*步進(jìn)補(bǔ)償*/;i++)
{
//////////////////////////////////前進(jìn)循跡程序段///////////////////////////
if(p2_0==1)
{ if(p2_0==1&&p2_1==1)
{ rightrun();
}
else if(p2_0==1&&p2_1==0&&p2_2==0)
{ rightrun();
}
}
else if(p2_2==1)
{ if(p2_2==1&&p2_1==1)
{ leftrun();
}
else if(p2_0==0&&p2_1==0&&p2_2==1)
{ leftrun();
}
}
else if(p2_1==1)
forwordrun();
else forwordrun();
/////////////////////////////////////////////////////////
if((cs%2)&&(cs<=10))//蹺蹺板過平衡點(diǎn)次數(shù)
{ cs++;
}
qj=1;//前進(jìn)參數(shù)置一
if (cf||bc==2)
{ ht=30;
if(bc==2)
bc=4;
}//若在沖鋒,后退參數(shù)置為30
else if(tz<=100||(ht<2))//若沒有沖鋒,且沒有進(jìn)入平衡狀態(tài)或后退參數(shù)<2時(shí),就將其置一,否則除以2
ht=1;
else ht=6;
}
}
TC=0;
p1_2=1;
p1_5=1;//使電機(jī)停止
}
/////////////////////////////////////////////////////////////////////////////
if(phzt==0)
if(p2_4==0||(p2_3&&p2_5))//平衡了
{ TC=1; //準(zhǔn)備電機(jī)運(yùn)行
if(cf)
cfsj=cfsj+3;
tz++; //停止?fàn)顟B(tài)次數(shù)累加
fy=0; //可能進(jìn)入平衡態(tài),不需電機(jī)轉(zhuǎn)動(dòng),反應(yīng)參數(shù)清零
if(cf==0&&tz>=100)//若無沖鋒信號(hào),平衡狀態(tài)>100,蹺蹺板翻滾次數(shù)置到最大
cs=8; //直接進(jìn)入微調(diào)
if(cf==0&&tz>=5)//若無沖鋒號(hào),則可以進(jìn)入平衡狀態(tài)
{/* if(bc==1)
if(fx==2)
{ for(i=0;i<=((bf-100)/2);i++)
forwordrun();
for(i=0;i<=((bf-50)/2);i++)
backrun();
bc=0;
}
else if(fx==1)
{ for(i=0;i<=((bf-50)/2);i++)
backrun();
for(i=0;i<=((bf-100)/2);i++)
forwordrun();
bc=0;
}*/
if(tz>=300)
tz=300; //停止態(tài)標(biāo)志置到最大
ph++; //平衡態(tài)系數(shù)自加1
if(ph>=15)
{
qj=10;ht=10;
}
if(ph>=24&&setnumber>4)//若平衡態(tài)系數(shù)>=10,則前進(jìn)、后退系數(shù)初值置為10,使其判斷時(shí)間加長
{tz=tz+10;
ph=0;
setnumber--;}
if(ph>=500)//若平衡系數(shù)>=500,已經(jīng)平衡.關(guān)閉中斷,顯示當(dāng)前時(shí)間
{phzt=1;
p3_4=0;
setnumber=4;
}
if(ph>=25&&fdd<=25)
{ //防抖動(dòng)參數(shù),逐漸增加,加長判斷時(shí)間
fdd=fdd+1;
}
}//增大防抖動(dòng)參數(shù)
TC=0;//關(guān)閉電機(jī)
fx=0;//方向?yàn)闊o
p1_2=1;//關(guān)閉電機(jī)使能
p1_5=1;//關(guān)閉電機(jī)使能
}
if((p2_3==0||phzt==4)&&phzt!=2)//前傾了
{ if(cf)
cfsj=cfsj+4;
fy++; //反應(yīng)系數(shù)自加一
if(phzt==4)
ht=fdd*qj; /****************還需要加程序********************/////////////////////////////////////////
if(fy>=20&&cf)//若在沖鋒,等待反應(yīng)系數(shù)到100時(shí),自動(dòng)退出沖鋒狀態(tài)
{ cf=0;
fy=0;
setnumber++; //通過PWM調(diào)節(jié)前進(jìn)的速度
}
/* else if(!cf&&bc==1)//若沒有沖鋒,當(dāng)防抖動(dòng)系數(shù)<=15時(shí),直接使后退參數(shù)滿足后退條件
{ ht=fdd*qj;
bc=2;
}*/
ht++; //后退(前傾)參數(shù)自加一。
TC=1; //打開電電機(jī)
if(fy>=200)//若反應(yīng)參數(shù)到200則自動(dòng)對(duì)前進(jìn)后退參數(shù),自動(dòng)置一
{fy=0;
qj=1;
ht=1;}
if(fy>=333&&tz<=4)
tz=0;
if(ht>=fdd*qj&&(tz>=10)&&cf==0)//防平衡器抖動(dòng);
{ ph=0;//電機(jī)啟動(dòng),平衡態(tài)系數(shù),自動(dòng)歸零
fx=1;//方向?yàn)楹? for(i=0;i<=bf*(bc+1);i++)
{
//////////////////////////////////////////////////////////////////////后退循跡程序段
/* if(p2_0==1)
{ if(p2_0==1&&p2_1==1)
{ brightrun();
}
else if(p2_0==1&&p2_1==0&&p2_2==0)
{ brightrun();
}
}
else if(p2_2==1)
{ if(p2_2==1&&p2_1==1)
{ bleftrun();
}
else if(p2_0==0&&p2_1==0&&p2_2==1)
{ bleftrun();
}
}
else if(p2_1==1)
backrun();
else */backrun();
/////////////////////////////////////////////////////////////////////////////
if(wt==1||cs>=3)//若打開微調(diào)或當(dāng)蹺蹺板翻滾次數(shù)達(dá)到3以上則調(diào)小步進(jìn)
{
if(bf!=200)
bf=200;//再次調(diào)小步進(jìn)
if(!(cs%2)&&(cs<=10))//記錄翻滾次數(shù)
{ cs++;
}
}
}
ht=1;//后退完畢,后退參數(shù)置一
if(tz<=100||(qj<2))//沒有進(jìn)入過平衡態(tài)時(shí)或前進(jìn)參數(shù)小于2時(shí),前進(jìn)參數(shù)置一,否則,除以2
qj=1;
else qj=6;
if(bc>=1)
{ bc=0;
fdd=fdd+2;
ht=100;
qj=100;
setnumber=6;
bf=300;
}
}//重新設(shè)置前進(jìn)后退參數(shù)
TC=0;
p1_2=1;
p1_5=1;//使電機(jī)停止
}
}
}
}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -