14 - VDMA彩条显示实验

文章目录

  • 1 实验任务
  • 2 系统框图
  • 3 硬件设计
  • 4 软件设计

1 实验任务

本实验任务是PS端写彩条数据至DDR3内存中,然后通过PL端的VDMA IP核将彩条数据通过HDMI接口输出显示。

2 系统框图

本实验是用HDMI接口固定输出1080P的彩条图,所以:

  1. rgb2lcd模块实际是rgb2dvi模块
  2. AXI GPIO不存在,因为不需要读取LCD屏幕的ID
  3. 动态时钟配置改为PLL,输出固定频率,与AXI-Interconnect不连
  4. VTC输出固定时序,与AXI-Interconnect不连
    在这里插入图片描述

3 硬件设计

注意事项:

  1. VTC的clken引脚
    • 该引脚不连接,VTC也能正常工作
    • pg016中描述该引脚是"Video Core active-High Clock Enable",即高有效
    • 在Block Design中添加VTC后,clken引脚前边有个小圆圈,且双击该引脚,Polarity参数显示为ACTIVE_LOW,即低有效
    • 将该引脚接常量1,视频输出正常
    • 将该引脚接常量0,视频无法输出,VTC未工作
    • 结论:以文档为准,clken高电平有效
  2. rgb2dvi模块
    • 使用正点原子的rgb2dvi模块,数据的3个字节是G在中间,R和B在两头
    • 使用Digilent的rgb2dvi模块,数据的3个字节是B在中间,R和G在两头(调试时一脸懵逼)
      在这里插入图片描述

4 软件设计

注意事项:

  1. PS往DDR3写入数据后,要使用Xil_DCacheFlushRange刷新;
  2. run_triple_frame_buffer函数并非只能用于三帧缓存的情况,实际1-32帧缓存均可使用该函数(取名triple可能和VDMA模式使用三帧缓存有关);ReadSetup函数和WriteSetup函数会根据VDMA配置时选择的Frame Buffers数量设置相应数量的帧缓冲区起始地址;本实验选择Frame Buffers数量=1,PS端只往DDR3中写入一帧彩条图;
  3. XAxiVdma_DmaStop函数往VDMACR寄存器的bit0写0(Run / Stop controls the running and stopping of the VDMA channel. ),当前VDMA操作完成后停止(0 = Stop – VDMA stops when current (if any) VDMA operations are complete)
/***************************** Include Files *********************************/
#include "stdio.h"
#include "xparameters.h"
#include "xstatus.h"
#include "xaxivdma.h"
#include "vdma_api.h"
#include "xil_cache.h"
#include "xuartps.h"
#include "sleep.h"
/************************** Constant Definitions *****************************/
#define VDMA_DEVICE_ID		XPAR_AXIVDMA_0_DEVICE_ID
#define IMAGE_WIDTH			1920
#define IMAGE_HEIGHT		1080
#define MEMORY_BASEADDR		XPAR_PS7_DDR_0_S_AXI_BASEADDR#define UART_DEVICE_ID		XPAR_XUARTPS_0_DEVICE_ID
#define UART_BASEADDR    	XPAR_XUARTPS_0_BASEADDR
/**************************** Type Definitions *******************************//***************** Macros (Inline Functions) Definitions *********************//************************** Function Prototypes ******************************/
s32  UartPsInit(XUartPs *UartPsInstPtr, XUartPsFormat* UartFormatPtr);void GenPureColor(u8* DestAddr, u32 ImageWidth, u32 ImageHeight);
void GenColorBar(u8* DestAddr, u32 ImageWidth, u32 ImageHeight);
/************************** Variable Definitions *****************************/
XAxiVdma VdmaInst;
XUartPs UartInst;int FrameBufferAddr = (MEMORY_BASEADDR + 0x02000000);XUartPsFormat UartFormat = {XUARTPS_DFT_BAUDRATE,     // 115200XUARTPS_FORMAT_8_BITS,XUARTPS_FORMAT_NO_PARITY,XUARTPS_FORMAT_1_STOP_BIT
};
/*****************************************************************************/int main()
{//int Status;u8* VdmaBufferAddr = (u8*)FrameBufferAddr;char cmd;// 串口初始化Status = UartPsInit(&UartInst, &UartFormat);if (Status != XST_SUCCESS) {printf("UART Initialization Failed.\n");return XST_FAILURE;}// 写入纯色图(用于确定RGB的字节位置)
//	GenPureColor(VdmaBufferAddr, (u32)IMAGE_WIDTH, (u32)IMAGE_HEIGHT);// 写入彩条图GenColorBar(VdmaBufferAddr, (u32)IMAGE_WIDTH, (u32)IMAGE_HEIGHT);//Status = run_triple_frame_buffer(&VdmaInst, VDMA_DEVICE_ID, IMAGE_WIDTH, IMAGE_HEIGHT, FrameBufferAddr, 0, 0);if (Status == XST_FAILURE) {printf("VDMA Run Failed.\n");}//printf("VDMA Control Ready (s=start, q=stop):\n");while (1) {if (XUartPs_IsReceiveData(UART_BASEADDR)) {cmd = XUartPs_ReadReg(UART_BASEADDR, XUARTPS_FIFO_OFFSET);if (cmd == 's') {  // 启动VDMAif (XAxiVdma_DmaStart(&VdmaInst, XAXIVDMA_READ) == XST_SUCCESS) {printf("VDMA Start Succeeded.\n");} else {printf("VDMA Start Failed.\n");}}else if (cmd == 'q') {  // 停止VDMAXAxiVdma_DmaStop(&VdmaInst, XAXIVDMA_READ);printf("VDMA Stop Succeeded.\n");}}usleep(10000); // 降低CPU占用}//return 0;
}
/*****************************************************************************/
s32 UartPsInit(XUartPs *UartInstPtr, XUartPsFormat* UartFormatPtr)
{//s32 Status;XUartPs_Config *UartConfigPtr;// 查找UART配置UartConfigPtr = XUartPs_LookupConfig(UART_DEVICE_ID);if(NULL == UartConfigPtr){return XST_FAILURE;}// 初始化UARTStatus = XUartPs_CfgInitialize(UartInstPtr, UartConfigPtr, UartConfigPtr->BaseAddress);if (Status != XST_SUCCESS) {return XST_FAILURE;}// 设置UART数据格式XUartPs_SetDataFormat(UartInstPtr, UartFormatPtr);// 设置UART操作模式XUartPs_SetOperMode(UartInstPtr, XUARTPS_OPER_MODE_NORMAL);//return XST_SUCCESS;
}
/*****************************************************************************/
void GenPureColor(u8* DestAddr, u32 ImageWidth, u32 ImageHeight)
{// 禁用缓存(如果目标内存是非缓存区域)Xil_DCacheDisable();for (u32 y = 0; y < ImageHeight; y++) {for (u32 x = 0; x < ImageWidth; x++) {// 计算当前像素的内存位置(3字节/像素)u32 PixelOffset = (y * ImageWidth + x) * 3;u8* PixelAddr = DestAddr + PixelOffset;// 写入RGB三个字节PixelAddr[0] = 0x00;PixelAddr[1] = 0x00;PixelAddr[2] = 0xff;}}// 如果需要,刷新缓存Xil_DCacheFlushRange((INTPTR)DestAddr, ImageWidth * ImageHeight * 3);//return;
}/*****************************************************************************/
void GenColorBar(u8* DestAddr, u32 ImageWidth, u32 ImageHeight)
{// 定义8种颜色(R, G, B顺序)const u8 color_bars[8][3] = {{0x00, 0x00, 0x00}, // 黑{0xff, 0xff, 0xff}, // 白{0xff, 0x00, 0x00}, // 蓝{0x00, 0xff, 0x00}, // 绿{0x00, 0x00, 0xff}, // 红{0xff, 0xff, 0x00}, // 青{0xff, 0x00, 0xff}, // 紫{0x00, 0xff, 0xff}  // 黄};// 计算每个色条的宽度u32 BarWidth = ImageWidth / 8;// 禁用缓存(如果目标内存是非缓存区域)Xil_DCacheDisable();for (u32 y = 0; y < ImageHeight; y++) {for (u32 x = 0; x < ImageWidth; x++) {// 计算当前色条索引u32 BarIndex = x / BarWidth;// 计算当前像素的内存位置(3字节/像素)u32 PixelOffset = (y * ImageWidth + x) * 3;u8* PixelAddr = DestAddr + PixelOffset;// 写入RGB三个字节PixelAddr[0] = color_bars[BarIndex][0];PixelAddr[1] = color_bars[BarIndex][1];PixelAddr[2] = color_bars[BarIndex][2];}}// 如果需要,刷新缓存Xil_DCacheFlushRange((INTPTR)DestAddr, ImageWidth * ImageHeight * 3);//return;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/901099.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HarmonyOS-ArkUIV2装饰器-@Param:组件外部输入

上文我们了解了@Local装饰器 ,讲明了Local装饰器不允许外部传入值对其进行初始化。详见: HarmonyOS-ArkUI V2装饰器@Local装饰器:组件内部状态-CSDN博客。 但总有场景是需要外部组件传值过来,然后本组件接收这个值这种场景的。而且很多情况下,一个状态变量的作用范围会是…

Java从入门到“放弃”(精通)之旅——运算符③

&#x1f31f;Java从入门到“放弃”&#xff08;精通&#xff09;之旅&#x1f680;&#xff1a;运算符深度解析 引言&#xff1a;运算符的本质与价值 作为Java语言的核心组成部分&#xff0c;运算符是构建程序逻辑的基础元素。它们不仅仅是简单的数学符号&#xff0c;更是程…

【sgSpliter】自定义组件:可调整宽度、高度、折叠的分割线

sgSpliter.vue <template><!-- 注意&#xff1a;父组件position必须是relative、absolute或fixed&#xff0c;不建议直接在绑定:data后面用"{属性}"&#xff0c;建议单独在script中声明data&#xff0c;避免拖拽过程重复调用 --><div :class"$…

Ningx负载均衡

Ningx负载均衡 upstream(上游)配置负载均衡1、weight&#xff08;加权轮询&#xff09;2、ip_hash&#xff08;负载均衡&#xff09;3、url hash负载均衡4、least_conn&#xff08;最小连接负载均衡&#xff09; upstream(上游)配置负载均衡 Nginx负载均衡 参考: nginx从安装…

一个插件,免费使用所有顶级大模型(Deepseek,Gpt,Grok,Gemini)

DeepSider是一款集成于浏览器侧边栏的AI对话工具&#xff0c;可免费使用所有顶级大模型 包括GPT-4o&#xff0c;Grok3,Claude 3.5 Sonnet,Claude 3.7,Gemini 2.0&#xff0c;Deepseek R1满血版等 以极简交互与超快的响应速度&#xff0c;完成AI搜索、实时问答、内容创作、翻译、…

众趣科技丨数字孪生技术,赋能交通公共设施管理数字化升级

春节假期期间&#xff08;1 月 21 日至 2 月 4 日&#xff09;&#xff0c;作为中国春节申遗成功后的首个春运&#xff0c;交通出行格外火热&#xff0c;全社会跨区域流动量超 23 亿人次&#xff0c;这一数据创下了历史新高。 面对如此庞大的客流量&#xff0c;传统的交通管理方…

Linux 入门五:Makefile—— 从手动编译到工程自动化的蜕变

一、概述&#xff1a;Makefile—— 工程编译的 “智能指挥官” 1. 为什么需要 Makefile&#xff1f; 手动编译的痛点&#xff1a;当工程包含数十个源文件时&#xff0c;每次修改都需重复输入冗长的编译命令&#xff08;如gcc file1.c file2.c -o app&#xff09;&#xff0c;…

Python-Django+vue二手电子设备交易平台功能说明

❥(^_-) 上千个精美定制模板,各类成品Java、Python、PHP、Android毕设项目,欢迎咨询。 ❥(^_-) 程序开发、技术解答、代码讲解、文档,💖文末获取源码+数据库+文档💖 💖软件下载 | 实战案例 💖文章底部二维码,可以联系获取软件下载链接,及项目演示视频。 本项目…

数据库管理工具实战:IDEA 与 DBeaver 连接 TDengine(二)

五、DBeaver 连接 TDengine 实战 5.1 安装 DBeaver 下载安装包&#xff1a;访问 DBeaver 官方网站&#xff08;https://dbeaver.io/download/ &#xff09;&#xff0c;根据你的操作系统选择合适的安装包。如果是 Windows 系统&#xff0c;下载.exe 格式的安装文件&#xff1…

Spring Boot接口返回Long类型的数据时丢失精度的全局处理

1、问题 当实体类中的字段为Long类型时&#xff0c;通过Ajax请求返回给前段&#xff0c;在js中数据会丢失精度 直接通过postman请求或通过浏览器请求&#xff0c;看下响应则不会丢失精度 2、处理方式 1、使用JsonSerialize注解 JsonSerialize(using ToStringSerializer.…

英伟达Llama-3.1-Nemotron-Ultra-253B-v1语言模型论文快读:FFN Fusion

FFN Fusion: Rethinking Sequential Computation in Large Language Models 代表模型&#xff1a;Llama-3.1-Nemotron-Ultra-253B-v1 1. 摘要 本文介绍了一种名为 FFN Fusion 的架构优化技术&#xff0c;旨在通过识别和利用自然并行化机会来减少大型语言模型&#xff08;LLM…

Django学习记录-1

Django学习记录-1 虽然网上教程都很多&#xff0c;但是感觉自己记录一下才属于自己&#xff0c;之后想找也方面一点&#xff0c;文采不佳看的不爽可绕道。 参考贴 从零开始的Django框架入门到实战教程(内含实战实例) - 01 创建项目与app、加入静态文件、模板语法介绍&#xff…

Python爬虫第7节-requests库的高级用法

目录 前言 一、文件上传 二、Cookies 三、会话维持 四、SSL证书验证 五、代理设置 六、超时设置 七、身份认证 八、Prepared Request 前言 上一节&#xff0c;我们认识了requests库的基本用法&#xff0c;像发起GET、POST请求&#xff0c;以及了解Response对象是什么。…

Python 要致富先修路

今天准备在原有基础上重新深入学习并记录python学习进程。 # 整体思路 不废话&#xff1a; 阶段1&#xff1a;精选入门电子教程坚持学习&#xff1b; 阶段2&#xff1a;跟着教程学习代码思维&#xff0c;做好学习笔记并构建知识库方便以后速查&#xff1b; 阶段3&#xff…

微服务无感发布实践:基于Nacos的客户端缓存与故障转移机制

微服务无感发布实践&#xff1a;基于Nacos的客户端缓存与故障转移机制 背景与问题场景 在微服务架构中&#xff0c;服务的动态扩缩容、滚动升级是常态&#xff0c;而服务实例的上下线需通过注册中心&#xff08;如Nacos&#xff09;实现服务发现的实时同步。但在实际生产环境…

2025年的Android NDK 快速开发入门

十年前写过一篇介绍NDK开发的文章《Android实战技巧之二十三&#xff1a;Android Studio的NDK开发》&#xff0c;今天看来已经发生了很多变化&#xff0c;NDK开发变得更加容易了。下面就写一篇当下NDK开发快速入门。 **原生开发套件 (NDK) **是一套工具&#xff0c;使开发者能…

Shell 编程之条件语句

目录 条件测试操作 文件测试 整数值比较 字符串比较 逻辑测试 if 条件语句 if语句的结构 1、单分支 if 语句 2、双分支 if 语句 3、多分支 if 语句 if语句应用实例 1、单分支 if 语句应用 2、双分支 if 语句应用 3、多分支 if 语句应用 case 分支语句 case语句的结构 case语…

【模板】缩点

洛谷p3387 思路: 算法:tarjan算法 根据题意,我们只要找到一个路径,使得最终权重最大即可,首先,根据题目可知,如果一个点在一个环上,那么我们就将这整个环都选上,题目上允许我们能够重复走,因此,我们可以将环缩成点,将环所称点后,就可以转换成树,从没有父节点的结点开始,我们向…

js触发隐式类型转换的场景

JavaScript 的隐式类型转换&#xff08;Implicit Type Coercion&#xff09;会在某些操作或上下文中自动触发&#xff0c;将值从一种类型转换为另一种类型。以下是常见的触发场景&#xff1a; 1. 使用 &#xff08;宽松相等&#xff09;比较时 会尝试将两边的值转换为相同类型后…

c++将jpg转换为灰度图

c将jpg转换为灰度图 step1:添加依赖 下载这两个文件&#xff0c;放在cpp同一目录下&#xff0c;编译生成 https://github.com/nothings/stb/blob/master/stb_image_write.h https://github.com/nothings/stb/blob/master/stb_image.hstep2:C:\Users\wangrusheng\source\repos…