带你了解单片机的通信协议
带你了解单片机的通信协议
通讯协议:通讯协议是指在单片机开发中,不同的硬件系统或者操作系统之间进行数据交换的方式。是一种数据要进行传输的约定规则。
通讯协议通常来说有很多种,那我们今天要说的就是串口通讯协议,我们是基于STM32简单的说一下。
串口通信。串口是单片机非常常见的一种外设。常见的UART串口主要有两条线,一条是发送、一条是接收。许多单片机所自带的串口都是已经把这个最底层的电平级别的协议做好了,我们直接使用就可以了,收发都是以一个字节为单位来进行的。
举个例子,我们想使用串口连接STM32的串口1到PC机,然后通过PC上位机给STM32发送一个字节0x01,然后在STM32接收到之后,判断一下是不是0x01,如果是的话,点亮一个小灯,如果不是的话,就不点亮灯。这个逻辑不论从理解还是实现起来都非常容易,基本上几行代码就实现了。
若果把刚才的例子进行扩展,STM32连接了很多的灯,然后我们要使用串口发送一个指令来控制所有灯,这时候应该怎么操作?
再把问题再扩展一下,假如我们要控制或通信的不是一个灯,而是一个更复杂的东西,比如是一个电机控制模块、是一个GPS模块、是一个物联网模块呢,这些东西在数据交互的时候都有很大的数据量,不可能一个一个字节去发送数据。
这时候我们就可以联想一下人类是怎么交互的,首先经过上万年的潜移默化,人类形成了很多种语言,同一个国家的人说话基本上都可以听懂,而不同国家的人说话的时候,如果不懂外语是听不懂的。这是为什么呢,因为同一个国家的人,说话的时候使用的协议是相同的,你说桌子,我就知道是桌子。而不同国家的人,通讯协议是不一样的,所以说话的时候不能理解,比如你说apple,我如果没有学过英语,我就不知道你说的是苹果。但是我学习了你的语言,也就是协议。就可以听懂你说的是苹果了。
所以,STM32和PC通讯,或者扩展到更多的场景,STM32和GPS,其他单片机和WIFI等等,这样的通讯都需要通讯双方执行同样的协议。那么对于刚接触单片机的人而言,就产生了几个问题,协议是什么样的,如何执行协议?
还是以最简单的场景来举例子。以使用PC机发指令来控制STM32点亮8个小灯中的若干个小灯固定时长(一秒到255秒之间)然后关闭这样一个实际小项目为例,如果只发一个指令,是没办法完成我们需要完成的任务。所以我们需要制定一个简单的协议。
比如我STM32的程序这么写:当串口收到0xAA然后又收到0x55的时候,我就开始不断收集,并把收集到的所有数据都放在一个数字中,直到收到0xA5x5A这两个的时候就停止收集。接下来我把收集到的数组里面的第一个拿出来,使用if进行判断,如果是0x01的话就点亮第一个小灯,如果是0x00或者其他的话,就不点亮灯,然后看看数组的第二个字节是多少,是多少就给延时多少。相当于通过前两个字节来控制第一个灯亮灭固定时间长度。同样的接下来的两个字节是第二个灯的亮灭和时间长度。按这样的节奏来,要控制这8个灯需要16个字节。那么我们是否可以优化一下这个协议呢?
假如把8个灯的亮灭信息只用一个字节来表示,后面加8个字节,分别用来表示每个灯的亮灭时间长度,这样的话,就可以用9个字节来完成这个任务。
现在我们再想想,假如在这个数据传输的过程中,出了一点小错误,其中有一个电平在跳变的时候受到了干扰,没有按照发送方的数据跳变,这时候接收方接收到的数据就是错误的,假如这个错误发生在第一个灯的亮灭位上,那这个灯就会发生错误的反应,这不是发送方想要的结果。那如何避免这种情况发生呢?使用校验位,校验位是什么意思呢,就是我在给你发的时候,我把9个字节的数据做一个运算。运算有很多种方式,以求和为例子,把9个字节的数据求和,然后拿出里面低八位的数据,放在我要发送的9个字节后面。这样,发送的内容除了0xAA,0x55,0xA5和x5A之外,还多了一个位,我们把多出来的这个通过数据位运算得到的这一字节称为校验位。
当发送出去之后,接收方在接收完这些数据之后,也对数据位做一个求和,然后取出低八位,和发送方发送过来的那个校验位做比较,如果相等,说明数据发送过程中没有出错,如果不相等,说明数据发送过程中有地方出错了,那么我们整个不要这一包数据了,然后给发送方通知一下,告诉他让他重新发送一下刚才的数据。
现在回到数据收发,PC端发数据,STM32端接收,这时候STM32也就要每过一会儿(很短暂的时间)就去看看串口是否有数据收到,这种方式称为扫描。扫描有一个缺点,就是需要不断的去看,结果可能去看了一百次,才有一次有数据收到,这样效率太低了,老板(cpu)肯定不高兴,就给串口说,以后你自己处理,有数据来了给我说一下我去处理就行,别让我自己去看,手里事情多着呢。所以就有了中断,中断就是当串口上有数据接了,就会产生一个接收中断,这时候串口就去通知老板来处理。原本要不断过来看看有没有数据,现在他有数据了才通知老板,老板开始还感觉不错,比以前扫描的时候轻松了点。
过了一段时间,老板想,这样每来一包数据,我得去拿几十次呀,太累,于是扔给串口一个仓库(数组),然后说,我给你一个特殊的通道(DMA)你以后收完一包数据直接通过这个通道把数据放在这个仓库里,放完了再通知我来处理,别让我来一次处理一个,手里事情多着呢。然后就有了串口空闲中断,串口每次收到一帧数据之后,才会产生一个中断通知cpu处理。串口空闲中断+DMA的方式简直是处理串口通讯的神器,没有之二。
接下来我们再想想,如果我们有一天突然觉得只控制8个灯不够用了,需要扩展几个呢,这时候,灯加上去之后,协议上还要有很大的变动,比如要把灯的控制位插在数据位的后面,就要把校验位往后挪挪,这样程序就需要改一下,那么有没有一种方式,可以允许你在一定范围之内随意改灯的数量而不需要修改协议呢?这就需要设计一个不定长的通讯协议了。既然不定长,那也就意味着,发送方每次都可能发送出不同长度的数据给接收方,这也就要求发送方在发送数据的时候,在这个数据包的前面要加上数据有几个字节,这样接收方才好根据这个数量去接收(串口空闲中断+dma的方式不需要根据这个数量去接收),并且根据这个数量去解析,进而控制灯。
本期先分享到这里,想要进群学习单片机编程的同学可以私信我,回复“我要入门”,与我们一起成长,喜欢的可以点个赞关注我们!
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
用串口助手检测到的数据如下图。
喜欢的话请点赞并分享,您的支持是我坚持下去的动力!送人玫瑰,手有余香!
相关问答
单片机通讯协议 有哪些?1、单片机与其他单片机或芯片级的通讯协议有:RS232、IIC、SPI、并口(I/O)、DMA(如msp430、ARM);2、单片机通过电缆与PC或其他设备通讯协议有:RS232、RS485...
安卓APP和 单片机 (stm32外设屏幕显示)蓝牙实现数据通信的步骤和要掌握的知识有哪些?安卓APP和单片机STM32蓝牙数据通信步骤:1.建立通讯模型Android端APP通过蓝牙和蓝牙模块比如HC05通讯数据,蓝牙模块通过串口将Android端发送的数据传递给STM32...
单片机 与PC 通讯 有什么方式?-ZOL问答电脑和单片机除了串口,再有就是网络通讯方式。但是需要有网口接口芯片,还要编写支持TCP/IP协议的程序。可是用传统的51单片机却很难实现。你可以用STM32单片...
传感器 单片机 通信原理?传感器单片机通信是指通过传感器将感应到的物理量转变为数字信号后,通过串口、I2C、SPI等通信协议传输到单片机,然后对信号进行采集、处理和分析。其中,传感...
不同 单片机 直接可以互相通信吗?例如AT与STC之间通信 - 赐我...可以通行分为好几类,你说的是单片机与单片机之间的通行,AT与STC之间可以进行通信,只要你按照通信协议的说明操作就可以了,记住:一定要理解通信协议...
51 单片机 有spi 协议 吗?有很多型号的51单片机具备SPI接口,内部通过特殊功能寄存器方式实现SPI通讯协议,例如STC系列51单片机几乎都有SPI接口。对于没有SPI接口的51单片机,也可以通过...
组态王怎么与 单片机 以太网通信组态王中的地址?这是个通讯协议的问题,比较简单的方法是:1.单片机写入标准的modbus协议库;2.组态王中,添加设备,驱动选择莫迪康即可。组态王会按照标准的modbus进行通信...
工业控制通信 协议 有哪些?-ZOL问答工业控制通信协议有CANBUS、MODBUS、profibus等。简介:1、作为ISO11898CAN标准的CANBus(ControLLerAreaNet-workBus),是制造厂中连接...
单片机 如何连接华为云?你好,要将单片机连接到华为云,可以按照以下步骤进行操作:1.创建华为云账号并登录:前往华为云官方网站,注册一个账号并登录。2.创建物联网平台实例:在华...
单片机 与手机如何实现远距离通信?单片机与手机实现远距离通信,有很多种可实施的方案。例举其中两个方案进行讲解:一:2G/4G移动通信方案器件选型1,单片机选用Cortex-M3内核,国产兆易创新...单...