以太网学习之TCP/IP:PC上位机通过Socket连接下发视频至FPGA的若干总结

VerweileDoch / 2024-02-22 / 原文

笔记:

TCP/IP LWIP FPGA 笔记-CSDN博客

上位机建立TCP/IP连接:Matlab实现-CSDN博客

别人的:

第一个很精炼简单有效,但我是PC发FPGA而不是FPGA发PC,所以也不是那么有用;

Xilinx ZYNQ+TCP通信+Python上位机 实现实时视频传输系统 - 知乎 (zhihu.com)

千兆以太网视频传输 - LeiWang1999 (leiblog.wang)

【开源、应用】QT—TCP网络上位机的设计_qt上位机-CSDN博客

TCP实时视频传输学习记录【附代码】【含视频】_tcp协议传输视频流-CSDN博客

前期搭建使用的Matlab测试代码:

clc;
clear all; 
close all; 
warning off;

% ConfigPacket Frame Packet
ConfigPacket_Length = 14;% 配置包单帧长
ConfigPacket_Content = zeros(1,ConfigPacket_Length,"uint8");% 配置包单帧内容初始化

image_w = 640;
image_h = 512;

Set_ConfigPacket_Content = [8,image_w,image_h,0];% 配置包内容数组
Set_ConfigPacket_Length = length(Set_ConfigPacket_Content);% 配置包总帧长

Readback_ConfigPacket = zeros(Set_ConfigPacket_Length, ConfigPacket_Length, "uint8");

% Data Frame Packet
framehead = uint8([170,170,170,170,170,170,170,170]);% 配置包单帧内容初始化
Data_Line_Buf = zeros(1, image_w * 2,"uint8");


% Set Connection 
Client_1 = tcpclient("192.168.1.10",10000,"Timeout",20,"ConnectTimeout",30);

for j = 1:Set_ConfigPacket_Length 
    for i = 1:ConfigPacket_Length 
        if i <= 8
            ConfigPacket_Content (i) = 85;% Frame Header
        elseif i == 9
            ConfigPacket_Content (i) = j - 1;% addr
        elseif i == 10
            ConfigPacket_Content (i) = 0;% R/W
        elseif i == 11
            ConfigPacket_Content (i) = uint8(bitand((bitshift(Set_ConfigPacket_Content(j),-24)),255));
        elseif i == 12
            ConfigPacket_Content (i) = uint8(bitand((bitshift(Set_ConfigPacket_Content(j),-16)),255));
        elseif i == 13
            ConfigPacket_Content (i) = uint8(bitand((bitshift(Set_ConfigPacket_Content(j),-8)),255));
        elseif i == 14
            ConfigPacket_Content (i) = uint8(bitand((bitshift(Set_ConfigPacket_Content(j),0)),255));
        end
    end  
    % s is a tcp/ip object
    write(Client_1,ConfigPacket_Content)
    pause(0.0001)
    Readback_ConfigPacket(j, 1:end) = read(Client_1, ConfigPacket_Length, "uint8");
end



pause(0.0001);
write(Client_1,framehead);
pause(0.0001);
for n = 1:image_h
    for m = 1:image_w
        Data_Line_Buf(2 * m -1) = 0;
        if n < image_h/4
            Data_Line_Buf(2 * m) = 64;
        elseif n < image_h/2
            Data_Line_Buf(2 * m) = 128;
        elseif n < image_h/2 + image_h/4
            Data_Line_Buf(2 * m) = 192;
        else
            Data_Line_Buf(2 * m) = 255;
        end
    end
    write(Client_1,Data_Line_Buf)
    pause(0.000001);
end
readreq = read(Client_1, 8, "uint8");

clear Client_1;
View Code

整体描述:完成了PC下发图像和读取方式等信息完成配置,通过FPGA收取图像完成处理并HDMI显示;

1.通过上位机软件发送配置包到FPGA PS端,Arm通过解析配置包完成对PL端DMA和HDMI模块的配置,主要配置图像的显示尺寸和其影响的DMA模块读取的数据地址;

  1.1.配置包要自定义合适的包头,并且根据包头解析;

  1.2 此过程中,TCP/IP上位机由于发送过快,难以完成相关任务,而本人暂时没有学好QT,打算之后再进行拓展;

  1.3 为了完成下文中的三帧缓存,每发完一帧需要Arm端接收并且通信FPGA完成读取地址的切换;

  1.4 为了保障读取数据的准确。要使用DCACHE相关函数完成及时的数据刷新;

2.配置好的DMA模块将数据读出,其中DMA模块需要完成三帧缓存以防止撕裂;

 

关于拓展:

上位机在发文件的时候出现了粘包的现象,即头尾文件相连;

为了缓解这个问题,重新写一个上位机是好的选择;

所以我会在近期学习QT进行编写;

而之后可能不会采用TCP完成相关操作,而是通过UDP,这是因为我发现:【正点原子FPGA连载】第四十六章以太网传输视频实验-摘自【正点原子】开拓者 FPGA 开发指南 - 知乎 (zhihu.com)

  这个链接中讲述了UDP传视频的若干好处,我决定投敌,TCP的上位机假若以后我有时间,有能力再写吧。

展示:

 那条线是因为屏幕自身的问题,不是我代码的问题,啥也不干也有线的。