讀書的時候因為學的自動化所以一直以為PLC是控制的王道,經常鄙視樓下電子系搞單片機的,而且灰常2B的認為單片機都TM弱電太嬌氣不耐艸玩單片機的都是吊絲!所以經常混跡于PLC實驗室電子實驗室居然只去了幾次,然而隨著對單片機和PC機的了解逐漸加深,越來越覺得自己當年的自己太傻太天真了哎……
個人覺得PLC和單片機的關系就好比圖章和圓珠筆一樣,圖章操作簡單傻子能蓋出漂亮的圖案但缺點也顯而易見靈活性太差了你不能用圖章蓋出一些復雜的圖案,圓珠筆就正好相反雖然操作難度大點但靈活性強了n個數量級。
既然單片機的靈活性那么強那么我們能用單片機來模擬PLC嗎,很明顯是可以的而且PLC的核心其實也是單片機,那么該怎么模擬PLC呢?PLC分程序和硬件部分,硬件部分主要是做好外圍電路設計,實現PLC的IO輸入輸出功能,一般用光耦做IO口電路設計提高單片機的抗干擾能力,做好穩定的電源設計,電源是可靠性的基礎。其實模擬PLC的關鍵再于程序部分,思路是寫個編譯器把梯形圖編譯成 單片機能執行的機器碼,但寫編譯器工程太大了,我們只是模擬又不是造PLC所以不用考慮寫那種直接把梯形圖編譯成機器碼的編譯器了,我們可以把編譯過程分解為梯形圖—>指令表—>C51代碼—>機器碼,這樣的話問題就簡單多了梯形圖轉指令表可以手工完成或者寫個圖形編輯程序來完成但這不是重點,指令表轉C51代碼才是模擬PLC的靈魂所在,雖然是個偽編譯器但每條指令的翻譯都是蛋疼的過程,我肯定是沒辦法把所有的三菱指令都模擬出來的,要完成這個任務還得認真學學編譯原理啊……
這是PLC模擬程序的運行截圖,對應指令表的邏輯,發現運行結果是正確的,雖然只完成了幾條最簡單指令的翻譯而且與反指令還存在問題但畢竟思路是正確的完成只是時間問題了,太晚了不搞了果然比泥瑪搬磚還辛苦想問題的時候根本睡不了……艾瑪
下面是我的模擬程序,因為只實現了幾條指令而且還并不完善所以編譯程序和PLC指令表程序混在一起的,但這只是個思路因為我發現有些指令按我的辦法基本不能實現但也算是個開始后面再慢慢改進吧,如果你想做一個更牛的可以去參考 http://www.zg4o1577.cn/mcu/1985.html 下面是模擬編譯的程序:
#include<reg52.h>
//指令表模擬
#define AND &&
#define ANI && !
#define LD if(
#define LDI if( !
#define OUT )
//輸入輸出指令模擬
#define X000 P1_0
#define Y000 P2_0=1; else P2_0=0;
#define X001 P1_1
#define Y001 P2_1=1; else P2_1=0;
#define X002 P1_2
#define Y002 P2_2=1; else P2_2=0;
#define X003 P1_3
#define Y003 P2_3=1; else P2_3=0;
#define X004 P1_4
#define Y004 P2_4=1; else P2_4=0;
#define X005 P1_5
#define Y005 P2_5=1; else P2_5=0;
#define X006 P1_6
#define Y006 P2_6=1; else P2_6=0;
#define X007 P1_7
#define Y007 P2_7=1; else P2_7=0;
//輸入輸出口資源定義
int P1_0,P2_0,P1_1,P2_1,P1_2,P2_2,P1_3,P2_3,P1_4,P2_4,P1_5,P2_5,P1_6,P2_6,P1_7,P2_7;
//初始化函數
void chushihua()
{
P1_0=0;
P2_0=0;
P1_1=0;
P2_1=0;
P1_2=0;
P2_2=0;
P1_3=0;
P2_3=0;
P1_4=0;
P2_4=0;
P1_5=0;
P2_5=0;
P1_6=0;
P2_6=0;
P1_7=0;
P2_7=0;
}
//顯示輸入輸出狀態
void shurushuchu()
{
printf("輸入輸出口狀態表\n");
printf("X0->%d X1->%d X2->%d X3->%d X4->%d X5->%d X6->%d X7->%d\n",P1_0,P1_1,P1_2,P1_3,P1_4,P1_5,P1_6,P1_7);
printf("Y0->%d Y1->%d Y2->%d Y3->%d Y4->%d Y5->%d Y6->%d Y7->%d\n\n",P2_0,P2_1,P2_2,P2_3,P2_4,P2_5,P2_6,P2_7);
}
//采集輸入狀態
void shuru()
{
printf("請更新輸入點狀態\n");
printf("X0<-");
scanf("%d",&P1_0);
printf("X1<-");
scanf("%d",&P1_1);
printf("X2<-");
scanf("%d",&P1_2);
printf("X3<-");
scanf("%d",&P1_3);
printf("X4<-");
scanf("%d",&P1_4);
printf("X5<-");
scanf("%d",&P1_5);
printf("X6<-");
scanf("%d",&P1_6);
printf("X7<-");
scanf("%d",&P1_7);
}
int main()
{
int x=0;
chushihua();
while(1)
{
shuru();
//進入PLC指令表程序部分編譯器主體完工的話就能把這部分直接拿出來通過編譯器編譯了
LD X000
AND X002
ANI X001
OUT Y000
LD X003
AND X004
ANI X006
AND X007
OUT Y001
shurushuchu();
}
return 0;
}