【【VDMA彩条显示实验之四 含C语言代码】】

VDMA彩条显示实验之四 含C语言代码

VTC 手册简介

所有的视频都需要有时序 有时序的地方就需要有 时序控制器

VTC的 主要作用是 产生 视频时序

相对于上一节 在这里 我们会理解的更多

观察 这个 HB 信号 其实这个和上一节的图片差不多

在 行同步信号 前面就是前沿 在 行同步信号的后侧 就是 后沿

VTC 还可以最多支持 16 个 帧同步信号

我们来配置 VTC

首先观察我们需要配置的 各项参数 设置

这是 LCD 时序参数

我们需要做的是将 这个参数 与 VTC的 配置 关联起来



下面我们来配置 帧时序



最终设计的block design

我们观察一下 像素时钟接到了 哪几个端口上

我们会发现 由 PLL 锁相环产生 的 像素时钟 连接到 了 VTC 模块 Video out的 一个 clk 还有 连接到了 lcd_clk 上

其他上用的大多是 100M的时钟

int run_triple_frame_buffer(XAxiVdma* InstancePtr , int DeviceId , int hsize, int vsize, int buf_base_addr, int number_frame_count, int enable_frm_cnt_intr)

第一个参数是 XAxiVdma* InstancePtr ----> VDMA 数据结构的 句柄

第二个参数是 int DeviceId -------> VDMA 器件 的 ID

第三个参数是 int hsize --------> 一帧水平方向上的大小

第四个参数是 int vsize ----------> 竖直方向上的大小

第五个参数是 int buf_base_addr ----------> VDMA 起始帧缓存的地址

第六个参数 是 int number_frame_count ----------> 指定了经过多少帧之后 会迎来中断

第七个参数是 int enable_frm_cnt_intr --------> 告诉我们是否需要使能帧计数器这样的 一个中断

因为在本次实验中 我们并不是很需要中断 所以最后两个参数可以不用去考虑

下面展示整个C语言代码

c 复制代码
#include "stdio.h"
#include"xparameters.h"
#include "xaxivdma.h"
#include "vdma_api.h"
#define VDMA_ID            XPAR_AXIVDMA_0_DEVICE_ID
#define DDR_BASE_ADDR      XPAR_PS7_DDR_0_S_AXI_BASEADDR  // DDR存储空间 的起始地址
//这个是 DDR的基地址 我们是需要写一个彩条图案 但是 彩条图案总不能从基地址
//开始,因为我们程序 也是 从基地址 开始运行的 。 如果彩条图案是从基地址开始
//运行的话 ,就会给我们程序带来冲突  所以我们要重新定义一个帧缓存的地址
// 把宏定义的形式 改写成 变量的形式 这样在 后续可以更方便使用
int frame_buffer_addr  = (DDR_BASE_ADDR + 0x1000000)  ;// VDMA 帧缓存的地址
#define WIDTH   800  // 图像的宽度
#define HEIGHT  480  // 图像的高度
int main()
{
int i , j ;
u8* vdma_buffer_addr ;
vdma_buffer_addr = (u8*) frame_buffer_addr ;


XAxiVdma vdma_inst;


// 配置并启动 VDMA

run_triple_frame_buffer(
&vdma_inst,        // vdma驱动实例
VDMA_ID,           // VDMA 的 ID信息
WIDTH,             //  图像的水平尺寸  宽度
HEIGHT,            //  图像的高度
frame_buffer_addr,   //  VDMA 究竟从DMA的哪个地址开始读取图像// VDMA 帧缓存的起始地址
0,
0);
//  往 VDMA 的帧缓存里面 写入 图案
for(j=0;j<HEIGHT ; j++){
for(i=0 ; i<WIDTH ; i++)
{
// 因为我们用的是 RGB 888 相当于 占据了 3个字节
// 我们使用的是 u8* 类型的 所以就如同下面写的那样 三个才表示一个数据
//
(vdma_buffer_addr + jWIDTH3 + i3+0 ) = 0xff ; //往像素的红色通道写入FF
(vdma_buffer_addr + jWIDTH3 + i3+1 ) = 0x00 ; //往像素的绿色通道写入00
(vdma_buffer_addr + jWIDTH3 + i3+2 ) = 0x00 ; //往像素的蓝色通道写入00
}
}
return 0  ;
}

我们在上电之后发现现象不对 开始修改

一个是红色和蓝色 的不对 还有一个是 只显示了一部分的颜色

为什么会没写好呢 是因为 我们 PS端的DDR控制器 会缓存一部分数据

我们需要把缓存的数据强行冲出来

void Xil_DCacheFlush(void); 添加 函数

下面是修改之后的代码

c 复制代码
#include "stdio.h"
#include"xparameters.h"
#include "xaxivdma.h"
#include "vdma_api.h"
#include "xil_cache.h"
#define VDMA_ID            XPAR_AXIVDMA_0_DEVICE_ID
#define DDR_BASE_ADDR      XPAR_PS7_DDR_0_S_AXI_BASEADDR  // DDR存储空间 的起始地址
//这个是 DDR的基地址 我们是需要写一个彩条图案 但是 彩条图案总不能从基地址
//开始,因为我们程序 也是 从基地址 开始运行的 。 如果彩条图案是从基地址开始
//运行的话 ,就会给我们程序带来冲突  所以我们要重新定义一个帧缓存的地址
// 把宏定义的形式 改写成 变量的形式 这样在 后续可以更方便使用
int frame_buffer_addr  = (DDR_BASE_ADDR + 0x1000000)  ;// VDMA 帧缓存的地址
#define WIDTH   800  // 图像的宽度
#define HEIGHT  480  // 图像的高度
int main()
{
int i , j ;
u8* vdma_buffer_addr ;
vdma_buffer_addr = (u8*) frame_buffer_addr ;


XAxiVdma vdma_inst;


// 配置并启动 VDMA

run_triple_frame_buffer(
&vdma_inst,        // vdma驱动实例
VDMA_ID,           // VDMA 的 ID信息
WIDTH,             //  图像的水平尺寸  宽度
HEIGHT,            //  图像的高度
frame_buffer_addr,   //  VDMA 究竟从DMA的哪个地址开始读取图像// VDMA 帧缓存的起始地址
0,
0);
//  往 VDMA 的帧缓存里面 写入 图案
for(j=0;j<HEIGHT ; j++){
for(i=0 ; i<WIDTH ; i++)
{
// 因为我们用的是 RGB 888 相当于 占据了 3个字节
// 我们使用的是 u8* 类型的 所以就如同下面写的那样 三个才表示一个数据
//
(vdma_buffer_addr + jWIDTH3 + i3+0 ) = 0x00 ; //往像素的蓝色通道写入FF
(vdma_buffer_addr + jWIDTH3 + i3+1 ) = 0x00 ; //往像素的绿色通道写入00
(vdma_buffer_addr + jWIDTH3 + i3+2 ) = 0xff ; //往像素的红色通道写入00
}
}
//将cache缓存的数据冲出来
Xil_DCacheFlush();
return 0  ;
}

纯色模块显示完毕 下面展示彩条代码的书写

c 复制代码
#include "stdio.h"
#include"xparameters.h"
#include "xaxivdma.h"
#include "vdma_api.h"
#include "xil_cache.h"
#define VDMA_ID            XPAR_AXIVDMA_0_DEVICE_ID
#define DDR_BASE_ADDR      XPAR_PS7_DDR_0_S_AXI_BASEADDR  // DDR存储空间 的起始地址
//这个是 DDR的基地址 我们是需要写一个彩条图案 但是 彩条图案总不能从基地址
//开始,因为我们程序 也是 从基地址 开始运行的 。 如果彩条图案是从基地址开始
//运行的话 ,就会给我们程序带来冲突  所以我们要重新定义一个帧缓存的地址
// 把宏定义的形式 改写成 变量的形式 这样在 后续可以更方便使用
int frame_buffer_addr  = (DDR_BASE_ADDR + 0x1000000)  ;// VDMA 帧缓存的地址
#define WIDTH   800  // 图像的宽度
#define HEIGHT  480  // 图像的高度
int main()
{
int i , j ;
u8* vdma_buffer_addr ;
vdma_buffer_addr = (u8*) frame_buffer_addr ;


XAxiVdma vdma_inst;


// 配置并启动 VDMA

run_triple_frame_buffer(
&vdma_inst,        // vdma驱动实例
VDMA_ID,           // VDMA 的 ID信息
WIDTH,             //  图像的水平尺寸  宽度
HEIGHT,            //  图像的高度
frame_buffer_addr,   //  VDMA 究竟从DMA的哪个地址开始读取图像// VDMA 帧缓存的起始地址
0,
0);
//  往 VDMA 的帧缓存里面 写入 图案
for(j=0;j<HEIGHT ; j++){
for(i=0 ; i<WIDTH ; i++)
{
// 因为我们用的是 RGB 888 相当于 占据了 3个字节
// 我们使用的是 u8* 类型的 所以就如同下面写的那样 三个才表示一个数据
//
if(i < WIDTH/3) {
(vdma_buffer_addr + jWIDTH3 + i3+0 ) = 0x00 ; //往像素的蓝色通道写入FF
(vdma_buffer_addr + jWIDTH3 + i3+1 ) = 0x00 ; //往像素的绿色通道写入00
(vdma_buffer_addr + jWIDTH3 + i3+2 ) = 0xff ; //往像素的红色通道写入00
}
else if( i <(2WIDTH)/3   ){(vdma_buffer_addr + jWIDTH3 + i3+0 ) = 0x00 ; //往像素的蓝色通道写入FF(vdma_buffer_addr + jWIDTH3 + i3+1 ) = 0xff ; //往像素的绿色通道写入00(vdma_buffer_addr + jWIDTH3 + i3+2 ) = 0x00 ; //往像素的红色通道写入00}else{(vdma_buffer_addr + jWIDTH3 + i3+0 ) = 0xff ; //往像素的蓝色通道写入FF(vdma_buffer_addr + jWIDTH3 + i3+1 ) = 0x00 ; //往像素的绿色通道写入00(vdma_buffer_addr + jWIDTH3 + i*3+2 ) = 0x00 ; //往像素的红色通道写入00
}
 }

}
//将cache缓存的数据冲出来
Xil_DCacheFlush();
return 0  ;
}
相关推荐
仲南音17 小时前
Xilinx FPGA——时钟IP核MMCM、PLL
fpga开发
I'm a winner1 天前
基于Xilinx FPGA的LVDS高速串行通信系统(三)--数据训练及握手机制【文末源码】
fpga开发
upper20201 天前
coremark移植坑之-nostartfiles -nostdlib参数
学习·fpga开发·coremark移植·riscv设计
Eloudy2 天前
Vivado 纯命令行构建 FPGA 项目教程
fpga开发
Rambo.xia2 天前
AXI跨时钟域与数据一致性——CDC FIFO深度不够、写后读冒险、多Master仲裁、乱序返回,出了Bug根本查不出来
fpga开发·bug
upper20202 天前
FPGA部署卷积神经网络识别MINST图片
fpga开发·卷积神经网络·minst·minst识别·部署神经网络·神经网络识别图片
你是我的解忧王子2 天前
嵌入式 ADC采样 原始数据分析上层(平均值 波动率 正态分布 线性补偿 系统误差)
fpga开发·数据挖掘·数据分析
9527华安3 天前
FPGA纯verilog代码ISP图像处理培训教程,基于IMX214,提供工程源码+视频教程+FPGA开发板
图像处理·fpga开发·isp·imx214·mipi
千寻xun3 天前
二、实战篇-NVME SSD控制之ZYNQ实现(六)-读写NVME SSD硬盘数据
fpga开发·nvme·nvme ssd
千寻xun3 天前
二、实战篇-NVME SSD控制之ZYNQ实现(三)
fpga开发·nvme ssd·nvme协议