SONY VISCA协议及其简单认识

2024-04-23 18:32
文章标签 简单 协议 认识 sony visca

本文主要是介绍SONY VISCA协议及其简单认识,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

visca是索尼公司搞出来的,用来控制相机的协议,一般通过rs232来通信(看了些资料,也有用rs485的)。

一、命令格式

命令通信的基本单元称为包(Packet)。一个包的长度为3到16字节,由头部、消息体和结束符三部分组成。命令包的第一个字节称为命令头(Header)。高半字节由1 (最高位,固定为1)和发送方(控制者)地址(地址一般为0)组成,低半字节由0和设备(相机)地址(或称“编号”)组成,从组成格式看,可以外接的相机最多有7台,如向1号相机发送命令,则命令头为0x81。命令包最后一个字节为终结符号,固定为0xff。中间部分字节称为消息体。协议说明文档中将命令头写成“8x”,其中x表示相机地址。

命令共2类:普通命令(Command)及查询命令(Inquiry)。前者是直接发送命令到相机,后者是从相机获取到数据。
具体的命令包格式如下:
8X QQ RR … FF
其中QQ为命令分类,01表示普通命令,09表示查询命令。RR为类别码(Category code)。X表示相机地址。范围1~7。

二、响应

每个命令均有响应包,格式如下:
X0 … … FF
其中X范围为9~F,数值为相机编号+8。以FF结束。发送普通命令时,相机会返回ACK响应,但查询命令不会返回ACK。

ACK响应包格式:X0 41 FF
普通命令响应包格式:X0 51 FF
查询命令响应包格式:X0 51 ... FF
其中,X范围为9~F,是相机地址值+8。查询命令的响应包中带有数据,每种数据均不相同,可以询查协议文档。

错误信息格式如下:
语法错误:X0 61 02 FF
命令取消:X0 61 04 FF
没有socket:X0 61 05 FF
命令没有执行:X0 61 41 FF
其中X的值和上面的一样。“socket”的范围暂时还不太了解。这些值就是代码做出判断的依据。

三、协议文档备注
对于协议文档中qprs这类的描述方式,直接将其放到16位的十六进制数据的各项(十六进制格式为0xAAAA)中即可。比如一个命令的响应包格式为“y0  50  0p 0q  0r  0s  FF”,则实际得到的数据是0xpqrs。如“01 02 03 04”,对应数据为0x1234。反之亦然。在代码中用移位来实现即可。下面看几个经典的命令格式。

1、不带参数的命令
相机上电CAM_Power命令格式: 8x  01  04  00  02  FF
“8x”中的“x”表示相机编号。此类命令,直接按命令字段来组装即可。

2、带参数的命令
变焦CAM_Zoom命令格式为:8x  01  04  47  0p 0q  0r  0s  FF。
“0p 0q 0r 0s”中的pqrs组成focus position参数。组装命令时,要将这个参数依次移位到对应的字段。假设参数值为0x1234,则对应的字段为“01 02 03 04”。
CAM_AFMode命令可以设置Active/Interval Time两个值,格式为:8x  01  04  27  0p 0q  0r  0s  FF
“0p 0q”对应于movement time,“0r 0s”对应于Interval,组装命令时,要分别进行组装。方式见上。

3、查询类命令,不带参数
像CAM_PowerInq查询命令,发送8x  09  04  00  FF,直接返回y0  50  02  FF或y0  50  03  FF
其中“y0  50  02  FF”是返回的数据,y值为相机编号+8。对于此类命令,直接读取第3个字节即可得到对应的状态。

4、查询类命令,带参数
像CAM_ZoomPosInq命令,发送8x  09  04  47  FF,返回y0  50  0p 0q  0r  0s  FF
在查询命令中,有大部分的命令是带有可变数据的,“y0  50  0p 0q  0r  0s  FF”中的“0p 0q 0r 0s”需要移位后才能知道确切的值,对应的值为0xpqrs。

四、实现

很庆幸,关于visca,已经有libvisca开源项目了(见参考资源)。下面参考这个项目,做了一些小修改,写一下关键的实现代码。

关于串口的打开、读写、关闭,在此不再多说。下面说一下命令的封装:

[cpp]  view plain  copy
在CODE上查看代码片 派生到我的代码片
  1. void _visca_append_byte(VISCAPacket_t *packet, unsigned char byte)  
  2. {  
  3.     packet->bytes[packet->length]=byte;  
  4.     (packet->length)++;  
  5. }  
  6.   
  7. void _visca_init_packet(VISCAPacket_t *packet)  
  8. {  
  9.     // set it to null  
  10.     memset(packet->bytes, '\0'sizeof(packet->bytes));  
  11.     // we start writing at byte 1, the first byte will be filled by the  
  12.     // packet sending function(_visca_send_packet). This function will also append a terminator.  
  13.     packet->length=1;  
  14. }  
[cpp]  view plain  copy
  1. void _visca_append_byte(VISCAPacket_t *packet, unsigned char byte)  
  2. {  
  3.     packet->bytes[packet->length]=byte;  
  4.     (packet->length)++;  
  5. }  
  6.   
  7. void _visca_init_packet(VISCAPacket_t *packet)  
  8. {  
  9.     // set it to null  
  10.     memset(packet->bytes, '\0'sizeof(packet->bytes));  
  11.     // we start writing at byte 1, the first byte will be filled by the  
  12.     // packet sending function(_visca_send_packet). This function will also append a terminator.  
  13.     packet->length=1;  
  14. }  

这两个函数是命令的填充,每次调用_visca_append_byte就填充一个字符,在未填充前,要调用_visca_init_packet来初始化包的长度。当然,实现上也可以直接用数组形式把每个命令合到一起发送出去。_visca_send_packet是填充头部和尾部数据,无须调用者进行考虑,调用者只需关注实际的命令数据即可。这也是使用了VISCAInterface_t的好处(后面写pelco实现的将会看到)。

[cpp]  view plain  copy
在CODE上查看代码片 派生到我的代码片
  1. int32_t _visca_send_packet(VISCAInterface_t *iface, VISCACamera_t *camera, VISCAPacket_t *packet)  
  2. {  
  3.     // check data:  
  4.     if ((iface->address>7)||(camera->address>7)||(iface->broadcast>1))  
  5.     {  
  6.         com_print("(%s): Invalid header parameters\n",__FILE__);  
  7.         com_print("addr: %d %d broadcast: %d(0x%x)\n",iface->address,camera->address,  
  8.                     iface->broadcast,iface->broadcast);  
  9.         return VISCA_FAILURE;  
  10.     }  
  11.   
  12.     // build header:  
  13.     packet->bytes[0]=0x80;  
  14.     packet->bytes[0]|=(iface->address << 4);  
  15.     if (iface->broadcast>0)  
  16.     {  
  17.         packet->bytes[0]|=(iface->broadcast << 3);  
  18.         packet->bytes[0]&=0xF8;  
  19.     }  
  20.     else  
  21.     {  
  22.         packet->bytes[0]|=camera->address;  
  23.     }  
  24.   
  25.     // append footer(0xff)  
  26.     _visca_append_byte(packet,VISCA_TERMINATOR);  
  27.   
  28.     return _visca_write_packet_data(iface,packet);  
  29. }  
[cpp]  view plain  copy
  1. int32_t _visca_send_packet(VISCAInterface_t *iface, VISCACamera_t *camera, VISCAPacket_t *packet)  
  2. {  
  3.     // check data:  
  4.     if ((iface->address>7)||(camera->address>7)||(iface->broadcast>1))  
  5.     {  
  6.         com_print("(%s): Invalid header parameters\n",__FILE__);  
  7.         com_print("addr: %d %d broadcast: %d(0x%x)\n",iface->address,camera->address,  
  8.                     iface->broadcast,iface->broadcast);  
  9.         return VISCA_FAILURE;  
  10.     }  
  11.   
  12.     // build header:  
  13.     packet->bytes[0]=0x80;  
  14.     packet->bytes[0]|=(iface->address << 4);  
  15.     if (iface->broadcast>0)  
  16.     {  
  17.         packet->bytes[0]|=(iface->broadcast << 3);  
  18.         packet->bytes[0]&=0xF8;  
  19.     }  
  20.     else  
  21.     {  
  22.         packet->bytes[0]|=camera->address;  
  23.     }  
  24.   
  25.     // append footer(0xff)  
  26.     _visca_append_byte(packet,VISCA_TERMINATOR);  
  27.   
  28.     return _visca_write_packet_data(iface,packet);  
  29. }  

命令响应包函数如下:

[cpp]  view plain  copy
在CODE上查看代码片 派生到我的代码片
  1. int32_t _visca_get_reply(VISCAInterface_t *iface, VISCACamera_t *camera)  
  2. {  
  3.     // first message: -------------------  
  4.     if (_visca_get_packet(iface)!= VISCA_SUCCESS)  
  5.         return VISCA_FAILURE;  
  6.   
  7.     iface->type=iface->ibuf[1]&0xF0;  
  8.   
  9.     // skip ack messages  
  10.     while (iface->type==VISCA_RESPONSE_ACK)  
  11.     {  
  12.         if (_visca_get_packet(iface)!=VISCA_SUCCESS)  
  13.             return VISCA_FAILURE;  
  14.         iface->type=iface->ibuf[1]&0xF0;  
  15.     }  
  16.   
  17.     switch (iface->type)  
  18.     {  
  19.     case VISCA_RESPONSE_CLEAR:  
  20.         return VISCA_SUCCESS;  
  21.         break;  
  22.     case VISCA_RESPONSE_ADDRESS:  
  23.         return VISCA_SUCCESS;  
  24.         break;  
  25.     case VISCA_RESPONSE_COMPLETED:  
  26.         return VISCA_SUCCESS;  
  27.         break;  
  28.     case VISCA_RESPONSE_ERROR:  
  29.         return VISCA_CMDERROR;  
  30.         break;  
  31.     }  
  32.   
  33.     return VISCA_FAILURE;  
  34. }  
[cpp]  view plain  copy
  1. int32_t _visca_get_reply(VISCAInterface_t *iface, VISCACamera_t *camera)  
  2. {  
  3.     // first message: -------------------  
  4.     if (_visca_get_packet(iface)!= VISCA_SUCCESS)  
  5.         return VISCA_FAILURE;  
  6.   
  7.     iface->type=iface->ibuf[1]&0xF0;  
  8.   
  9.     // skip ack messages  
  10.     while (iface->type==VISCA_RESPONSE_ACK)  
  11.     {  
  12.         if (_visca_get_packet(iface)!=VISCA_SUCCESS)  
  13.             return VISCA_FAILURE;  
  14.         iface->type=iface->ibuf[1]&0xF0;  
  15.     }  
  16.   
  17.     switch (iface->type)  
  18.     {  
  19.     case VISCA_RESPONSE_CLEAR:  
  20.         return VISCA_SUCCESS;  
  21.         break;  
  22.     case VISCA_RESPONSE_ADDRESS:  
  23.         return VISCA_SUCCESS;  
  24.         break;  
  25.     case VISCA_RESPONSE_COMPLETED:  
  26.         return VISCA_SUCCESS;  
  27.         break;  
  28.     case VISCA_RESPONSE_ERROR:  
  29.         return VISCA_CMDERROR;  
  30.         break;  
  31.     }  
  32.   
  33.     return VISCA_FAILURE;  
  34. }  

里面一些宏定义如下:

[cpp]  view plain  copy
在CODE上查看代码片 派生到我的代码片
  1. /* response types */  
  2. #define VISCA_RESPONSE_CLEAR             0x40  
  3. #define VISCA_RESPONSE_ADDRESS           0x30  
  4. #define VISCA_RESPONSE_ACK               0x40  
  5. #define VISCA_RESPONSE_COMPLETED         0x50  
  6. #define VISCA_RESPONSE_ERROR             0x60  
[cpp]  view plain  copy
  1. /* response types */  
  2. #define VISCA_RESPONSE_CLEAR             0x40  
  3. #define VISCA_RESPONSE_ADDRESS           0x30  
  4. #define VISCA_RESPONSE_ACK               0x40  
  5. #define VISCA_RESPONSE_COMPLETED         0x50  
  6. #define VISCA_RESPONSE_ERROR             0x60  

其实判断也十分简单,就是根据协议给出的错误码来一一判断。
其它的代码,直接参考libvisca即可,不在这里列出。

 

参考资源:

1、开源的visca协议库:libvisca: http://damien.douxchamps.net/libvisca/
2、visca协议的wiki介绍:http://en.wikipedia.org/wiki/VISCA_Protocol

 

后记:截止本文编写时,手上还没有得到硬件资源,文章是根据libvisca和visca协议文档中的描述来写的,应该不具有实践价值。

李迟记于2014年6月30日

这篇关于SONY VISCA协议及其简单认识的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/929562

相关文章

Java8需要知道的4个函数式接口简单教程

《Java8需要知道的4个函数式接口简单教程》:本文主要介绍Java8中引入的函数式接口,包括Consumer、Supplier、Predicate和Function,以及它们的用法和特点,文中... 目录什么是函数是接口?Consumer接口定义核心特点注意事项常见用法1.基本用法2.结合andThen链

Qt 中集成mqtt协议的使用方法

《Qt中集成mqtt协议的使用方法》文章介绍了如何在工程中引入qmqtt库,并通过声明一个单例类来暴露订阅到的主题数据,本文通过实例代码给大家介绍的非常详细,感兴趣的朋友一起看看吧... 目录一,引入qmqtt 库二,使用一,引入qmqtt 库我是将整个头文件/源文件都添加到了工程中进行编译,这样 跨平台

C++初始化数组的几种常见方法(简单易懂)

《C++初始化数组的几种常见方法(简单易懂)》本文介绍了C++中数组的初始化方法,包括一维数组和二维数组的初始化,以及用new动态初始化数组,在C++11及以上版本中,还提供了使用std::array... 目录1、初始化一维数组1.1、使用列表初始化(推荐方式)1.2、初始化部分列表1.3、使用std::

redis群集简单部署过程

《redis群集简单部署过程》文章介绍了Redis,一个高性能的键值存储系统,其支持多种数据结构和命令,它还讨论了Redis的服务器端架构、数据存储和获取、协议和命令、高可用性方案、缓存机制以及监控和... 目录Redis介绍1. 基本概念2. 服务器端3. 存储和获取数据4. 协议和命令5. 高可用性6.

JAVA调用Deepseek的api完成基本对话简单代码示例

《JAVA调用Deepseek的api完成基本对话简单代码示例》:本文主要介绍JAVA调用Deepseek的api完成基本对话的相关资料,文中详细讲解了如何获取DeepSeekAPI密钥、添加H... 获取API密钥首先,从DeepSeek平台获取API密钥,用于身份验证。添加HTTP客户端依赖使用Jav

利用Python编写一个简单的聊天机器人

《利用Python编写一个简单的聊天机器人》这篇文章主要为大家详细介绍了如何利用Python编写一个简单的聊天机器人,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 使用 python 编写一个简单的聊天机器人可以从最基础的逻辑开始,然后逐步加入更复杂的功能。这里我们将先实现一个简单的

使用IntelliJ IDEA创建简单的Java Web项目完整步骤

《使用IntelliJIDEA创建简单的JavaWeb项目完整步骤》:本文主要介绍如何使用IntelliJIDEA创建一个简单的JavaWeb项目,实现登录、注册和查看用户列表功能,使用Se... 目录前置准备项目功能实现步骤1. 创建项目2. 配置 Tomcat3. 项目文件结构4. 创建数据库和表5.

使用PyQt5编写一个简单的取色器

《使用PyQt5编写一个简单的取色器》:本文主要介绍PyQt5搭建的一个取色器,一共写了两款应用,一款使用快捷键捕获鼠标附近图像的RGB和16进制颜色编码,一款跟随鼠标刷新图像的RGB和16... 目录取色器1取色器2PyQt5搭建的一个取色器,一共写了两款应用,一款使用快捷键捕获鼠标附近图像的RGB和16

四种简单方法 轻松进入电脑主板 BIOS 或 UEFI 固件设置

《四种简单方法轻松进入电脑主板BIOS或UEFI固件设置》设置BIOS/UEFI是计算机维护和管理中的一项重要任务,它允许用户配置计算机的启动选项、硬件设置和其他关键参数,该怎么进入呢?下面... 随着计算机技术的发展,大多数主流 PC 和笔记本已经从传统 BIOS 转向了 UEFI 固件。很多时候,我们也

基于Qt开发一个简单的OFD阅读器

《基于Qt开发一个简单的OFD阅读器》这篇文章主要为大家详细介绍了如何使用Qt框架开发一个功能强大且性能优异的OFD阅读器,文中的示例代码讲解详细,有需要的小伙伴可以参考一下... 目录摘要引言一、OFD文件格式解析二、文档结构解析三、页面渲染四、用户交互五、性能优化六、示例代码七、未来发展方向八、结论摘要