串口传图显示

串口传图

使用串口通信协议传输一张图像到SDRAM存储后VGA协议显示到屏幕。

工程设计

图片生成 使用小梅哥资源中的Picture2Hex软件生成任意分辨率的图片(我这里选择640*480)。
在这里插入图片描述
matlab将得到合适分辨率的照片使用matlab软件分析为文本便于串口发送(图片中每一个像素点都有具体的数值)。这里有两种方法:
1 将图片转为RGB332 使用野火提供视频资源基于RS232的VGA显示中的matlab代码,一个像素点为8位数据使用串口发送。

clc;                    %清理命令行窗口
clear all;              %清理工作区
RGB=imread('0003.bmp');     %使用imred函数读取图片数据
[ROW,COL,D]=size(RGB);  %图片行,列,维度
R=RGB(:,:,1);           %提取图片中的红色分量
G=RGB(:,:,2);           %提取图片中的绿色分量
B=RGB(:,:,3);           %提取图片中的蓝色分量
imgdata=zeros(1,ROW*COL);%定义一个初值为0的数组,存储转换后的图片数据
%转化为RGB332格式
for r=1:ROW
    for c=1:COL
        imgdata((r-1)*COL+c)=bitand(R(r,c),224)+bitshift(bitand(G(r,c),224),-3)+bitshift(bitand(B(r,c),192),-6);
    end
end
%打开或生成txt文件,将格式转换完成的数据写入txt文件
fidc=fopen('picture3.txt','w+');
for i=1:ROW*COL
    fprintf(fidc,'%02x',imgdata(i));
end
fclose(fidc);

2 将图片转为RGB565 使用串口传图中的matlab代码,一个像素点为16位数据。串口一次发送8位,使用此代码发送一个像素点的信息需要发送两次。由于工程中VGA模块输入端口为16位故采用此方法。

clear all;
RGB24 = imread('0001.bmp');            %读取图片文件
fid = fopen('rgb565_1.txt','w+');         %打开文件
[ROW,COL,N] = size(RGB24);              %获得图片尺寸[高度,长度,维度]
for i = 1:ROW
    for j = 1:COL
         RG = bitand(RGB24(i,j,1),248) + bitshift(RGB24(i,j,2),-5); %{R[7:3],3'd0} + {5'd0,G[7:5]}
         G = bitand(RGB24(i,j,2),28);                               %{3'd0,G[4:2],2'd0}
         GB = bitshift( G,3) + bitshift(RGB24(i,j,3),-3);           %{G[4:2],5'd0} + {3'd0,B[7:3]}
         fprintf(fid,'%02x %02x ',RG,GB);%将字符打印到txt文件中
    end
end

工程整体图
在这里插入图片描述

工程源码

注: 由于串口传输8位数据,故将SDRAM中读缓存IP输入端口设置为8位。

顶层源码
module  UART_DISP(
   input    wire                Rx              ,
   input    wire                Clk             ,
   input    wire                Rst_n           ,
   //VGA显示端口                        
   output   wire     [15:0]     Rgb             ,
   output   wire                Hsync           ,
   output   wire                Vsync           ,
   output   wire                Clk_vga         ,
   output   wire                Disp_DE         ,
   //与SDRAM硬件端口                    
   inout    wire     [15:0]     Sdram_dq        ,   
   output   wire                Sdram_cke       ,
   output   wire                Sdram_cs_n      ,
   output   wire                Sdram_cas_n     ,
   output   wire                Sdram_ras_n     ,
   output   wire                Sdram_we_n      ,
   output   wire     [1:0]      Sdram_ba        ,
   output   wire     [12:0]     Sdram_addr      ,
   output   wire     [1:0]      Sdram_dqm       ,
   output   wire                Sdram_clk       ,
   output   wire                 Led             
);  

parameter   baud_set = 3'd4;        //波特率设置,115200bps
parameter   img_h    = 640;         //图片宽度    //640
parameter   img_v    = 480;         //图片高度    //480
parameter   img_data_byte = img_h*img_v;   
    
    
wire                wr_en               ;           //写SDRAM数据使能信号
reg     [31:0]      byte_cnt            ;           //计数8位串口发送次数计数器 
reg                 disp_state          ;           //显示状态使能信号
wire                sys_rst_n           ;
wire                locked              ;
wire                clk_50M             ;
wire                clk_100M            ;
wire                clk_100M_shit       ;
wire                clk_40M             ;
wire    [7:0]       data_out_rx         ;           //8位串口输出数据
wire                pix_reg             ;           //读SDRAM读缓存请求信号
wire                vga_begin           ;           //SDRAM端读FIFO清零使能信号
wire    [15:0]      pix_data            ;           //16位像素数据
reg                 rd_en               ;           //读SDRAM读FIFO使能信号
wire                sdram_rd_en         ;           //读SDRAM读缓存请求信号

assign  sdram_rd_en = (disp_state) ? pix_reg:1'b0 ;

always @(posedge Clk or negedge Rst_n)
    if(!Rst_n)
        rd_en <= 1'b0;
    else
    if(disp_state && vga_begin)
        rd_en <= 1'b1;
    else
        rd_en <= rd_en;
        
assign Led = rd_en;

assign   sys_rst_n   =  Rst_n && locked    ;
//计数串口发送的次数 
always @(posedge Clk or negedge sys_rst_n)
    if(!sys_rst_n)
        byte_cnt    <=  1'b0    ;
    else
    if(wr_en)
        begin
            if( byte_cnt < (img_data_byte<<1))
                byte_cnt <= byte_cnt + 32'b1     ;
            else
                byte_cnt <= (img_data_byte<<1) ;      
        end
    else
        byte_cnt <= byte_cnt ;
//串口发送图片尺寸一半变为可读取状态          
always @(posedge Clk or negedge sys_rst_n)
    if(!sys_rst_n)
        disp_state  <=  1'b0 ;
    else
    if(byte_cnt == (img_data_byte<<1))
        disp_state  <=  1'b1 ;
    else
        disp_state  <=  1'b0 ;        
    
UART_RX     UART_RX_inst(  //串口接收模块
    .Clk        (  clk_50M      )    ,
    .Rst_n      (  sys_rst_n    )    ,
    .Rs232_rx   (  Rx           )    ,
    .Bps_set    (  baud_set     )    ,
        
    .Data_out   (  data_out_rx  )    ,
    .Done_rx    (  wr_en      )
);    

CLK_STRAT	CLK_STRAT_inst(
	.areset ( !Rst_n ),
	.inclk0 ( Clk    ),
	.c0     ( clk_50M ),            //50M
	.c1     ( clk_100M ),           //100M
	.c2     ( clk_100M_shit ),      //100M位移信号
	.c3     ( clk_40M ),            //25M
	.locked ( locked )
	);

SDRAM_TOP  SDRAM_TOP_inst(
    .Clk                  ( clk_100M     ),
    .Rst_n                ( sys_rst_n    ),
    .Clk_out              ( clk_100M_shit     ),     //输入相位偏移时钟
    // 写FIFO                           
    .Wr_fifo_wr_clk       ( clk_50M          ),    
    .Wr_fifo_wr_req       ( wr_en            ),
    .Wr_fifo_wr_data      ( data_out_rx      ),      //写入写FIFO中的数据
    .Sdram_wr_b_addr      ( 24'b0            ),
    .Sdram_wr_e_addr      ( img_data_byte    ),
    .Wr_burst_len         ( 10'd512          ),      //max512
    .Wr_rst               ( ~sys_rst_n       ),      //写复位信号
    // 读FIFO                           
    .Rd_fifo_rd_clk       ( clk_40M          ),
    .Rd_fifo_rd_req       ( sdram_rd_en      ),
    .Sdram_rd_b_addr      ( 24'b0            ),
    .Sdram_rd_e_addr      ( img_data_byte    ),
    .Rd_burst_len         ( 10'd512          ),      //读突发长度
    .Rd_rst               ( ~sys_rst_n       ),      //读复位信号
    .Rd_value             ( rd_en            ),
    .Rd_fifo_rd_data      ( pix_data         ),      //读FIFO中读出的数据
    .Rd_fifo_num          (      ),      //读FIFO中存在的数据个数
    // 与SDRAM的硬件接口                         
    .Sdram_clk            ( Sdram_clk       ),
    .Sdram_cke            ( Sdram_cke       ),                                         
    .Sdram_cs_n           ( Sdram_cs_n      ),
    .Sdram_cas_n          ( Sdram_cas_n     ),
    .Sdram_ras_n          ( Sdram_ras_n     ),
    .Sdram_we_n           ( Sdram_we_n      ),
    .Sdram_ba             ( Sdram_ba        ),
    .Sdram_addr           ( Sdram_addr      ),
    .Sdram_dq             ( Sdram_dq        ),     // SDRAM 数据总线
    .Sdram_dqm            ( Sdram_dqm       )

);

VGA_CTRL   
            // #(
              // .H_SYNC  (11'd128)   ,
              // .H_BACK  (11'd88)    ,
              // .H_LEFT  (11'd0)     ,
              // .H_ABLE  (11'd800)   ,
              // .H_RIGHT (11'd0)     ,
              // .H_PRONT (11'd40)    ,
              // .H_TORAL (11'd1056)  ,
                                  
              // .V_SYNC  (11'd4)    ,
              // .V_BACK  (11'd23)   ,
              // .V_LEFT  (11'd0)    ,
              // .V_ABLE  (11'd600)  ,
              // .V_RIGHT (11'd0)    ,
              // .V_PRONT (11'd1)    ,  
              // .V_TORAL (11'd628)
            // )
VGA_CTRL_inst(

    .Clk        ( clk_40M     )   ,               
    .Rst_n      ( sys_rst_n   )   ,
    .Pix_data   ( {pix_data[7:0],pix_data[15:8]} ) , 
    
    .Rgb        ( Rgb          )   ,
    .Hsync      ( Hsync        )   ,
    .Vsync      ( Vsync        )   ,
    .Pix_x      (       )   ,
    .Pix_y      (       )   ,
    .Clk_vga    ( Clk_vga     )   ,
    .Disp_DE    ( Disp_DE     )   ,  //VGA 场消隐信号
    .Vga_begin  (  vga_begin    )   ,  //SDRAM读FIFO缓存清零信号 高电平有效
    .Pix_reg    (  pix_reg    )      //每个像素点显示16位信息请求信号
);                                            
endmodule  
顶层仿真源码
`timescale 1ns/1ns
`define CLOCK 20

module  UART_DISP_tb();

defparam    UART_DISP_inst.VGA_CTRL_inst.H_SYNC  =   11'd96     ,         //行同步周期     
            UART_DISP_inst.VGA_CTRL_inst.H_BACK  =   11'd40     ,         //行后沿周期     
            UART_DISP_inst.VGA_CTRL_inst.H_LEFT  =   11'd8      ,         //行左边框周期     
            UART_DISP_inst.VGA_CTRL_inst.H_ABLE  =   11'd640    ,         //行有效图像周期数     
            UART_DISP_inst.VGA_CTRL_inst.H_RIGHT =   11'd8      ,         //行右边框     
            UART_DISP_inst.VGA_CTRL_inst.H_PRONT =   11'd8      ,         //行前沿     
            UART_DISP_inst.VGA_CTRL_inst.H_TORAL =   11'd800    ,         //行总扫描周期                              
            UART_DISP_inst.VGA_CTRL_inst.V_SYNC  =   11'd2      ,         //列同步周期     
            UART_DISP_inst.VGA_CTRL_inst.V_BACK  =   11'd25     ,         //列后沿周期     
            UART_DISP_inst.VGA_CTRL_inst.V_LEFT  =   11'd8      ,         //列左边框周期     
            UART_DISP_inst.VGA_CTRL_inst.V_ABLE  =   11'd480    ,         //列有效图像周期数     
            UART_DISP_inst.VGA_CTRL_inst.V_RIGHT =   11'd8      ,         //列右边框     
            UART_DISP_inst.VGA_CTRL_inst.V_PRONT =   11'd2      ,         //列前沿     
            UART_DISP_inst.VGA_CTRL_inst.V_TORAL =   11'd525    ;         //列总扫描周期     
          

  
reg                 Clk             ;
reg                 Rst_n           ;
reg                 con_en          ;                               
reg      [7:0]      data_in         ;                          
wire                rs232_tx        ;           
wire                done_tx         ;  
    //VGA显示端口 
wire      [15:0]    rgb             ;
wire                hsync           ;
wire                vsync           ;
wire                clk_vga         ;
wire                disp_DE         ;
    //与SDRAM硬件端口 
wire      [15:0]    sdram_dq        ;
wire                sdram_cke       ;
wire                sdram_cs_n      ;
wire                sdram_cas_n     ;
wire                sdram_ras_n     ;
wire                sdram_we_n      ;
wire      [1:0]     sdram_ba        ;
wire      [12:0]    sdram_addr      ;
wire      [1:0]     sdram_dqm       ;
wire                sdram_clk       ;       
reg      [7:0]      randone         ; 



initial Clk = 1;
always #(`CLOCK/2) Clk = ~ Clk;

UART_TX     UART_TX_inst(
    .Clk        (Clk        )    ,
	.Rst_n      (Rst_n      )    ,
	.Bps_set    (3'd4)           ,
	.Con_en     (con_en     )    ,
	.Data_in    (data_in    )    ,

	.Rs232_tx   (rs232_tx   )    ,
	.Done_tx    (done_tx    )    ,
	.Uart_state ()
  );

UART_DISP   #(  .img_h(10),
                .img_v(5)
    )   
UART_DISP_inst(
    .Rx             (rs232_tx)      ,
    .Clk            (Clk   )      ,
    .Rst_n          (Rst_n )      ,
    //VGA显示端口                            
    .Rgb            (rgb             )      ,
    .Hsync          (hsync           )      ,
    .Vsync          (vsync           )      ,
    .Clk_vga        (clk_vga         )      ,
    .Disp_DE        (disp_DE         )      ,
    //与SDRAM硬件端口                            
    .Sdram_dq       (sdram_dq   )      ,   
    .Sdram_cke      (sdram_cke  )      ,
    .Sdram_cs_n     (sdram_cs_n )      ,
    .Sdram_cas_n    (sdram_cas_n)      ,
    .Sdram_ras_n    (sdram_ras_n)      ,
    .Sdram_we_n     (sdram_we_n )      ,
    .Sdram_ba       (sdram_ba   )      ,
    .Sdram_addr     (sdram_addr )      ,
    .Sdram_dqm      (sdram_dqm  )      ,
    .Sdram_clk      (sdram_clk  )   
);  

sdram_model_plus    sdram_model_plus_inst(
    .Dq     (sdram_dq       ),
    .Addr   (sdram_addr     ),
    .Ba     (sdram_ba       ),
    .Clk    (sdram_clk      ),
    .Cke    (sdram_cke      ),
    .Cs_n   (sdram_cs_n     ),
    .Ras_n  (sdram_ras_n    ),
    .Cas_n  (sdram_cas_n    ),
    .We_n   (sdram_we_n     ),
    .Dqm    (2'b0           ),
    .Debug  (1'b1           )

);
//发送8位字节数据任务
task send_bit_data;
    begin
        @(posedge done_tx);
        #(`CLOCK*2) ;        
        con_en = 1  ;
        #(`CLOCK)   ;
        con_en = 0  ;
    end
endtask 


initial 
begin
    randone = {$random} % 60             ;                     //通过位并接操作产生一个值在0到59之间的数。
    Rst_n = 0;
    #(`CLOCK*5+1);
    con_en = 0   ;
    Rst_n = 1;
    #(`CLOCK*5);
    data_in = 1'b0 ;
    #(`CLOCK*50);   
    con_en = 1  ;
    #(`CLOCK)   ;
    con_en = 0  ;
    repeat(230)   //输出串口次数像素尺寸的两倍
        begin
            data_in = data_in + randone;
            send_bit_data;
        end
    #(`CLOCK*500+1);    
    $stop ;   
end
endmodule

顶层仿真结果

在这里插入图片描述

在这里插入图片描述
在VGA协议扫描一帧后串口图像传输完成,扫描下一帧时产生VGA_begin信号,读SDRAM信号Rd_value使能有效。
在这里插入图片描述

  • 1
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值