PLC如何与单片机进行通讯?共有三种方法!你会用几个?
原创不易,请勿抄袭!
通讯是一个工控朋友学习或者工作到一定程度不得不面对的一个难题,可也是区别新手和高手的一道分水岭,新手遇到通讯问题往往会比较抓狂,不知道如何着手,而老手即使面对没有经验的设备也会有一个大概的思路.有朋友问我关于西门子PLC与单片机通讯的问题,今天给大家汇总一下.
首先西门子PLC与单片机共有三种办法进行信号交换:
1 信号线连接.这是一种最简单的方式,即在单片机和PLC之间进行连接信号线,PLC的输入接单片机输出;PLC输出接单片机输入,这是一种最普遍的方式,通过这种方式PLC几乎可以和任何工控的控制装置连接,比如伺服系统,变频器,机器人等等!缺点是如果需要传递的信号太多,那么电缆数量也会很大,而且一旦电缆损坏,维护起来很困难!
2 自由口通讯,以前我们多次讲到过自由口通讯,而且专门讲解过ASCII码,有需要的朋友可以去我以前的文章里去找,今天不重复了。
3 第三种方法是利用ModBus协议进行通讯。
本节主要讲解以PLC作主站,51单片机作从站,用ModBus协议进行通讯。PLC读取单片机保持寄存器区的数据。S7-200PLC程序主要通过调用Modubs RTU 主站指令库完成。
一、调用 Modbus RTU 主站初始化和控制子程序
使用 SM0.0 调用 MBUS_CTRL 完成主站的初始化,并启动其功能控制:
各参数意义如下:
1 EN 使能:必须保证每一扫描周期都被使能(使用 SM0.0)
2 Mode 模式:为 1 时,使能 Modbus 协议功能;为 0 时恢复为系统 PPI 协议
3 Baud 波特率:支持的通讯波特率为1200,2400,4800,9600,19200,38400,57600,115200。
4 Parity 校验:校验方式选择;0=无校验,1=奇较验,2=偶较验。
5 Timeout 超时:主站等待从站响应的时间,以毫秒为单位,典型的设置值为 1000 毫秒(1 秒),允许设置的范围为 1 - 32767。
注意: 这个值必须设置足够大以保证从站有时间响应。
6 Done 完成位:初始化完成,此位会自动置1。可以用该位启动 MBUS_MSG 读写操作(见例程)
7 Error 初始化错误代码(只有在 Done 位为1时有效): 0= 无错误,1= 校验选择非法,2= 波特率选择非法,3= 模式选择非法。
二、调用 Modbus RTU 主站读写子程序MBUS_MSG,发送一个Modbus 请求;
各参数意义如下:
常见的错误:
如果多个 MBUS_MSG 指令同时使能会造成 6 号错误库存储区被程序其它地方复用,有时也会造成6 号错误从站 delay 参数设的时间过长会造成主站 3 号错误从站掉电或不运行,网络故障都会造成主站 3 号错误。
含义如下:
1 EN 使能:同一时刻只能有一个读写功能(即 MBUS_MSG)使能
注意:建议每一个读写功能(即 MBUS_MSG)都用上一个 MBUS_MSG 指令的 Done 完成位来激活,以保证所有读写指令循环进行(见例程)。
2 First 读写请求位:每一个新的读写请求必须使用脉冲触发
3 Slave 从站地址:可选择的范围 1 - 247
4 RW 从站地址:0 = 读, 1 = 写;注意:
1. 开关量输出和保持寄存器支持读和写功能
2. 开关量输入和模拟量输入只支持读功能
5 Addr 读写从站的数据地址:选择读写的数据类型
00001 至 0xxxx - 开关量输出
10001 至 1xxxx - 开关量输入
30001 至 3xxxx - 模拟量输入
40001 至 4xxxx - 保持寄存器
6 Count 数据个数;通讯的数据个数(位或字的个数)
注意: Modbus主站可读/写的最大数据量为120个字(是指每一个 MBUS_MSG 指令)
7 DataPtr 数据指针:
1. 如果是读指令,读回的数据放到这个数据区中
2. 如果是写指令,要写出的数据放到这个数据区中
8 Done 完成位 读写功能完成位
9 Error 错误代码:只有在 Done 位为1时,错误代码才有效
0 = 无错误
1 = 响应校验错误
2 = 未用
3 = 接收超时(从站无响应)
4 = 请求参数错误(slave address, Modbus address, count, RW)
5 = Modbus/自由口未使能
6 = Modbus正在忙于其它请求
7 = 响应错误(响应不是请求的操作)
8 = 响应CRC校验和错误
-
101 = 从站不支持请求的功能
102 = 从站不支持数据地址
103 = 从站不支持此种数据类型
104 = 从站设备故障
105 = 从站接受了信息,但是响应被延迟
106 = 从站忙,拒绝了该信息
107 = 从站拒绝了信息
108 = 从站存储器奇偶错误
三、需要从站支持的功能及Modbus 保持寄存器地址映射
为了支持上述 Modbus 地址的读写,Modbus Master 协议库需要从站支持下列功能:
Modbus 保持寄存器地址映射举例:
四、S7-200PLC程序
五、单片机程序;STC11F04E单片机,9600波特率
START: MOV TMOD,#21H ;定时器1是8位再装入,定时器0为16位定时器
MOV TH1,#0FDH;预置初值(按照波特率9600BPS预置初值)
MOV TL1,#0FDH; 0FDH=9600=11.0592
MOV TH0, #0DCH;88H ;8800=12t,7000=stc1t
MOV TL0, #00H
ORL IE, #92H ;EA=1,ES=1;ET0=1
SETB PS ;串口中断优先
SETB TR1 ;启动定时器1
MOV 98H,#50H ;scon
MOV P1M0,#01000000b ; P1M0=0 P1M1=0双向口 P1M0=1 P1M1=0输入口 P1M0=0 P1M1=1推挽输出20ma
MOV P1M1,#10000000b
MOV WDT_CONTR ,#27H 看门狗设置使能
QL0: MOV A,#00H
MOV R0,#10H
MOV R2,#9BH ;10-ABH清零
CLEAR: MOV @R0,A
INC R0
DJNZ R2,CLEAR
CLR FLAG
CLR FLAG_0
SETB TR0 ;启动定时器0
;ANL AUX,#07FH ;p3.0p3.1当串口
ORL AUX,#80H ;p1.7,p1.6当串口
CLR P3.7 ;485芯片接收使能
WA1: ;MOV WDT_CONTR ,#37H;喂狗; SETB CW
JNB FLAG_0,WA1 ;FLAG_0=1表示已经接收到上位机数据
CLR TR0
MOV A,2CH ;检查设备地址是01h码,设本机地址码是1
MOV R2,A
XRL A,#01H
JNZ QL0
ACALL FSZJ ;FH: DB 01H,03H,16,00H,01H,02H,03H,04H,05H,06H,07H,08H,09H,10H,11H,12H,0DH,0EH,0FH,10H,11H,12H,13H,14H,15H,16H,17H,18H,19H,1AH,1BH,1CH,1DH,1EH,1FH;18
ACALL DELAY
CALL FZJ
AJMP QL0
FZJ: MOV R0,#2cH ;向主机发送数据子程序
FZJ0: MOV R2,#10H
FZJ1: CLR EA
ANL AUX,#07FH ;p3.0p3.1当串口
FZL1: MOV A,@R0
MOV SBUF,A
JNB TI,$
CLR TI
INC R0
DJNZ R2,FZL1
SETB EA
RET
FSZJ: MOV DPTR,#FH
MOV R2,#19;
ORL AUX,#80H
SETB P3.7 ;发送数据
MOV R0,#40H
FSZJA: MOV A,#0H
MOVC A,@A+DPTR
MOV @R0,A
INC R0
INC DPTR
DJNZ R2,FSZJA
MOV R0,#40H
MOV CRCCD,#19
LCALL CRC1
MOV R2,#21
MOV R0,#40H
FSZJ2: MOV A,@R0
MOV SBUF,A
JNB TI,$
CLR TI
INC R0
DJNZ R2,FSZJ2
SETB EA
RET
FH:DB 01H,03H,16,00H,01H,02H,03H,04H,05H,06H,07H,08H,09H,10H,11H,12H,0DH,0EH,0FH,10H,11H,12H,13H,14H,15H,16H,17H,18H,19H,1AH,1BH,1CH,1DH,1EH,1FH;18
用串口助手检测到的数据如下图。
喜欢的话请点赞并分享,您的支持是我坚持下去的动力!送人玫瑰,手有余香!
详解单片机程序的运行过程
从单片机上知道,在上电的那一刻,MCU的程序指针PC会被初始化为上电复位时的地址,从哪个地址处读取将要执行的指令,由此程序在MCU上开始执行(当然在调用程序的 main之前,还有一系列其他的的初始化要做,如堆栈的初始化,不过这些我们很少回去修改)。PC在上电时,和MCU差不多,不过读取的是BIOS,有它完成了很多初始化操作,最后,调用系统的初始化函数,将控制权交给了操作系统,于是我们看到了Windows,Linux系统启动了。
如果将操作系统看作是在处理器上跑的一个很大的裸机程序(就是直接在硬件上跑的程序,因为操作系统就是直接跑在CPU上的,这样看待是可以的,不过这个裸机程序功能很多,很强大),那么操作系统的启动很像MCU程序的启动。前者有一个很大的初始化程序完成很复杂的初始化,后者有一段不长的汇编代码完成一些简单的初始化。这一点看,它们在流程上是很相似的。
详解单片机程序的运行过程
如果是系统上的程序启动呢?它们是由系统来决定的。Linux上在shell下输入。/p后,首先检查是否是一个内建的shell命令;如果不是,则shell假设他是一个可执行文件(Linux上一般是elf格式),然后调用一些相关的函数,将在硬盘上的p文件的内容拷贝到内存(DDR RAM)中,并建立一个它的运行环境(当然这里边还有内存映射,虚拟内存,连接与加载,等一些其他东西),准备执行。
由以上可知,单片机上的程序和平时在系统上运行的程序,在启动时差异是很大的(如果将程序调用main以前的动作,都抽象为初始化的话,程序的启动可以简化为:建立运行环境+调用main函数,这样程序的执行差异是不大的)。因为单片机上跑的程序(裸机程序),是和操作系统一样跑在硬件上的,它们属于一个层次的。过去之所以没有区分出单片机上的程序和PC机上的程序的一些差异,就是没有弄明白这一点。
由此,以前的一些疑惑也就解开了。为什么在单片机上的程序不怎么使用malloc,而PC上经常使用?因为单片机上没有已经写好的内存管理算法的代码,而在PC上操作系统里运行的程序,libc已经把这些都做了,只需要调用就可以了。如果在单片机上想用动态内存,也可以,但是这些代码要自己去实现,并定义一个相应的malloc,有时候一些公司会给提供一些库函数可能会实现malloc,但是因为单片机上RAM内存十分有限,如果不知道它的运行方式,估计会很危险。同样,因为在PC的系统上运行的程序与逻机程序的不同,裸机程序不会有动态链接,有的只是静态链接。
关于程序在执行时,从哪里读取指令,哪里读取数据,也曾因为没有弄清楚系统上的程序和裸机程序之间的区别,而疑惑了很久。虽然在《微型计算机原理》课上知道程序运行时,从内存中读取指令和数据进行执行和回写。但是单片机上只有几K的RAM,而flash一般有几十K甚至1M,这个时候指令和数据都在内存中吗(这里指的内存仅指RAM,因为PC上我们常说的内存就是DDR RAM memory,先入为主以至于认为单片机上也是这样,还没有明白其实RAM和Flash都是内存)?这不可能,因为课上老师只说内存,但是PC上内存一般就是DDR RAM,不会是硬盘,硬盘是保存数据的地方;由此类比时,自己把自己弄晕菜了,单片机的RAM对应于DDR RAM,那Flash是不是就对应于硬盘了呢?在CSAPP上明白了,PC上之所以都在DDR RAM上,是速度的因素。
硬盘的速度太慢,即使是即将到来的SSD比起DDRRAM,还是差着几个数量级,所以拷贝到DDRRAM中。这时,一个程序的代码和数据是连续存放的,其中代码段是只读区域,数据段是可读写区域(这是由操作系统的内存管理机制决定的)。运行时,再将它们拷贝到速度更快的SRAM中,以得到更快的执行速度。而对于,单片机而言工作频率也就几M,几十M,从Flash中与从RAM中读的差异可能并不明显,不会成为程序执行的瓶颈(而对于PC而言,Flash的速度太慢,DDRRAM的速度也是很慢,即使是SRAM也是慢了不少,于是再提高工作频率也提高不了程序的执行速度,所以现在CPU工作频率最快是在2003左右。一个瓶颈出现了。
为了提高CPU的使用率,换个角度想一下,既然不能减少一段程序的执行时间,就在同样的时间执行更多的程序,一个核执行一段程序,两个核就可以执行两段程序,于是多核CPU成为了现在的主流)。所以裸机程序指令就在Flash(Flash memory)中存放,而数据就放在了RAM中(flash的写入次数有限制,同时它的速度和RAM还是差很多)。更广泛说,在单片机上RAM存放data段,bss段,堆栈段;ROM(EPROM,EEPROM,Flash等非易失性存储设备)存放代码,只读数据段。本质上说,这和PC上程序都在RAM中存放是一样的,PC 上是操作系统规定了可读与可写,而单片机上是依靠不同的存储设备区分了可读与可写(当然现在的Flash是可读写的,如果Flash没有写入次数限制,速度又可以和RAM相差不多,单片机上是不是只要Flash就可以了呢(直接相当于PC上的DDRRAM)?这样成本也会比一个RAM,一个Flash低,更节省成本,对于生产商更划算)。
对于单片机的程序执行时指令和数据的存放与读取,理解如下:
对单片机编程后,程序的代码段,data段,bss段,rodata段等都存放在Flash中。当单片机上电后,初始化汇编代码将data段,bss段,复制到RAM中,并建立好堆栈,开始调用程序的main函数。以后,便有了程序存储器,和数据存储器之分,运行时从Flash(即指令存储器,代码存储器)中读取指令 ,从RAM中读取与写入数据。RAM存在的意义就在于速度更快。
无论是单片机也好,PC也罢,存在的存储器金字塔都是一致的,速度的因素,成本的限制导致了一级级更快的存储器的更快速度与更高的成本。应该说,对于它们的理解,就是存储器金字塔的理解。
相关问答
怎样把 单片机 内的 程序读取 出来?将单片机的程序读取出来需要使用专门的工具和技术,具体步骤如下:首先需要使用编程器将程序烧录到单片机中,然后使用仿真器将单片机连接到计算机上。接着,使...
stc 单片机 如何读出里面的 程序 ?STC单片机的程序是通过编译器编写出来的HEX文件,需要通过编程器将HEX文件下载到STC单片机的闪存中。如果你想读取STC单片机中的程序,需要使用专门的编程器,具...
PIC16C54C 单片机 能把里面的 程序 读出来吗?怎么解密,用什么编程器?但所有伪指令和宏指令都没有了,这个看起来很难懂得。如果已经加密了,拷出来也看不了,黑客一不行,因为加密算法是不可逆的。如果程序原本是C语言写的,但C...
单片机 如何检测信号的频率?如果被测信号频率远大于单片机工作频率(机器周期),可以通过外部可编程分频器降到单片机可以接受的频率范围。如果被测信号频率稍低于单片机工作频率,可以采...
跪求,怎样读出 单片机 加密的 程序 ?有些编程器可以直接读取一般的加密单片机芯片,但是OTP加密的话,一般都无能为力了。另外,解密时,有可能损坏被解密的单片机芯片。有些编程器可以直接读取一般...
单片机 控制板里边的固件怎么样 读取 出来?单片机控制板中的固件可以通过多种方式进行读取,具体取决于单片机的型号和特性。以下是几种常见的读取固件的方法:1.使用专用的编程工具:某些单片机可以通过...
单片机 如何 读取 存储IC的代码?您可能遇到加密的了,一般情况下是可以方便的读出来的。但是如果有加密就不可能了。比如采用焊丝深埋技术的集成芯片就根本无法读出内部信息。不过有时候可能...
单片机 温度报警器实验步骤?3.连接显示器和报警器到单片机的输出引脚,用于显示当前温度和触发报警。4.在单片机开发环境中,编写程序,包括读取温度传感器的值、判断是否触发报警以及控制...
电脑如何 读取单片机 USB接口的数据?单片机串口是TTL电平输出,所以必须通过TTL-rs232转换,一般用max232芯片,很简单。本来可以直接接电脑的COM口9RS232电平)。但要求接USB口,所以,还必须要有rs...
如何实现 单片机 通过WIFI获取时间和天气数据?如果是arm的开发板,很简单,能够直接实现获取互联网上的数据,编个程序提取网站上的信息就行(wifi的驱动如果已经有了最好,没有就要自己写驱动了……),,如果...