如何用AT89系列单片机自制PLC控制板

[复制链接]
查看9471 | 回复5 | 2007-4-28 11:30:00 | 显示全部楼层 |阅读模式

设计者: 施志鹏
在如今自动化生产过程中,大多都是以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日星期一

yf820625 | 2007-5-13 20:53:00 | 显示全部楼层

不知道有没有实用性啊

就是说拿到企业,别人会不会用呢?

xuliang987 | 2007-5-17 19:45:00 | 显示全部楼层

学习中

takaoksj | 2007-8-9 12:15:00 | 显示全部楼层
谢了,学习中!!!
didhuang | 2007-8-16 15:26:00 | 显示全部楼层

工控产品重要不是价格而是稳定性,不知这个的长期工作的稳定性如何

xlian5105 | 2007-8-28 10:13:00 | 显示全部楼层

用2051制作用三菱PLC编辑软件编写程序自制PLC

嵌入式单片PLC简介

可用资源

输入:8 X0—X7

输出:8 Y0—Y7

程序空间: 500

中间继电器:128 M0—M127

时间继电器:16点 T0—T15 160.1秒定时器 定时范围(0-65535*0.1

计数器:  16点 C0—C15 16位增计数器  计数范围(0-65535

数据寄存器 16点 D0—D15 16位无符号整数  0-65535

编程注意:

块操作不能超过7

堆栈操作不能超过7

脉冲执行点数不能超过128

用三菱编程软件编辑程序,选择PLC型号 FX1N

下载上传程序选择全范围

设置密码无效

无监控功能

指令功能详解:

LD  取常开  XYMCTM8  

LDI  取常闭  XYMCTM8

AND 串联常开 XYMCTM8

ANI  串联常闭 XYMCTM8

OR  并联常开 XYMCTM8

ORI 并联常闭 XYMCTM8

LDP 取上升沿 XYMCTM8

LDF 取下降沿 XYMCTM8

PLS 上升沿脉冲 YM

PLF 下降沿脉冲 YM

ANDP 串联上升沿 XYMCTM8

ANDF 串联下降沿 XYMCTM8

ORP 并联上升沿 XYMCTM8

ORF 并联下降沿 XYMCTM8

ORB 块并联

ANB 块串联

MPS 入栈

MPR 读栈

MPP 出栈

ALT  输出取反     可用触点 YM

ALTP 脉冲执行输出取反 可用触点 YM

OUT  输出 YMCT

SET  置位YM

RST  复位YMCT

LD> 大于  操作数可为KnX KnY KnM D C T

LD< 小于  操作数可为KnX KnY KnM D C T

LD= 等于  操作数可为KnX KnY KnM D C T

LD<> 不等    操作数可为KnX KnY KnM D C T

LD>= 大于等于  操作数可为KnX KnY KnM D C T

LD<= 小于等于  操作数可为KnX KnY KnM D C T

AND> 与大于   操作数可为KnX KnY KnM D C T

AND< 与小于   操作数可为KnX KnY KnM D C T

AND= 与等于   操作数可为KnX KnY KnM D C T

AND>= 与大于等于 操作数可为KnX KnY KnM D C T

AND<= 与小于等于 操作数可为KnX KnY KnM D C T

AND<> 与不等于  操作数可为KnX KnY KnM D C T

OR>   或大于   操作数可为KnX KnY KnM D C T

OR<   或小于   操作数可为KnX KnY KnM D C T

OR=   或等于   操作数可为KnX KnY KnM D C T

OR<>  或不等于  操作数可为KnX KnY KnM D C T

OR>=  或大于等于 操作数可为KnX KnY KnM D C T

OR<=  或小于等于 操作数可为KnX KnY KnM D C T

MOV n1 n2 传数  n1 操作数可为KnX KnY KnM D C T

n 2 操作数可为KnY KnM D C T

INC 加一     操作数可为 D C T

DEC   减一     操作数可为 D C T

NOP 空操作

END 程序结束指令

8289490@zsnet.com

您需要登录后才可以回帖 登录 | 注册哦

本版积分规则