热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

基于CameraLink的串行口通讯

文章目录1.引言2.CameraLink串行口协议3.串口通讯编程方法3.1DLL技术3.2通用API3.3编程流程4.CameraLink协议中串行通讯函数介绍4.1初始化前4.


文章目录

    • 1. 引言
    • 2. CameraLink串行口协议
    • 3. 串口通讯编程方法
      • 3.1 DLL技术
      • 3.2通用API
      • 3.3 编程流程
    • 4. CameraLink协议中串行通讯函数介绍
      • 4.1 初始化前
        • 4.1.1 clGetNumSerialPorts
        • 4.1.2 clGetManufacturerInfo
        • 4.1.3 clGetSerialPortIdentifier
      • 4.2 串口初始化和参数设置
        • 4.2.1 clSerialInit
        • 4.2.2.1 clGetSupportedBaudRates
        • 4.2.2.2 clSetBaudRate
        • 4.2.3 clSetFlowControlMode
        • 4.2.4 clSetParity
        • 4.2.5 clSetPortFeature
      • 4.3 串口读写
        • 4.3.1 clSerialRead
        • 4.3.3 clSerialWrite
        • 4.3.3 clGetNumBytesAvail
        • 4.3.4 clGetErrorText
      • 4.4 关闭串口
        • 4.4.1 clSerialClose


1. 引言

CameraLink是2002年10月由NI公司与其它图像采集公司联合推出的一种高速的、应用于视觉系统的接口协议,旨在简化数字相机同采集卡之间的连接。在扩展ChannelLink基本技术的基础上, CameraLink协议与以往的标准相比有更大的优势:减少了开发时间和成本;标准电缆支持增加的信号速度,且其结构允许根据流量定价来减少用户的费用;采用了更小的接插件,5对信号线可以传送多达28位的数据,从而可以制造体积更小的相机;高数据传输速率,ChannelLink芯片的数据传输速率高达2.38Gbits/s,支持目前传输速率的增长趋势。总体来说, CameraLink协议为高速高精度数字相机提供了简单灵活的连接。

标准CameraLink协议中、电缆包括电源信号、高速相机控制信号(即外部同步信号、重置信号、向前信号和保留信号)、低速串行通讯命令和高速图像数据信号,通过低速串行通讯命令,可以完成主机端对相机的配置和其它操作。

本文根据2004年1月的Camera Link v1.1协议,介绍了其中串行口通讯部分的编程方法,并在Visual C++编程环境下完成了对自主研发的CameraLink高速线扫描相机的通讯软件,成功对相机进行了设置。


2. CameraLink串行口协议

CameraLink协议提供了异步串行口通讯功能,允许相机制造者编写独立于采集卡的程序,通过CameraLink串行口与相机通讯,从而完成对相机的配置。在此协议下,相机制造者能够简单地操作串行口,而不用留意异步串行口通讯的实际执行方法。

CameraLink协议采用了动态链接库技术(DLL),定义了两个串行口通讯应用程序接口(API)。


  • 一个是通用API,提供给相机制造者来完成独立于采集卡的相机设置程序,其中的函数包含在clallserial.dl文件中。
  • 另一个API由采集卡制造者提供,完成特定采集卡的异步串行口通讯功能的执行方法,它的所有函数包含在clserxxx.d文件中。xxx为采集卡公司的英文简称,采集卡公司通过在AIA(自动化成像协会)注册,获得一个特定的名称(xxx)为它的DLL命名。

相机设置程序调用clallserial.dll的函数, clallserial.dll会自动加载与此工程应用相关的相应采集卡的特定DLL文件。它会发送所有命令至这个DLL,图1说明了这种关系。
在这里插入图片描述

通用API通过导入链接库(import library)支持C/C++程序,且在Visual Basic版的DLL中采用类型链接库(type library)资源,从而简化了应用程序之间的接口。当clallserial.dll被加载,它搜HKEY_LOCAL_MACHINE\software\cameralink注册表项中定义的CameraLink目录,并在此目录下寻找使用约定名称clserxxx.dll的文件。clallserial.dll自动加载找到的文件,并查询每一个文件的制造商名称和串行口名称。它会返回一个系统内所有CameraLink串行口列表。当所需的DLL文件加载后,clallserial.dll管理并传递应用程序的消息至指定串行口相应的DLL执行

当前CameraLink标准下的串行口通讯有以下特征:


  1. 支持同时多串行口(包括不同采集卡)通讯;
  2. 支持二进制数据和字符数据传输;
  3. 通用API、通用错误码、通用错误文本;
  4. 所有函数都有严格的定义和明确的行为;
  5. 开放具体供应商的错误码和错误文本;
  6. 可列举系统串行口;
  7. 可查询/调整串行口波特率;
  8. 支持Win32(向其它平台串行口开敬资源);
  9. 通过导入库支持C/C++;
  10. 通过类型库支持Visual Basic;
  11. 向下兼容2000年10月的Camera Link说明;
  12. 串行口标准默认通讯设置;
  13. 线程安全

3. 串口通讯编程方法


3.1 DLL技术

DLL是包含函数和数据的模块,它在需要调用它的模块(. EXE或. DLL)运行时加载DLL加载后,它映射到调用它的进程的地址空间。在DLL中可以定义两种函数:导出函数和内部函数。导出函数可以被其它模块调用;内部函数只能由定义它的DLL在内部调用。DLL提供了模块化的一种方式,它使一些功能可以更容易地被更新和重用,在多个工程同时使用同样的功能时,它通过每个工程使用自己数据的拷贝的同时共享同一段代码来减少所需的内存。


3.2通用API

在C/C++编程中,clallserial.dll文件及其导入库文件clallserial.lib和头文件clallserial.h使用了如表1所示的数据类型,表1同时列出了windows操作系统中其相应的数据类型。

clallserial.dll也提供了可以被C/C++程序调用的函数,如表2所示。利用这些函数我们可以编写独立于采集卡的程序,实现与Camera Link接口相机的通讯,从而完成对相机的配置。


3.3 编程流程

基本流程:


  1. 定义需要的数据类型和函数指针。
  2. 在程序中动态加载clallserial.dll文件,它会自动加载系统安装的采集卡的DLL链接库。
  3. 对CameraLink串口进行所需要的的操作。

4. CameraLink协议中串行通讯函数介绍


4.1 初始化前


4.1.1 clGetNumSerialPorts

此函数返回特定制造商在您系统中的串行端口数。


  1. 声明

    int clGetNumSerialPorts(unsigned int *numSerialPorts
    );

  2. 参数
    numSerialPorts:获得您可以使用当前DLL访问的系统中的串行端口数。
  3. 返回值
    CL_ERR_NO_ERR :函数成功返回。

4.1.2 clGetManufacturerInfo

此函数返回创建DLL的图像采集卡制造商的名称,以及DLL遵循的Camera Link规范的版本。


  1. 声明

    int clGetManufacturerInfo(char *manufacturerName, unsigned int *bufferSize, unsigned int *version
    );

  2. 参数
    manufacturerName指向用户分配的缓冲区的指针,该函数将制造商名称复制到该缓冲区中。返回的名称以NULL终止。
    bufferSize作为输入,此值应该是传递的缓冲区的大小。成功返回后,此参数包含写入缓冲区的字节数,包括NULL终止字符。在 CL_ERR_BUFFER_TOO_SMALL上,此参数包含写入数据文本所需的缓冲区大小。
    version一个常量,说明此DLL遵循的Camera Link规范的版本。
  3. 返回值
    CL_ERR_NO_ERR#define CL_ERR_NO_ERR 0:函数成功返回。
    CL_ERR_BUFFER_TOO_SMALL#define CL_ERR_BUFFER_TOO_SMALL -10001:用户缓冲区不足以容纳数据。ManufacturerName太小,无法包含制造商名称,需要将其缩放为写入bufferSize的值。

4.1.3 clGetSerialPortIdentifier

此函数为系统中的每个串行端口返回制造商特定的标识符。

这将返回一个字符串,其中包含Silicon Software framegrabber SDK使用的板卡和端口索引.


  1. 声明

    int clGetSerialPortIdentifier(unsigned int serialIndex,char* portID,unsigned int* bufferSize
    );

  2. 参数
    serialIndex从零开始的索引值。serialIndex的有效范围是0到(n–1),其中n是由clGetNumSerialPorts()返回的numSerialPorts的值。
    portID串行端口的制造商特定标识符
    bufferSize作为输入,此值应该是传递的缓冲区的大小。成功返回后,此参数包含写入缓冲区的字节数,包括NULL终止字符。在CL_ERR_BUFFER_TOO_SMALL上,此参数包含写入数据文本所需的缓冲区大小
  3. 返回值
    CL_ERR_NO_ERR#define CL_ERR_NO_ERR 0:函数成功返回。
    CL_ERR_INVALID_INDEX#define CL_ERR_INVALID_INDEX -10005:不是有效的索引。
    CL_ERR_BUFFER_TOO_SMALL#define CL_ERR_BUFFER_TOO_SMALL -10001:用户缓冲区不足以容纳数据。portID太小,无法包含端口标识字符串,因此需要将其缩放为写入bufferSize的值

4.2 串口初始化和参数设置


4.2.1 clSerialInit

该函数初始化由serialIndex引用的设备,并返回一个指向内部串行引用结构的指针。

串口将使用默认设置进行初始化。波特率将设置为9600,没有奇偶校验,并且任何高级端口功能都将设置为硬件默认值。如果串行端口同时支持UART和USART模式,它将被设置为UART模式。


  1. 声明

    int clSerialInit(unsigned int serialIndex, void **serialRefPtr
    );

  2. 参数

    erialIndex从零开始的索引值。对于此库支持的系统中的n个串行设备,serialIndex的范围为0到(n-1)。
    serialRefPtr成功调用时,指向一个值,该值包含指向当前会话的特定于供应商的引用的指针。
  3. 返回值

    返回值意义
    CL_ERR_NO_ERR#define CL_ERR_NO_ERR 0:函数成功返回。
    CL_ERR_PORT_IN_USE#define CL_ERR_PORT_IN_USE -10003:端口有效,但由于正在使用中而无法打开。
    CL_ERR_INVALID_INDEX#define CL_ERR_INVALID_INDEX -10005:不是有效的索引。
    CL_ERR_INVALID_REFERENCE#define CL_ERR_INVALID_REFERENCE -10006 串口参数无效。

4.2.2.1 clGetSupportedBaudRates

此函数返回当前接口的有效波特率。


  1. 声明

    int clGetSupportedBaudRates(void *serialRef, unsigned int *baudRates
    );

  2. 参数
    serialRef从clSerialInit()函数获得的值,该值描述要查询的波特率的端口。
    baudRates用于描述串行端口支持的所有波特率,如serialRefPtr所述。
  3. 返回值
    CL_ERR_NO_ERR#define CL_ERR_NO_ERR 0:函数成功返回。
    CL_ERR_INVALID_REFERENCE#define CL_ERR_INVALID_REFERENCE -10006: 串口参数无效。

4.2.2.2 clSetBaudRate

此功能设置所选设备的串行端口的波特率。

使用clGetSupportedBaudRates()确定支持的波特率。串口将使用默认设置进行初始化。奇偶校验将被禁用,所有高级端口功能都将设置为硬件默认值。


  1. 声明

    int clSetBaudRate(void *serialRef,unsigned int baudRate
    );

  2. 参数

    serialRef从clSerialInit()函数获得的值。
    baudRate您要使用的波特率。此参数需要由CL_BAUDRATE常量表示的值。
  3. 返回值

    CL_ERR_NO_ERR#define CL_ERR_NO_ERR 0:函数成功返回。
    CL_ERR_BAUD_RATE_NOT_SUPPORTED#defineCL_ERR_BAUD_RATE_NOT_SUPPORTED -10008:此接口不支持请求的波特率。
    CL_ERR_INVALID_REFERENCE#define CL_ERR_INVALID_REFERENCE -10006: 串口参数无效。

4.2.3 clSetFlowControlMode

此功能允许启用非对称RTS / CTS硬件流控制。

一些串行端口支持标准的非对称RTS / CTS硬件流控制。由于RTS和CTS信号需要额外的连接,因此必须组合两个UART模块。主端口用于通信,而使用硬件流控制时,次端口将被禁用。请参阅设备文档以获取硬件流控制的支持,以及必须组合哪些UART模块的详细信息。


  1. 声明

    int clSetFlowControlMode ( void * serialRef,void * secondRef,unsigned int flowControl
    )

  2. 参数

    serialRef从clSerialInit()函数获得的主端口句柄
    secondRef从clSerialInit()函数获得的辅助端口句柄。
    flowControl0:关闭流控制,0x01使用硬件流控制
  3. 返回值

    返回值意义
    CL_ERR_NO_ERR#define CL_ERR_NO_ERR 0:函数成功返回。
    CL_ERR_FUNCTION_NOT_FOUND#define CL_ERR_FUNCTION_NOT_FOUND -10099: 该功能在制造商的库中不存在。即主端口不支持USART模式。
    CL_ERR_INVALID_INDEX#define CL_ERR_INVALID_INDEX -10005: 辅助端口与主端口不匹配
    CL_ERR_INVALID_REFERENCE#define CL_ERR_INVALID_REFERENCE -10006 无效的串行句柄

4.2.4 clSetParity

此功能设置所选设备的串行端口的奇偶校验。

任何高级端口设置都将重置为硬件默认值。


  1. 声明

    int clSetParity( void * serialRef,unsigned int parityOn
    )

  2. 参数

    serialRef从clSerialInit()函数获得的值。
    parityOn应使用的奇偶校验(0:关闭奇偶校验; 1:偶数奇偶校验)
  3. 返回值

    返回值意义
    CL_ERR_NO_ERR#define CL_ERR_NO_ERR 0:函数成功返回。
    CL_ERR_INVALID_REFERENCE#define CL_ERR_INVALID_REFERENCE -10006 串口参数无效。

4.2.5 clSetPortFeature

此功能可以激活不同的增强设置。

这些功能特定于某些硬件和帧捕获器类型。该功能保留给Silicon Software硬件的将来版本使用。位掩码的每个位代表一个特定的开关。


  1. 声明

    int clSetPortFeature(void * serialRef,unsigned int feature,unsigned int value
    )

  2. 参数

    serialRef从clSerialInit()函数获得的值
    feature特定功能的标识符
    value为功能设置的值
  3. 返回值

    返回值意义
    CL_ERR_NO_ERR#define CL_ERR_NO_ERR 0:函数成功返回。
    CL_ERR_FUNCTION_NOT_FOUND无效的端口功能或不支持的功能
    CL_ERR_INVALID_ARG端口功能的值无效
    CL_ERR_INVALID_REFERENCE#define CL_ERR_INVALID_REFERENCE -10006 串口参数无效。

4.3 串口读写


4.3.1 clSerialRead

此函数从serialRef引用的串行设备读取numBytes。


  1. 声明

    int clSerialRead( void * serialRef,char * buffer,unsigned int * numBytes,unsigned int serialTimeout
    )

  2. 参数

    erialRef从clSerialInit()函数获得的值。
    buffer指向用户分配的缓冲区。调用成功后,缓冲区包含从串行设备读取的数据。发生故障时,此缓冲区不受影响。调用方应确保缓冲区的大小至少为numBytes。
    numBytes调用方请求的字节数。
    serialTimeout表示超时(以毫秒为单位)。
  3. 返回值
    当在串行端口上有numBytes可用时,或当serialTimeout周期过去时,clSerialRead()将返回。

    • 成功后,将numBytes复制到缓冲区。
    • 如果发生任何错误(包括CL_ERR_TIMEOUT),则不会将任何数据复制到缓冲区中。
    返回值意义
    CL_ERR_NO_ERR#define CL_ERR_NO_ERR 0:函数成功返回。
    CL_ERR_TIMEOUT#define CL_ERR_TIMEOUT -10004:在指定的超时时间内操作未完成。
    CL_ERR_INVALID_REFERENCE#define CL_ERR_INVALID_REFERENCE -10006 串口参数无效。

4.3.3 clSerialWrite

该函数将缓冲区中的数据写入由serialRef引用的串行设备。


  1. 声明

    int clSerialWrite(void * serialRef,char * buffer,unsigned int * bufferSize,unsigned int serialTimeout
    )

  2. 参数
    erialRef从clSerialInit()函数获得的值。
    buffer包含要写入串行端口的数据。
    numBytes包含指示要写入的最大字节数的缓冲区大小。成功调用后,bufferSize包含写入串行设备的字节数。
    serialTimeout表示超时(以毫秒为单位)。

    📢📢 CameraLink规范将输入缓冲区的类型定义为“ char *”。Silicon Software实现保证永远不会修改此数据,实际上,它将立即将输入指针转换为“ const char *”。因此可以传入强制转换为“ char *”的任意常量数据来满足此接口。

  3. 返回值
    返回值意义
    CL_ERR_NO_ERR#define CL_ERR_NO_ERR 0:函数成功返回。
    CL_ERR_TIMEOUT#define CL_ERR_TIMEOUT -10004:在指定的超时时间内操作未完成。
    CL_ERR_INVALID_REFERENCE#define CL_ERR_INVALID_REFERENCE -10006 串口参数无效。

4.3.3 clGetNumBytesAvail

此函数从serialRef引用的串行设备读取numBytes。


  1. 声明

    int clGetNumBytesAvail(void *serialRef, unsigned int *numBytes
    );

  2. 参数
    serialRef由clSerialInit()函数获得的值
    numBytes当前可从端口读取的字节数。
  3. 返回值
    CL_ERR_NO_ERR#define CL_ERR_NO_ERR 0:函数成功返回。
    CL_ERR_INVALID_REFERENCE#define CL_ERR_INVALID_REFERENCE -10006: 串口参数无效。

4.3.4 clGetErrorText

此功能将错误代码转换为错误文本,以显示在对话框或标准I / O窗口中。


  1. 声明

    int clGetErrorText(int errorCode,char *errorText,unsigned int* errorTextSize
    );

  2. 参数

    rrorCode错误代码,用于查找对应的错误文本。该库中的每个函数均返回错误代码。
    errorText分配给调用方的缓冲区,该缓冲区包含函数返回时以NULL结尾的错误文本。
    errorTextSize成功时,包含写入缓冲区的字节数,包括NULL终止字符。此值应该是传入的错误文本缓冲区的大小(以字节为单位)。在CL_ERR_BUFFER_TOO_SMALL上,包含编写错误文本所需的缓冲区大小。
  3. 返回值

    CL_ERR_NO_ERR错误文本已被写入errorText
    CL_ERR_BUFFER_TOO_SMALL#define CL_ERR_BUFFER_TOO_SMALL -10001:用户缓冲区不足以容纳数据。即errorText太小而无法包含错误消息,需要将其缩放到写入errorTextSize的值
    CL_ERR_ERROR_NOT_FOUND#define CL_ERR_FUNCTION_NOT_FOUND -10099:该功能在制造商的库中不存在。

4.4 关闭串口


4.4.1 clSerialClose

此函数关闭串行设备并清理与serialRef相关的资源。
返回时,serialRef不再可用。


  1. 声明

    void clSerialClose(void *serialRef);

  2. 参数
    serialRef : 从clSerialInit()函数获得的用于清除的值。


总结:

  • 基于CameraLink的串行口通讯编程方法
  • clser.h文件参考: API


推荐阅读
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • 本文介绍了在处理不规则数据时如何使用Python自动提取文本中的时间日期,包括使用dateutil.parser模块统一日期字符串格式和使用datefinder模块提取日期。同时,还介绍了一段使用正则表达式的代码,可以支持中文日期和一些特殊的时间识别,例如'2012年12月12日'、'3小时前'、'在2012/12/13哈哈'等。 ... [详细]
  • 本文讨论了在VMWARE5.1的虚拟服务器Windows Server 2008R2上安装oracle 10g客户端时出现的问题,并提供了解决方法。错误日志显示了异常访问违例,通过分析日志中的问题帧,找到了解决问题的线索。文章详细介绍了解决方法,帮助读者顺利安装oracle 10g客户端。 ... [详细]
  • 使用freemaker生成Java代码的步骤及示例代码
    本文介绍了使用freemaker这个jar包生成Java代码的步骤,通过提前编辑好的模板,可以避免写重复代码。首先需要在springboot的pom.xml文件中加入freemaker的依赖包。然后编写模板,定义要生成的Java类的属性和方法。最后编写生成代码的类,通过加载模板文件和数据模型,生成Java代码文件。本文提供了示例代码,并展示了文件目录结构。 ... [详细]
  • Linux重启网络命令实例及关机和重启示例教程
    本文介绍了Linux系统中重启网络命令的实例,以及使用不同方式关机和重启系统的示例教程。包括使用图形界面和控制台访问系统的方法,以及使用shutdown命令进行系统关机和重启的句法和用法。 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • 本文介绍了Oracle数据库中tnsnames.ora文件的作用和配置方法。tnsnames.ora文件在数据库启动过程中会被读取,用于解析LOCAL_LISTENER,并且与侦听无关。文章还提供了配置LOCAL_LISTENER和1522端口的示例,并展示了listener.ora文件的内容。 ... [详细]
  • 本文介绍了使用PHP实现断点续传乱序合并文件的方法和源码。由于网络原因,文件需要分割成多个部分发送,因此无法按顺序接收。文章中提供了merge2.php的源码,通过使用shuffle函数打乱文件读取顺序,实现了乱序合并文件的功能。同时,还介绍了filesize、glob、unlink、fopen等相关函数的使用。阅读本文可以了解如何使用PHP实现断点续传乱序合并文件的具体步骤。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • 拥抱Android Design Support Library新变化(导航视图、悬浮ActionBar)
    转载请注明明桑AndroidAndroid5.0Loollipop作为Android最重要的版本之一,为我们带来了全新的界面风格和设计语言。看起来很受欢迎࿰ ... [详细]
  • 自动轮播,反转播放的ViewPagerAdapter的使用方法和效果展示
    本文介绍了如何使用自动轮播、反转播放的ViewPagerAdapter,并展示了其效果。该ViewPagerAdapter支持无限循环、触摸暂停、切换缩放等功能。同时提供了使用GIF.gif的示例和github地址。通过LoopFragmentPagerAdapter类的getActualCount、getActualItem和getActualPagerTitle方法可以实现自定义的循环效果和标题展示。 ... [详细]
  • IjustinheritedsomewebpageswhichusesMooTools.IneverusedMooTools.NowIneedtoaddsomef ... [详细]
  • 本文介绍了Swing组件的用法,重点讲解了图标接口的定义和创建方法。图标接口用来将图标与各种组件相关联,可以是简单的绘画或使用磁盘上的GIF格式图像。文章详细介绍了图标接口的属性和绘制方法,并给出了一个菱形图标的实现示例。该示例可以配置图标的尺寸、颜色和填充状态。 ... [详细]
  • 合并列值-合并为一列问题需求:createtabletab(Aint,Bint,Cint)inserttabselect1,2,3unionallsel ... [详细]
  • OpenMap教程4 – 图层概述
    本文介绍了OpenMap教程4中关于地图图层的内容,包括将ShapeLayer添加到MapBean中的方法,OpenMap支持的图层类型以及使用BufferedLayer创建图像的MapBean。此外,还介绍了Layer背景标志的作用和OMGraphicHandlerLayer的基础层类。 ... [详细]
author-avatar
王永星2012
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有