用 51 做了个 PLC:X、Y、高速计数输入、高速输出、Modbus等直接用,超低学习成本
大家好,我是一名嵌入式开发者。一直觉得工业 PLC 价格高、定制难,于是决定用 51 单片机从零做一个小型 PLC。现在已经实现了DI、DO、AI、AO、高速计数输入、Modbus RTU 通信、辅助继电器、通用数据寄存器、16位通用加计数器、32位通用加减计数器、1ms定时器、10ms定时器、100ms定时器、1s定时器、1min定时器,这个帖子将逐步介绍,项目在proteus上的STC15W4K32S4上实现,若有需要可提供实板原理图,进行定制专用的MCU-PLC。2026.3.14
视频教程已上传至B站 本项目是一个已建立好的KEIL工程,下载后直接打开即可。
直接在app_plc文件夹编写自己的代码就好了,
图片中的程序代码是在Y103输出500Hz,占空比50%的PWM波形
高速计数输入计250时,即250/500为0.5s,
在仿真中,将Y103连接到了X0,Y0接了一个LED灯,可以看到LED闪烁。
这里放上proteus的仿真(需要8.15版本)、工程(内含设计说明书)。
通用输入/通用输出操作。
X为输入,Y为输出。
读取输入,直接写名称即可。
IF (X0)
{
……
}
将输出置为0的三种写法:
RST(Y0);
Y0=0;
MOV(0,Y0);
将输出置为1的三种写法:
SET(Y0);
Y0=1;
MOV(1,Y0);
将输入短路至输出的两种写法:
Y0=X0;
MOV(X0,Y0); 定时器。
所有的定时器,都是倒计时定时器,将从设置的值开始倒计时,若计数值达到0,运行状态T_STA_RUN,将转变为计时到达状态T_STA_OK。定时器有4种状态、5种使用方法。
4种状态分别是:停止(T_STA_STOP)、运行(T_STA_RUN)、暂停(T_STA_PAUSE)、计时到达(T_STA_OK)。
5种使用方法分别是TON、TPAUSE、TRST、TGetSta、TGetVal,用以下例子加以说明。
//若T0定时10ms时间到,则输出Y0。
IF (TON(T0,10)==T_STA_OK)
{
SET(Y0);
} ELSE {
RST(Y0);
}
//时间未到时,若X0输入,则暂停定时器,若X1输入,则重置定时器
IF (TGetSta(T0)!=T_STA_OK)
{
IF (X0) TPAUSE(T0);
IF (X1) TRST(T0);
}
//将计数值导出到D0
D0 = TGetVal(T0);
注意,定时器定时值的单位为对应时基:如1ms定时器T0,TON(T0,10)表示定时10ms;100ms定时器T100,TON(T100,5)表示定时500ms,以此类推。 计数器
计数器有3种状态,分别是停止(C_STA_STOP)、运行(C_STA_RUN)、计数到达(C_STA_OK)。
16位通用加计数器有2种方法。
第1种方法,加计数:CTU(要使用的计数器,信号源,计数目标值)。
例如使用计数器C0对X0的上升沿,进行加计数,到达10次时,Y0输出1s后重新开始计数。
IF (CTU(C0,X0,10)==C_STA_OK)//若计数器C0,捕捉到X0上升沿10次
{
TON(T50,100);//启动1s定时器
SET(Y0);//输出Y0
} ELSE {
RST(Y0);//清除Y0
}
IF (TGetSta(T50)==T_STA_OK)//若1s时间到
{
RST(Y0);//清除Y0
TRST(T50);//重置定时器
C16RST(C0);//重置计数器
}
第2种方法,减计数:CTD(要使用的计数器,信号源,计数目标值)。
例如使用计数器C1对X1的下降沿,进行减计数,到达10次时,Y1输出2s后重新开始计数。
IF (CTD(C1,NOT(X1),10)==C_STA_OK)//若计数器C1,捕捉到X0下降沿10次
{
TON(T50,200);//启动2s定时器
SET(Y1);//输出Y1
} ELSE {
RST(Y1);//清除Y1
}
IF (TGetSta(T50)==T_STA_OK)//若计时时间到
{
RST(Y1);//清除Y1
TRST(T50);//重置定时器
C16RST(C1);//重置计数器
}
32位通用计数器有1种方法。CTUD(计数器,加计数信号源,减计数信号源,计数目标值)。
例如使用计数器C200,X0作为加计数信号源,X1作为减计数信号源,当数值到达200时,Y0输出2s,然后重新计数。
由于32位通用计数器在计数完成后,仍会受到加减操作的影响,导致状态变更,因此引入辅助继电器,避免Y0的输出波动。
IF (M0==0)//若M0为0
{
IF (CTUD(C200,X0,X1,200)==C_STA_OK)//若计数器C200,在X0和X1的计数信号下,达到200次
{
TON(T50,200);//启动2s定时器
SET(Y0);//输出Y0
SET(M0);//置位M0
} ELSE {
RST(Y0);//清除Y0
}
}
IF (TGetSta(T50)==T_STA_OK)//若定时时间到
{
RST(Y0);//清除Y0
C32RST(C200);//重置计数器
RST(M0);//清除M0
TRST(T50);//重置定时器
}
佩服版主!
我先慢慢看懂,打算好好跟您学习这个技能! 不错,加上EtherCAT、Profinet、ModbusTCP吧 请问能控制几轴? jwd 发表于 2026-3-3 15:55
请问能控制几轴?
可以做4轴控制,目前这个基础免费版项目是建立在proteus仿真上面的。要落地电路板,需要有客户定制