网站首页 > 文章中心 > 其它

go语言rs485

作者:小编 更新时间:2023-11-29 12:34:21 浏览量:28人看过

RS485和MODBUS的区别

MODBUS是一种国际标准的通讯协议,用于不同厂商之间的设备交换数据(一般是工业用途);

所谓协议,也可以理解为上面有人说的"语言"吧,简单的说是软件.

一般情况下,两台设备通过MODBUS协议传输数据:

TCP三种模式:

而MODBUS TCP则是为了顺应当今世界发展潮流,什么都可以用Ethernet网或Internet来连接,传送数据.所以又MODBUS TCP模式,该模式的硬件接口就是以太网(Ethernet)口了,也就是我们电脑上一般用的网络口了.

急!请教RS485串口通讯的问题

你用vb还是vc?

go语言rs485-图1

看OnComm事件应该是vb吧.

(参照出处):

MSComm控件使用详解

摘要:本文详细介绍了MSComm控件在串口编程中使用.

目 次

MSComm控件两种处理通讯的方式

go语言rs485-图2

CommPort属性

RThreshold 属性

CTSHolding 属性

SThreshold 属性

CDHolding 属性

DSRHolding 属性

Settings 属性

InputLen 属性

EOFEnable 属性

Handshake 常数

OnComm 常数

InputMode 常数

错误消息

MSComm 控件通过串行端口传输和接收数据,为应用程序提供串行通讯功能.MSComm控件在串口编程时非常方便,程序员不必去花时间去了解较为复杂的API函数,而且在VC、VB、Delphi等语言中均可使用. Microsoft Communications Control(以下简称MSComm)是Microsoft公司提供的简化Windows下串行通信编程的ActiveX控件,它为应用程序提供了通过串行接口收发数据的简便方法.具体的来说,它提供了两种处理通信问题的方法:一是事件驱动(Event-driven)方法,一是查询法.

①MSComm控件两种处理通讯的方式

MSComm控件提供下列两种处理通讯的方式:事件驱动方式和查询方式.

①1 事件驱动方式

事件驱动通讯是处理串行端口交互作用的一种非常有效的方法.在许多情况下,在事件发生时需要得到通知,例如,在串口接收缓冲区中有字符,或者 Carrier Detect (CD) 或 Request To Send (RTS) 线上一个字符到达或一个变化发生时.在这些情况下,可以利用 MSComm 控件的 OnComm 事件捕获并处理这些通讯事件.OnComm 事件还可以检查和处理通讯错误.所有通讯事件和通讯错误的列表,参阅 CommEvent 属性.在编程过程中,就可以在OnComm事件处理函数中加入自己的处理代码.这种方法的优点是程序响应及时,可靠性高.每个MSComm 控件对应着一个串行端口.如果应用程序需要访问多个串行端口,必须使用多个 MSComm 控件.

查询方式实质上还是事件驱动,但在有些情况下,这种方式显得更为便捷.在程序的每个关键功能之后,可以通过检查 CommEvent 属性的值来查询事件和错误.如果应用程序较小,并且是自保持的,这种方法可能是更可取的.例如,如果写一个简单的电话拨号程序,则没有必要对每接收一个字符都产生事件,因为唯一等待接收的字符是调制解调器的"确定"响应.

MSComm 控件有很多重要的属性,但首先必须熟悉几个属性.

CommPort 设置并返回通讯端口号.

Settings 以字符串的形式设置并返回波特率、奇偶校验、数据位、停止位.

PortOpen 设置并返回通讯端口的状态.也可以打开和关闭端口.

Input 从接收缓冲区返回和删除字符.

Output 向传输缓冲区写一个字符串.

下面分别描述:

CommPort属性 设置并返回通讯端口号.

语法 object.CommPort[value ] (value 一整型值,说明端口号.)

注意:必须在打开端口之前设置 CommPort 属性.

RThreshold 属性:在 MSComm 控件设置 CommEvent 属性为 comEvReceive 并产生 OnComm 之前,设置并返回的要接收的字符数.

语法 object.Rthreshold [ = value ](value 整型表达式,说明在产生 OnComm 事件之前要接收的字符数. )

说明 当接收字符后,若 Rthreshold 属性设置为 0(缺省值)则不产生 OnComm 事件.例如,设置 Rthreshold 为 1,接收缓冲区收到每一个字符都会使 MSComm 控件产生 OnComm 事件.

CTSHolding 属性:确定是否可通过查询 Clear To Send (CTS) 线的状态发送数据.Clear To Send 是调制解调器发送到相联计算机的信号,指示传输可以进行.该属性在设计时无效,在运行时为只读.

语法: object.CTSHolding(Boolean)

Mscomm 控件的 CTSHolding 属性设置值:

True Clear To Send 线为高电平.

False Clear To Send 线为低电平.

说明:如果 Clear To Send 线为低电平 (CTSHolding = False) 并且超时时,MSComm 控件设置 CommEvent 属性为 comEventCTSTO (Clear To Send Timeout) 并产生 OnComm 事件.

Clear To Send 线用于 RTS/CTS (Request To Send/Clear To Send) 硬件握手.如果需要确定 Clear To Send 线的状态,CTSHolding 属性给出一种手工查询的方法.

详细信息 有关握手协议,请参阅 Handshaking 属性.

SThreshold 属性: MSComm 控件设置 CommEvent 属性为 comEvSend 并产生 OnComm 事件之前,设置并返回传输缓冲区中允许的最小字符数.

语法 object.SThreshold [ = value ]

value 整形表达式,代表在 OnComm 事件产生之前在传输缓冲区中的最小字符数.

常数 值 描述

comNone 0 无握手.

comXonXoff 1 XOn/Xoff 握手.

comEvSend 1 发送事件.

Error 常数

comEventBreak 1001 接收到中断信号

comEventTxFull 1010 传输缓冲区满

comEventDCB 1011 检索端口 设备控制块 (DCB) 时的意外错误

comInputModeText 0 (缺省)通过 Input 属性以文本方式取回数据.

comInputModeBinary 1 通过 Input 属性以二进制方式检取回数据.

CDHolding 属性:通过查询 Carrier Detect (CD) 线的状态确定当前是否有传输.Carrier Detect 是从调制解调器发送到相联计算机的一个信号,指示调制解调器正在联机.该属性在设计时无效,在运行时为只读.

语法 object.CDHolding

设置值:CDHolding 属性的设置值为:

设置 描述

True Carrier Detect 线为高电平

False Carrier Detect 线为低电平

说明:注意当 Carrier Detect 线为高电平 (CDHolding = True) 且超时时,MSComm 控件设置CommEvent 属性为 comEventCDTO(Carrier Detect 超时错误),并产生 OnComm 事件.

注意 在主机应用程序中捕获一个丢失的传输是特别重要的,例如一个公告板,因为呼叫者可以随时挂起(放弃传输).

Carrier Detect 也被称为 Receive Line Signal Detect (RLSD).

数据类型 Boolean

DSRHolding 属性:确定 Data Set Ready (DSR) 线的状态.Data Set Ready 信号由调制解调器发送到相连计算机,指示作好操作准备.该属性在设计时无效,在运行时为只读.

语法:object.DSRHolding

object 所在处表示对象表达式,其值是"应用于"列表中的对象.

DSRHolding 属性返回以下值:

值 描述

True Data Set Ready 线高

False Data Set Ready 线低

说明:当 Data Set Ready 线为高电平 (DSRHolding = True) 且超时时,MSComm 控件设置 CommEvent 属性为 comEventDSRTO(数据准备超时)并产生 OnComm 事件.

当为 Data Terminal Equipment (DTE) 机器写 Data Set Ready/Data Terminal Ready 握手例程时该属性是十分有用的.

数据类型:Boolean

Settings 属性: 设置并返回波特率、奇偶校验、数据位、停止位参数.

语法: object.Settings[ = value]

Value 由四个设置值组成,有如下的格式:

"BBBB,P,D,S"

BBBB 为波特率,P 为奇偶校验,D 为数据位数,S 为停止位数.value 的缺省值是:

InputLen 属性:设置并返回 Input 属性从接收缓冲区读取的字符数.

语法 object.InputLen [ = value]

InputLen 属性语法包括下列部分:

value 整型表达式,说明 Input 属性从接收缓冲区中读取的字符数.

说明:InputLen 属性的缺省值是 0.设置 InputLen 为 0 时,使用 Input 将使 MSComm 控件读取接收缓冲区中全部的内容.

若接收缓冲区中 InputLen 字符无效,Input 属性返回一个零长度字符串 ("").在使用 Input 前,用户可以选择检查 InBufferCount 属性来确定缓冲区中是否已有需要数目的字符.该属性在从输出格式为定长数据的机器读取数据时非常有用.

EOFEnable 属性:确定在输入过程中 MSComm 控件是否寻找文件结尾 (EOF) 字符.如果找到 EOF 字符,将停止输入并激活 OnComm 事件,此时 CommEvent 属性设置为 comEvEOF,

语法:object.EOFEnable [ = value ]

EOFEnable 属性语法包括下列部分:

value 布尔表达式,确定当找到 EOF 字符时,OnComm 事件是否被激活,如"设置值"中所描述.

value 的设置值:

True 当 EOF 字符找到时 OnComm 事件被激活.

False (缺省)当 EOF 字符找到时 OnComm 事件不被激活.

说明:当 EOFEnable 属性设置为 False,OnComm 控件将不在输入流中寻找 EOF 字符.

错误消息(MS Comm 控件)

下表列出 MSComm 控件可以捕获的错误:

///-----------------------------------------------------

串口数据接收方式

①.、 在OnComm 事件中接收数据:

这种方式能充分MSCOMM控件的特性.OnComm 事件还可以检查和处理通讯错误;可以通过检查 CommEvent 属性的值来查询事件和错误;对于不定长数据以及对数据进行处理比较复杂的情况,此法不是很方便.

Private Sub MSComm_OnComm ()

Select Case MSComm1.CommEvent

' 错误

Case comEventBreak ' 收到 Break.

Case comEventCDTO ' CD (RLSD) 超时.

Case comEventCTSTO ' CTS Timeout.

Case comEventDSRTO ' DSR Timeout.

Case comEventFrame ' Framing Error

Case comEventOverrun '数据丢失.

Case comEventRxOver'接收缓冲区溢出.

Case comEventRxParity' Parity 错误.

Case comEventTxFull '传输缓冲区已满.

Case comEventDCB '获取 DCB] 时意外错误

' 事件

Case comEvCD ' CD 线状态变化.

Case comEvCTS ' CTS 线状态变化.

Case comEvDSR ' DSR 线状态变化.

Case comEvRing ' Ring Indicator 变化.

Case comEvReceive ' 收到 RThreshold # of chars.

Case comEvSend ' 传输缓冲区有 Sthreshold 个字符 '

Case comEvEof ' 输入数据流中发现 EOF 字符

End Select

End Sub

A、定时器轮循法

对于数据包方式收发数据以及不需即时响应情况,用轮循法更好些.实际上轮循法最大的好处在于集中处理数据而且不太占用CPU.轮循法要注意定时采集的时间片段大小;这里用二进制收发模式;使属性RThreshold、SThreshold为0,屏蔽ONCOMM事件.

InputMode = comInputModeBinary

RThreshold = 0

SThreshold = 0

Private Sub TmrComm_Timer()

'采用轮循法采集数据

Dim Rx_buff() As Byte

Dim okstring As String

Dim ReceivedLen As Integer

On Error GoTo ErrorHandler

TmrComm.Enabled = False '关闭定时器

If commport.InBufferCount 0 Then

ReceivedLen = commport.InBufferCount

Rx_buff = commport.Input

okstring = StrConv(tempbyte, vbUnicode)

....

End If

If Instr(okstring ,":@END*",vbBinaryCompare) Then

TmrComm.Enabled = True '打开定时器

B、直接轮循法

此法用于接收少量控制命令字;

' 保存输入子串的缓冲区

go语言rs485-图3

Dim Instring As String

' 使用 COM1.

MSComm1.CommPort = 1

' 当输入占用时,

' 告诉控件读入整个缓冲区.

MSComm1.InputLen = 0

' 打开端口.

MSComm1.PortOpen = True

' 将 attention 命令送到调制解调器.

' 确保

' 调制解调器以"OK"响应.

' 等待数据返回到串行端口.

Do

DoEvents

Buffer$ = Buffer$ MSComm1.Input

Loop Until InStr(Buffer$, "OK" vbCRLF)

' 从串行端口读 "OK" 响应.

' 关闭串行端口.

MSComm1.PortOpen = False

如何处理不定长数据的接收

在处理串口通讯时,经常会遇到不定长数据的接收.由于通讯任务不同及编程要求的差异所以采用的方法也有所不同.本文就此问题进行探讨.不定长数据从数据格式上分,可分为有格式和无格式.

第一段:无格式不定长数据的接收

这种格式在实际串口通讯中用得不多,一般只用传送字符串数据.问题在于怎么判断接收结束.一般用时间延迟的方法解决.

A、对于非握手式通讯,可用一个定时器定时轮循接收,并假定每个轮循接收完成.用ONCOMM事件接收也可,只是不如定时器定时轮循接收简便.

B、对于握手方式通讯,可用直接轮循法提高接收的准确性.下面是实现此法的函数:

Function sComm(sCommand As String, comReceive As MSComm) As String

Dim nReceiveCount As Integer

If comReceive.PortOpen = False Then

comReceive.PortOpen = True

comReceive.Output = sCommand

nReceiveCount = comReceive.InBufferCount

Loop Until comReceive.InBufferCount = nReceiveCount

If comReceive.PortOpen = True Then

sComm = comReceive.Input

End Function

注:此函数参照了xth一文.

此法一般是能确保数据接收的正确,但由于WINDOWS是多任务操作系统,当有耗时的进程运行时会丢失数据.如果系统会出现这种情况,可增大函数sleep()的参数值.

第二段:不定长格式数据的接收

对于不定长数据接收最好的方法是制定通讯协议,比如定义开始字符和结束字符.由于单片机系统通讯一般不太复杂,没必要去制定一套象通用计算机间通讯的协议,而根据单片机系统的大小和性能要求制定通讯协议.实际上为便于交流、维护以及一致性,可制定一套可伸缩的通讯协议.定义了开始字符和结束字符就容易实现不定长格式数据通讯,但在实际通讯编程还是容易出现一些比较隐蔽的通讯错误.下面就常用方法分别进行分析.

A、定时器轮循法.

假定每个轮循期数据接收完毕,并在每个轮循期处理数据,由于有开始字符和结束字符很容易确定接收数据的完整性.好象合理设定轮循时间值就万无一失了,但被动接收数据时无论如何也找不合适的轮循时间值,因为启动定时器和数据到来基本不同步,这就会出现一次发送的数据被分在两个轮循期接收,所以被动接收数据时不能假定每个轮循期数据接收完毕.在接收到结束字符后才确定一次数据接收完毕就可解决此问题.

B、OnComm事件法.

对于不定长数据的接收,最佳方法可能是在OnComm事件中启动定时器轮循接收,并同时停止OnComm事件的触发,接收完毕后或超时开启OnComm事件.

由于C语言不能返回两个参数,所以用数组指针.

void Filt(char code[],char c)

{

if(c=='F')

}

else

code[1]=0XFF; /*0XFF作为标记code[1]不可能产生0XFF*/

else if(c=='H')

code[1]=0xFE; /*转换完成标记*/

if(code[1]==0XFE)

code[1]=0XFF; /*接收下一个码的标记*/

code[0]=code[0]+code[1];

code[1]=0XFE;

发送时:

SendChar[0]=c; /*c为待发ASCII码*/

Filt(SendChar,'F');

if(SendChar(1)==0XFF)

..... /*发送SendChar[0]*/

...... /*发送SendChar[0],SendChar[1]*/

接收时:

.....

ReceiveChar[0]=c0; /*c0接收的ASCII码*/

Filt(ReceiveChar,'H');

if(ReceiveChar[1]==0xFF)

ReceiveChar[1]=c1; /*c1为下一个*/

Filt(ReceiveChar,'H);

else if(ReceiveChar[1]==0xFE)

...... /*存储转换后的ReceiveChar[0]*/

以上代码仅提供一种思路,实际情况视编程需要而定.

串口通讯问答录

①.、Q:各位vb高手:我有一个问题想请教一下.我从COM口用BIN方式接收到数据(一串汉字),存入一BYTE数组,但无法还原为一串汉字,我认为是ANSI和UNICODE的转换,请问如何转换.

JY

发:

Dim ytemp() As Byte

Dim stemp As String

stemp = "土嘎嘎的粉丝们大家好!"

ytemp = StrConv(stemp, vbFromUnicode)

Debug.Print UBound(ytemp)

MSComm1.Output = ytemp

收:

Private Sub mscTest_OnComm()

'中文收发

Dim yTemp() As Byte

Dim i As Integer

If mscTest.InBufferCount 0 Then

i = mscTest.InBufferCount

yTemp = mscTest.Input

stemp = StrConv(yTemp, vbUnicode)

txtTest1.Text = stemp

Deson

--------------------------------------------------------------------------------

Private Sub OkBtn_Click()

Dim Data() as byte

Dim Temp as variant

redim data(10)

For i = 0 to 10

next

temp = data

mscomm.output = temp

end Sub

A:接收方式使用了文本方式,用二进制方式即可.

go语言实现一个简单的简单网关

网关=反向代理+负载均衡+各种策略,技术实现也有多种多样,有基于 nginx 使用 lua 的实现,比如 openresty、kong;也有基于 zuul 的通用网关;还有就是 golang 的网关,比如 tyk.

这篇文章主要是讲如何基于 golang 实现一个简单的网关.

转自: troy.wang/docs/golang/posts/golang-gateway/

整理:go语言钟文文档:

启动两个后端 web 服务(代码)

这里使用命令行工具进行测试

具体代码

直接使用基础库 httputil 提供的NewSingleHostReverseProxy即可,返回的reverseProxy对象实现了serveHttp方法,所以呢可以直接作为 handler.

director中定义回调函数,入参为*http.Request,决定如何构造向后端的请求,比如 host 是否向后传递,是否进行 url 重写,对于 header 的处理,后端 target 的选择等,都可以今天这一节完成.

director今天这一节具体做了:

modifyResponse中定义回调函数,入参为*http.Response,用于修改响应的信息,比如响应的 Body,响应的 Header 等信息.

最终依旧是返回一个ReverseProxy,然后将这个对象作为 handler 传入即可.

随便 random 一个整数作为索引,然后取对应的地址即可,实现比较简单.

使用curIndex进行累加计数,一旦超过 rss 数组的长度,则重置.

后端真实节点包含三个权重:

操作步骤:

一致性 hash 算法,主要是用于分布式 cache 热点/命中问题;这里用于基于某 key 的 hash 值,路由到固定后端,但是只能是基本满足流量绑定,一旦后端目标节点故障,会自动平移到环上最近的那么个节点.

实现:

每一种不同的负载均衡算法,只需要实现添加以及获取的接口即可.

然后使用工厂方法,根据传入的参数,决定使用哪种负载均衡策略.

作为网关,中间件必不可少,这类包括请求响应的模式,一般称作洋葱模式,每一层都是中间件,一层层进去,然后一层层出来.

中间件的实现一般有两种,一种是使用数组,然后配合 index 计数;一种是链式调用.

版权声明:倡导尊重与保护知识产权。未经许可,任何人不得复制、转载、或以其他方式使用本站《原创》内容,违者将追究其法律责任。本站文章内容,部分图片来源于网络,如有侵权,请联系我们修改或者删除处理。

编辑推荐

热门文章