1. 项目缘起从HDMI到BT1120的“翻译”难题最近在折腾一个基于海思Hi3531D的视频处理项目核心需求是把一路标准的HDMI视频信号“喂”给Hi3531D的VI视频输入模块进行处理。听起来很简单不就是接根线吗但实际一上手就发现问题没那么简单。Hi3531D的VI模块通常接收的是并行的数字视频信号比如BT1120、BT656这类格式而HDMI是一个包含视频、音频、控制信息的复杂串行协议两者根本“语言不通”。这就好比你想让一个只懂方言的人听懂普通话新闻直播中间必须有个翻译官。在这个项目里IT6801这颗芯片就是我们要找的“翻译官”——一款专门将HDMI信号解码并转换成并行数字视频输出的桥接芯片。选择IT6801的原因很实际它支持HDMI 1.4能处理常见的1080P60Hz及以下分辨率输出格式正好包含我们需要的BT112016位YUV422而且外围电路相对成熟成本可控。网上关于Hi3531D和IT6801的资料都有但把它们俩搭配起来从硬件连接到软件驱动调试再到图像稳定采集的完整记录却不多。很多帖子要么只讲硬件原理图要么只贴几句配置代码真正在调试中遇到的时序问题、寄存器配置细节、图像异常排查这些“坑”往往一笔带过。这篇手记就是记录我把IT6801成功配置为Hi3531D的BT1120输入源并稳定驱动VI模块的完整过程重点会放在那些容易让人卡住的关键步骤和排查思路上。2. IT6801硬件设计要点与Hi3531D的对接硬件是基础连接不对软件调死也没用。IT6801和Hi3531D的硬件对接核心是理解BT1120接口的电气特性和时序关系。2.1 IT6801输出引脚与BT1120信号映射IT6801作为HDMI接收端其并行输出接口模式需要配置为“BT1120模式”。在这个模式下其关键输出引脚与BT1120标准对应关系如下数据线Y[7:0], C[7:0]对应BT1120的16位数据总线DATA[15:0]。这里需要特别注意位序对齐。通常IT6801的Y[7:0]输出Y亮度分量C[7:0]输出CbCr色度分量。在BT1120的YUV422格式中数据在时钟沿交替输出Y和CCb或Cr。因此我们需要将Y[7:0]连接到DATA[15:8]C[7:0]连接到DATA[7:0]具体映射需根据芯片数据手册和Hi3531D的接收习惯调整有时可能需要高低位互换。时钟线CLKIT6801输出的像素时钟PCLK直接连接到Hi3531D VI的输入时钟引脚。这个时钟的频率取决于输入的HDMI分辨率如1080P60Hz的像素时钟约为148.5MHz。这是整个接口同步的“心跳”必须保证信号质量。行场同步信号HSYNC, VSYNCIT6801会输出行有效HDE和场有效VDE信号或者行同步HSYNC、场同步VSYNC信号。Hi3531D的VI接口通常支持多种同步模式我们需要根据IT6801的输出模式来配置VI的同步极性。更常见的做法是使用HSYNC和VSYNC。数据使能信号DEBT1120标准有时也使用数据使能DE信号来标识有效数据区间。IT6801也支持输出DE信号。如果使用DE模式则HSYNC和VSYNC可能就不需要了或者作为辅助参考。Hi3531D的VI同样支持DE同步模式配置上更简洁。注意硬件连接前务必仔细核对IT6801数据手册中“BT1120 Output Mode”的引脚定义表和时序图以及Hi3531D《硬件设计指南》中VI接口的引脚说明。两者的电压域通常是3.3V也需要匹配。时钟和数据线的PCB走线应尽可能等长以减少时序偏移。2.2 电源、复位与I2C配置电路除了数据接口IT6801的正常工作离不开几个基础电路电源需要干净的3.3V和1.2V或1.8V具体看芯片型号电源为数字核心和IO供电。电源引脚附近必须放置足够且容值搭配合理的去耦电容如10uF 0.1uF这是芯片稳定工作的基石尤其是处理高频像素时钟时。复位电路一个简单的RC复位电路确保上电后芯片能可靠复位。复位引脚RESET#通常低电平有效需要保持一定时间的低电平后再拉高。I2C配置接口IT6801的工作模式、输出格式、中断等全部通过内部的寄存器来配置而访问这些寄存器需要通过I2C总线。需要将IT6801的I2C引脚SCL, SDA连接到主控这里就是Hi3531D的I2C控制器上并加上拉电阻。同时IT6801的I2C设备地址需要通过其硬件地址引脚如ADDR0的电平来决定例如接地表示地址0x48。HDMI输入检测IT6801的HPD热插拔检测引脚需要按照HDMI标准通过一个上拉电阻通常47kΩ接到5V电源并通过一个缓冲电路连接到HDMI接口的HPD引脚。当HDMI源设备插入时它会检测到这个电压变化从而开始握手通信。RXSENSE引脚用于检测TMDS信号是否存在。硬件焊接并检查无误后就可以上电进入软件调试阶段了。如果硬件有问题后续的软件调试会举步维艰常见现象包括I2C通信失败、无时钟输出、图像数据全乱等。3. Hi3531D SDK中VI模块的配置逻辑Hi3531D的SDK提供了强大的视频处理平台MPPVI模块是入口。我们的目标是将IT6801输出的BT1120信号正确配置为VI的一个物理通道Pipe和扩展通道Channel的输入源。3.1 MPP系统与VI初始化流程首先需要理解海思MPP的基本初始化流程这是所有业务的基础// 1. 配置系统参数VB池、时钟等 HI_S32 s32Ret; VB_CONFIG_S stVbConf; MPP_SYS_CONF_S stSysConf; // 设置视频缓存池Video Buffer大小这是存放原始图像数据的内存区域 // 需要根据分辨率、帧率、buffer数量精确计算 memset(stVbConf, 0, sizeof(VB_CONFIG_S)); stVbConf.u32MaxPoolCnt 2; // ... 计算并填充各个VB块的大小 ... // 配置系统参数并初始化 memset(stSysConf, 0, sizeof(MPP_SYS_CONF_S)); stSysConf.pstVbConf stVbConf; s32Ret HI_MPI_SYS_SetConf(stSysConf); s32Ret HI_MPI_SYS_Init(); // 2. 初始化VI模块 s32Ret HI_MPI_VI_Init();VB池的配置是关键如果分配不足会导致后续创建通道失败。对于1080P的YUV422图像一帧图像的大小为1920 * 1080 * 2 bytes ≈ 4 MB。假设我们需要缓存3帧那么这个VB块的大小至少需要12MB。3.2 VI设备、物理通道与扩展通道的关联海思的VI模块概念稍显复杂需要理清VI Dev设备对应一个物理的传感器或解码芯片接口。对于BT1120输入我们使用VI_DEV_BT1120_0假设接在BT1120接口0上。VI Pipe物理通道隶属于某个Dev负责实际的图像数据采集、预处理如降噪、去马赛克。一个Dev下可以有多个Pipe。VI Chn扩展通道隶属于某个Pipe可以理解为数据出口。一个Pipe下的多个Chn可以输出不同尺寸、格式的图像例如一个Pipe抓1080P其下的Chn0输出1080P给编码Chn1缩放输出720P给预览。在我们的场景中IT6801接在BT1120接口上所以我们需要配置一个VI_DEV_BT1120_0设备。在该设备下创建一个Pipe例如Pipe 0。在这个Pipe下创建一个Chn例如Chn 0用于输出图像。配置的核心是填充VI_DEV_ATTR_S、VI_PIPE_ATTR_S和VI_CHN_ATTR_S这三个结构体。其中VI_DEV_ATTR_S的配置必须与IT6801输出的信号格式严格一致。3.3 关键结构体VI_DEV_ATTR_S的配置详解这是连接硬件信号和软件驱动的桥梁任何一项配错图像都可能无法采集或异常。VI_DEV_ATTR_S stDevAttr; memset(stDevAttr, 0, sizeof(VI_DEV_ATTR_S)); // 接口模式BT1120标准模式 stDevAttr.enIntfMode VI_MODE_BT1120_STANDARD; // 工作模式多路复用模式对应BT1120的YUV422交错数据 stDevAttr.enWorkMode VI_WORK_MODE_1Multiplex; // 输入数据顺序Y和C交替 (C Cb/Cr) stDevAttr.au32CompMask[0] 0xFF000000; // Bit31:24 对应DATA[15:8]? 需要根据硬件连接确认 stDevAttr.au32CompMask[1] 0x00FF0000; // Bit23:16 对应DATA[7:0]? 这里映射是关键 stDevAttr.enScanMode VI_SCAN_PROGRESSIVE; // 逐行扫描 // 时序配置 - 必须与IT6801输出的时序完全匹配 stDevAttr.stSynCfg.enVsync VI_VSYNC_PULSE; // 垂直同步脉冲 stDevAttr.stSynCfg.enVsyncNeg VI_VSYNC_NEG_HIGH; // VSYNC极性高有效 stDevAttr.stSynCfg.enHsync VI_HSYNC_PULSE; // 水平同步脉冲 stDevAttr.stSynCfg.enHsyncNeg VI_HSYNC_NEG_HIGH; // HSYNC极性高有效 stDevAttr.stSynCfg.enVsyncValid VI_VSYNC_VALID_NEG_HIGH; // VBLANK极性 stDevAttr.stSynCfg.enHsyncValid VI_HSYNC_VALID_NEG_HIGH; // HBLANK极性 // 如果使用DE模式则配置会简化为 stDevAttr.stSynCfg.enSynMode VI_SYN_MODE_DE // 图像尺寸 stDevAttr.stSize.u32Width 1920; stDevAttr.stSize.u32Height 1080; // 帧率应与输入信号一致用于内部buffer管理 stDevAttr.stFrameRate.s32SrcFrameRate 60; stDevAttr.stFrameRate.s32DstFrameRate 60; // 数据格式 stDevAttr.enPixFmt PIXEL_FORMAT_YVU_PLANAR_422; // YUV422平面格式VI常用 // 注意BT1120线上传输的是YUV422交错格式但VI模块内部会将其转换为平面格式存储。这里最易出错的点是au32CompMask和同步极性。au32CompMask定义了输入数据总线DATA[15:0]的哪几位对应Y分量哪几位对应C分量。这需要根据硬件原理图上IT6801数据线到Hi3531D数据线的具体连接顺序来决定。同步极性enHsyncNeg,enVsyncNeg则必须用示波器测量IT6801实际输出的HSYNC和VSYNC波形来确定有效同步脉冲期间是高电平还是低电平配置反了VI就无法正确找到一帧图像的起始位置。4. IT6801寄存器配置与I2C驱动调试硬件连接和VI参数都准备好了但IT6801本身还是个“黑盒”需要将它配置成我们需要的模式。这需要通过Hi3531D的I2C控制器向IT6801的寄存器写入特定的值。4.1 I2C通信基础与海思操作接口首先确保Hi3531D的I2C控制器驱动已加载并在设备树DTS或板级配置中正确配置了引脚复用和时钟。海思SDK提供了hi_i2c的操作接口。一个典型的IT6801寄存器写入函数如下#include hi_i2c.h int it6801_i2c_write_byte(unsigned char dev_addr, unsigned short reg_addr, unsigned char data) { HI_S32 s32Ret; I2C_DATA_S i2c_data; unsigned char buf[2] { reg_addr 8, reg_addr 0xFF }; // 寄存器地址16位 buf[2] data; // 要写入的数据 i2c_data.pbuf buf; i2c_data.len 3; // 地址(2字节) 数据(1字节) i2c_data.dev_addr dev_addr; // IT6801的I2C地址如0x48 i2c_data.reg_addr 0; // 这里reg_addr已包含在buf中此项可置0或忽略 i2c_data.reg_addr_num 0; // 地址字节数已在buf中体现 // 假设使用I2C通道0 s32Ret hi_i2c_write(0, i2c_data); if (s32Ret ! HI_SUCCESS) { printf(I2C write failed at reg 0x%04x, ret 0x%x\n, reg_addr, s32Ret); return -1; } return 0; }调试的第一步是验证I2C通信是否正常。可以尝试读取IT6801的芯片ID寄存器例如0x00和0x01看是否能返回正确的值如0x68, 0x01。如果读失败检查I2C总线是否有上拉电阻通常4.7kΩ。SCL和SDA线是否接反、虚焊。Hi3531D的I2C控制器配置时钟频率是否合适通常用100kHz调试。IT6801的电源和复位是否正常。4.2 IT6801关键寄存器配置序列IT6801的配置寄存器多达数百个但核心配置围绕几个方面系统复位、输入检测、视频解码、输出格式设置。以下是一个简化的配置流程用于实现HDMI转BT1120 YUV422输出系统复位与初始化写入系统控制寄存器进行软复位等待复位完成。it6801_i2c_write_byte(0x48, 0x04, 0x01); // 软件复位 usleep(10000); // 等待复位稳定使能HDMI输入检测配置相关寄存器使能HPD和RXSENSE检测。it6801_i2c_write_byte(0x48, 0x10, 0x01); // 使能HPD控制 it6801_i2c_write_byte(0x48, 0x11, 0x01); // 设置HPD为高通知源设备配置输入颜色空间和视频格式告诉IT6801输入的是HDMI信号并开始解码。it6801_i2c_write_byte(0x48, 0x0A, 0x10); // 选择HDMI输入端口 it6801_i2c_write_byte(0x48, 0xBC, 0x00); // 配置输入颜色空间为RGB/YUV444 // ... 更多关于输入格式的配置核心配置并行输出接口为BT1120模式这是最关键的一步。// 设置输出接口为并行数字输出 it6801_i2c_write_byte(0x48, 0x15, 0x80); // 使能并行输出 // 设置输出格式为YUV422 it6801_i2c_write_byte(0x48, 0x17, 0x0C); // 输出格式寄存器0x0C通常对应YUV422 // 设置输出数据位宽和同步模式 it6801_i2c_write_byte(0x48, 0x19, 0x07); // 输出控制可能包含DE/HSYNC/VSYNC选择 // 设置BT1120特定模式 it6801_i2c_write_byte(0x48, 0x1A, 0x40); // 设置为BT1120输出模式 // 配置同步极性需与VI配置匹配 it6801_i2c_write_byte(0x48, 0x1B, 0x00); // 例如00表示HSYNC和VSYNC高有效读取EDID和自动配置可选IT6801可以读取HDMI源设备的EDID信息并自动配置输出分辨率以匹配输入。这通常通过一系列寄存器操作完成也可以手动强制设置输出时序。重要提示以上寄存器地址和值仅为示例绝对不能直接照抄必须依据你所使用的IT6801芯片的具体型号和版本查阅其官方数据手册Datasheet或编程指南Programming Guide。不同版本、不同封装的IT6801寄存器定义可能有差异。最好的方法是找到原厂的参考配置代码C Code。4.3 调试技巧如何验证配置是否生效测量时钟用示波器测量IT6801的PCLK引脚。如果配置成功在接入有效的HDMI信号后应该能看到稳定、频率正确的像素时钟波形如1080P60Hz约为148.5MHz方波。如果没有时钟说明IT6801可能未正确锁定HDMI信号或输出未使能。测量同步信号测量HSYNC和VSYNC引脚。应该能看到与帧率、行频对应的脉冲信号。观察其极性和宽度。读取状态寄存器通过I2C读取IT6801的状态寄存器如0x0E可以查看是否成功锁定HDMI信号Lock位、检测到的分辨率、颜色深度等信息。这是软件判断硬件状态的重要依据。Hi3531D端检测在初始化VI Dev时如果配置正确调用HI_MPI_VI_EnableDev后可以尝试读取VI的某些状态虽然SDK直接接口不多或者观察系统是否报错。更直接的方法是在使能VI Chn后去获取一帧图像数据看是否能成功拿到以及数据是否合理。5. 图像采集测试与典型问题排查当硬件连接、IT6801配置、VI初始化都完成后就进入了最后的联调测试阶段让Hi3531D真正把图像数据读出来。这里使用海思MPP的标准流程使能通道启动流然后从通道中获取图像缓冲区VB。5.1 完整的VI通道使能与图像获取流程// 1. 配置并启用VI Dev (使用前面定义的stDevAttr) s32Ret HI_MPI_VI_SetDevAttr(VI_DEV_BT1120_0, stDevAttr); s32Ret HI_MPI_VI_EnableDev(VI_DEV_BT1120_0); // 2. 配置并启用VI Pipe VI_PIPE_ATTR_S stPipeAttr; // ... 配置Pipe属性通常与Dev属性关联或简化 s32Ret HI_MPI_VI_SetPipeAttr(VI_PIPE_BT1120_0, stPipeAttr); // Pipe 0 对应 Dev 0 s32Ret HI_MPI_VI_EnablePipe(VI_PIPE_BT1120_0); // 3. 配置并启用VI Chn VI_CHN_ATTR_S stChnAttr; stChnAttr.enCapSel VI_CAPSEL_BOTH; // 采集奇偶场 stChnAttr.stSize.u32Width 1920; stChnAttr.stSize.u32Height 1080; stChnAttr.enPixelFormat PIXEL_FORMAT_YVU_PLANAR_422; stChnAttr.enCompressMode COMPRESS_MODE_NONE; // 无压缩 s32Ret HI_MPI_VI_SetChnAttr(VI_PIPE_BT1120_0, VI_CHN_0, stChnAttr); s32Ret HI_MPI_VI_EnableChn(VI_PIPE_BT1120_0, VI_CHN_0); // 4. 开始接收图像数据流 s32Ret HI_MPI_VI_StartStream(VI_PIPE_BT1120_0, VI_CHN_0); // 5. 主循环中获取图像帧 VIDEO_FRAME_INFO_S stFrameInfo; while (1) { // 获取一帧图像超时时间设为1000ms s32Ret HI_MPI_VI_GetChnFrame(VI_PIPE_BT1120_0, VI_CHN_0, stFrameInfo, 1000); if (s32Ret HI_SUCCESS) { // 成功获取到帧stFrameInfo包含图像数据指针(VB物理地址)、宽高、时间戳等 printf(Got a frame! Addr: %p, Size: %dx%d\n, stFrameInfo.stVFrame.vir_addr[0], stFrameInfo.stVFrame.u32Width, stFrameInfo.stVFrame.u32Height); // 在这里可以对图像进行处理如显示、编码、分析... // 处理完毕后必须释放这一帧否则VB池会耗尽 s32Ret HI_MPI_VI_ReleaseChnFrame(VI_PIPE_BT1120_0, VI_CHN_0, stFrameInfo); } else if (s32Ret HI_ERR_VI_NO_BUF) { printf(No buffer available.\n); } else { printf(Get frame failed: 0x%x\n, s32Ret); } usleep(33000); // 粗略控制循环频率 }如果HI_MPI_VI_GetChnFrame成功返回并且stFrameInfo中的宽高信息正确那么恭喜最艰难的一步已经迈过。你可以将获取到的图像数据通常是YUV平面数据保存为文件用YUV查看工具如YUV Player检查图像内容是否正确。5.2 典型问题现象与排查思路在实际调试中很少能一次成功。以下是几种常见问题及排查方向问题现象可能原因排查步骤HI_MPI_VI_GetChnFrame始终返回超时或错误1. VI Dev/Pipe/Chn 未成功使能。2. IT6801无视频信号输出。3. VI设备属性时序、极性配置错误。4. VB池配置不足或未初始化。1. 检查每一步HI_MPI_VI_EnableXXX的返回值。2. 用示波器测IT6801的PCLK、HSYNC、VSYNC、DATA是否有信号。3.重点核对VI_DEV_ATTR_S中的enIntfMode,enWorkMode,au32CompMask, 同步极性与IT6801实际输出是否一致。4. 确认HI_MPI_SYS_Init前VB池大小计算正确且足够。能获取到帧但图像错乱、花屏、颜色异常1. 数据位序 (au32CompMask) 配置错误。2. 像素格式 (enPixFmt) 不匹配。3. IT6801输出格式如YUV顺序与VI预期不符。4. 时钟抖动或数据线干扰严重。1. 尝试交换au32CompMask中Y和C分量的位掩码。2. 确认IT6801配置为YUV422输出并尝试更改YUV顺序Y/Cb/Cr 还是 Y/Cr/Cb。3. 尝试更改VI的enPixFmt如PIXEL_FORMAT_YUV_PLANAR_422和PIXEL_FORMAT_YVU_PLANAR_422互换。4. 用示波器检查PCLK和数据线的信号完整性看是否有过冲、振铃或噪声。图像有固定位置的竖线或横线干扰1. 时序参数中的消隐期Blanking设置不对。2. 内存访问越界或VB块边界不对齐。1. 核对VI_DEV_ATTR_S中的stSynCfg时序参数特别是u32HsyncHfb,u32HsyncAct,u32HsyncHbb,u32VsyncVfb,u32VsyncVact,u32VsyncVbb。这些值需要根据输入视频的精确时序来设定。可以先用IT6801的自动检测功能或查阅标准视频时序表如CEA-861。2. 检查VB池配置确保为图像分配的内存块是连续且对齐的。图像闪烁、不稳定1. 时钟不稳定。2. VI帧率与输入信号帧率不匹配。3. 电源噪声。1. 测量PCLK的时钟抖动Jitter。2. 检查stDevAttr.stFrameRate的配置确保与HDMI源输出帧率一致。3. 检查IT6801和Hi3531D的电源纹波加强电源滤波。5.3 一个实用的调试技巧保存原始YUV数据在排查图像问题时将获取到的原始帧数据保存为文件是最直接的方法。可以写一个简单的函数将stFrameInfo.stVFrame.vir_addr[0]Y分量地址、vir_addr[1]V分量地址、vir_addr[2]U分量地址指向的数据按照YUV420或YUV422平面格式写入文件。然后在PC上用专业的YUV播放器如7yuv、YUV Player Deluxe打开可以非常直观地看到图像是颜色错误、错位、还是撕裂这能极大缩小问题范围。例如发现图像整体偏绿很可能就是Y和UV分量的数据映射反了如果图像像老式电视雪花可能是数据线接触不良或时钟不同步。6. 进阶话题稳定性优化与分辨率自适应当基本功能调通后我们还需要考虑系统的稳定性和鲁棒性。6.1 信号锁存与中断处理IT6801在状态变化如HDMI信号插入、拔出、分辨率改变时可以通过中断引脚如INT通知主控。我们可以将Hi3531D的GPIO配置为中断输入模式连接到IT6801的INT引脚。在中断服务程序中读取IT6801的中断状态寄存器判断事件类型并做出相应处理如重新初始化VI参数。这比轮询方式更高效、更及时。6.2 分辨率自适应处理我们的初始配置固定了分辨率如1920x1080。但如果HDMI源设备切换了分辨率例如从1080P切换到720P当前的VI配置就会失效。实现自适应有两种思路被动检测与重启在中断中检测到分辨率变化后先HI_MPI_VI_DisableChn,HI_MPI_VI_DisablePipe,HI_MPI_VI_DisableDev然后根据IT6801读取到的新分辨率参数如通过寄存器0x0E, 0x0F等重新计算并设置VI_DEV_ATTR_S、VI_PIPE_ATTR_S等再重新启用。这个过程会有短暂的黑屏或丢帧。预先配置与切换海思VI支持多个“设备属性集”。我们可以预先配置好几套常见分辨率1080P, 720P, 576P等的参数。当检测到分辨率切换时调用HI_MPI_VI_SetDevAttr快速切换到另一套属性可能不需要完全关闭设备体验会更流畅。但这需要更精细的测试。6.3 降低CPU占用的设计在while(1)循环中不断调用HI_MPI_VI_GetChnFrame是阻塞式的会占用一个CPU核。在生产环境中更好的做法是使用VB池回调机制海思MPP支持设置VB池用完或补充的回调函数可以在数据就绪时通知应用避免忙等待。绑定到VO或VPSS直接将VI通道与视频输出VO或视频处理子系统VPSS绑定数据通过硬件通路自动传递不经过CPU搬运效率最高。例如可以将VI Chn绑定到VPSS的Grp和Chn进行缩放、裁剪等处理再送给编码或显示。调试这类嵌入式视频项目示波器和逻辑分析仪是眼睛数据手册和参考代码是地图而耐心和系统的排查方法则是走下去的腿。从IT6801的I2C寄存器配置到海思VI复杂的属性结构每一步都可能藏着一个小坑。最深刻的体会就是时序和极性是数字视频接口的“方言”两边的设备必须说同一种方言才能对话。务必确保IT6801输出的同步信号极性、数据顺序与Hi3531D VI的配置一字不差。当图像终于稳定出现的那一刻之前所有的折腾都值了。这个方案为Hi3531D这类本身不带HDMI输入的视频处理芯片提供了一种稳定可靠的HDMI视频接入能力在数字标牌、视频会议终端、工业视觉等领域都有不小的应用潜力。