光机接口测试

DLPC-API-1.10给的API比较杂,有很多也用不上,需要自己另外定义接口,官方给的有一个示例程序,程序里封装了一部分接口,先测试这些接口能不能用,然后在这个基础上增加需要的接口,实例程序中的包括:

  • I2C 写入
  • I2C 读取
  • 初始化命令层
  • 以秒为单位等待指定的时间
  • 生成一个1位(二维)图案
  • 生成一个8位(灰度)图案
  • 填充数组s_PatternSets 中的 DLPC34XX_INT_PAT_PatternSet_s结构
  • 填充数组s_PatternOrderTable 中的 DLPC34XX_INT_PAT_PatternOrderTableEntry_s结构
  • 将数据复制到 Flash 编程缓冲区以便后续写入
  • 将缓冲区数据编程到 Flash 中
  • 将数据写入文件
  • 生成图案数据并写入到文件
  • 缓存图案数据并编程到 Flash 中
  • 生成和编程图案数据到 Flash 中
  • 从 Flash 中加载图案顺序表条目
  • 加载特定的图案顺序表条目
  • 写入测试图案网格线
  • 写入测试图案色条
  • 写入选定视图外观(Look)
  • 加载预构建的模式数据
  • 写入 LABB 和 CAIC 设置
  • 加载固件

过程记录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
unsigned int WriteI2C(uint16_t WriteDataLength, uint8_t *WriteData, DLPC_COMMON_CommandProtocolData_s *ProtocolData) {
// 实现写入 I2C 设备的逻辑
// ...
return SUCCESS; // 或者在出错时返回错误代码
}

// 假设您有一个函数接受一个回调函数指针
void ExecuteWriteOperation(DLPC_COMMON_WriteCommandCallback callback) {
// ...
unsigned int result = callback(WriteDataLength, WriteData, &ProtocolData);
// ...
}

// 在调用 ExecuteWriteOperation 时,您可以传递 WriteI2C 函数
ExecuteWriteOperation(WriteI2C);

在这个例子中,ExecuteWriteOperation 函数接受一个类型为 DLPC_COMMON_WriteCommandCallback 的回调函数,并在内部调用它。这样,您可以将不同的写入操作作为回调传递给 ExecuteWriteOperation,而不需要修改其内部实现。

1
2
(gdb) ptype DLPC_COMMON_WriteCommandCallback
type = unsigned int (*)(uint16_t, uint8_t *, DLPC_COMMON_CommandProtocolData_s *)
  • 函数指针:定义回调函数,可以在不同的上下文中被调用。抽象特定的行为,使得代码更加模块化和可重用。
  • 返回类型:unsigned int
  • 参数列表:
    • uint16_t:无符号的16位整数
    • uint8_t *:指向无符号8位的整数的指针参数,数据缓冲区
    • DLPC_COMMON_CommandProtocolData_s *:指向结构体的指针,协议相关

当光机接入或者没有接入USB的时候均出现:Status = CY_ERROR_REQUEST_FAILED, NumDevices = 0 ‘\000’

  • CY_ERROR_REQUEST_FAILED:发送到 USB Serial 设备的请求失败
  • 表明函数 CyGetListofDevices 没有成功地找到任何连接的设备
1
2
3
4
5
6
7
8
zhm@Ubuntu:~/Jetson/StructLight/CyUSBSerial_SDK_Linux/linux/library$ lsusb
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 002: ID 0bda:8771 Realtek Semiconductor Corp. Bluetooth Radio
Bus 001 Device 003: ID 0000:3825 USB OPTICAL MOUSE
Bus 001 Device 004: ID 1c4f:0026 SiGma Micro Keyboard
Bus 001 Device 005: ID 05e3:0608 Genesys Logic, Inc. Hub
Bus 001 Device 018: ID 04b4:000a Cypress Semiconductor Corp. USB-Serial (Dual Channel)
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub

说明Cypress USB-Serial设备已经被系统识别,并且分配了设备ID 04b4:000a

驱动程序:libusb-1.0库(需要测试它能不能用)
经过测试,是可以用的。

使用sudo apt-get install 的时候,出现无法命中等问题,换源之后问题依然没有解决,可以尝试使用下面的方法。

1
2
3
4
5
6
1. sudo vim /etc/resolv.conf # 添加如下内容
nameserver 8.8.8.8
nameserver 8.8.4.4
nameserver 127.0.0.1

2. 输入Esc,:wq,保存并退出

解决方法

InitConnectionAndCommandLayer();出现错误,函数内部为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
* 初始化命令层,设置读/写缓冲区和回调函数。
*/
void InitConnectionAndCommandLayer()
{
// 初始化命令库,设置读/写缓冲区和对应的 I2C 读写函数
DLPC_COMMON_InitCommandLibrary(s_WriteBuffer,
sizeof(s_WriteBuffer),
s_ReadBuffer,
sizeof(s_ReadBuffer),
WriteI2C,
ReadI2C);

// 连接到 Cypress I2C
CYPRESS_I2C_ConnectToCyI2C();
}

CYPRESS_I2C_ConnectToCyI2C();函数内部为,添加printf定位问题出现位置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
bool CYPRESS_I2C_ConnectToCyI2C()
{
CY_RETURN_STATUS Status;
CY_I2C_CONFIG I2CConfig;
if (GetCyI2CHandle(&s_Handle) == false)
{
printf("Get CyI2C Handle Failed!!! \n");
return false;
}

I2CConfig.frequency = I2C_CLOCK_FREQUENCY_HZ;
I2CConfig.slaveAddress = 0x30;
I2CConfig.isMaster = true;
I2CConfig.isClockStretch = false;

Status = CySetI2cConfig(s_Handle, &I2CConfig);
if (Status != CY_SUCCESS)
{
printf("Connect to I2C Error %d!!! \n", Status);
return false;
}

s_DataConfig.isNakBit = true;
s_DataConfig.isStopBit = true;
s_DataConfig.slaveAddress = DLP_I2C_SLAVE_ADDRESS;

return true;
}

GetCyI2CHandle(&s_Handle)这里出现错误,添加printf定位问题,函数内部为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
/* Gets the handle of the connected Cypress USB-Serial bridge controller */
bool GetCyI2CHandle(CY_HANDLE* Handle)
{
CY_RETURN_STATUS Status;
CY_DEVICE_INFO DeviceInfo;
uint8_t NumDevices = 0;
uint8_t DeviceIdx;
uint8_t InterfaceIdx;

Status = CyGetListofDevices(&NumDevices);
if ((Status != CY_SUCCESS) || (NumDevices == 0))
{
printf("Status: %d\n", Status);
printf("NumDevices: %d\n", NumDevices);
printf("无设备连接成功,没有设备连接!!!\n");
return false;
}

for (DeviceIdx = 0; DeviceIdx < NumDevices; DeviceIdx++)
{
Status = CyGetDeviceInfo(DeviceIdx, &DeviceInfo);
if (Status != CY_SUCCESS)
{
continue;
}

for (InterfaceIdx = 0; InterfaceIdx < DeviceInfo.numInterfaces; InterfaceIdx++)
{
if (DeviceInfo.deviceType[InterfaceIdx] == CY_TYPE_I2C)
{
Status = CyOpen(DeviceIdx, InterfaceIdx, Handle);
if (Status == CY_SUCCESS)
{
return true;
}
}
}
}

printf("Get I2C Handle Error %d!!! \n", Status);
return false;
}

使用gdb定位到Status = CyGetListofDevices(&NumDevices);,Status输出为CY_ERROR_REQUEST_FAILED,定位到CyGetListofDevices(&NumDevices);

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/*
Summary
This API retrieves number of USB devices connected to the host.

Description
This API retrieves the number of devices connected to the host.
In Windows family of operating systems the API retrieves only the number of devices that are attached
to CyUSB3.SYS driver. For other operating systems, it retrieves the total number of USB devices present
on the bus. It includes both USB Serial device as well as other devices.

Note: In case of Linux and Mac apart from providing number of devices connected, it builds the
device list which is used for opening the device and obtaining device handle. Thus the API should be
called during device discovery in the application.

Return Value
* CY_SUCCESS on success
* CY_ERROR_DEVICE_NOT_FOUND if there are no devices attached.
* CY_ERROR_REQUEST_FAILED if library was not initialized.

See Also
* CyGetDeviceInfo
* CyGetDeviceInfoVidPid
* CyOpen
* CyClose
*/
CYWINEXPORT CY_RETURN_STATUS CyGetListofDevices (
UINT8* numDevices /*Number of Devices connected*/
);

定位到这里CY_ERROR_REQUEST_FAILED if library was not initialized.出现的原因是,因为library没有初始化。修改GetCyI2CHandle(CY_HANDLE* Handle)代码,添加初始化函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
bool GetCyI2CHandle(CY_HANDLE* Handle)
{
CY_RETURN_STATUS Status;
CY_DEVICE_INFO DeviceInfo;
uint8_t NumDevices = 0;
uint8_t DeviceIdx;
uint8_t InterfaceIdx;

Status = CyLibraryInit();
if (Status != CY_SUCCESS) {
printf("%d 设备初始化失败!!!\n", Status);
}
Status = CyGetListofDevices(&NumDevices);
if ((Status != CY_SUCCESS) || (NumDevices == 0))
{
printf("Status: %d\n", Status);
printf("NumDevices: %d\n", NumDevices);
printf("无设备连接成功,没有设备连接!!!\n");
return false;
}

for (DeviceIdx = 0; DeviceIdx < NumDevices; DeviceIdx++)
{
Status = CyGetDeviceInfo(DeviceIdx, &DeviceInfo);
if (Status != CY_SUCCESS)
{
continue;
}

for (InterfaceIdx = 0; InterfaceIdx < DeviceInfo.numInterfaces; InterfaceIdx++)
{
if (DeviceInfo.deviceType[InterfaceIdx] == CY_TYPE_I2C)
{
Status = CyOpen(DeviceIdx, InterfaceIdx, Handle);
if (Status == CY_SUCCESS)
{
return true;
}
}
}
}

printf("Get I2C Handle Error %d!!! \n", Status);
return false;
}

问题解决。

总结:
1、首先是单独测试USB驱动程序能不能用,写了一个单独测试USB的程序,可以正常运行。
2、检查PC机有没有连接到光机设备,可以使用lsusb指令。光机是连接到PC机上的。
3、检查程序有没有问题。printfgdb定位问题。


光机接口测试
http://example.com/2025/02/22/StructLight/projector/光机-接口测试/
作者
ZhangHangming
发布于
2025年2月22日
许可协议