單詞量比較少,有時候需要變量名的時候真的是捉襟見肘 !
程序是在邏輯分析儀輔助下反復修改完成的,節省了大量時間,再次感謝下這30塊不到的神器!
指針還不會用,目前就這個水平了,自己的目前主業不是程序員,但希望這可以成為主業!
以下程序還望大師多多指教!
/* 程序要求:
1:控制兩個兩相步進電機A,B運轉;
2:轉的時候要做到可以不共同開始,停的時候以各自的停止信號為準
3:有運轉信號輸入的時候要立馬切斷,上一周期的運轉完成信號
4:在啟動的時候馬達會先轉動一定的角度,避開檢測開關的范圍,之后才開始檢測是否到位。
*/
#include <STC89C5xRC.H>
sbit StartM = P1^0; //開始運轉信號
sbit StopA = P1^4; //A停止信號
sbit StopB = P1^6; //B停止信號
sbit TurnB = P2^4; //B馬達脈沖輸出 板子線路都焊死了懶得再改板子,就改程序了
sbit TurnA = P2^6; //A馬達運轉脈沖輸出
sbit OK = P2^0; //兩個電機都到位之后輸出信號
sbit LED = P2^2; //程序運轉指示燈
bit EnTimerA = 0,EnTimerB = 0; //電機延時開始計數使能
bit EnStartMA = 1, EnStartMB = 1; //電機延時結束輸出位
unsigned int ta = 0 ,tb = 0,i = 0,n = 0;//電機延時指令計數變量ta,tb;i是掃描消抖變量,n是指示燈變量
//unsigned char Index = 0; //電機當前脈沖相位,用于不使用驅動器
//unsigned char BateCode[]={0x08,0x0a,0x02,0x06,0x04,0x05,0x1,0x09}; //不使用驅動器,步進電機電機運轉參數
unsigned char StartMotor = 1, StopAMotor = 1,StopBMotor = 1,bate = 0,StartMotorbuf = 1;//啟動,A停止,B停止,節拍,啟動緩存
unsigned char StopAbuf = 0,StopBbuf = 0, KA = 1,KB = 1;//記錄電機是否到位緩存 和一些變量
void SignalInput(); //信號消抖輸出函數(使用是位移消抖)
void TurnMotor(); //馬達運轉函數,因為不需要倒轉,所以么有添加倒轉功能
void InitTimer0(); //啟動定時器0;開啟中斷2ms定時
void BeatMotor(); //電機脈沖節拍,可以在此處調節脈沖寬度
void DelayStartMotor(); //電機啟動延時函數
void main(void)
{
P0 = 0xff; //初始化,各數位置1
P1 = 0xff;
P3 = 0xff;
P2 = 0xff;
InitTimer0(); //初始化定時器
while(1)
{
if(n >= 250) //運轉指示燈變量
{
n = 0;
LED = !LED;
}
}
}
void InitTimer0() //啟動T0,初始化
{
TMOD = 0x01;
TH0 = 0xf8;
TL0 = 0xd0;
EA = 1;
ET0 = 1;
TR0 = 1;
}
void BeatMotor() //節拍器.到時間后輸出計時置位信號,此處可以調速,調脈沖占空比等參數
{
static unsigned char cnt = 0; //節拍器計時
cnt ++;
if(cnt <= 2 )
{
bate = 0;
}
if(cnt > 2)
{
bate = 1;
}
if(cnt > 4)
{
cnt = 0;
//Index ++;
}
/*if(Index >= 8) //用于不用驅動器的時候
{
Index = 0;
} */
}
void SignalInput() //按鍵消抖檢測函數,48ms秒消抖。
{
static unsigned char StartBuf=0,StopABuf =0,StopBBuf=0 ;//(啟動緩存,A停止緩存,B停止緩存,A之前狀態,B之前狀態)
StartBuf = (StartBuf<<1) | StartM; //通過位移消抖
if(StartBuf == 0x00 )
{
StartMotor = 0; //確認穩定后,輸出啟動信號
}
else StartMotor = 1; //信號必須敏感,不是0就是1。而且要及時變動
StopABuf = (StopABuf<<1) | StopA;
if(StopABuf == 0)
{
StopAMotor = 0; //輸出A停止信號
}
else StopAMotor = 1;
StopBBuf = (StopBBuf<<1) | StopB;
if(StopBBuf == 0)
{
StopBMotor = 0; //輸出B停止信號,0代表停止
}
else StopBMotor = 1;
}
void DelayStartMotor()
{
if(ta == 220) //200*2ms = 400ms = 0.4s;實測0.44s應該是誤差,我是
{
EnTimerA = 0; //關閉計時使能
EnStartMA = 0; //延時結束,啟動馬達
}
if(tb == 220)
{
EnTimerB = 0; //關閉計數使能
EnStartMB = 0; //延時結束,輸出啟動馬達信號
}
}
void TurnMotor() //電機運轉函數,
{
static unsigned int i = 0,e = 0;
static unsigned char batebufa,batebufb;/*tmp,*/ //上半個脈沖高低電平的緩存,
if(StartMotorbuf != StartMotor) //對比電機運轉使能信號是否發生變化
{ //有變化就說明本次周期結束,將電機電機轉到位的信號緩存清零
StopAbuf = 0;
StopBbuf = 0;
}
if(StopAbuf == 0) //A電機無轉到位信號的時候才允許運轉
{
if(StartMotor == 0) //檢測運轉使能,有運轉使能的時候
{
EnTimerA = 1; //打開延時計數器使能,ta 開始計
if(EnStartMA == 0) //當延時器時間到后輸出信號。0
{
if(batebufa != bate) //當電平值不等于上一個值的時候
{
TurnA = bate; //A電機運轉
i ++; //脈沖計數加1
KA = 0; //再次清零 運轉完時成輸出信號的 緩存數據
batebufa = bate; //保存上一個電平值,用來做對比;
}
if(i >= 250) //先走一定的步數,保證離開檢測開關的檢測范圍
{
if((StopAMotor || StartMotor) == 0) //要求必須一直給運轉使能,能允許輸出轉到位信號
{
i = 0; //脈沖計數清零
StopAbuf = 1; //A轉到位的信號緩存;
KA = 1; //輸出A到位
EnStartMA = 1; //關閉延時函數給的電機運轉使能 ,等待下一周期
StartMotorbuf = StartMotor; //將啟動使能信號另外保存,用以判斷該信號是否有變化
}
}
}
}
else
{
EnTimerA = 0; //當使能信號有低到高發生變化之后,并且沒有運轉使能輸進來
ta = 0; //的時候,將不開始運轉延時的計時,并清零延時用的變量
}
}
if(StopBbuf == 0) // B運轉函數。驅動器用
{
if(StartMotor == 0)
{
EnTimerB = 1;
if(EnStartMB == 0)
{
if(batebufb != bate)
{
TurnB = bate;
KB = 0;
e ++;
}
batebufb = bate;
if(e >= 250)
{
if((StopBMotor || StartMotor) == 0)
{
e = 0;
StopBbuf = 1;
KB = 1;
EnStartMB = 1;
StartMotorbuf = StartMotor;
}
}
}
}
else
{
EnTimerB = 0;
tb = 0;
}
}
/* 這個函數是沒用步進電機驅動器,直接用單片機發數據;后來買了步進電機驅動器之后,只需要發脈沖。
這段就不需要了,這是個兩相四線的步進電機驅動函數但是后面用驅動器之后就沒給這個函數再做修改了;
if(StopBbuf == 0) // B運轉函數。驅動板函數。
{
if(StartMotor == 0)
{
if(BateCode[Index] != tmp)
{
n ++;
} ;
tmp = BateCode[Index];
P2 = tmp;
if(n >= 25)
{
if((StopBMotor || StartMotor) == 0)
{
n = 0;
StopBbuf = 1; //B轉到位的信號;
StartMotorbuf = StartMotor;
}
}
}
} */
if (KA && KB) //兩個電機都到位的時候輸出到信號供機械手使用。
{ //延時使能清零
OK = 0; //輸出點P1.0
}
else OK = 1;
}
void Timer0Interrupt(void) interrupt 1
{
TH0 = 0xf9; //定時2ms初值
TL0 = 0x29;
BeatMotor(); //節拍函數
i ++;
if(i == 3)
{
i = 0;
SignalInput(); //信號輸入消抖函數,消抖時間理論48ms,實測50ms,具體原因:沒查,但可能不是誤差
}
if(EnTimerA == 1) //運轉信號輸入后,電機延時運轉計時使能
{
ta ++; //計時變量
if(ta < 2) //這個判斷的作用是:運轉信號輸入后直接將電機到位信號切斷,而不是到延時結束時再切斷
{ //目的是為了避免重復將 K1 置 0 ;
KA = 0; //
}
}
if(EnTimerB == 1) //同A電機
{
tb ++;
if(tb < 2)
{
KB = 0;
}
}
DelayStartMotor(); //一個延時函數,可以分別調節兩個電機的起始運轉延時
n ++; //程序運轉指示燈變量
TurnMotor(); //電機運轉程序
}
51hei圖片_20190907002637.jpg (807.79 KB, 下載次數: 74)
下載附件
該程序最終的運行的波形圖
2019-9-7 00:26 上傳
|