方案有很多 有专门的asic的
但是建议用fpga自己写一个 其实很简单的
但是要用高速da 来输出信号 stm32的估计速度不够
以下是别人写的fpga 驱动vga的verilog
占用就几十个le单元 用cpld也可以写出来的
//==========================================================================
// 640*480@60hz.
//==========================================================================
`define ud #1
`define pixel_max 16'h320 //800
`define line_max 16'h20d //525
`define hs_time 16'h60 //96
`define vs_time 16'h2 //2
module vga_ctl
(
//input ports.
sysclk,
rst_b,
key_b,
//output ports.
red,
green,
blue,
vsync,
hsync
);
//==========================================================================
//input and output declaration
//==========================================================================
input sysclk;
input rst_b;
input key_b;
output [1:0] red;
output [2:0] green;
output [2:0] blue;
output vsync;
output hsync;
//==========================================================================
//wire and reg declaration
//==========================================================================
wire sysclk;
wire rst_b;
wire key_b;
reg [1:0] red;
reg [2:0] green;
reg [2:0] blue;
reg vsync;
reg hsync;
//==========================================================================
//wire and reg in the module.
//==========================================================================
reg [15:0] pixel_cnt;
reg [15:0] line_cnt;
reg [15:0] pixel_cnt_n;
reg [15:0] line_cnt_n;
reg vsync_n;
reg hsync_n;
//==========================================================================
//logic
//==========================================================================
//==========================================================================
//vertical and horizontal sync control
//==========================================================================
//pixel number in one line counter.
always @ (posedge sysclk or negedge rst_b)
begin
if(!rst_b)
pixel_cnt <= `ud 16'h0;
else
pixel_cnt <= `ud pixel_cnt_n;
end
always @ (*)
begin
if(pixel_cnt == `pixel_max)
pixel_cnt_n = 16'h0;
else
pixel_cnt_n = pixel_cnt + 16'h1;
end
//line number counter.
always @ (posedge sysclk or negedge rst_b)
begin
if(!rst_b)
line_cnt <= `ud 16'h0;
else
line_cnt <= `ud line_cnt_n;
end
always @ (*)
begin
if((line_cnt == `line_max) && (pixel_cnt == `pixel_max))
line_cnt_n = 16'h0;
else if((line_cnt != `line_max) && (pixel_cnt == `pixel_max))
line_cnt_n = line_cnt + 16'h1;
else
line_cnt_n = line_cnt;
end
//hsync control, before enable pixel, sync first.
always @ (posedge sysclk or negedge rst_b)
begin
if(!rst_b)
hsync <= `ud 1'h0;
else
hsync <= `ud hsync_n;
end
always @ (*)
begin
if(pixel_cnt == `pixel_max)
hsync_n = 1'h0;
else if(pixel_cnt == `hs_time)
hsync_n = 1'h1;
else
hsync_n = hsync;
end
//vsync control, before enable line, sync first.
always @ (posedge sysclk or negedge rst_b)
begin
if(!rst_b)
vsync <= `ud 1'h0;
else
vsync <= `ud vsync_n;
end
always @ (*)
begin
if(line_cnt == `line_max)
vsync_n = 1'h0;
else if(line_cnt == `vs_time)
vsync_n = 1'h1;
else
vsync_n = vsync;
end
//==========================================================================
//rgb output control
//==========================================================================
always @ (*)
begin
case(line_cnt[8:7])
2'h0 : begin
red = 2'h3;
green = 3'h0;
blue = 3'h0;
end
2'h1 : begin
red = 2'h0;
green = 3'h7;
blue = 3'h0;
end
2'h2 : begin
red = 2'h0;
green = 3'h0;
blue = 3'h7;
end
2'h3 : begin
red = 2'h3;
green = 3'h7;
blue = 3'h7;
end
default : begin
red = 2'h0;
green = 3'h0;
blue = 3'h0;
end
endcase
end
endmodule