
简介PYNQ-Z2开发板HDMI输入输出控制实践工程包面向学习Xilinx FPGA与Zynq SoC软硬件协同设计的开发者提供基于Vivado 2018.3与SDK的完整视频接口实现方案。工程深入HDMI接口的硬件描述、TMDS信号传输、时钟与数据恢复、色彩空间转换等关键环节通过Vivado创建HDMI IP核并生成硬件描述文件配合SDK中C/C控制代码完成HDMI初始化、分辨率设置、视频数据读取与显示。实验流程涵盖硬件工程与软件应用两部分可指导读者从创建IP核、加载bitstream到ARM端程序运行最终连接HDMI源与显示设备进行输入输出验证。压缩包共640个文件以C/H源码、Vivado工程与IP配置xci/vhd/xdc、编译中间产物o/bit等类型为主整体仅7.47MB目录结构完整便于按模块复现和二次开发。已有1430人学习下载适合作为FPGA视频处理入门及PYNQ-Z2项目开发的重要参考资料。1. 项目背景这块板子和这个压缩包到底能干什么先聊个实际场景。很多刚接触 FPGA 的同学第一块板子就是 PYNQ-Z2。它的优势很明显Zynq 7020 芯片双核 ARM Cortex-A9 可编程逻辑官方做了 PYNQ 镜像直接网页端敲 Python 就能控制硬件不用一上来就啃 Verilog 和 Vivado 的复杂流程。但不少人买到板子之后点亮 LED、跑个例程然后就不知道下一步该干嘛了——这是非常典型的中期瓶颈。而 HDMI 项目恰恰是打破瓶颈最好的方向之一因为它同时涉及 FPGA 逻辑设计、时序约束、视频协议、DMA 数据传输、Python 上层应用一条链路学下来整个 Zynq 平台的核心用法基本就打通了。先说清楚这个“pynq-z2.hdmi.zip”项目解决的核心问题在 PYNQ-Z2 上通过 PL可编程逻辑端实现 HDMI 信号的输入采集和输出显示然后通过 PS处理器系统端的 Python 脚本对视频流进行实时的抓取、处理和可视化。压缩包里包含的东西典型来看应该是完整的 Vivado 工程或者已经生成的 bitstream 和 hwh 文件、Overlay 的 Python 驱动封装、以及一两个演示用的 notebook。也就是说拿到这个包你不必自己从零搭一个 HDMI 控制器直接把它部署上去就能看到画面。这种“下载 zip 跑 demo”的方式看起来很省事实际操作中的坑反而比从零写代码更多。你回想一下那些号称“解压即用”的开源项目在 Windows 上解压出来路径带中文、目录层级改变、文件缺失、版本不兼容任何一个环节都能让 Cairo 报错、Jupyter 内核崩溃。所以这篇分享我不打算只做 zip 包的搬运工而是带你理解这个项目的完整链路再给出从下载到跑通的每一步实操指南。无论你是刚开始摸板卡的新手还是想快速验证某个视频处理思路的工程师这篇都值得花十分钟看完。2. HDMI 显示通路的整体设计思路拆解2.1 为什么在 PYNQ-Z2 上做 HDMI 既有优势又有坑PYNQ-Z2 板卡上的 HDMI 接口设计是“一进一出”一个 HDMI 输入用于捕获外部视频源一个 HDMI 输出用于显示 FPGA 处理后的画面。从硬件规格看它使用的是 Silicon Image SiI9134 作为 HDMI 接收芯片以及 Analog Devices ADV7513 作为 HDMI 发送芯片。这两颗芯片的分工非常明确——前者把 HDMI 串行信号转成并行视频数据后者把并行数据打包成 TMDS 信号发出去中间的桥接和图像处理逻辑全部由 Zynq 的 PL 部分承担。这个架构有一个很关键的先天优势不需要自己搞定 HDCP 解密和 TMDS 高速收发因为编码解码芯片已经把最麻烦的物理层处理完了。但代价是你拿到的只是并行数据总线和 I2C 控制接口什么时候采样、什么时候输出、用什么时钟全都要靠 FPGA 逻辑精确控制。换句话说物理层虽然被大大简化但视频时序协议层面的工作一点都没少。实际做这个项目的时候你会明显感觉到它和纯软件开发的思维差异。软件里你调一个cv2.VideoCapture(0)就能从摄像头拿数据但在这里一个像素什么时候从输入芯片的数据线上出现、什么时候把它写入内存、DMA 描述符怎么组织每一个环节都需要时钟和信号对齐。不过这也是这个项目的魅力所在——一旦理解了这条链路整个 Zynq 平台的数据流概念就通了。2.2 HDMI 时序和速率参数绕不过去的核心概念网络中关于“edp转hdmi out时panel 时序、lane和速率等参数要求”的讨论特别多虽然 eDP 和 HDMI 在应用场景上有所不同但底层对时序和速率的严谨要求是相通的。HDMI 输出端的核心参数可以概括为三个像素时钟、行场消隐、数据通道数。先看像素时钟。以 1080p60Hz 为例总的像素时钟大约 148.5MHz。这个数字不是随便定的它由有效分辨率、消隐区和刷新率共同计算得出水平方向总共 2200 个像素周期1920 有效 280 消隐垂直方向总共 1125 行1080 有效 45 行消隐两者相乘再乘以 60Hz得到的值刚好约等于 148.5MHz。如果你要做 720p60Hz对应的像素时钟是 74.25MHz1080p30Hz 则需要 74.25MHz。选择哪种分辨率直接决定了 PL 端时钟频率的设计。再说行场消隐。很多人第一次写 HDMI 控制逻辑时很容易只关心有效像素区域把消隐期当成“空白时间”随便填。但实际上行同步前肩、同步脉宽、同步后肩的每一个参数都有标准规定随便改动会导致显示器黑屏、闪烁或者画面偏移。CEA-861 标准文档里对这些时序参数定义得清清楚楚比如 1080p60Hz 的典型值是水平前肩 88、同步脉宽 44、后肩 148垂直前肩 4、同步脉宽 5、后肩 36。关于数据通道HDMI 1.4 规范定义了 4 对 TMDS 通道——3 对数据通道加 1 对时钟通道。但在 PYNQ-Z2 这种 FPGA 实现场景下物理层已经被 ADV7513 处理掉了你在 PL 端面对的不是字节流而是并行像素总线。ADV7513 的输出数据位宽是 24-bitRGB888配合同步信号FPGA 需要做的是准确地把行场同步信号和数据按标准时序送进去。速率方面1080p60Hz 时单通道数据率大约 3.4Gbps所以 PCB 布线和芯片端信号完整性极重要——这也是 PYNQ-Z2 出厂设计时已经考虑好的你不需要过分担心但要明白它为什么能稳定跑较高分辨率。2.3 方案选型为什么推荐直接基于官方 Overlay 改在搜索热词里能看到很多类似“fpga hdmi”、“hdmi circuit”的搜索说明很多人在这个阶段卡住。常见的做法有三种第一自己用 Verilog 写完整的 HDMI 控制器从时序生成到 TMDS 编码全部手撸第二用 Xilinx 提供的 Video Processing Subsystem IP 组合第三基于社区或官方的现成 Overlay 进行二次开发。我强烈建议初次动手的人选择第三种。原因不复杂手写 HDMI 控制器确实能学到最多底层知识但调试周期非常长一个时序参数写错现象都是黑屏排查难度极大。Video Processing Subsystem IP 虽然功能强大但配置项极其复杂——输入源格式、色彩空间转换、裁剪缩放、FIFO 深度任何一项不合适都会导致连锁问题。而现成 Overlay 提供的是一个已经在真实板卡上跑通的最小可用系统你可以在它的基础上先“跑起来”再“改起来”遇到问题时能对照的参考实现也是现成的。从工程效率角度讲这也符合行业的普遍做法。实际产品开发中除非你是在做芯片原厂的参考设计否则不太可能从零开始造轮子。FPGA 开发的核心能力在于理清数据流、定位瓶颈、裁剪功能而不是重复造 HDMI 控制器这个已经被做烂的模块。当然如果你目标就是深入研究 HDMI 协议本身那我鼓励你去手写——只是要准备好充足的调试时间。3. 核心细节解析压缩包里到底有哪些东西需要准备什么环境3.1 从 zip 到可运行文件部署的完整流程先说部署流程。在 Windows 环境下把下载的 “pynq-z2.hdmi.zip” 解压后你会看到类似这样的目录结构boards/存放硬件定义文件、bitstream/.bit 和 .hwh 文件、notebooks/Jupyter 演示脚本、src/Python 驱动源码等。关键的一点是PYNQ 框架的 Overlay 加载机制依赖两个文件.bit比特流定义 PL 的硬件逻辑和.hwh硬件握手文件描述 IP 核的寄存器映射两者必须同名且放在同一目录下否则 Overlay 加载必然失败。具体的操作步骤是将整个项目文件夹上传到 PYNQ-Z2 板卡的/home/xilinx/pynq-xxxx/目录下。常用的方式有两种一种是通过 Jupyter Notebook 页面的上传功能逐文件上传另一种是直接在板卡上通过 wget 从服务器拉取 zip 再解压后一种在文件较多时更高效。如果在 Windows 下解压后直接上传要特别注意路径中不能有中文或空格否则文件路径解析可能出错。上传完成后通过 SSH 或者 Jupyter 终端执行解压命令cd /home/xilinx/ unzip pynq-z2.hdmi.zip cd pynq-z2.hdmi解压后建议先查看目录里的 README 或 requirements.txt确认是否有额外的依赖包。很多项目在 PYNQ 原始镜像上还需要pynq-dpu或额外的视频库如果缺少依赖代码运行到 import 阶段就会报ModuleNotFoundError。3.2 常用依赖与 Overlay 加载机制PYNQ 2.5 或 2.6 版本的标准镜像中已经预装了pynq基础库、Jupyter Notebook、OpenCV 等常见包但具体到 HDMI demo通常还需要确认pynq.lib.video模块是否存在。在 PYNQ 2.4 之后的版本里pynq.lib.video被整合进了pynq.lib核心包通常不需要单独安装但如果你用的是比较早的镜像需要确认版本兼容性。真正关键的部分是 Overlay 的加载和 HDMI 设备的初始化。标准的加载代码如下from pynq import Overlay from pynq.lib.video import HDMI # 加载 Overlay overlay Overlay(path/to/design.bit) # 创建 HDMI 输出设备 hdmi_out HDMI(out, overlay)这里有一点容易被忽略HDMI(out, overlay)中的overlay参数不能省略。它告诉 HDMI 驱动类从哪个 Overlay 中找到对应的 IP 核寄存器地址。如果没有传参驱动会尝试从默认位置加载导致找不到寄存器基址而报错。这个错误在很多初学者的报错记录中反复出现。初始化完成后需要设置输出分辨率hdmi_out.configure(1920, 1080, 60) hdmi_out.start()configure参数依次是宽度、高度、刷新率。这里要重点提醒configure这个操作不仅是在软件层设置参数背后的驱动程序会向 PL 端的 Video Timing Controller 写入对应的时序寄存器值并配置 ADV7513 芯片的 I2C 寄存器。也就是说分辨率设置错误会直接导致芯片配置错误HTOTAL/VTOTAL 等参数不对显示端就没有稳定的同步信号表现为黑屏或画面撕裂。3.3 从 GitHub 拉取项目后如何与本地 Git 仓库关联热词里有“github上下载的zip项目与git项目关联 变基到远程仓库失败”这样的问题做 FPGA 项目同样绕不开 Git 版本管理。很多项目作者把代码同时发布在 GitHub Releases 里和仓库源码里你下载了 zip 包解压后想在本地继续跟踪上游更新就需要把它重新初始化成 Git 仓库并与远程关联。正确做法是先删除解压目录里可能的.git文件夹如果项目发布时包含了然后在解压目录里执行git init git remote add origin https://github.com/username/repo.git git fetch origin git checkout -b main --track origin/main如果你之前已经改过代码想保持本地修改的同时合并上游更新建议用git stash暂存本地修改再git pull拉取远程更新最后git stash pop恢复本地改动的文件。遇到“变基到远程仓库失败”的情况通常是因为本地和远程存在不兼容的历史记录最直接的排查方式是git status git log --oneline git fetch origin git rebase origin/main如果一个一个查起来太麻烦没必要把所有细节都背下来项目里一个简单的.gitignore就能避免后续大量不必要的冲突——把*.bit、*.hwh、*.cache、*.hw这些生成文件全部忽略只保留源码和工程文件。这样你拉取远端更新时就不会因为大文件的二进制差异导致冲突。4. 实操过程从零跑通 HDMI 输出彩色条与图像显示4.1 第一步验证你的硬件环境和 Jupyter 能正常通信在玩任何 HDMI demo 之前第一步永远都是确认硬件最小系统能正常工作。上电后等待 PYNQ 板卡的 Linux 系统启动完成Jupyter 服务监听在 9090 端口。浏览器访问http://板卡IP:9090密码默认为xilinx。如果页面能正常打开说明 PS 端的 Linux 系统没有问题。接下来需要验证 PL 端的 Overlay 是否能正常加载。新建一个 Notebook执行from pynq import Overlay overlay Overlay(base.bit) print(overlay.ip_dict.keys())base.bit是 PYNQ 镜像自带的默认工程在/home/xilinx/pynq-xxxx/bitstream/目录下。如果能正常输出 IP 核列表说明 PL 端配置链路也没有问题此时才适合继续加载 HDMI 的 Overlay。这一步看似简单却能帮你区分“板卡硬件坏了”“PYNQ 镜像损坏”“项目文件不兼容”这三个完全不同的排障方向。我自己遇到过几次“黑屏”问题排查到最后发现是 Jupyter 的 kernel 缓存过旧导致 Overlay 加载没有生效——这时候重启 kernel 往往就能解决。4.2 跑通 HDMI 输出的完整代码流程当基础环境验证通过后就可以开始 HDMI 输出的核心实验了。在 pynq-z2.hdmi 项目中通常会自带一个或多个示例 notebook其中最简单、最有价值的 demo 是输出彩色测试条。彩色条的价值在于它不是随机图像而是经过专门设计的标准测试图——不同位置对应不同的颜色值可以用来直观判断 PL 端输出的 RGB 数据通道是否正常以及 ADV7513 的配置是否正确。如果示例代码不完整或者你想理解每一步在做什么这里的完整流程可以作为一个参考实现from pynq import Overlay from pynq.lib.video import HDMI, PixelFormat import numpy as np # 1. 加载 HDMI Overlay overlay Overlay(hdmi_demo.bit) # 2. 初始化 HDMI 输出 hdmi_out HDMI(out, overlay) hdmi_out.configure(1920, 1080, 60) hdmi_out.start() # 3. 获取可用于写入的 frame 对象 frame hdmi_out.newframe() # 4. 将 frame 的数据视图转为 numpy 数组用于填充图像 frame_buffer np.asarray(frame) # 生成一张渐变图颜色从左上角到右下角平滑过渡 for y in range(1080): for x in range(1920): frame_buffer[y, x, 0] x % 256 # R frame_buffer[y, x, 1] y % 256 # G frame_buffer[y, x, 2] (x y) % 256 # B # 5. 把帧推送到显示器 hdmi_out.writeframe(frame)看到这里你可能会问为什么frame可以直接转成 numpy 数组这正是 PYNQ 的一个优秀设计——它基于 DMA 的零拷贝框架让 PL 端的内存和 PS 端 Python 进程共享同一块物理内存。frame对象的底层就是一块连续物理内存np.asarray(frame)做的是视图转换而不是数据复制。大多数情况下这样就能在 HDMI 显示器上看到渐变图像了。但要注意这段代码中双重循环会拖慢速度在 Notebook 中实际执行可能需要数秒。这只是演示逻辑实际使用中更推荐用向量化操作、图像文件加载或 OpenCV 读取视频流填充帧。4.3 HDMI 输入的采集与图像回显如果项目包含 HDMI 输入大多数 pynq-z2.hdmi.zip 都支持则可以用类似方式初始化输入设备然后通过 DMA 获取图像帧。这里我提供一段可用的回显代码from pynq import Overlay from pynq.lib.video import HDMI import numpy as np overlay Overlay(hdmi_demo.bit) hdmi_in HDMI(in, overlay) hdmi_in.configure() hdmi_in.start() # 采集一帧图像 frame hdmi_in.readframe() frame_data np.asarray(frame) print(f采集到图像分辨率: {frame.height} x {frame.width}) print(f图像数据的形状: {frame_data.shape})这段代码要注意的地方是hdmi_in.configure()不需要给定分辨率参数因为输入侧的分辨率是由外部信号源决定的——HDMI 输入芯片会在检测到信号后自动解析出行场时序驱动代码只需要根据解析结果配置 DMA 接收缓冲区即可。如果外部没有信号输入readframe()可能会阻塞等待所以务必先接上 HDMI 信号源机顶盒、电脑、游戏机都行再执行采集代码。采集到第一帧图像后数据就存在于内存中。你可以在同一个 Notebook 里用 matplotlib 显示、用 numpy 做颜色空间转换或其他图像处理然后把处理后的帧通过hdmi_out.writeframe()输出——这就是一个完整的 HDMI 视频采集-处理-显示通路也是这个项目最有价值的部分。4.4 常见问题彩色条显示正常但图像偏色或偏移如果你能看到图像但颜色不对通常不是 PL 逻辑的问题而是色彩空间定义不匹配。HDMI 标准支持的色彩空间包含 RGB、YCbCr 4:4:4、YCbCr 4:2:2 等多种格式ADV7513 芯片通过 I2C 寄存器配置色彩空间模式。PYNQ 驱动中hdmi_out.configure()方法有一个可选的参数pixel_format默认值是PixelFormat.RGB但部分 HDMI Overlay 可能默认配置为 YCbCr。如果上游驱动里的配置和你的信号源不一致图像颜色就会有明显的偏差。解决办法是检查 Overlay 的驱动源码确认configure中传给 ADV7513 的颜色格式寄存器值或者在调用configure时显式指定from pynq.lib.video import PixelFormat hdmi_out.configure(1920, 1080, 60, PixelFormat.RGB)图像偏移则一般与消隐参数设置有关。部分驱动代码可能在行场消隐上做了裁剪或调整导致整个画面的有效区偏移。如果只是偏移几像素显示器菜单里的“自动调整”通常能纠正如果偏移量很大需要检查 PL 端 Video Timing Controller 中 HActive/VActive 的设置是否正确。5. 常见问题与排查技巧实录5.1 黑屏问题排查从物理层到逻辑层黑屏是这个项目里最高频的问题现象是 HDMI 显示器完全没有信号或保持待机状态。我经过多轮调试后把它按排查顺序整理如下排查步骤检查内容常见原因1硬件连接HDMI 线材或接口接触不良换一根线试试2显示器状态显示器是否切到正确的输入源3PL 加载状态Overlay 是否加载成功检查overlay.is_loaded()4时钟锁定状态PL 端的时钟生成器是否正确生成像素时钟5芯片 I2C 状态ADV7513 是否被正确初始化检查驱动日志6时序参数分辨率配置是否匹配标准 CEA 时序这个顺序是经验之谈。初学者最容易犯的错误是直接跳到第 6 步去改时序参数但实际上大部分黑屏都是第 1、2 步的物理连接问题。我自己遇到过一次很折腾的情况显示器是 4K 的也能兼容 1080p但它的 HDMI 端口在省电模式下对 148.5MHz 像素时钟的同步信号极为敏感经常黑屏换了另一个显示器就一切正常。所以遇到问题时前面几步的“穷举式排查”永远比直接改代码更高效。5.2 导入 Overlay 失败Invalid ZIP Archive 问题专项分析热词里反复出现“invalid zip archive: could not find eocd”——这其实是 zip 文件损坏或格式被错误识别的典型报错在 FPGA 项目部署时极为常见。EOCDEnd of Central Directory是 zip 文件的结构标识如果这个标志找不到基本上能确定文件被破坏或根本没有正确上传。产生这个问题的原因一般在三处第一下载不完整文件未经校验就上传到板卡第二上传方式不对通过 Jupyter 上传大文件时断流或编码错误文件被截断第三在 Windows 下解压后又重新压缩成 zip 时压缩工具的兼容性出了问题。排查核心思路也很清晰先在本地把 zip 用标准工具Windows 资源管理器的解压缩功能或 7-Zip测试能否完整解压再用ls -l查看上传到板卡后的文件大小和本地大小对比最后在板卡上用unzip -t检查完整程度unzip -t pynq-z2.hdmi.zip如果输出类似No errors detected in compressed data说明文件完好问题在解压环境否则需要重新上传。这里有个小技巧在板卡上下载 GitHub 文件时用wget配合-O参数能避免浏览器下载时对 zip 的 MIME 类型改动造成的兼容性问题。5.3 时序约束与 PL 端调试技巧不仅仅是“编译通过”很多人在跑通基础 demo 后想自己修改 PL 端逻辑比如添加自定义图像处理 IP。改完发现在 Vivado 中综合实现都通过了上板却花屏或黑屏。这时大概率是时序约束没有加对。HDMI 相关的时序约束核心是像素时钟域的信号 —— 你需要用create_clock告诉工具像素时钟的频率是多少用set_input_delay和set_output_delay约束芯片与 FPGA 之间的接口延时。举一个实际中很典型的例子假设你的 IP 处理链路比较长导致从输入 FIFO 读数据到 ADV7513 接口的路径超过了时钟周期的一半就可能出现偶发性的画面撕裂。这种问题在时序报告中体现为某个路径的 WNSWorst Negative Slack为负但数值只是略微负几皮秒——在很多工程里这种微小的负 slack 往往被忽略但对 HDMI 这种对稳定性和带宽要求极高的接口来说几皮秒的偏差足以引发周期性花屏。遇到这类问题第一件事是打开实现后的时序报告按“WNS 从负到正”的顺序逐条修复优先处理多周期路径和跨时钟域路径。其次在逻辑设计上尽量采用类似“双缓冲”的帧架构不要让读和写同时操作同一个 DDR 地址区域否则会出现不可预测的读写冲突。5.4 一个成功采集的完整 Debug 日志参考从实际调试角度来看很多问题很难用单一原因解释更多是“环境不兼容 配置不明确”叠加的结果。我不建议遇到问题就到处搜“xx 报错怎么解决”更好的路径是按模块逐一排查。举一个实际案例我的采集侧一直获取不到数据。先交叉验证了信号源换了两台电脑都是核显输出都无信号说明信号源没问题再用逻辑分析仪抓取 HDMI 输入芯片的输出行场同步信号确认外部信号已经正确转换为并行数据最后定位到驱动代码里 DMA 的虚拟地址映射不正确——因为 PYNQ 框架的 DMA 驱动对 Buffer 申请有对齐要求而我参考的代码里使用了未经对齐的 buffer导致 DMA 传输失败。调整代码如下即可解决from pynq import allocate buffer allocate(shape(1080, 1920, 4), dtypenp.uint8, cacheableTrue)这段代码看起来很简单但它背后涉及 PYNQ 的 Buffer 分配机制allocate分配的地址不仅物理连续而且按照页对齐这是 DMA 传输能够正确工作的前提。直接使用 Python 原生的np.array分配内存底层地址是虚拟地址且不保证物理连续传给 DMA 后系统就会报 invalid argument 的错误。6. 经验总结把这个项目用好比跑通它更重要跑通 PYNQ-Z2 的 HDMI 通路本身不算难难的是理解它的分层结构和调试方法。很多参考设计扔给你一个跑通的模块却没人解释为什么这里要用 FIFO、为什么 DMA 描述符要这样组织、为什么源图像要经过 VDMA 才能写到 DDR。这些问题的答案只有在踩过坑、看过dmesg日志、用 ILA 抓过波形之后才会在你的知识结构里沉淀下来。从实际经验来讲我越来越认为 PYNQ 系列板卡的真正价值不是替代传统的 FPGA 开发流程而是降低了硬件和软件之间的交互门槛——研究 PL 的人能方便地从 Python 侧注入激励、抓取数据研究 PS 的人不必过多了解底层逻辑就能验证算法。这种协同开发方式在现在的嵌入式视觉项目里越来越常见Xilinx 后续的 Kria 系列也是沿着这个思路往下走的。如果你拿到了类似的 zip 项目不管是不是 PYNQ-Z2我的建议都是先不加修改地把 demo 跑通再去读核心驱动代码最后尝试做一个小改动——比如把分辨率从 720p 改到 1080p或者在帧数据上叠加一个简单的图像处理函数。这个过程会逼出很多之前没注意到的细节比如内存带宽是否足够、时序余量是否充足、驱动代码是否留有可配置的接口。最后说一个非常实际的小技巧在 PYNQ 板卡上如果你修改了 Overlay 工程生成了新的 bit 和 hwh 文件上传覆盖旧文件之前最好先备份原文件。很多项目在长期迭代过程中新版本可能引入未预料的问题而旧版本是已知能工作的——这个“备份意识”能帮你省下一整天的回滚时间。本文还有配套的精品资源点击获取