设计者: 施志鹏 在如今自动化生产过程中,大多都是以PLC为核心,或者是用PLC来改造生产设备。它的稳定性,通用性,易学性等,特别是它的通信及网络技术,使得无数学者为它着迷。在众多的优点下,为独的遗憾就是贵啊!因此就有朋友问我,能否用单片机代替PLC。可以,完全可以,只不过会在制作与编程上比较困难一点。下面我将大家介绍如何自制一款,用AT89C2051单片机制作的仿PLC八进六出控制板,当然还比不上真正的PLC,但是制作成本不过80多元。用在一般的小型改造上,我想也够了。 线路原理如(图一),线路中的单片机为AT89C2051,也可以是AT89C4051, 后者的程序储存空间为4K。输入通道与输出通道采用了4颗TLP-521-4光电耦合,在输出通道的后级还用了一颗ULN2003电流放大器,主要是驱动小型继电器线圈。D1—D8为输入端口指示, D9—D14为输出端口指示,D15为线路板上的指示灯,它的用途由用户定义,比如某个工作步的指示。控制板的输入电压为5V和12V两种,5V主要是供给输入部份和单片机本身使用,12V电压是供给输出部份。在这就有朋友问道:为什么要用到两个电源?5V直流电的继电器在市面上也有得卖。选用两种电源作为供给,只是为了提高控制板本身工作时的稳定性,因为继电器在释放时会产生反电势,对电源有点影响,除非用户选用5V的开关电源,不过我相信大多的DIY最后会选择7812和7805作为电源部份,所以在设计上采用了两种电源,这样比较划算。(图二)为控制板的工程接线图,用过PLC的朋友们是否会觉得很像熟悉。(图三)为这个线路的PCB走线图。 为了让大家在设计上有个程序参考,本人分别用汇编语言与C语言各写一个程序供大家参考。这两个程序只要稍作修改,就可以得到另一种用户程序。 汇编语言: ;============================== ;定义输入部份 SB1 EQU P3.0 SB2 EQU P3.1 SB3 EQU P3.2 SB4 EQU P3.3 SB5 EQU P3.4 SB6 EQU P3.5 SB7 EQU P3.7 SB8 EQU P1.0 KA1 EQU P1.7 KA2 EQU P1.6 KA3 EQU P1.5 KA4 EQU P1.4 KA5 EQU P1.3 KA6 EQU P1.2 LED EQU P1.1 ;这样的定义,可以方便设计。 ORG 0030H RESET: MOV R0,#00H DJNZ R0,$ ;系统延时 MOV SP,#60H MOV P3,#0FFH MOV P1,#0FFH ;输出初始化 NOP NOP ;=========================================== ;主程序部份 输入按钮 MAIN: MOV R0,#0FFH MOV DPTR,#TAB ;跳转表赋值 ;按钮程序判断 START: JNB SB1,LL1 JNB SB2,LL2 JNB SB3,LL3 JNB SB4,LL4 JNB SB5,LL5 JNB SB6,LL6 JNB SB7,LL7 JNB SB8,LL8 CJNE R0,#0FFH,NEXT AJMP START NEXT: MOV A,R0 ;程序跳转表 RL A JMP @A+DPTR ;========================================== LL1: CALL KT10MS ;调用10ms的时间延时,躲过开关抖动 JNB SB1,LLL1 AJMP START LLL1: MOV R0,#00H AJMP NEXT ;========================= LL2: CALL KT10MS JNB SB2,LLL2 AJMP START LLL2: MOV R0,#01H AJMP NEXT ;========================= LL3: CALL KT10MS JNB SB3,LLL3 AJMP START LLL3: MOV R0,#02H AJMP NEXT ;========================= LL4: CALL KT10MS JNB SB4,LLL4 AJMP START LLL4: MOV R0,#03H AJMP NEXT ;========================= LL5: CALL KT10MS JNB SB5,LLL5 AJMP START LLL5: MOV R0,#04H AJMP NEXT ;========================= LL6: CALL KT10MS JNB SB6,LLL6 AJMP START LLL6: MOV R0,#05H AJMP NEXT ;========================= LL7: CALL KT10MS JNB SB7,LLL7 AJMP START LLL7: MOV R0,#06H AJMP NEXT ;======================== LL8: CALL KT10MS JNB SB8,LLL8 AJMP START LLL8: MOV R0,#07H AJMP NEXT ;============================================== ;跳转表入口处 TAB: AJMP SQ1 AJMP SQ2 AJMP SQ3 AJMP SQ4 AJMP SQ5 AJMP SQ6 AJMP SQ7 AJMP SQ8 ;============================================== ;跳转表入口程序处理部份,即是按每个按钮SB1至SB8的不信号进行处理 ;可以在每个按钮程序部份插入用户想实现的动作步 ;按钮SB1的程序处理 SQ1: CLR KA1 ;KA1动作 MOV R0,#0FFH AJMP START ;按钮SB2的程序处理 SQ2: CLR KA2 ;KA2动作 MOV R0,#0FFH AJMP START ;按钮SB3的程序处理 SQ3: CLR KA3 ;KA3动作 MOV R0,#0FFH AJMP START ;按钮SB4的程序处理 SQ4: CLR KA4 ;KA4动作 MOV R0,#0FFH AJMP START ;按钮SB5的程序处理 SQ5: CLR KA5 ;KA5动作 MOV R0,#0FFH AJMP START ;按钮SB6的程序处理 SQ6: CLR KA6 ;KA6动作 MOV R0,#0FFH AJMP START ;按钮SB7的程序处理 SQ7: CLR LED ;LED指示亮 MOV R0,#0FFH AJMP START ;按钮SB8的程序处理 SQ8: SETB KA1 ;停KA1 SETB KA2 ;停KA2 SETB KA3 ;停KA3 SETB KA4 ;停KA4 SETB KA5 ;停KA5 SETB KA6 ;停KA6 SETB LED ;停LED MOV R0,#0FFH AJMP START ;====================================================== ;时间继电器 KT10MS: MOV R5,#0BH F1: MOV R7,#02H F2: MOV R6,#0FFH F3: DJNZ R6,F3 DJNZ R7,F2 DJNZ R5,F1 RET END C语言部份 /*设计者:施志鹏*/ #include<reg52.h> /*输入按钮定义*/ sfr p1=0x90; sfr p3=0xb0; sbit P3_0=P3^0; sbit P3_1=P3^1; sbit P3_2=P3^2; sbit P3_3=P3^3; sbit P3_4=P3^4; sbit P3_5=P3^5; sbit P3_7=P3^7; sbit P1_0=P1^0; #define SB1 P3_0 #define SB2 P3_1 #define SB3 P3_2 #define SB4 P3_3 #define SB5 P3_4 #define SB6 P3_5 #define SB7 P3_7 #define SB8 P1_0 /*输出继电器定义*/ sbit P1_7=P1^7; sbit P1_6=P1^6; sbit P1_5=P1^5; sbit P1_4=P1^4; sbit P1_3=P1^3; sbit P1_2=P1^2; sbit P1_1=P1^1; #define KA1 P1_7 #define KA2 P1_6 #define KA3 P1_5 #define KA4 P1_4 #define KA5 P1_3 #define KA6 P1_2 #define LED P1_1 /*声明函数*/ unsigned ch* ar i=0; /*声明变量i*/ void kt10ms(unsigned int co u* nt); /*定义时间继电器的延时时间*/ void sq1(void); void km1(void); void km2(void); void km3(void); void km4(void); void km5(void); void km6(void); void km7(void); void km8(void); /*程序初始化函数声明*/ /*==================================================*/ /* 主函数 */ void main(void) { /*程序初始化*/
P1=0XFF; P3=0XFF; SP=0X60; while(1) { sq1(); /*按钮判断子函数*/ switch(i) { case 1 : km1(); break; case 2 : km2(); break; case 3 : km3(); break; case 4 : km4(); break; case 5 : km5(); break; case 6 : km6(); break; case 7 : km7(); break; case 8 : km8(); break; default : break; } } } /*==================================================*/
/*=================================================*/ void sq1(void) { do { if(SB1==0) i=1; if(SB2==0) i=2; if(SB3==0) i=3; if(SB4==0) i=4; if(SB5==0) i=5; if(SB6==0) i=6; if(SB7==0) i=7; if(SB8==0) i=8; kt10ms(1); } while(i==0); } /*============================================= */ void km1(void) { KA1=0; i=0; while(!SB1); } void km2(void) { KA2=0; i=0; while(!SB2); } void km3(void) { KA3=0; i=0; while(!SB3); } void km4(void) { KA4=0; i=0; while(!SB4); } void km5(void) { KA5=0; i=0; while(!SB5); } void km6(void) { KA6=0; i=0; while(!SB6); } void km7(void) { LED=0; i=0; while(!SB7); } void km8(void) { KA1=1; KA2=1; KA3=1; KA4=1; KA5=1; KA6=1; LED=1; i=0; while(!SB8); } /*====================================== */ void kt10ms(unsigned int co u* nt) { unsigned int i,j,k; for(i=0;i<co u* nt;i++) for(j=0;j<10;j++) for(k=0;k<120;k++) ; }
如果大家有点什么疑问,可以通过电子邮箱sizipon@21cn.com与我联系。下次如有机会,将为大家介绍一种更加复杂的,也是用8051单片机制作,线路中加入RS485串口通讯,24C系列串行存储器,结合VB程序与Flash MX 2004,来实现PC联网程控。 地址:广西柳州市跃进路114号白沙客运站 姓名: 施志鹏 2006年9月4日星期一
|