□□ ,
(1.山西職業(yè)技術(shù)學(xué)院,山西 太原 030006;2.天津工業(yè)職業(yè)學(xué)院,天津 300232)
按照規(guī)定的順序依次完成各種操作的控制系統(tǒng)稱為順序控制。在工業(yè)應(yīng)用方面,順序功能圖(SFC)是順序控制程序設(shè)計(jì)中的一種方法,該方法可以描述控制系統(tǒng)的整個(gè)工作過程,是設(shè)計(jì)電氣控制系統(tǒng)的重要方法,廣泛用于可編程控制器(PLC)的程序設(shè)計(jì)。如果采用單片機(jī)代替可編程控制器,可以降低成本,但此時(shí)單片機(jī)需要在C語言的支持下。C語言具有很強(qiáng)的邏輯描述能力,比可編程控制器中使用的梯形圖語言更加好用。本文就如何用C語言實(shí)現(xiàn)順序功能圖(SFC)進(jìn)行探討。
啟動(dòng)單片機(jī)后就進(jìn)入有效工作步。可以設(shè)置一個(gè)局部變量,該變量在while(1)循環(huán)語句執(zhí)行前為1,在循環(huán)語句結(jié)束前使該變量為0,這樣該局部變量只在第一個(gè)while(1)循環(huán)中為1,因此可以作為進(jìn)入有效工作步的條件。另外,還可以使用按鈕進(jìn)入有效工作步,但應(yīng)該加以限制條件,以避免按鈕的按下影響工作步正常轉(zhuǎn)移的情況。
可以使用按鈕停止流程,方法是在while(1)循環(huán)結(jié)束前增加語句:
if(n0){step0=0;step1=0;…stepn=0;}//n0是按鈕,stepn是工作步。
停止有效工作步后,若返回到工作步step0,則可以按照如下語句描述:
if(n0){step0=1;step1=0;…stepn=0;}//n0是按鈕,stepn是工作步。
一般情況下,需要在最后一個(gè)工作步完成之后,返回第一個(gè)工作步,但有時(shí)需要做一些判斷,例如在一個(gè)工藝流程結(jié)束后,是否進(jìn)行第二個(gè)工藝流程等。
如果在程序中有tj=1為條件停止有效工作步的語句,或者有tj=0為條件返回第一個(gè)工作步的語句,則可實(shí)現(xiàn)下一個(gè)流程的啟動(dòng)與停止操作。一般是增加一個(gè)鈕子開關(guān)判斷語句:
if(n1)tj=1;else tj=0;//n1是鈕子開關(guān)信號(hào),如果n1=1,則tj=1,否則tj=0。
轉(zhuǎn)移條件可以是來自單片機(jī)外部的按鈕、行程開關(guān)、傳感器等輸出的信號(hào),也可以是來自內(nèi)部的定時(shí)器的時(shí)間到條件、計(jì)數(shù)器的計(jì)數(shù)數(shù)值條件等。
單片機(jī)中可以直接使用定時(shí)器的時(shí)間數(shù)值。例如if(t0>12),表示定時(shí)器t0的數(shù)值>12時(shí)就滿足轉(zhuǎn)移條件,其中t0是對單片機(jī)定時(shí)器中斷計(jì)數(shù)的全局變量;又例如,if(cnt>8)表示計(jì)數(shù)器cnt數(shù)值>8時(shí)就滿足轉(zhuǎn)移條件,其中cnt是可以對按鈕動(dòng)作、流程循環(huán)次數(shù)等計(jì)數(shù)的全局變量。
工作步的得電條件是:該步的上一個(gè)工作步是有效工作步,而該步的下一步?jīng)]有工作,這時(shí)若出現(xiàn)轉(zhuǎn)移條件,則該工作步就會(huì)得電變成有效工作步。
工作步失電的條件是:該步的下一個(gè)工作步得電,則該工作步失電。
一般情況下工作步都需要自鎖。例如:若step0,step1和step2是三個(gè)順序執(zhí)行的工作步,則step1得電與失電的條件可以寫為:If(((step0&轉(zhuǎn)移條件)I step1)&step2) step1=1;else step1=0;
一般工作步得電與失電條件的梯形圖如圖1所示。
圖1 工作步梯形圖
選擇性分支是指各分支具有各自的工作步得電的條件,若滿足該條件,則該分支工作步得電;若不滿足,則該分支工作步就不能得電。
選擇性分支如圖2所示,圖中n0,n1,n2,n3是按鈕或開關(guān)條件。其中step1的得電條件是:step0得電,step3失電,選擇條件n1=1。應(yīng)該使轉(zhuǎn)移條件n1與n2互斥,就是只能向一個(gè)分支轉(zhuǎn)移。
圖2 選擇性分支
對應(yīng)的C語言描述如下:
start=1;//啟動(dòng)條件,在while語句中,只在一個(gè)周期中有效。
while(1)
{if(((n0&step3) I step0 l start)&! step1&! step2)step0=1;else step0=0;//n0為轉(zhuǎn)移條件,step3為有效工作步。
if(((n1&step0) I step1)&!step3) step1=1;else step1=0;//分支step1,n1為轉(zhuǎn)移條件,step0為有效工作步。
if(((n2&step0) I step2)&!step3) step2=1,else step2=0;//分支step2,n2為轉(zhuǎn)移條件,step0為有效工作步。
if(((n3&step1 I n3&step2) I step3)&!step0) step3=1;else step3=0;
start=0;//n3為轉(zhuǎn)移條件,step1或step2為有效工作步。
}
并發(fā)工作步是指在一個(gè)得電條件下,幾個(gè)并發(fā)分支都得電,所以幾個(gè)并發(fā)分支的得電條件是一樣的。所有并發(fā)工作步都結(jié)束后,才能進(jìn)行工作步轉(zhuǎn)移。所以,若要工作步轉(zhuǎn)移,則需要所有并發(fā)分支的轉(zhuǎn)移條件相“與”。
圖3所示為一個(gè)具有并發(fā)分支的SFC圖。圖中工作步step1和工作步step2是并發(fā)分支,n0,n1,n2,n3是按鈕或開關(guān)條件。
圖3 具有并發(fā)分支的SFC圖
start=1;//第1周期信號(hào)。
while(1)
{
if(((n0&step3) l step0 l start)&! Step1&! step2) step0=1;else step0=0;
if(((n1&step0) I step1)&! step3)step1=1;else step1=0;//并發(fā)分支step1。
if(((n1&step0) I step2)&! step3)step2=1;else step2=0;//并發(fā)分支step2。
if(((n2&n3&step1& step2) I step3)&! step0)step3=1;else step3=0;
start=0;}//第一周期信號(hào)失效語句。
第0工作步是單片機(jī)上電后的狀態(tài)。當(dāng)除了第0工作步以外的工作步都無效時(shí),第0工作步有效。所以,第0工作步的一個(gè)得電條件是,除了第0工作步以外的工作步都無效。停止條件出現(xiàn)后,程序應(yīng)該回到第0工作步。
在有些系統(tǒng)中,工作步就是動(dòng)作輸出。在這種情況下,工作步的繼電器就是單片機(jī)的輸出引腳。而在另一些系統(tǒng)中,動(dòng)作輸出是工作步的邏輯組合。
動(dòng)作開始時(shí)刻就是工作步得電時(shí)刻,動(dòng)作結(jié)束時(shí)刻就是工作步失電時(shí)刻。若動(dòng)作時(shí)間是一個(gè)工作步,則工作步就可以是輸出;若該動(dòng)作還需要在下一個(gè)工作步繼續(xù)動(dòng)作,則這時(shí)該動(dòng)作就是這兩個(gè)工作步的“或”。
描述SFC的一般C語言結(jié)構(gòu)如下:
while(1)
{
輸入掃描部分;
工作步流程部分;
輸出部分;
其他部分;
}
其中:
(1)輸入掃描部分就是處理按鈕、行程開關(guān)、傳感器等信號(hào)。
(2)工作步流程部分就是按照輸入條件,實(shí)現(xiàn)工作步的轉(zhuǎn)移。輸入條件可以是按鈕、行程開關(guān)或傳感器等外部輸入的信號(hào),也可以是單片機(jī)內(nèi)部的定時(shí)器或計(jì)數(shù)器信號(hào)。
(3)輸出部分就是描述對應(yīng)各個(gè)工作步的輸出動(dòng)作。
(4)其他部分:停止信號(hào)、首次whie(1)循環(huán)有效信號(hào)、按鈕信號(hào)和歸零信號(hào)等。
圖4是送料小車運(yùn)行的示意圖,該小車可以在A和B之間往返運(yùn)動(dòng),在A和B點(diǎn)各存在一個(gè)行程開關(guān),小車從A點(diǎn)向B點(diǎn)前進(jìn),到達(dá)B點(diǎn)后,停車6 s,然后從B點(diǎn)后退到A點(diǎn),在A點(diǎn)停車8 s后再向B點(diǎn)前進(jìn),如此循環(huán)往復(fù)。在這個(gè)過程中,要求可以人為控制小車的前進(jìn)啟動(dòng)和后退啟動(dòng),并且能夠在任何時(shí)候可以使小車停止運(yùn)行。根據(jù)所描述過程,該控制的信號(hào)接線如圖5所示。
圖4 小車運(yùn)行示意圖
圖5 小車運(yùn)行信號(hào)接線圖
該工作過程的工作步是小車前進(jìn)、在B點(diǎn)定時(shí)6 s、小車后退、在A點(diǎn)定時(shí)8 s,一共四步:轉(zhuǎn)移條件是小車到達(dá)B點(diǎn)后行程開關(guān)閉合、B點(diǎn)定時(shí)6 s時(shí)間到、小車到達(dá)A點(diǎn)后行程開關(guān)閉合和A點(diǎn)定時(shí)8 s時(shí)間到;動(dòng)作是小車從A點(diǎn)向B點(diǎn)的前進(jìn)動(dòng)作、啟動(dòng)6 s定時(shí)器動(dòng)作、小車從B點(diǎn)向A點(diǎn)的退回動(dòng)作和啟動(dòng)8 s定時(shí)器動(dòng)作。
該工作過程要求小車能夠前進(jìn)啟動(dòng)和后退啟動(dòng),這時(shí)需要采用選擇分支結(jié)構(gòu)。當(dāng)按下前進(jìn)啟動(dòng)按鈕時(shí),小車向B點(diǎn)前進(jìn);當(dāng)按下后退啟動(dòng)按鈕時(shí),小車向A點(diǎn)后退。停止按鈕的動(dòng)作是停止正在工作的步,回到第0步。
綜上所述,該工作過程的SFC圖如圖6所示。
圖6 小車運(yùn)行SFC圖
根據(jù)工作過程,有變量(PLC中又稱為地址)如下:
n0前進(jìn)按鈕、n1后退按鈕、n2停止按鈕、n3為B點(diǎn)行程開關(guān)、n4為A點(diǎn)行程開關(guān);step0上電狀態(tài)步、step1為小車前進(jìn)運(yùn)行步、step2為B點(diǎn)定時(shí)工作步、step3為小車后退運(yùn)行步、step4為A點(diǎn)定時(shí)工作步。run0前進(jìn)啟動(dòng)、run1后退啟動(dòng),time0為B點(diǎn)定時(shí)器、time1為A點(diǎn)定時(shí)器。
該工作過程的C語言程序如下:
#include"AT89X51.h"
unsigned char code table[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90};
unsigned char n0,n1,n2,n3,n4,sn;
unsigned char kk=8,start,run0,run1;
unsigned char step0=0,step1=0,step2=0,step3=0,step4=0;
unsigned char time0,time1;
unsigned char t0,t1;
void main ()
{
unsigned int nn;//如下是定時(shí)器0初始化描述:
TMOD=0x01;//定時(shí)器0,M1M0=01(模式1),gate=0,C/T=0。
TH0=0x3c;//初值為0x3cb0=65 536-50 000=15 536,50 ms中斷一次,20次/s,時(shí)鐘12 MHz。
TL0=0xb0;//TL初值。
TR0=1;//啟動(dòng)定時(shí)器0。
ET0=1;//設(shè)置中斷使能寄存器,允許定時(shí)器0中斷。
EA=1;//允許所有中斷。
Start=1;//第一周期啟動(dòng)標(biāo)志1。
while(1)
{
P3=0xff;//P3口連接8個(gè)按鍵作為輸入,用按鍵代替前進(jìn)、后退和停止按鈕與行程開關(guān)等。
if(P3_0==0) //如果與P3.0引腳(n0)連接的按鍵按下,前進(jìn)啟動(dòng)。
{for(nn=0;n<1 000;nn++);//延時(shí)消抖。
if(P3_0==0){n0=1;kk=0;}
else{n0=0;}
}
if(P3_1==0)//如果與P3.1引腳(n1)連接的鍵按下,后退啟動(dòng)。
{for(nn=0;nn<1 000;n++);
if(P3_1==0){n1=1;kk=1;}
else{n1=0;}
}
if(P3_2==0)//如果與P3.2引腳(n2)連接的按鍵按下,小車停止運(yùn)行。
{for(nn=0;nn<1 000;nn++);
if(P3_2==0){n2=1;Kk=2;}
else{n2=0;}
}
if(P3_3==0)//如果與P3.3引腳(n3)連接的按鍵核下,到達(dá)B點(diǎn)。
{for(nn=0;nn<1 000;nn++);
if(P3_3==0){n3=1;kk=3;}
else{n3=0;}
}
if(P3_4==0)//如果與P3.4引腳(n4)連接的按鍵按下,返回A點(diǎn)。
{for(nn=0;nn<1 000,nn++);
if(P3_4=0){n4=1;kk=4;}
else{n4=0;}
}
if(n0&! step1&! step2&!step3&!step4) run0=1;else run0=0;//小車前進(jìn),不自鎖,手工控制到B點(diǎn)。
if(n1&! step1&! step2&!step3&!step4) run1=1;else run1=0;//小車后退,不自鎖,手工控制到A點(diǎn)。
if((start I step0)&!step1&!step3) step0=1;else step0=0;//上電初始步step0=1。
if((run0&step0 I time1&step4 I step1)&!step2) step1=1;else step1=0;//前進(jìn)步step1=1。
if((n3&step1 l step2)&!step3)step2=1,else{step2=0;t0=0;}//到達(dá)B點(diǎn),step2=1,啟動(dòng)定時(shí)t0。
if(t0>6)time0=1;else time0=0;//如果t0>6,定時(shí)器time0=1。
if((run1&step0 I time0&step2 I step3)&! step4) step3=1;else step3=0;//后退步,step3=1。
if((n4&step3 I step4)&! step1) step4=1;else{step4=0;t1=0;}//到達(dá)A點(diǎn),step4=1,啟動(dòng)定時(shí)t1。
if(t1>8)time1=1;else time1=0;//如果t1>8,定時(shí)器time1=1。
if(step1)P2_6=0;else P2_6=1;//前進(jìn)動(dòng)作信號(hào)輸出,LED燈顯示小車前進(jìn)。
if(step3)p2_7=0;else P2_7=1;//后退動(dòng)作信號(hào)輸出,LED燈顯示小車后退。
if(n2){Step0=1;step1=0;step2=0;step3=0;step4=0;}//停止按鈕按下,回到初始步step0。
start=0;//上電啟動(dòng)標(biāo)志清零。
if(step0)sn=0;//將工作步轉(zhuǎn)換成數(shù)子在數(shù)碼管上顯示。
if(step1)sn=1;
if(step2)sn=2;
if(step3)sn=3;
if(step4)sn=4;
P0=table[sn〗;//與P0口連接的數(shù)碼管顯示工作步。
if(step0)P2_0=0;e1se P2_0=1;//用LED燈顯示工作步。
if(step1)P2_1=0;e1se P2_1=1;
if(step2)P2_2=0;e1se P2_2=1;
if(step3)P2_3=0;e1se P2_3=1;
if(step4)P2_4=0;e1se P2_4=1;
if(step2)P1=table[t0];//將定時(shí)數(shù)據(jù)顯示在與P1口連接的數(shù)碼管上。
if(step4)P1=table[t1];
}}
void timer0() interrupt 1 //定時(shí)器0中斷服務(wù)程序。
{
static unsigned char jj;
TH0=0x3c;//重置初值。
TL0=0xb0;//重置初值。
jj++;
if(jj==20) //如果jj=20,則為1 s,為調(diào)試方便,可以減小jj值。
{jj=0;
t0++;
if(t0>10)t0=0;
t1++;
if(t1>10)t1=0;
}}
當(dāng)采用51單片機(jī)實(shí)現(xiàn)SFC圖,可以使學(xué)習(xí)者從可編程控制器和單片機(jī)兩個(gè)不同的角度拓展編程思路。同時(shí),利用C語言進(jìn)行編程,邏輯性強(qiáng),操作簡單,降低成本,比可編程控制器中使用的順序功能圖(SFC)語言更為好用。