CameraLink是2002年10月由NI公司与其它图像采集公司联合推出的一种高速的、应用于视觉系统的接口协议,旨在简化数字相机同采集卡之间的连接。在扩展ChannelLink基本技术的基础上, CameraLink协议与以往的标准相比有更大的优势:减少了开发时间和成本;标准电缆支持增加的信号速度,且其结构允许根据流量定价来减少用户的费用;采用了更小的接插件,5对信号线可以传送多达28位的数据,从而可以制造体积更小的相机;高数据传输速率,ChannelLink芯片的数据传输速率高达2.38Gbits/s,支持目前传输速率的增长趋势。总体来说, CameraLink协议为高速高精度数字相机提供了简单灵活的连接。
标准CameraLink协议中、电缆包括电源信号、高速相机控制信号(即外部同步信号、重置信号、向前信号和保留信号)、低速串行通讯命令和高速图像数据信号,通过低速串行通讯命令,可以完成主机端对相机的配置和其它操作。
本文根据2004年1月的Camera Link v1.1协议,介绍了其中串行口通讯部分的编程方法,并在Visual C++编程环境下完成了对自主研发的CameraLink高速线扫描相机的通讯软件,成功对相机进行了设置。
CameraLink协议提供了异步串行口通讯功能,允许相机制造者编写独立于采集卡的程序,通过CameraLink串行口与相机通讯,从而完成对相机的配置。在此协议下,相机制造者能够简单地操作串行口,而不用留意异步串行口通讯的实际执行方法。
CameraLink协议采用了动态链接库技术(DLL),定义了两个串行口通讯应用程序接口(API)。
相机设置程序调用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标准下的串行口通讯有以下特征:
DLL是包含函数和数据的模块,它在需要调用它的模块(. EXE或. DLL)运行时加载DLL加载后,它映射到调用它的进程的地址空间。在DLL中可以定义两种函数:导出函数和内部函数。导出函数可以被其它模块调用;内部函数只能由定义它的DLL在内部调用。DLL提供了模块化的一种方式,它使一些功能可以更容易地被更新和重用,在多个工程同时使用同样的功能时,它通过每个工程使用自己数据的拷贝的同时共享同一段代码来减少所需的内存。
在C/C++编程中,clallserial.dll文件及其导入库文件clallserial.lib和头文件clallserial.h使用了如表1所示的数据类型,表1同时列出了windows操作系统中其相应的数据类型。
clallserial.dll也提供了可以被C/C++程序调用的函数,如表2所示。利用这些函数我们可以编写独立于采集卡的程序,实现与Camera Link接口相机的通讯,从而完成对相机的配置。
基本流程:
此函数返回特定制造商在您系统中的串行端口数。
int clGetNumSerialPorts(unsigned int *numSerialPorts
);
此函数返回创建DLL的图像采集卡制造商的名称,以及DLL遵循的Camera Link规范的版本。
int clGetManufacturerInfo(char *manufacturerName, unsigned int *bufferSize, unsigned int *version
);
manufacturerName | 指向用户分配的缓冲区的指针,该函数将制造商名称复制到该缓冲区中。返回的名称以NULL终止。 |
---|---|
bufferSize | 作为输入,此值应该是传递的缓冲区的大小。成功返回后,此参数包含写入缓冲区的字节数,包括NULL终止字符。在 CL_ERR_BUFFER_TOO_SMALL 上,此参数包含写入数据文本所需的缓冲区大小。 |
version | 一个常量,说明此DLL遵循的Camera Link规范的版本。 |
CL_ERR_NO_ERR | #define CL_ERR_NO_ERR 0:函数成功返回。 |
---|---|
CL_ERR_BUFFER_TOO_SMALL | #define CL_ERR_BUFFER_TOO_SMALL -10001:用户缓冲区不足以容纳数据。ManufacturerName太小,无法包含制造商名称,需要将其缩放为写入bufferSize的值。 |
此函数为系统中的每个串行端口返回制造商特定的标识符。
这将返回一个字符串,其中包含Silicon Software framegrabber SDK使用的板卡和端口索引.
int clGetSerialPortIdentifier(unsigned int serialIndex,char* portID,unsigned int* bufferSize
);
serialIndex | 从零开始的索引值。serialIndex的有效范围是0到(n–1),其中n是由clGetNumSerialPorts()返回的numSerialPorts的值。 |
---|---|
portID | 串行端口的制造商特定标识符 |
bufferSize | 作为输入,此值应该是传递的缓冲区的大小。成功返回后,此参数包含写入缓冲区的字节数,包括NULL终止字符。在CL_ERR_BUFFER_TOO_SMALL上,此参数包含写入数据文本所需的缓冲区大小 |
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的值 |
该函数初始化由serialIndex引用的设备,并返回一个指向内部串行引用结构的指针。
串口将使用默认设置进行初始化。波特率将设置为9600,没有奇偶校验
,并且任何高级端口功能都将设置为硬件默认值。如果串行端口同时支持UART和USART模式,它将被设置为UART模式。
声明
int clSerialInit(unsigned int serialIndex, void **serialRefPtr
);
参数
erialIndex | 从零开始的索引值。对于此库支持的系统中的n个串行设备,serialIndex的范围为0到(n-1)。 |
---|---|
serialRefPtr | 成功调用时,指向一个值,该值包含指向当前会话的特定于供应商的引用的指针。 |
返回值
返回值 | 意义 |
---|---|
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 串口参数无效。 |
此函数返回当前接口的有效波特率。
int clGetSupportedBaudRates(void *serialRef, unsigned int *baudRates
);
serialRef | 从clSerialInit()函数获得的值,该值描述要查询的波特率的端口。 |
---|---|
baudRates | 用于描述串行端口支持的所有波特率,如serialRefPtr所述。 |
CL_ERR_NO_ERR | #define CL_ERR_NO_ERR 0:函数成功返回。 |
---|---|
CL_ERR_INVALID_REFERENCE | #define CL_ERR_INVALID_REFERENCE -10006: 串口参数无效。 |
此功能设置所选设备的串行端口的波特率。
使用clGetSupportedBaudRates()确定支持的波特率。串口将使用默认设置进行初始化。奇偶校验将被禁用,所有高级端口功能都将设置为硬件默认值。
声明
int clSetBaudRate(void *serialRef,unsigned int baudRate
);
参数
serialRef | 从clSerialInit()函数获得的值。 |
---|---|
baudRate | 您要使用的波特率。此参数需要由CL_BAUDRATE常量表示的值。 |
返回值
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: 串口参数无效。 |
此功能允许启用非对称RTS / CTS硬件流控制。
一些串行端口支持标准的非对称RTS / CTS硬件流控制。由于RTS和CTS信号需要额外的连接,因此必须组合两个UART模块。主端口用于通信,而使用硬件流控制时,次端口将被禁用。请参阅设备文档以获取硬件流控制的支持,以及必须组合哪些UART模块的详细信息。
声明
int clSetFlowControlMode ( void * serialRef,void * secondRef,unsigned int flowControl
)
参数
serialRef | 从clSerialInit()函数获得的主端口句柄 |
---|---|
secondRef | 从clSerialInit()函数获得的辅助端口句柄。 |
flowControl | 0:关闭流控制,0x01使用硬件流控制 |
返回值
返回值 | 意义 |
---|---|
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 无效的串行句柄 |
此功能设置所选设备的串行端口的奇偶校验。
任何高级端口设置都将重置为硬件默认值。
声明
int clSetParity( void * serialRef,unsigned int parityOn
)
参数
serialRef | 从clSerialInit()函数获得的值。 |
---|---|
parityOn | 应使用的奇偶校验(0:关闭奇偶校验; 1:偶数奇偶校验) |
返回值
返回值 | 意义 |
---|---|
CL_ERR_NO_ERR | #define CL_ERR_NO_ERR 0:函数成功返回。 |
CL_ERR_INVALID_REFERENCE | #define CL_ERR_INVALID_REFERENCE -10006 串口参数无效。 |
此功能可以激活不同的增强设置。
这些功能特定于某些硬件和帧捕获器类型。该功能保留给Silicon Software硬件的将来版本使用。位掩码的每个位代表一个特定的开关。
声明
int clSetPortFeature(void * serialRef,unsigned int feature,unsigned int value
)
参数
serialRef | 从clSerialInit()函数获得的值 |
---|---|
feature | 特定功能的标识符 |
value | 为功能设置的值 |
返回值
返回值 | 意义 |
---|---|
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 串口参数无效。 |
此函数从serialRef引用的串行设备读取numBytes。
声明
int clSerialRead( void * serialRef,char * buffer,unsigned int * numBytes,unsigned int serialTimeout
)
参数
erialRef | 从clSerialInit()函数获得的值。 |
---|---|
buffer | 指向用户分配的缓冲区。调用成功后,缓冲区包含从串行设备读取的数据。发生故障时,此缓冲区不受影响。调用方应确保缓冲区的大小至少为numBytes。 |
numBytes | 调用方请求的字节数。 |
serialTimeout | 表示超时(以毫秒为单位)。 |
返回值
当在串行端口上有numBytes可用时,或当serialTimeout周期过去时,clSerialRead()将返回。
返回值 | 意义 |
---|---|
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 串口参数无效。 |
该函数将缓冲区中的数据写入由serialRef引用的串行设备。
int clSerialWrite(void * serialRef,char * buffer,unsigned int * bufferSize,unsigned int serialTimeout
)
erialRef | 从clSerialInit()函数获得的值。 |
---|---|
buffer | 包含要写入串行端口的数据。 |
numBytes | 包含指示要写入的最大字节数的缓冲区大小。成功调用后,bufferSize包含写入串行设备的字节数。 |
serialTimeout | 表示超时(以毫秒为单位)。 |
📢📢 CameraLink规范将输入缓冲区的类型定义为“
char *
”。Silicon Software实现保证永远不会修改此数据,实际上,它将立即将输入指针转换为“const char *
”。因此可以传入强制转换为“char *
”的任意常量数据来满足此接口。
返回值 | 意义 |
---|---|
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 串口参数无效。 |
此函数从serialRef引用的串行设备读取numBytes。
int clGetNumBytesAvail(void *serialRef, unsigned int *numBytes
);
serialRef | 由clSerialInit()函数获得的值 |
---|---|
numBytes | 当前可从端口读取的字节数。 |
CL_ERR_NO_ERR | #define CL_ERR_NO_ERR 0:函数成功返回。 |
---|---|
CL_ERR_INVALID_REFERENCE | #define CL_ERR_INVALID_REFERENCE -10006: 串口参数无效。 |
此功能将错误代码转换为错误文本,以显示在对话框或标准I / O窗口中。
声明
int clGetErrorText(int errorCode,char *errorText,unsigned int* errorTextSize
);
参数
rrorCode | 错误代码,用于查找对应的错误文本。该库中的每个函数均返回错误代码。 |
---|---|
errorText | 分配给调用方的缓冲区,该缓冲区包含函数返回时以NULL结尾的错误文本。 |
errorTextSize | 成功时,包含写入缓冲区的字节数,包括NULL终止字符。此值应该是传入的错误文本缓冲区的大小(以字节为单位)。在CL_ERR_BUFFER_TOO_SMALL上,包含编写错误文本所需的缓冲区大小。 |
返回值
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:该功能在制造商的库中不存在。 |
此函数关闭串行设备并清理与serialRef相关的资源。
返回时,serialRef不再可用。
声明
void clSerialClose(void *serialRef);
参数
serialRef : 从clSerialInit()函数获得的用于清除的值。
总结:
- 基于CameraLink的串行口通讯编程方法
- clser.h文件参考: API