一、GigE Vision协议概要
GigE Vision协议,主要用于相机的控制和传输。它基于以太网UDP协议,提供了一种统一的控制和传输图像的方式,被广泛应用于工业自动化、机器视觉、影像医疗等领域。
本文的目的是记录自己学习的一些知识,并且按照自己的理解统筹描述一下GigE协议,希望也能够帮助大家带来一些帮助吧。
GigE Vision的手册可以从官网或以下网址获取:https://download.csdn.net/download/yindq1220/89472776
二、GigE Vision协议的核心协议解析
本文仅描述能够实现GigE Vision协议的核心部分协议,包括发现设备、GVCP寄存器配置、GVSP流解析。关于数据重发、消息通道等暂未涉猎。
2.1发现设备
在指令发现设备之前,要求PC机和设备处于同一个IP网段下。可以采用以下几种方法:
1、可以使用DHCP协议自动给设备分配一个IP地址;
2、可以使用FORCEIP_CMD强制给设备配置一个IP地址(与PC机同一个网段);
3、使能Persistent IP,也就是静态持久IP,将Persistent IP设置为与PC机处于同一网段的IP地址
4、更改PC机IP地址,与设备IP地址一致。
本人在本次介绍中,暂时使用固定的IP地址,即FPGA设备或者FPGA应用中使用固定IP地址,使其主机与设备在同一网段。主要是提供一个简易的GigE Vision实现demo。
2.1.1 发现设备命令
在设备与主机处于同一网段的基础上,当设备与主机连接后,主机会发送设备发现指令(存在于UDP协议的有效数据字段中,后续所有的GVCP或者GVSP数据均存在于UDP协议的有效字段中)
名称 | 长度 | 数值 | 备注 |
---|---|---|---|
帧头 | 1字节 | 0x42 | 固定值 |
Flag | 1字节 | 0x11 | 表示广播应答 |
COMMAND | 2字节 | 0x0002 | 发现设备命令 |
LENGTH | 2字节 | 0x0000 | req_id后无数据,因此数值为0 |
req_id | 2字节 | / | 每发送一包命令,该数值加1。取值不能为0 |
2.1.2发现设备应答
设备解析到设备发现指令,则会返回设备发现应答。协议格式如下:
名称 | 长度 | 数值 | 备注 |
---|---|---|---|
status | 2字节 | 0x0000 | 0x0000表示命令指令成功,其他数值表示存在错误 |
ack | 2字节 | 0x0003 | 发现设备的应答指示字 |
length | 2字节 | / | 返回的数据长度 |
ack_id | 2字节 | / | 与对应的req_id取值相同,表示为哪一个命令的应答 |
Spec_version_major | 2字节 | / | 设备支持的规范版本,大版本号 |
Spec_version_minor | 2字节 | / | 设备支持的规范版本,小版本号 |
Device_mode | 4字节 | / | / |
Reserved | 2字节 | / | / |
MAC地址 | 2字节 | / | / |
MAC地址 | 4字节 | / | / |
IP_config_options | 4字节 | / | / |
IP_config_current | 4字节 | / | / |
Reserved | 4字节 | / | / |
Reserved | 4字节 | / | / |
Reserved | 4字节 | / | / |
设备当前IP地址 | 4字节 | / | / |
Reserved | 4字节 | / | / |
Reserved | 4字节 | / | / |
Reserved | 4字节 | / | / |
设备当前子网掩码 | 4字节 | / | / |
Reserved | 4字节 | / | / |
Reserved | 4字节 | / | / |
Reserved | 4字节 | / | / |
设备默认网关 | 4字节 | / | / |
制造商名称 | 32字节 | / | / |
模型名称 | 32字节 | / | / |
设备版本 | 32字节 | / | / |
制造商特定信息 | 48字节 | / | / |
串号 | 16字节 | / | / |
用户定义名称 | 16字节 | / | / |
设备发现应答中,主要是提供了设备当前的一些状态,主机应用可以根据需要选取信息进行使用。一般判断前8个字节,即可判断设备发现是否成功。
2.2 GVCP寄存器配置
2.2.1 心跳计数清零
主机应用需要定时清零设备的心跳计数器,用以保持主机应用与设备的连接。一般使用READREG命令读取CCP寄存器来实现此功能。
主机应用定时发送READREG命令读取CC怕寄存器,设备接收到此命令后,会清零心跳计数器,保持设备与主机应用的连接。同时设备会返回应答,以此通知主机应用目前连接处于保持状态。
读CCP寄存器的命令格式如下:
名称 | 长度 | 数值 | 备注 |
---|---|---|---|
帧头 | 1字节 | 0x42 | 固定值 |
Flag | 1字节 | 0x01 | 表示设备需要返回应答 |
COMMAND | 2字节 | 0x0080 | READREG命令 |
LENGTH | 2字节 | 0x0004 | 地址字段的字节长度 |
req_id | 2字节 | / | 每发送一包命令,该数值加1。取值不能为0 |
第一个地址 | 4字节 | 0x0000_0A00 | CCP寄存器的地址 |
设备返回正常的应答格式如下:
名称 | 长度 | 数值 | 备注 |
---|---|---|---|
status | 2字节 | 0x0000 | 正常应答 |
ack | 2字节 | 0x0081 | READREG_ACK |
LENGTH | 2字节 | 0x0004 | 地址字段的字节长度 |
ack_id | 2字节 | / | 与req_id相同 |
第一个寄存器的数据 | 4字节 | / | 读取的CCP寄存器的数据 |
当需要读取其他寄存器是,也是按照此协议格式读取即可。
2.2.2 正常的寄存器配置WRITEREG
主机应用配置设备的寄存器,使用WRITEREG命令,先描述一下WRITEREG命令的解析。以下以GVCPconfiguration寄存器的配置为例(其他寄存器的地址和数值,请参考GigE的协议手册)。
名称 | 长度 | 数值 | 备注 |
---|---|---|---|
帧头 | 1字节 | 0x42 | 固定值 |
Flag | 1字节 | 0x01 | 表示设备需要返回应答 |
COMMAND | 2字节 | 0x0082 | WRITEREG命令 |
LENGTH | 2字节 | 0x0008 | 地址字段和数据字段的字节长度 |
req_id | 2字节 | / | 每发送一包命令,该数值加1。取值不能为0 |
第一个地址 | 4字节 | 0x0000_0A00 | GVCP configuration寄存器的地址 |
第一个数据 | 4字节 | 0x0004_0006 | 使能扩展码状态,使能pending_ACK |
设备收到此配置信息后,需要返回给主机应用一个应答包。格式如下:
名称 | 长度 | 数值 | 备注 |
---|---|---|---|
status | 2字节 | 0x0000 | 正常应答 |
ack | 2字节 | 0x0083 | WRITEREG_ACK |
LENGTH | 2字节 | 0x0004 | 地址字段的字节长度 |
ack_id | 2字节 | / | 与req_id相同 |
reserved | 2字节 | 0x0000 | / |
index | 2字节 | 0x0001 | 返回正确配置的寄存器的数量 |
2.2.3 设备连接
主机连接设备,按照如下的顺序配置相关寄存器。本文中的配置方式仅为我个人的理解,根据不同应用,可以进行不同的配置顺序和寄存器数值。这里需要注意的是,设备的GVCP端口固定为3956,主机访问端口3956实现对GVCP寄存器的配置。
执行序号 | 寄存器名称 | 寄存器地址 | 寄存器数值 | 描述 |
---|---|---|---|---|
1 | CCP寄存器 | 0x0000_0A00 | 0x0000_0002 | 配置设备为控制访问模式,秘钥为0 |
2 | GVCP_CONFIG | 0x0000_0954 | 0x0004_0006 | 使能扩展状态码,使能PENDING_ACK |
3 | GVSP_CONFIG | 0x0000_0960 | 0x4000_0000 | 使能GVSP block_id64 |
4 | SCCFG0 | 0x00000D24 | 0x00000020 | 禁能multi-part,使能GVSP包大小由SCPSx决定 |
5 | SCDA0 | 0x00000D18 | 0xC0A80180 | 配置相机的目标IP地址为192.168.1.128 |
6 | SCP0 | 0x0000_0D00 | 0x0000_C350 | GVSP数据流的目标端口50000 |
7 | SCPS0 | 0x00000D04 | 0x40001030 | 数据包是4144字节,不分片,禁能test_packet |
8 | 其他可能需要配置的寄存器 | / | / | / |
注意,设备连接过程中,主机应用不仅需要配置相关寄存器,还需要读取XML文件信息,并且根据XML文件获取相机自身定义的寄存器的地址和描述。读取XML文件的流程如下:
第一步,通过READMEM命令(与READREG命令类似,COMMAND命令字不同,具体参考手册),读取XML文件的URL,获取到XML文件的保存形式(.xml或.zip,若是.zip,应用需要自行解压),内存保存起始地址和字节长度。
第二步,通过READMEM命令,读取对应内存地址的XML文件或zip文件。
第三步,解析xml文件,获取厂家自定义的寄存器地址和数值描述信息。
2.2.4 启动相机采集
相机启动采集命令,需要配置3个寄存器。其中配置SCDA0和SCP0的目的是,打开流通道。
配置顺序 | 寄存器名称 | 获取方式 | 寄存器地址 | 寄存器数值 | 描述 |
---|---|---|---|---|---|
1 | SCDA0 | GigE定义 | 0x00000D18 | 0xC0A80180 | 配置相机的目标IP地址为192.168.1.128 |
2 | SCP0 | GigE定义 | 0x0000_0D00 | 0x0000_C350 | GVSP数据流的目标端口50000 |
3 | 启动采集寄存器 | XML文件解析获取 | / | / | 通过XML获取具体的寄存器地址和数值,启动图像采集 |
2.2.5停止相机采集
相机停止采集指令,同样需要配置3个寄存器。其中配置SCDA0和SCP0的目的是,关闭流通道。
配置顺序 | 寄存器名称 | 获取方式 | 寄存器地址 | 寄存器数值 | 描述 |
---|---|---|---|---|---|
1 | SCDA0 | GigE定义 | 0x00000D18 | 0x00000000 | 配置相机的目标IP地址为0.0.0.0 |
2 | SCP0 | GigE定义 | 0x0000_0D00 | 0x0000_C350 | GVSP数据流的目标端口0 |
3 | 启动采集寄存器 | XML文件解析获取 | / | / | 通过XML获取具体的寄存器地址和数值,停止图像采集 |
2.3 GVSP数据流的解析
在启动相机发送图像后,相机设备需要发送GVSP数据流,上位机软件需要对GVSP数据流进行接收和解析。GVSP数据流,有三种类型的数据:leader包,payload包和尾包。
2.3.1 leader包
名称 | 长度 | 数值 | 备注 |
---|---|---|---|
status | 2字节 | / | 正常时,数值为0x0000 |
block_id/flag | 2字节 | / | 根据GVCP控制,来确认此时是block_id还是flag。 |
EI & reserved & packet_format | 1字节 | 0x81 | block_id64数据包。前导包。 |
Packet_id/reserved | 3字节 | / | 根据GVCP控制,来确认此时是Packet_id还是reserved |
Block_id64 highpart | 4字节 | 累加 | 块ID,不能为0(0位测试数据),每发送一帧图像,累加1。 |
Block_id64 lowpart | 4字节 | 累加 | |
Packet_id32 | 4字节 | 累加 | 包ID,从0开始累加,前导包为0 |
field_id | 0.5字节 | / | 用于隔行扫描模式。逐行扫描,永远为0 |
field_count | 0.5字节 | / | |
reserved | 1字节 | 0x00 | |
payload_type | 2字节 | / | 表明payload包的类型: 0x0001表示未压缩的图像数据 |
时间戳 highpart | 4字节 | / | |
时间戳 lowpart | 4字节 | / | |
像素格式 | 4字节 | / | 指示像素的位宽和元素数目。0x01080001表示8UC1 |
size_x | 4字节 | / | payload中传输图像的宽度 |
size_y | 4字节 | / | payload中传输图像的高度 |
offeset_x | 4字节 | / | ROI区域X方向的偏移 |
offeset_y | 4字节 | / | ROI区域Y方向的偏移 |
padding_x | 2字节 | / | 每行末尾的字节填充数,用于图像对齐。类似于水平消隐 |
padding_y | 2字节 | / | 图像末尾的字节填充数,用于图像对齐。类似于垂直消隐。 |
上表中,注意的是,如果上位机通过GVCP将数据传输方式配置为Block_id和packet_id的模式,那么block_id64和packet_id32应该为0。反之,如果GVCP将数据传输方式配置为Block_id64和packet_id32的模式,那么block_id和packet_id应该为0。
2.3.2 payload包
相机发送完leader包后,紧接着应该发送payload包,payload包的数据格式 如下:
名称 | 长度 | 数值 | 备注 |
---|---|---|---|
status | 2字节 | / | 正常时,数值为0x0000 |
block_id/flag | 2字节 | / | 此处应为flag,正常情况下为0x0000。 |
EI & reserved & packet_format | 1字节 | 0x83 | block_id64数据包。通用数据负载格式。 |
Packet_id/reserved | 3字节 | / | 包ID,因采用block_id64,此处为保留位 |
Block_id64 highpart | 4字节 | 累加 | 块ID,不能为0(0位测试数据),每发送一帧图像,累加1。 |
Block_id64 lowpart | 4字节 | 累加 | |
Packet_id32 | 4字节 | 累加 | 包ID,从0开始累加,前导包为0,有效数据包累加 |
data | / | / | GVCP中指定大小的图像数据。小端字节模式 |
假设GVCP协议配置中,配置一包payload包中发送A字节的数据。则为了发送完整幅图像的有效数据,则可能分成N包payload包进行发送。
注意,除了最后一包之外,其余所有的payload数据包应该为A字节数据。
2.3.3 trailer包
发送完所有的payload数据包后,将发送trailer数据包,完成一整幅图像的发送。trailer包的格式如下:
名称 | 长度 | 数值 | 备注 |
---|---|---|---|
status | 2字节 | / | 正常时,数值为0x0000 |
block_id/flag | 2字节 | / | 此处应为flag,正常情况下为0x0000。 |
EI & reserved & packet_format | 1字节 | 0x82 | block_id64数据包。尾数据包。 |
Packet_id/reserved | 3字节 | / | 包ID,因采用block_id64,此处为保留位 |
Block_id64 highpart | 4字节 | / | 块ID,不能为0(0为测试数据块),每发送一帧图像,累加1。 |
Block_id64 lowpart | 4字节 | / | |
Packet_id32 | 4字节 | / | 包ID,从0开始累加,前导包为0,有效数据包累加 |
Reserved | 2字节 | / | 保留 |
Payload_type | 2字节 | / | 表明payload包的类型: 0x0001表示未压缩的图像数据 |
Size_y | 4字节 | / | 指示图像的实际高度,即有时候图像高度可变 |
三、FPGA实现
目前,作者使用FPGA分别实现了gige发送器和gige接收器,实现较为粗糙。
gige发送器(相机),实现了数量较少的GVCP配置,实现了未压缩图像数据的发送,使用halcon测试,接收gige图像正常。
gige接收器(上位机),实现了指定相机的图像数据接收(未解析XML文件,提前获知各个功能的寄存器地址和数值,在FPGA代码中固定配置)。
由于涉及一些原因,暂时不分享代码,望理解。