NV2+GW1N+STM32红外热成像数据显示
[复制链接]
本帖最后由 littleshrimp 于 2022-1-10 12:20 编辑
为了让热成像的数据能在STM32上显示,上次计划使用GW1N将DS90C124的并行数据转成SPI串行数据热成像数据采集的GW1N DS90C124到SPI的并串转换,因为是使用飞线连接50MHz的时钟频率STM32那边没法正确读取,这个问题需要将FPGA芯片直接和STM32画在一个板子上才以解决。当然上次的程序在FIFO处理上也有些问题,没有对FIFO为空时的数据做处理,使得收到的数据会有大量重复,不过这不是功能不能实现的主因。
目前情况SPI的方式不行还有DCMI的方式可用,DCMI是STM32的摄像头接口,使用8bit并行数据。使用GW1N可以非常方便的将DS90C124的并行数据转换成对应的8bit摄像头数据。这里为了简化STM32部分的编程我直用GW1N把14bit的热像数据做了处理,使它直接输出8bit/pixel的数据,STM32可以直接显示灰度数据。为了能显示颜色我又在STM32上做了CLUT(颜色查找表)这样就可以为黑白数据增加相应色彩的调色板功能。
FPGA部分的代码也比较简单,只需要对vsync和hsync做相应处理,然后再把14bit的数据做相应的剪裁即可,不过这里的offset是固定的,如果GW1N板子上有轻触按键就可以使用板子上的按键控制动态调节“亮度”。
module ds90c124(
input rst_n,
input rclk,
input wire[15:0]rout,
output reg vsync,
output wire hsync,
output wire[7:0] data
);
reg hsync_reg,hsync_reg1;
assign hsync = ~hsync_reg;
reg [7:0]data_reg;
assign data = data_reg;
reg vsync_reg,vsync_reg1;
reg [13:0]offset = 14'd3000;
reg [13:0]temp = 14'd0;
reg[8:0]cnt = 9'd0;
//rout[15] = 1时行起始
//rout[14] = rout[15] = 1时,1时为帧起始
//rout[9] = rout[15] = 1时,1时为数据无效/0时数据有效
reg data_valid,data_valid1,data_valid2;
reg[4:0]vsync_cnt;
always@(posedge rclk) begin
if(~rst_n) begin
vsync_cnt <= 1'b0;
end else begin
if(rout[15] & rout[14])begin
vsync_cnt <= 1'b0;
end else if(vsync_cnt < 5)begin
vsync_cnt <= vsync_cnt + 1'b1;
end
end
end
always@(posedge rclk) begin
if(~rst_n) begin
vsync <= 1'b0;
end else begin
if(rout[15] & rout[14])begin
vsync <= 1'b1;
end else if(vsync_cnt == 3)begin
vsync <= 1'b0;
end
end
end
always@(posedge rclk) begin
if(~rst_n) begin
data_valid <= 1'b0;
data_valid1 <= 1'b0;
end else begin
if(rout[15] == 1'b1 && rout[14] == 1'b0 && rout[9] == 1'b0) begin
data_valid1 <= 1'b1;
end else if(rout[15] == 1'b1 && (rout[14] == 1'b1 || rout[9] == 1'b1))begin
data_valid <= 1'b0;
data_valid1 <= 1'b0;
data_valid2 <= 1'b0;
end else begin
data_valid2 <= data_valid1;
data_valid <= data_valid2;
end
end
end
always@(posedge rclk) begin
if(~rst_n) begin
vsync_reg <= 1'b0;
vsync_reg1 <= 1'b0;
end else begin
if(rout[15] == 1'b1 && rout[14] == 1'b1) begin
vsync_reg1 <= 1'b1;
end else if (data_valid1 == 1'b1)begin
vsync_reg1 <= 1'b0;
vsync_reg <= 1'b0;
end
vsync_reg <= vsync_reg1;
end
end
always@(posedge rclk) begin
if(~rst_n) begin
data_reg <= 8'b0;
end else begin
if(rout[12:1] > offset)begin
if(rout[12:1] - offset > 8'd255)
data_reg <= 8'd255;
else
data_reg <= rout[12:1] - offset;
end else begin
data_reg <= 8'b0;
end
end
end
always@(posedge rclk) begin
if(~rst_n) begin
cnt <= 9'b0;
end else begin
if(cnt == 324 || rout[15] == 1'b1)begin
cnt <= 9'b0;
end else begin
cnt <= cnt + 1'b1;
end
end
end
always@(posedge rclk) begin
if(~rst_n) begin
hsync_reg <= 1'b0;
hsync_reg1 <= 1'b0;
end else begin
if(rout[15] == 1'b1 && rout[14] == 1'b0 && rout[9] == 1'b0) begin
hsync_reg1 <= 1'b1;
end else if(cnt == 324)begin
hsync_reg <= 1'b0;
hsync_reg1 <= 1'b0;
end else begin
hsync_reg <= hsync_reg1;
end
end
end
endmodule
TOP模块主要在前期调试时生成一些测试代码,调好后把测试代码删除基本就没什么内容了。
module top(
input rst_n,
input rclk,
input [15:0]rout,
output pixck,
output vsync,
output hsync,
output [7:0]data
);
ds90c124 ds90c124_ins(
.rst_n(rst_n),
.rclk(rclk),
.rout(rout),
.vsync(vsync),
.hsync(hsync),
.data(data)
);
assign pixck = rclk;
endmodule
因为这个STM32H7的显示屏分辨率比较高(800x472),热成像是324*256没做放大处理看起来有点小。
板子上还是使用了大量的飞线,因为速率比较低(5MHz)显示324*256 30fps数据没受影响。
STM32的DCMI使用的是30*0.5的FPC接口,我在网上买了一个FPC到2.54的转接板这样就可以将GW1N和STM32连接。
我这几天在外地没带示波器这类的工具过来,实际测试时遇到一个问花了很长时间才找到问题,原因是商家赠送了一个小锡珠正好夹在2条数据线中间,造成短路。
现在不确定GW1N的芯片在哪能买到,如果能买到芯片画个板玩起来就更方便了。
|