网页
资讯
视频
图片
知道
文库
贴吧
地图
采购
进入贴吧
全吧搜索
吧内搜索
搜贴
搜人
进吧
搜标签
日
一
二
三
四
五
六
签到排名:今日本吧第
个签到,
本吧因你更精彩,明天继续来努力!
本吧签到人数:0
一键签到
成为超级会员,使用一键签到
一键签到
本月漏签
0
次!
0
成为超级会员,赠送8张补签卡
如何使用?
点击日历上漏签日期,即可进行
补签
。
连续签到:
天 累计签到:
天
0
超级会员单次开通12个月以上,赠送连续签到卡3张
使用连续签到卡
03月12日
漏签
0
天
单片机吧
关注:
213,355
贴子:
1,051,403
看贴
图片
吧主推荐
视频
游戏
17
回复贴,共
1
页
<<返回单片机吧
>0< 加载中...
用 51 做了个 PLC,面向单片机极速入门、PLC替换开发者
只看楼主
收藏
回复
青穗三三
少校
10
该楼层疑似违规已被系统折叠
隐藏此楼
查看此楼
大家好,我是一名嵌入式开发者。一直觉得工业 PLC 价格高、定制难,于是决定用 51 单片机从零做一个小型 PLC。现在已经实现了DI、DO、AI、AO、高速计数输入、Modbus RTU 通信、辅助继电器、通用数据寄存器、16位通用加计数器、32位通用加减计数器、1ms定时器、10ms定时器、100ms定时器、1s定时器、1min定时器,这个帖子将逐步介绍,项目在proteus上的STC15W4K32S4上实现,若有需要可提供实板原理图,进行定制专用的MCU-PLC。
青穗三三
少校
10
该楼层疑似违规已被系统折叠
隐藏此楼
查看此楼
本项目是一个已建立好的KEIL工程,下载后直接打开即可。
直接在app_plc文件夹编写自己的代码就好了,
图片中的程序代码是在Y103输出500Hz,占空比50%的PWM波形
高速计数输入计250时,即250/500为0.5s,
在仿真中,将Y103连接到了X0,Y0接了一个LED灯,可以看到LED闪烁。
2026-03-12 18:04:12
广告
不感兴趣
开通SVIP免广告
青穗三三
少校
10
该楼层疑似违规已被系统折叠
隐藏此楼
查看此楼
由于贴吧不能上传附件,所以我把仿真文件、工程,都上传到了QQ群761120428,可以到QQ群文件下载。位于:群文件——MCU-PLC项目
青穗三三
少校
10
该楼层疑似违规已被系统折叠
隐藏此楼
查看此楼
通用输入/通用输出操作。
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);
青穗三三
少校
10
该楼层疑似违规已被系统折叠
隐藏此楼
查看此楼
定时器。
定时器有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,以此类推。
青穗三三
少校
10
该楼层疑似违规已被系统折叠
隐藏此楼
查看此楼
计数器有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); //重置定时器
}
青穗三三
少校
10
该楼层疑似违规已被系统折叠
隐藏此楼
查看此楼
高速输出/PWM
控制高速输出有4种方法。分别为以下:
以Y100为例。
输出控制:PWM_OUT(Y100,频率,占空比)。频率范围为400Hz~100KHz,占空比范围为0-100,为整数,请勿使用小数。占空比0=无输出,100=持续高电平。
获取输出频率:PWM_GetFre(Y100)。返回设置的频率,若未设置,返回0。
获取输出占空比:PWM_GetDuty(Y100)。返回设置的占空比,若未设置,返回255。
停止输出:PWM_STOP(Y100)。Y100将为0。
注:若不进行高速输出,其默认将为一个通用输出。
青穗三三
少校
10
该楼层疑似违规已被系统折叠
隐藏此楼
查看此楼
高速计数输入
需要用到特殊辅助继电器、特殊数据寄存器,这里使用了一看就明白的变量值。
使能高速计数输入X0,注意使能后,请勿将其用作通用输入接口:
DX0_CNT=0; //设置起始计数值
MX0_OUT=0; //清除溢出标志
DX0_MAX=100; //定义设置上限
SET(MX0_EN); //启动
停用高速计数输入X0,停用后,可用作通用输入接口:
RST(MX0_EN); //清除使能。除非用户手动清除计数值DX0_CNT,否则启动后继续计数
当起始计数值DX0_CNT达到设置上限DX0_MAX,溢出标志MX0_OUT会置1,并且DX0_CNT从0开始。需要用户手动清除溢出标志MX0_OUT。
需要注意,受限于MCU的性能,若值范围为0~255,则计数的设置上限,以及起始计数值,设置时均不可超出此范围。
若需要使用高速计数输入X3,将以上代码中的X0修改为X3使用即可。
2026-03-12 17:58:12
广告
不感兴趣
开通SVIP免广告
贴吧用户_JRCyMaE
新兵
1
该楼层疑似违规已被系统折叠
隐藏此楼
查看此楼
大佬有抗干扰吗
青穗三三
少校
10
该楼层疑似违规已被系统折叠
隐藏此楼
查看此楼
模拟量输入
直接读取值即可:
D0=AI0;
青穗三三
少校
10
该楼层疑似违规已被系统折叠
隐藏此楼
查看此楼
日期和时间
dhms是一个集合了设备已运行时间的对象。包含天数、时、分、秒。
dhms.day,天,最大到32767。
dhms.hour,时。
dhms.min,分。
dhms.sec,秒。
用户可将其加载至通用数据寄存器。
青穗三三
少校
10
该楼层疑似违规已被系统折叠
隐藏此楼
查看此楼
【Modbus-RTU从站协议】
通信配置:4800,N,8,1。访问地址固定为1。
寄存器表就不贴图了,可以下载下来看设计说明中的详细内容。
总之,就是直接连上Modscan工具就可以使用,很方便。
在仿真上,你需要安装虚拟串口驱动,才能使用modscan连接到proteus仿真。
在app_plc_reg_update文件中,填写了默认的更新事件内容,用户可自定义其它行为
青穗三三
少校
10
该楼层疑似违规已被系统折叠
隐藏此楼
查看此楼
本 log 函数是针对 MCU-PLC 硬件场景定制的日志输出函数。
/********************************
功能描述:打印到控制台(串口输出)
参数说明:*format:格式控制。支持以下格式:
%d:s16数据
%u:u16数据
%ld:s32数据
%lu:u32数据
%s:字符串
%c:ASCII字符
%X:u16数据的16进制字符串
%lX:u32数据的16进制字符串
%[0][1-5]u:以n的宽度显示u16数据,不足时可前置添0,超过时宽度限制无效
%[0][1-10]lu:以n的宽度显示u32数据,不足时可前置添0,超过时宽度限制无效
%.[0-4]d:对s16数据以小数形式呈现
%.[0-9]ld:对s32数据以小数形式呈现
%.[0-4]u:对u16数据以小数形式呈现
%.[0-9]lu:对u32数据以小数形式呈现
%.nd:参数1为保留小数位数,参数为2为s16数据
%.nld:参数1为保留小数位数,参数为2为s32数据
%.nu:参数1为保留小数位数,参数为2为u16数据
%.nlu:参数1为保留小数位数,参数为2为u32数据
%t:参数1为字符串指针。参数2为限制长度,可以是参数1的空间大小-1。将此字符之前的格式化的字符复制到第1个字符串指针位置
%hs:参数1为u8指针。参数2为限制长度。将此数据转为十六进制字符串。
%hn:参数1为u8指针。参数2为限制长度。直接拷贝源数据。
返回值:指向数据缓冲区的指针,除%t参数外,其它功能都会使得该数据区以字符串结束符结束(\0)
********************************/
char *log(char *format, ...);
例如,将AI0打印至窗口
log("AI0:%u\r\n",AI0);
受限MCU的资源,打印多个参数时,可能输出异常,可以分解进行单个打印。
贴吧用户_5GyeRK1
新兵
1
该楼层疑似违规已被系统折叠
隐藏此楼
查看此楼
大佬,我想请问一下vscode上有什么插件可以实现开发stc32g144k246这块板子吗
登录百度账号
扫二维码下载贴吧客户端
下载贴吧APP
看高清直播、视频!
贴吧页面意见反馈
违规贴吧举报反馈通道
贴吧违规信息处理公示