找回密码
 立即注册
查看: 190|回复: 22

用 51 做了个 PLC:X、Y、高速计数输入、高速输出、Modbus等直接用,超低学习成本

[复制链接]
  • 打卡等级:偶尔看看III
  • 打卡总天数:40
  • 最近打卡:2026-03-05 13:45:21

9

主题

68

回帖

893

积分

高级会员

积分
893
发表于 4 天前 | 显示全部楼层 |阅读模式
大家好,我是一名嵌入式开发者。一直觉得工业 PLC 价格高、定制难,于是决定用 51 单片机从零做一个小型 PLC。现在已经实现了DI、DO、AI、AO、高速计数输入、Modbus RTU 通信、辅助继电器、通用数据寄存器、16位通用加计数器、32位通用加减计数器、1ms定时器、10ms定时器、100ms定时器、1s定时器、1min定时器,这个帖子将逐步介绍,项目在proteus上的STC15W4K32S4上实现,若有需要可提供实板原理图,进行定制专用的MCU-PLC。

1.png
2.png
微信qsssuv
回复

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:40
  • 最近打卡:2026-03-05 13:45:21

9

主题

68

回帖

893

积分

高级会员

积分
893
发表于 4 天前 | 显示全部楼层
本项目是一个已建立好的KEIL工程,下载后直接打开即可。
截图202603030858307033.jpg
直接在app_plc文件夹编写自己的代码就好了,
图片中的程序代码是在Y103输出500Hz,占空比50%的PWM波形
高速计数输入计250时,即250/500为0.5s,
在仿真中,将Y103连接到了X0,Y0接了一个LED灯,可以看到LED闪烁。
1.png
截图202603021754488387.jpg
微信qsssuv
回复

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:40
  • 最近打卡:2026-03-05 13:45:21

9

主题

68

回帖

893

积分

高级会员

积分
893
发表于 4 天前 | 显示全部楼层
这里放上proteus的仿真(需要8.15版本)、工程(内含设计说明书)。

PLC单片机.pdsprj

22.08 KB, 下载次数: 11

v1.0.0.260228.zip

545.87 KB, 下载次数: 23

微信qsssuv
回复

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:40
  • 最近打卡:2026-03-05 13:45:21

9

主题

68

回帖

893

积分

高级会员

积分
893
发表于 3 天前 | 显示全部楼层
通用输入/通用输出操作。
X为输入,Y为输出。
读取输入,直接写名称即可。
  1. IF (X0)
  2. {
  3.     ……
  4. }
复制代码

将输出置为0的三种写法:
  1. RST(Y0);
  2. Y0=0;
  3. MOV(0,Y0);
复制代码

将输出置为1的三种写法:
  1. SET(Y0);
  2. Y0=1;
  3. MOV(1,Y0);
复制代码

将输入短路至输出的两种写法:
  1. Y0=X0;
  2. MOV(X0,Y0);
复制代码
微信qsssuv
回复

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:40
  • 最近打卡:2026-03-05 13:45:21

9

主题

68

回帖

893

积分

高级会员

积分
893
发表于 3 天前 | 显示全部楼层
定时器。
所有的定时器,都是倒计时定时器,将从设置的值开始倒计时,若计数值达到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,用以下例子加以说明。
  1. //若T0定时10ms时间到,则输出Y0。
  2. IF (TON(T0,10)==T_STA_OK)
  3. {
  4.     SET(Y0);
  5. } ELSE {
  6.     RST(Y0);
  7. }
  8. //时间未到时,若X0输入,则暂停定时器,若X1输入,则重置定时器
  9. IF (TGetSta(T0)!=T_STA_OK)
  10. {
  11.     IF (X0) TPAUSE(T0);
  12.     IF (X1) TRST(T0);
  13. }
复制代码

//将计数值导出到D0
  1. D0 = TGetVal(T0);
复制代码

注意,定时器定时值的单位为对应时基:如1ms定时器T0,TON(T0,10)表示定时10ms;100ms定时器T100,TON(T100,5)表示定时500ms,以此类推。
微信qsssuv
回复

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:40
  • 最近打卡:2026-03-05 13:45:21

9

主题

68

回帖

893

积分

高级会员

积分
893
发表于 3 天前 | 显示全部楼层
计数器
计数器有3种状态,分别是停止(C_STA_STOP)、运行(C_STA_RUN)、计数到达(C_STA_OK)。
16位通用加计数器有2种方法。
第1种方法,加计数:CTU(要使用的计数器,信号源,计数目标值)。
例如使用计数器C0对X0的上升沿,进行加计数,到达10次时,Y0输出1s后重新开始计数。
  1. IF (CTU(C0,X0,10)==C_STA_OK)  //若计数器C0,捕捉到X0上升沿10次
  2. {
  3.     TON(T50,100);  //启动1s定时器
  4.     SET(Y0);  //输出Y0
  5. } ELSE {
  6.     RST(Y0);  //清除Y0
  7. }
  8. IF (TGetSta(T50)==T_STA_OK)  //若1s时间到
  9. {
  10.     RST(Y0);  //清除Y0
  11.     TRST(T50);  //重置定时器
  12.     C16RST(C0);  //重置计数器
  13. }
复制代码

第2种方法,减计数:CTD(要使用的计数器,信号源,计数目标值)。
例如使用计数器C1对X1的下降沿,进行减计数,到达10次时,Y1输出2s后重新开始计数。
  1. IF (CTD(C1,NOT(X1),10)==C_STA_OK)  //若计数器C1,捕捉到X0下降沿10次
  2. {
  3.     TON(T50,200);  //启动2s定时器
  4.     SET(Y1);  //输出Y1
  5. } ELSE {
  6.     RST(Y1);  //清除Y1
  7. }
  8. IF (TGetSta(T50)==T_STA_OK)  //若计时时间到
  9. {
  10.     RST(Y1);  //清除Y1
  11.     TRST(T50);  //重置定时器
  12.     C16RST(C1);  //重置计数器
  13. }
复制代码

32位通用计数器有1种方法。CTUD(计数器,加计数信号源,减计数信号源,计数目标值)。
例如使用计数器C200,X0作为加计数信号源,X1作为减计数信号源,当数值到达200时,Y0输出2s,然后重新计数。
由于32位通用计数器在计数完成后,仍会受到加减操作的影响,导致状态变更,因此引入辅助继电器,避免Y0的输出波动。
  1. IF (M0==0)  //若M0为0
  2. {
  3.     IF (CTUD(C200,X0,X1,200)==C_STA_OK)  //若计数器C200,在X0和X1的计数信号下,达到200次
  4.     {
  5.         TON(T50,200);  //启动2s定时器
  6.         SET(Y0);  //输出Y0
  7.         SET(M0);  //置位M0
  8.     } ELSE {
  9.         RST(Y0);  //清除Y0
  10.     }
  11. }
  12. IF (TGetSta(T50)==T_STA_OK)  //若定时时间到
  13. {
  14.     RST(Y0);  //清除Y0
  15.     C32RST(C200);  //重置计数器
  16.     RST(M0);  //清除M0
  17.     TRST(T50);  //重置定时器
  18. }
复制代码

微信qsssuv
回复

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:55
  • 最近打卡:2026-03-03 08:35:54
已绑定手机

5

主题

1092

回帖

1374

积分

金牌会员

积分
1374
发表于 3 天前 | 显示全部楼层
佩服版主!

我先慢慢看懂,打算好好跟您学习这个技能!
回复

使用道具 举报 送花

  • 打卡等级:以坛为家III
  • 打卡总天数:797
  • 最近打卡:2026-03-05 08:17:59
已绑定手机

25

主题

625

回帖

3917

积分

论坛元老

积分
3917
发表于 3 天前 | 显示全部楼层
不错,加上EtherCAT、Profinet、ModbusTCP吧
回复

使用道具 举报 送花

  • 打卡等级:以坛为家III
  • 打卡总天数:823
  • 最近打卡:2026-03-05 08:20:20
已绑定手机

58

主题

2004

回帖

3568

积分

论坛元老

积分
3568
发表于 3 天前 | 显示全部楼层
请问能控制几轴?
回复

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:40
  • 最近打卡:2026-03-05 13:45:21

9

主题

68

回帖

893

积分

高级会员

积分
893
发表于 3 天前 | 显示全部楼层
jw*** 发表于 2026-3-3 15:55
请问能控制几轴?

可以做4轴控制,目前这个基础免费版项目是建立在proteus仿真上面的。要落地电路板,需要有客户定制
微信qsssuv
回复

使用道具 举报 送花

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

本版积分规则

QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2026-3-6 05:11 , Processed in 0.124449 second(s), 88 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表