资讯

精准传达 • 有效沟通

从品牌网站建设到网络营销策划,从策略到执行的一站式服务

go语言串口通讯怎么设置 go语言通道

go语言做串口通信,我应该从什么地方入手,IO是什

//创建一个串口通讯 SerialPort CurrentPort = null; CurrentPort = new SerialPort(); CurrentPortReadBufferSize = 128; CurrentPortPortName = comName; //端口号 CurrentPortBaudRate = bandRate; //比特率 CurrentPortParity =parity;/go语言做串口通信,我应该从什么地方入手,IO是什

创新互联是一家企业级云计算解决方案提供商,超15年IDC数据中心运营经验。主营GPU显卡服务器,站群服务器,绵阳电信机房,海外高防服务器,机柜大带宽、租用·托管,动态拨号VPS,海外云手机,海外云服务器,海外服务器租用托管等。

golang开发modbus-rtu通信

用到的gomodbus包是坛友slzm40编写和共享的,感谢他的无私分享,本帖只是抛砖引玉,将我自己学习的一些经历分享给大家;有关modbus包可以直接向slzm40请教或一起讨论;

包地址"github.com/thinkgos/gomodbus";

添加一对虚拟串口

打开modbus-slave从机软件,用来测试从机;

需要注意设置通信地址和读取寄存器的地址和数量;

查看可用串口,因为虚拟串口选择com1和com2,虚拟中我选择使用/dev/ttyS1

编译运行,会提示串口打开失败,这是因为linux对设备的权限做了限制

获取串口读写、运行等权限

我们已经能正确读取03寄存器的值;其他功能可以自行测试;

package main

import (

"fmt"

modbus "github.com/thinkgos/gomodbus"

"github.com/thinkgos/gomodbus/mb"

"time"

)

func main(){

//调用RTUClientProvider的构造函数,返回结构体指针

p := modbus.NewRTUClientProvider()

p.Address = "/dev/ttyS1"

p.BaudRate = 115200

p.DataBits = 8

p.Parity = "N"

p.StopBits = 1

p.Timeout = 100 * time.Millisecond

client := mb.NewClient(p)

client.LogMode(true)

err := client.Start()

if err != nil {

fmt.Println("start err,", err)

return

}

for {

value, err := client.ReadHoldingRegisters(1, 1, 3)

if err != nil {

fmt.Println("readHoldErr,", err)

} else {

fmt.Printf("%#v\n", value)

}

time.Sleep(time.Second * 3)

}

}

关于串口通讯

利用串口进行数据通讯在通讯领域重占有着重要的地位。利用RS232-RS485进行数据信号的采集和传递是VC编程的又一大热点。串口通讯在通讯软件重有着十分广泛的应用。如电话、传真、视频和各种控制等。在各种开发工具中间,VC由于功能强大和灵活,同时也得到了Microsoft的最大支持,所以在一般进行涉及硬件操作的通讯编程中,大都推荐使用VC作为开发工具。然而工业控制串口通讯这个又不同于一般的串口通讯程序,因为控制外围设备传送的大都是十六进制数据(BYTE类型),所以,为了提高程序的运行稳定性,我们在编写程序进行通讯时可以不考虑传送BYTE类型数据的工作。

串口通讯目前流行的方法大概有两种:一是利用Microsoft提供的CMSCOMM控件进行通讯,不过现在很多程序员都觉应该放弃这种方式。二是利用WINAPI函数进行编程,这种编程的难度最高,要求你要掌握很多的API函数。三是利用现在网络上面提供的一些串口通讯控件进行编写,比如CSerial类等。

程序实现:

我在经过许多的项目的开发和实践中发现,采用WIN API函数进行串口的开发能够给程序员很大的控件,并且程序运也很稳定。所以我将与串口接触的函数进行封装,然后在各个工程中进行调用,效果还是比较好的,现将各个函数和调用方法列举出来,希望对各位有所帮助。

一、设置串口相关工作

#define MAXBLOCK 2048

#define XON 0x11

#define XOFF 0x13

BOOL SetCom(HANDLE m_hCom, const char *m_sPort, int BaudRate, int Databit, CString parity, CString stopbit)

{

COMMTIMEOUTS TimeOuts; ///串口输出时间 超时设置

DCB dcb; ///与端口匹配的设备

m_hCom=CreateFile(m_sPort, GENERIC_READ | GENERIC_WRITE, 0, NULL,

OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,

NULL); // 以重叠方式打开串口

if(m_hCom==INVALID_HANDLE_VALUE)

{

AfxMessageBox("设置串口部分,串口打开失败"); /////重叠方式 异步通信(INVALID_HANDLE_VALUE)函数失败。

return FALSE;

}

SetupComm(m_hCom,MAXBLOCK,MAXBLOCK); //设置缓冲区

memset(TimeOuts,0,sizeof(TimeOuts));

TimeOuts.ReadIntervalTimeout=MAXDWORD; // 把间隔超时设为最大,把总超时设为0将导致ReadFile立即返回并完成操作

TimeOuts.ReadTotalTimeoutMultiplier=0; //读时间系数

TimeOuts.ReadTotalTimeoutConstant=0; //读时间常量

TimeOuts.WriteTotalTimeoutMultiplier=50; //总超时=时间系数*要求读/写的字符数+时间常量

TimeOuts.WriteTotalTimeoutConstant=2000; //设置写超时以指定WriteComm成员函数中的

SetCommTimeouts(m_hCom, TimeOuts); //GetOverlappedResult函数的等待时间*/

if(!GetCommState(m_hCom, dcb)) ////串口打开方式、端口、波特率 与端口匹配的设备

{

AfxMessageBox("GetCommState Failed");

return FALSE;

}

dcb.fParity=TRUE; //允许奇偶校验

dcb.fBinary=TRUE;

if(parity=="NONE")

dcb.Parity=NOPARITY;

if(parity=="ODD")

dcb.Parity=ODDPARITY;

if(parity=="EVEN")

dcb.Parity=EVENPARITY;

if(stopbit=="1")//设置波特率

dcb.StopBits=ONESTOPBIT;

//if(stopbit=="0")//设置波特率

// dcb.StopBits=NONESTOPBIT;

if(stopbit=="2")//设置波特率

dcb.StopBits=TWOSTOPBITS;

BOOL m_bEcho=FALSE; ///

int m_nFlowCtrl=0;

BOOL m_bNewLine=FALSE; ///

dcb.BaudRate=BaudRate; // 波特率

dcb.ByteSize=Databit; // 每字节位数

// 硬件流控制设置

dcb.fOutxCtsFlow=m_nFlowCtrl==1;

dcb.fRtsControl=m_nFlowCtrl==1 ?RTS_CONTROL_HANDSHAKE:RTS_CONTROL_ENABLE;

// XON/XOFF流控制设置(软件流控制!)

dcb.fInX=dcb.fOutX=m_nFlowCtrl==2;

dcb.XonChar=XON;

dcb.XoffChar=XOFF;

dcb.XonLim=50;

dcb.XoffLim=50;

if(SetCommState(m_hCom, dcb))

return TRUE; ////com的通讯口设置

else

{

AfxMessageBox("串口已打开,设置失败");

return FALSE;

}

}

二、读串口操作:

int ReadCom(HANDLE hComm, BYTE inbuff[], DWORD nBytesRead, int ReadTime)

{

DWORD lrc; ///纵向冗余校验

DWORD endtime; /////////jiesuo

static OVERLAPPED ol;

int ReadNumber=0;

int numCount=0 ; //控制读取的数目

DWORD dwErrorMask,nToRead;

COMSTAT comstat;

ol.Offset=0; ///相对文件开始的字节偏移量

ol.OffsetHigh=0; ///开始传送数据的字节偏移量的高位字,管道和通信时调用进程可忽略。

ol.hEvent=NULL; ///标识事件,数据传送完成时设为信号状态

ol.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);

endtime=GetTickCount()+ReadTime;//GetTickCount()取回系统开始至此所用的时间(毫秒)

for(int i=0;i2000;i++)

inbuff[i]=0;

Sleep(ReadTime);

ClearCommError(hComm,dwErrorMask,comstat);

nToRead=min(2000,comstat.cbInQue);

if(int(nToRead)2)

goto Loop;

if(!ReadFile(hComm,inbuff,nToRead,nBytesRead,ol))

{

if((lrc=GetLastError())==ERROR_IO_PENDING)

{

///////////////////

endtime=GetTickCount()+ReadTime;//GetTickCount()取回系统开始至此所用的时间(毫秒)

while(!GetOverlappedResult(hComm,ol,nBytesRead,FALSE))//该函数取回重叠操作的结果

{

if(GetTickCount()endtime)

break;

}

}

}

return 1;

Loop: return 0;

}

三、写串口命令

int WriteCom(HANDLE hComm, BYTE Outbuff[], int size, int bWrite[])

{

DWORD nBytesWrite,endtime,lrc;

static OVERLAPPED ol;

DWORD dwErrorMask,dwError;

COMSTAT comstat;

ol.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);

ol.Offset=0;

ol.OffsetHigh=0;

ol.hEvent=NULL; ///标识事件,数据传送完成时,将它设为信号状态

ClearCommError(hComm,dwErrorMask,comstat);

if(!WriteFile(hComm,Outbuff,size,nBytesWrite,ol))

{

if((lrc=GetLastError())==ERROR_IO_PENDING)

{

endtime=GetTickCount()+1000;

while(!GetOverlappedResult(hComm,ol,nBytesWrite,FALSE))

{

dwError=GetLastError();

if(GetTickCount()endtime)

{

AfxMessageBox("写串口时间过长,目前串口发送缓冲区中的数据数目为空");

break;

}

if(dwError=ERROR_IO_INCOMPLETE)

continue; //未完全读完时的正常返回结果

else

{

// 发生错误,尝试恢复!

ClearCommError(hComm,dwError,comstat);

break;

}

}

}

}

FlushFileBuffers(hComm);

PurgeComm(hComm,PURGE_TXCLEAR);

bWrite=0;

return 1;

}

四、调用方法很简单,只需要将你的串口参数进行简单的设置就可以了。比如:

BOOL Main_OpenCom()//设置COM

{

int Boundrate=9600;//波特率

CString StopBits="1";//停止位

int DataBits=8;//数据位

CString Parity="ODD";//奇偶校验

CString m_Port="COM1";

return SetCom(m_hCom1,m_Port,Boundrate,DataBits,Parity,StopBits);

}

void Main()

{

int SIZE;

DWORD BytestoRead=52*Count+6;//要11个字节

int BWRITE[2];

int ReadTime=2000;

BYTE Outbuff[12]={0xff,0x00,0xea,0xff,0xea,0xff,0,0,0,0,0,0};

SIZE=sizeof(Outbuff);

WriteCom(m_hCom,Outbuff,SIZE,BWRITE);

ReadCom(m_hCom,m_Inbuff,BytestoRead,ReadTime);

//进行湘阴的解包处理

}


分享文章:go语言串口通讯怎么设置 go语言通道
文章起源:http://cdkjz.cn/article/doeossg.html
多年建站经验

多一份参考,总有益处

联系快上网,免费获得专属《策划方案》及报价

咨询相关问题或预约面谈,可以通过以下方式与我们联系

大客户专线   成都:13518219792   座机:028-86922220