[X]关闭
0

S02-CH26 SD卡读写电子广告屏实验

摘要: 软件版本:VIVADO2017.4操作系统:WIN10 64bit硬件平台:适用米联客 ZYNQ系列开发板米联客(MSXBO)论坛:www.osrc.cn答疑解惑专栏开通,欢迎大家给我提问!26.1 概述 结合前面的讲解,包括从SD/TF卡读写数据,利用VD ...

软件版本:VIVADO2017.4

操作系统:WIN10 64bit

硬件平台:适用米联客 ZYNQ系列开发板

米联客(MSXBO)论坛:www.osrc.cn答疑解惑专栏开通,欢迎大家给我提问!

26.1 概述

      结合前面的讲解,包括从SD/TF卡读写数据,利用VDMA和HDMI显示视频图像,本节课,实现从SD卡读取图片并且在HDMI显示器上显示。这节课的内容具备一定的实用性,比如可以用用于液晶屏的测试或者展示。

26.2 FPGA BD工程

     Step1:新建一个名为为Miz_sys的工程。

     Step2:创建一个BD文件,并命名为system,添加并且配置好ZYNQ IP。读者需要根据自己的硬件类型配置好输入时钟频率、内存型号、串口,连接时钟等。新手不清楚这些内容个,请参考“CH01 HelloWold/DDR/网口测试及固化”这一节课。

26.3 SDK程序

26.3.1 main.c

/*

 *

Company: cz123 Electronic Technology Co., Ltd.

         Liyang Milian Electronic Technology Co., Ltd.

Brand: MSXBO

BBS: www.osrc.cn

WEB: www.msxbo.com

Author: tjy

Copyright:  by msxbo 2019-2029

 *

 *

 * */

#include <stdio.h>

#include "xparameters.h"

#include "xsdps.h"

#include "xil_printf.h"

#include "ff.h"



#define H_STRIDE            1280

#define H_ACTIVE            1280

#define V_ACTIVE            720

#define VIDEO_LENGTH  (H_STRIDE*V_ACTIVE)



#define VDMA_BASEADDR   XPAR_AXI_VDMA_0_BASEADDR

#define DDR_BASEADDR    0x00000000

#define VIDEO_BASEADDR0 0x01000000

#define BUF_SIZE 1280*720*3


static FATFS SD_Dev; // File System instance

char *SD_Path = "0:/";  //  string pointer to the logical drive number


u8 RD_Buf1[BUF_SIZE] __attribute__ ((aligned(32)));

u8 RD_Buf2[BUF_SIZE] __attribute__ ((aligned(32)));

u8 RD_Buf3[BUF_SIZE] __attribute__ ((aligned(32)));

u8 RD_Buf4[BUF_SIZE] __attribute__ ((aligned(32)));



void Xil_DCacheFlush(void);


void show_img( const unsigned char * addr, u32 size_x, u32 size_y)

{

u32 x=0;

u32 y=0;

u32 r,g,b;

for(y=size_y;y>0;y--)

{

for(x=0;x<size_x;x++)

{

b = *(addr++);

g = *(addr++);

r = *(addr++);

Xil_Out32((VIDEO_BASEADDR0+(((y-1)*size_x)+x)*4),((r<<16)|(g<<8)|(b<<0)));

}

}


Xil_DCacheFlush();

}



void VDMA_init()

{

int i;

for(i=0;i<VIDEO_LENGTH;i++)

{

Xil_Out32(VIDEO_BASEADDR0+i*4,0);

}

Xil_DCacheFlush();

Xil_Out32((VDMA_BASEADDR + 0x000), 0x3);

Xil_Out32((VDMA_BASEADDR + 0x05c), VIDEO_BASEADDR0);

Xil_Out32((VDMA_BASEADDR + 0x060), VIDEO_BASEADDR0);

Xil_Out32((VDMA_BASEADDR + 0x064), VIDEO_BASEADDR0);

Xil_Out32((VDMA_BASEADDR + 0x058), (H_STRIDE*4));

Xil_Out32((VDMA_BASEADDR + 0x054), (H_ACTIVE*4));

Xil_Out32((VDMA_BASEADDR + 0x050), V_ACTIVE);


}


int SD_init()

{

FRESULT result;

//-----------------------mount dev-----------------------------------------------

result = f_mount(&SD_Dev,SD_Path, 0);

if (result != 0) {

return XST_FAILURE;

}

return XST_SUCCESS;

}



int main()

{


VDMA_init();

SD_init();

BMP_Picture((u8 *)"1.bmp" , RD_Buf1 ,BUF_SIZE);

BMP_Picture((u8 *)"2.bmp" , RD_Buf2 ,BUF_SIZE);

//BMP_Picture((u8 *)"3.bmp" , RD_Buf3 ,BUF_SIZE);

//BMP_Picture((u8 *)"4.bmp" , RD_Buf4 ,BUF_SIZE);


while(1)

{

show_img(RD_Buf1,1280,720);

sleep(2);

show_img(RD_Buf2,1280,720);

sleep(2);

//show_img(RD_Buf3,1280,720);

//sleep(5);

//show_img(RD_Buf4,1280,720);

//sleep(5);

}


    return 0;

}

      在这个函数中,读取SD卡中的图片然后,在显示器上显示,测试的图片的大小是1280*720P ,图片格式为BMP格式。所以下面还需要对BMP格式的图像做个简单的界面。另外需要注意,BMP格式的图像数据是颠倒的,所以在show_img函数中,还需要对BMP格式做个地址计算后再写入到DDR。

26.3.2 bmp.c

#include "bmp.h"

#include "ff.h"



/****************************************************************************

* Function Name  : BMP_ReadHeader

* Description    : 将读取到的数组函数转换位BPM文件信息结构体类型。由于在内存

*                * 上面数组的存储方式与结构体不同,所以要转换,而且SD读取到的

*                * 文件信息是小端模式。高位是低字节,低位是高字节,跟我们常用

*                * 的正好相反所以将数据转换过来。

* Input          : header:要转换的数组

*                * bmp:转换成的结构体

* Output         : None

* Return         : None

****************************************************************************/


void BMP_ReadHeader(uint8_t *header, BMP_HeaderTypeDef *bmp)

{


bmp->fileHeader.bfType = ((*header) << 8) | (*(header + 1));

header += 2;


bmp->fileHeader.bfSize = ((*(header + 3)) << 24) | ((*(header + 2)) << 16) |

                         ((*(header + 1)) << 8) | (*header);

header += 8;


bmp->fileHeader.bfOffBits = ((*(header + 3)) << 24) | ((*(header + 2)) << 16) |

                            ((*(header + 1)) << 8) | (*header);

header += 4;


bmp->infoHeader.bitSize = ((*(header + 3)) << 24) | ((*(header + 2)) << 16) |

                          ((*(header + 1)) << 8) | (*header);

header += 4;


bmp->infoHeader.biWidth = ((*(header + 3)) << 24) | ((*(header + 2)) << 16) |

                          ((*(header + 1)) << 8) | (*header);

header += 4;


bmp->infoHeader.biHeight = ((*(header + 3)) << 24) | ((*(header + 2)) << 16) |

                           ((*(header + 1)) << 8) | (*header);

header += 6;


bmp->infoHeader.biBitCount = ((*(header + 1)) << 8) | (*header);

                         

header += 2;


bmp->infoHeader.biCompression = ((*(header + 3)) << 24) | ((*(header + 2)) << 16) |

                                ((*(header + 1)) << 8) | (*header);

header += 4;


bmp->infoHeader.biSizeImage = ((*(header + 3)) << 24) | ((*(header + 2)) << 16) |

                              ((*(header + 1)) << 8) | (*header);

header += 4;


bmp->infoHeader.biXPelsPerMeter = ((*(header + 3)) << 24) | ((*(header + 2)) << 16) |

                                  ((*(header + 1)) << 8) | (*header);

header += 4;


bmp->infoHeader.biYPelsPerMeter = ((*(header + 3)) << 24) | ((*(header + 2)) << 16) |

                                  ((*(header + 1)) << 8) | (*header);

}



/****************************************************************************

* Function Name  : BMP_Picture

* Description    : 显示BMP格式的图片

* Input          : dir:要显示的图片路径和名字

* Output         : None

* Return         : None

****************************************************************************/



void BMP_Picture(uint8_t *dir , uint8_t  * buf ,uint32_t len)

{

FRESULT res;

FIL fsrc;

UINT  br;

UINT  a;


uint8_t buffer[1024];


BMP_HeaderTypeDef bmpHeader;


/* 打开要读取的文件 */

res = f_open(&fsrc, (const TCHAR*)dir, FA_READ);


if(res == FR_OK)   //打开成功

    {

/* 读取BMP文件的文件信息 */

        res = f_read(&fsrc, buffer, sizeof(buffer), &br);


/* 将数组里面的数据放入到结构数组中,并排序好 */

BMP_ReadHeader(buffer, &bmpHeader);


a = bmpHeader.fileHeader.bfOffBits;    //去掉文件信息才开始是像素数据


res=f_lseek(&fsrc, a);

if(res)

{

return 0;

}

res = f_read(&fsrc, buf, len, &br);

    }

    f_close(&fsrc);  //不论是打开,还是新建文件,一定记得关闭

}


      Bmp.c函数中重要是需要对BMP图片格式的头部进行解析,并且获取图像数据的开始位置,然后用f_lseek(&fsrc, a)函数,定位到图像数据的位置,之后再读出图像的数据。

typedef struct 

{

uint16_t bfType;        //文件类型,BMP格式为字符串BM

uint32_t bfSize; //图片大小,单位为KB

uint16_t bfReserved1; //保留位

uint16_t bfReserved2; //保留位

uint32_t bfOffBits;   //从文件头到实际图像数据之间的字节偏移量

} BMP_FileHeaderTypeDef;


typedef struct 

{

uint32_t bitSize;  //BMP_InfoHeaderTypeDef结构体所需要的字节数

uint32_t biWidth;  //图片宽度,像素位单位

int32_t  biHeight;  //图片高度,像素为单位。正为倒立,负为正向。

uint16_t biPlanes;  //颜色平面数,总为1

uint16_t biBitCount;  //比特数/像素。其值为:1、4、8、16、24或32

uint32_t biCompression;  //数据压缩类型

uint32_t biSizeImage;  //图像大小

uint32_t biXPelsPerMeter;//水平分辨率

uint32_t biYPelsPerMeter;//垂直分辨率

uint32_t biClrUsed;  //颜色索引数

uint32_t biClrImportant; //重要颜色索引数


}BMP_InfoHeaderTypeDef;

26.4 测试结果

26.5图片素材

教程中提供的图片素材,在配套的工程下的user_src里面。

26.7 注意事项

使用FAT文件系统需要勾选以下库,如果不清楚的请看“CH14 TF/SD卡/EMMC读写实验”


路过

雷人

握手

鲜花

鸡蛋

最新评论

本文作者
2019-9-6 19:34
  • 7
    粉丝
  • 2012
    阅读
  • 0
    回复

关注米联客

扫描关注,了解最新资讯

联系人:汤经理
电话:0519-80699907
EMAIL:270682667@qq.com
地址:常州溧阳市天目云谷3号楼北楼201B
热门评论
排行榜