颠倒

点击查看代码
#include "xaxivdma.h" // 引入Xilinx提供的VDMA驱动库 
#include "xaxivdma_i.h"
#include "sleep.h" // 引入Xilinx提供的延时函数库
#include "ff.h" // 引入FatFs文件系统库

#define DDR_BASEADDR        0x00000000 // 定义DDR存储器的起始地址
#define VDMA_BASEADDR       XPAR_AXI_VDMA_0_BASEADDR // 定义VDMA模块的基地址
#define H_STRIDE            800 // 定义图像水平方向的跨度(即一行像素所占的字节数)
#define H_ACTIVE            800 // 定义图像水平方向的分辨率
#define V_ACTIVE            480 // 定义图像垂直方向的分辨率
#define COUNTS_PER_SECOND   (XPAR_CPU_CORTEXA9_CORE_CLOCK_FREQ_HZ)/64 // 定义每秒钟的计数数目

#define VIDEO_LENGTH  (H_STRIDE*V_ACTIVE) // 定义视频数据的长度(以字节为单位)
#define VDMA_MM2S_START DDR_BASEADDR + 0x2000000 // 定义VDMA偏移量,用于指定VDMA接收数据的存储地址

static FATFS fatfs; // 定义FatFs文件系统对象
u8 picture[800*480*3]={0}; // 定义图像数据缓冲区大小(尺寸为800x480,并且每个像素由RGB三个分量组成)
u8 picture_reverse[800*480*3]={0}; // 定义反转后的图像数据缓冲区

void Xil_DCacheFlush(void); // 声明函数Xil_DCacheFlush,用于刷新CPU高速缓存

// 显示图像的函数,参数disp_base_addr为显示窗口的起始地址,addr为待显示图像的首地址,size_x和size_y为图像的分辨率,scale_x和scale_y为缩放比例,mode为缩放方式(1表示垂直方向缩放,2表示水平方向缩放,0表示不缩放)
void show_img(u8 *disp_base_addr, u8 *addr, u32 size_x, u32 size_y, u32 scale_x, u32 scale_y, u8 mode)
{
    u32 i, j, k, l;
    for(j=0;j<size_y/scale_y;j++) // 遍历行
    {
        for(i=0;i<size_x/scale_x;i++) // 遍历列
        {
            if (mode == 1) { // 如果是垂直方向缩放
                u32 r = 0, g = 0, b = 0;
                for(k=0;k<scale_x;k++) {
                    for(l=0;l<scale_y;l++) {
                        r += *(addr+((i*scale_x+k)+(j*scale_y+l)*size_x)*3+0); // 累加红色分量
                        g += *(addr+((i*scale_x+k)+(j*scale_y+l)*size_x)*3+1); // 累加绿色分量
                        b += *(addr+((i*scale_x+k)+(j*scale_y+l)*size_x)*3+2); // 累加蓝色分量
                    }
                }
                *(disp_base_addr+(i+j*size_x/scale_x)*3+0) = r/(scale_x*scale_y); // 计算平均值并存储到显示窗口对应位置的缓冲区中(红色)
                *(disp_base_addr+(i+j*size_x/scale_x)*3+1) = g/(scale_x*scale_y); // (绿色)
                *(disp_base_addr+(i+j*size_x/scale_x)*3+2) = b/(scale_x*scale_y); // (蓝色)
            } else if (mode == 2) { // 如果是水平方向缩放
                for(l = 0; l < scale_y; l++) {
                    for(k = 0; k < scale_x; k++) {
                        u8 r = *(addr+((i*scale_x+k)+(j*scale_y+l)*size_x)*3+0); // 取出原始图像的RGB三个分量
                        u8 g = *(addr+((i*scale_x+k)+(j*scale_y+l)*size_x)*3+1);
                        u8 b = *(addr+((i*scale_x+k)+(j*scale_y+l)*size_x)*3+2);

                        // 将RGB颜色值转换为灰度值
                        u8 gray = (u8)(0.2989 * r + 0.5870 * g + 0.1140 * b);

                        // 对灰度值进行阈值化处理(如果大于等于128,则置为白色255,否则置为黑色0)
                        u8 binary = (gray >= 128) ? 255 : 0;

                        *(disp_base_addr+((i*scale_x)+k + ((j*scale_y)+l)*size_x*scale_x)*3+0) = binary; // 存储到显示窗口对应位置的缓冲区中(红色)
                        *(disp_base_addr+((i*scale_x)+k + ((j*scale_y)+l)*size_x*scale_x)*3+1) = binary; // (绿色)
                        *(disp_base_addr+((i*scale_x)+k + ((j*scale_y)+l)*size_x*scale_x)*3+2) = binary; // (蓝色)
                    }
                }
            } else { // 如果不需要缩放
                for(k = 0; k < scale_x*scale_y; k++) {
                    *(disp_base_addr+(i+j*size_x/scale_x)*scale_x*scale_y*3+k*3+0) = *(addr+(i*scale_x*scale_y+k+j*size_x*scale_y)*3+0); // 直接将原始图像的RGB三个分量存储到显示窗口对应位置的缓冲区中(红色)
                    *(disp_base_addr+(i+j*size_x/scale_x)*scale_x*scale_y*3+k*3+1) = *(addr+(i*scale_x*scale_y+k+j*size_x*scale_y)*3+1); // (绿色)
                    *(disp_base_addr+(i+j*size_x/scale_x)*scale_x*scale_y*3+k*3+2) = *(addr+(i*scale_x*scale_y+k+j*size_x*scale_y)*3+2); // (蓝色)
                }
            }
        }
    }
    Xil_DCacheFlush(); // 刷新CPU高速缓存
}

// 初始化SD卡并挂载文件系统
int SD_Init()
{
    FRESULT rc;
    rc = f_mount(&fatfs,"",0);
    if(rc)
    {
        xil_printf("ERROR : f_mount returned %d\r\n",rc);
        return XST_FAILURE;
    }
    return XST_SUCCESS;
}

// 读取SD卡中指定文件的数据到指定地址
int SD_Transfer_read(char *FileName,u8 *DestinationAddress,u32 ByteLength)
{
    FIL fil;
    FRESULT rc;
    UINT br;
    rc = f_open(&fil,FileName,FA_READ); // 打开指定文件
    if(rc)
    {
        xil_printf("ERROR : f_open returned %d\r\n",rc);
        return XST_FAILURE;
    }
    rc = f_lseek(&fil, 54); // 跳过位图文件头(54字节)
    if(rc)
    {
        xil_printf("ERROR : f_lseek returned %d\r\n",rc);
        return XST_FAILURE;
    }
    rc = f_read(&fil, DestinationAddress,ByteLength,&br); // 读取文件数据
    if(rc)
    {
        xil_printf("ERROR : f_read returned %d\r\n",rc);
        return XST_FAILURE;
    }
    rc = f_close(&fil); // 关闭文件
    if(rc)
    {
        xil_printf(" ERROR : f_close returned %d\r\n", rc);
        return XST_FAILURE;
    }
    return XST_SUCCESS;
}

int main(void)
{
    int i, j;

    SD_Init(); // 初始化SD卡并挂载文件系统
    SD_Transfer_read("A.bmp",picture,800*480*3); // 读取图像数据

    // 反转图像颜色
    for (i = 0; i < 800*480*3; i += 3) {
        picture_reverse[i] = picture[i + 2]; // 将蓝色分量赋值给红色分量
        picture_reverse[i + 1] = picture[i + 1]; // 将绿色分量保持不变
        picture_reverse[i + 2] = picture[i]; // 将红色分量赋值给蓝色分量
    }

    // 设置VDMA
    Xil_Out32((VDMA_BASEADDR + 0x000), 0x0000008b);         // VDMA控制寄存器,启用循环模式
    Xil_Out32((VDMA_BASEADDR + 0x05c), VDMA_MM2S_START);   // VDMA写通道(MM2S)起始地址
    Xil_Out32((VDMA_BASEADDR + 0x058), (H_ACTIVE*3));      // VDMA写通道(MM2S)水平方向偏移量
    Xil_Out32((VDMA_BASEADDR + 0x054), (H_STRIDE*3));      // VDMA写通道(MM2S)水平方向大小
    Xil_Out32((VDMA_BASEADDR + 0x050), V_ACTIVE);          // VDMA写通道(
posted @ 2023-04-17 12:48  闲人张  阅读(92)  评论(0)    收藏  举报