FPGA-串口接收图像写入RAM并读出在TFT显示屏上显示

news2025/1/19 7:12:23

系统框图:

需要用到的模块有:

1,UART_RX(串口接收模块);

2,串口接受的数据存放到RAM模块;

3,RAM IP核;

4,时钟IP核 (TFT显示屏驱动时钟的产生);

5,TFT显示驱动模块;

1,UART_RX(串口接收模块)

具体构建方式及详见(其中的串口接收部分)

FPGA-UART串口icon-default.png?t=N7T8https://blog.csdn.net/weixin_46897065/article/details/135586405?spm=1001.2014.3001.5502

2,串口接受的数据存放到RAM模块

串口接受的数据存放到RAM的逻辑时序图如下:

然后编辑控制器逻辑代码:

module img_rx_wr(
    Clk        ,
    Reset_n    ,
    rx_data    ,
    rx_done    ,
    ram_wren   ,
    ram_eraddr ,
    ram_wrdata ,
    led        
    );
    input                  Clk        ;
    input                  Reset_n    ;
    input        [7:0]     rx_data    ;
    input                  rx_done    ;
    output reg             ram_wren   ;
    output reg  [15:0]     ram_eraddr ;
    output      [15:0]     ram_wrdata ;
    output reg             led        ;
    
    reg[16:0]data_cnt;    //统计串口接收数据个数计数器
    always@(posedge Clk or negedge Reset_n)
    if(!Reset_n)
        data_cnt <= 0;
    else if(rx_done)
        data_cnt <= data_cnt + 1'd1;
        

    
    reg [15:0]rx_data_temp; 
    always@(posedge Clk or negedge Reset_n)
    if(!Reset_n)
        rx_data_temp <= 1'b0;
    else if(rx_done)
        rx_data_temp <= {rx_data_temp[7:0],rx_data};
    
    always@(posedge Clk or negedge Reset_n)
    if(!Reset_n)
        ram_wren <= 0;
    else if(rx_done && data_cnt[0])
        ram_wren <= 1'd1;
    else
        ram_wren <= 0;
        
    always@(posedge Clk or negedge Reset_n)
    if(!Reset_n)        
        ram_eraddr <= 0;
    else if (rx_done && data_cnt[0])
        ram_eraddr <= data_cnt[16:1];  // data_cnt/2
    
    
    assign ram_wrdata = rx_data_temp;
        
    always@(posedge Clk or negedge Reset_n)
    if(!Reset_n)
        led <= 0;
    else if((rx_done)&&(data_cnt == 131071))
        led <= ~led ;  
endmodule

测试此逻辑代码的正确性:

编写测试文件:

`timescale 1ns / 1ps
module img_rx_wr_tb;
    reg              Clk        ;
    reg              Reset_n    ;
    reg    [7:0]     rx_data    ;
    reg              rx_done    ;
    wire             ram_wren   ;
    wire  [15:0]     ram_eraddr ;
    wire  [15:0]     ram_wrdata ;
    wire             led        ;
    
    img_rx_wr img_rx_wr(
        .Clk       (Clk       ) ,
        .Reset_n   (Reset_n   ) ,
        .rx_data   (rx_data   ) ,
        .rx_done   (rx_done   ) ,
        .ram_wren  (ram_wren  ) ,
        .ram_eraddr(ram_eraddr) ,
        .ram_wrdata(ram_wrdata) ,
        .led       (led       ) 
        );
        
    initial Clk =1;
    always #10 Clk = ~Clk;
    initial begin
        Reset_n = 0;
        rx_data = 0;
        rx_done = 0;
        #201;
        Reset_n = 1;
        #2000;
        rx_data = 8'd255;
        repeat(131072)begin
            rx_done = 1;
            #20;
            rx_done = 0;
            #200;
            rx_data = rx_data - 1;
        end
        #2000000;
        
        repeat(131072)begin
            rx_done = 1;
            #20;
            rx_done = 0;
            #200;
            rx_data = rx_data - 1;
        end
        $stop;
             
    end

    
endmodule

仿真波形如下:

写入第一个数据时:

写入最后一个数据时:

RAM写逻辑已经完成,接下来完成RAM的读逻辑。

3,构建RAM IP核

具体构建方式及其内部参数详见FPGA-学会使用vivado中的存储器资源RAM(IP核)icon-default.png?t=N7T8https://blog.csdn.net/weixin_46897065/article/details/136325283?spm=1001.2014.3001.5502

4,TFT显示屏驱动时钟产生

具体构建方式详见:

FPGA-时钟管理单元icon-default.png?t=N7T8https://blog.csdn.net/weixin_46897065/article/details/136356331?spm=1001.2014.3001.5502

5,TFT显示驱动模块

具体原理详见

FPGA- RGB_TFT显示屏原理及驱动逻辑icon-default.png?t=N7T8https://blog.csdn.net/weixin_46897065/article/details/136401589?spm=1001.2014.3001.5502      以及FPGA-VGA成像原理与时序icon-default.png?t=N7T8https://blog.csdn.net/weixin_46897065/article/details/136386813?spm=1001.2014.3001.5502

在以上链接中介绍的TFT显示逻辑其中使用的组合逻辑,为了使得整体得到更好的时序性(RAM得出地址后数据输出是有延迟时,后面使用时为了确保数据一个都不丢,进行时序对齐)将链接中的逻辑代码重新设计,如下:

`include "disp_parameter_cfg.v" 
//800x480
//H_Right_Borde = 0      V_Bottom_Bord   =  8
//H_Front_Porch = 40     V_Front_Porch   =  2
//H_Sync_Time   = 128    V_Sync_Time     =  2
//H_Back_Porch  = 88     V_Back_Porch    =  25
//H_Left_Border = 0      V_Top_Border    =  8
//H_Data_Time   = 800    V_Data_Time     =  480
//H_Total_Time  = 1056   V_Total_Time    =  525

module TFT_Ctrl(
    Clk_33M   ,
    Reset_n   ,
    Data_in   ,
    Data_req  ,
    hcount    ,   //行扫描位置(显示图像行扫描地址)
    vcount    ,   //场扫描位置(显示图像场扫描地址)
    TFT_HS    ,   //行同步信号
    TFT_VS    ,   //场同步信号
    TFT_DE   ,   //有效数据输出 
    TFT_CLK   ,   
    TFT_DATA ,     //红绿蓝三色 分别8位量化 R[7:0]G[7:0]B[7:0]  
    TFT_BL
    );
    input                Clk_33M;
    input                Reset_n;
    input   [15:0]       Data_in;
    output  reg          Data_req;
    output  reg [11:0]   hcount;
    output  reg [11:0]   vcount;
    output               TFT_HS;
    output               TFT_VS;
    output               TFT_DE;
    output               TFT_CLK;
    output  reg [15:0]   TFT_DATA;  //红绿蓝三色 分别8位量化 R[7:0]G[7:0]B[7:0]  
    output               TFT_BL;
//    parameter  VGA_HS_end = 11'd127  ,
//                hdat_begin = 11'd216  ,
//                hdat_end   = 11'd1016 ,
//                hpixel_end = 11'd1055 ,
//                VGA_VS_end = 11'd1    , 
//                vdat_begin = 11'd35   ,
//                vdat_end   = 11'd515  ,
//                vline_end  = 11'd524  ;
    parameter TFT_HS_end = `H_Sync_Time-1  ;
    parameter hdat_begin = `H_Sync_Time + `H_Back_Porch +`H_Left_Border - 1'b1;
    parameter hdat_end = `H_Total_Time - `H_Right_Border -`H_Front_Porch - 1'b1;
    parameter vdat_begin = `V_Sync_Time + `V_Back_Porch +`V_Top_Border - 1'b1;
    parameter vdat_end = `V_Total_Time - `V_Bottom_Border -`V_Front_Porch - 1'b1;    
    parameter hpixel_end = `H_Total_Time -1 ;
    parameter TFT_VS_end = `V_Sync_Time-1  ;     
    parameter vline_end  = `V_Total_Time -1 ; 
                
    reg [11:0] hcount_r;
    reg [11:0] vcount_r;
    
    always@(posedge Clk_33M or negedge Reset_n)
    if(!Reset_n)
       hcount_r <= 11'd0; 
    else if(hcount_r == hpixel_end )
        hcount_r <= 11'd0;
    else
        hcount_r <= hcount_r + 1'd1;
        
    always@(posedge Clk_33M or negedge Reset_n)
    if(!Reset_n)
       vcount_r <= 11'd0; 
    else if(hcount_r == hpixel_end) 
            if(vcount_r == vline_end )
                vcount_r <= 11'd0;
            else
                vcount_r <= vcount_r + 1'd1;
    else
        vcount_r <= vcount_r;
    
    always@(posedge Clk_33M)
        Data_req <= ((hcount_r >= hdat_begin) && (hcount_r < hdat_end)&&
                         (vcount_r >= vdat_begin) && (vcount_r < vdat_end)) ? 1'b1 : 1'b0; 
    reg [3:0]TFT_DE_r; 
    always@(posedge Clk_33M) begin
        TFT_DE_r[0] <= Data_req;
        TFT_DE_r[3:1] <= TFT_DE_r[2:0];
    end
    
    assign  TFT_DE = TFT_DE_r[2];    
//    assign  TFT_DE   =  ((hcount_r >= hdat_begin) && (hcount_r < hdat_end)&&
//                         (vcount_r >= vdat_begin) && (vcount_r < vdat_end)) ? 1'b1 : 1'b0;  
  
    always@(posedge Clk_33M) begin
        hcount <= Data_req ? (hcount_r - hdat_begin) : 10'd0;
        vcount <= Data_req ? (vcount_r - vdat_begin) : vcount;
    end
//    assign  hcount   =   TFT_DE ? (hcount_r - hdat_begin) : 10'd0;  
//    assign  vcount   =   TFT_DE ? (vcount_r - vdat_begin) : 10'd0;  
  
    reg [3:0]TFT_HS_r; 
    always@(posedge Clk_33M) begin
        TFT_HS_r[0] <= (hcount_r > TFT_HS_end)? 1'b1 :1'b0; 
        TFT_HS_r[3:1] <= TFT_HS_r[2:0];
    end  
    assign  TFT_HS = TFT_HS_r[2];      
//    assign  TFT_HS   =  (hcount_r > TFT_HS_end)? 1'b1 :1'b0;

    reg [3:0]TFT_VS_r; 
    always@(posedge Clk_33M) begin
        TFT_VS_r[0] <= (vcount_r > TFT_VS_end)? 1'b1 :1'b0; 
        TFT_VS_r[3:1] <= TFT_VS_r[2:0];
    end  
    assign  TFT_VS  = TFT_VS_r[2];   
//    assign  TFT_VS   =  (vcount_r > TFT_VS_end)? 1'b1 :1'b0; 

    always@(posedge Clk_33M) begin
        TFT_DATA <=  (TFT_DE) ? Data_in : 16'h0000;    
        end
//    assign  TFT_DATA =  (TFT_DE) ? Data_in : 24'h000000;
    assign  TFT_CLK  =  ~Clk_33M;
    assign  TFT_BL = 1;
    
endmodule

6,顶层模块

将以上5个小模块设计好后,根据以下系统框图设计顶层模块。

代码如下:

`timescale 1ns / 1ps
module UART_RAM_TFT(
    Clk, 
    Reset_n,
    uart_rx,
    TFT_RGB,   //TFT数据输出
    TFT_HS,   // TFT行同步信号
    TFT_VS,   //TFT场同步信号
    TFT_DE,   //TFT数据有效信号
    TFT_CLK,
    TFT_BL,   //TFT背光
    led
    );
    input  Clk; 
    input  Reset_n;
    input  uart_rx;
    output [15:0]TFT_RGB;
    output TFT_HS;
    output TFT_VS;
    output TFT_DE;
    output TFT_CLK;
    output TFT_BL;
    output led;
    
//    assign TFT_BL = 1;
    
    reg     [15:0]   ram_rdaddr ;
    wire    [15:0]   ram_rdata  ;
    wire    [7:0]    rx_data    ;
    wire             rx_done    ;
    wire             ram_wren   ;
    wire  [15:0]     ram_eraddr ;
    wire  [15:0]     ram_wrdata ;
    wire             led        ;   
    wire             clk_TFT    ;
//    wire             locked     ;
    
    MMCM MMCM
        (
        // Clock out ports
        .clk_out1(clk_TFT),     // output clk_out1
        // Status and control signals
        .reset(!Reset_n), // input reset
        // Clock in ports
        .clk_in1(Clk));  
  
        
    img_rx_wr img_rx_wr(
        .Clk       (Clk       ) ,
        .Reset_n   (Reset_n   ) ,
        .rx_data   (rx_data   ) ,
        .rx_done   (rx_done   ) ,
        .ram_wren  (ram_wren  ) ,
        .ram_eraddr(ram_eraddr) ,
        .ram_wrdata(ram_wrdata) ,
        .led       (led       ) 
        );
        
    uart_byte_rx uart_byte_rx(
        .Clk     (Clk    )    ,
        .Reset_n (Reset_n)    ,
        .uart_rx (uart_rx)    ,
        .Baud_Set(2      )    ,
        .Data    (rx_data)    ,
        .Rx_done (rx_done)
        ); 

    RAM RAM (
          .clka(Clk),    // input wire clka
          .ena(1),      // input wire ena
          .wea(ram_wren),      // input wire [0 : 0] wea
          .addra(ram_eraddr),  // input wire [15 : 0] addra
          .dina(ram_wrdata),    // input wire [15 : 0] dina
          .clkb(clk_TFT),    // input wire clkb
          .enb(1),      // input wire enb
          .addrb(ram_rdaddr),  // input wire [15 : 0] addrb
          .doutb(ram_rdata )  // output wire [15 : 0] doutb
        ); 


    wire ram_data_en;
    wire Data_req;
    //RAM中存储的数据时256*256的像素矩阵
    always@(posedge clk_TFT or negedge Reset_n)
    if(!Reset_n)
        ram_rdaddr <= 0;
    else if(ram_data_en)
        ram_rdaddr <= ram_rdaddr + 1'd1;
        
    wire [11:0]h_count,v_count;
    wire [15:0]dis_data;
    assign ram_data_en = Data_req && (h_count >= 272 && h_count < 528) && (v_count >= 112 && v_count < 368);
    assign dis_data = ram_data_en ? ram_rdata: 0;
    TFT_Ctrl TFT_Ctrl(
        .Clk_33M (clk_TFT)  ,
        .Reset_n (Reset_n)  ,
        .Data_in (dis_data)  ,
        .Data_req(Data_req)  ,
        .hcount  (h_count)  ,   //行扫描位置(显示图像行扫描地址)
        .vcount  (v_count)  ,   //场扫描位置(显示图像场扫描地址)
        .TFT_HS  (TFT_HS  )  ,   //行同步信号
        .TFT_VS  (TFT_VS  )  ,   //场同步信号
        .TFT_DE  (TFT_DE  ) ,   //有效数据输出 
        .TFT_CLK (TFT_CLK )  ,   
        .TFT_DATA(TFT_RGB) ,     //红绿蓝三色 分别8位量化 R[7:0]G[7:0]B[7:0]  
        .TFT_BL  (TFT_BL  )
        );      
endmodule

为了仿真验证逻辑代码的准确性,我们可以在RAM中提前写入一张256*256大小的图片数据,如下图:

然后编写测试代码,验证逻辑的正确性:

测试代码如下:

`timescale 1ns / 1ps
module UART_RAM_TFT_TB();
    reg   Clk; 
    reg   Reset_n;
    reg   uart_rx;
    wire [15:0]TFT_RGB;
    wire TFT_HS;
    wire TFT_VS;
    wire TFT_DE;
    wire TFT_CLK;
    wire TFT_BL;
    wire led;

    UART_RAM_TFT UART_RAM_TFT(
        .Clk    (Clk    ) , 
        .Reset_n(Reset_n) ,
        .uart_rx(uart_rx) ,
        .TFT_RGB(TFT_RGB) ,   //TFT数据输出
        .TFT_HS (TFT_HS ) ,   // TFT行同步信号
        .TFT_VS (TFT_VS ) ,   //TFT场同步信号
        .TFT_DE (TFT_DE ) ,   //TFT数据有效信号
        .TFT_CLK(TFT_CLK) ,
        .TFT_BL (TFT_BL ) ,   //TFT背光
        .led    (led    )
        );   
    initial Clk = 1;
    always #10 Clk = ~Clk;
    
    initial begin
        Reset_n = 0;
        #201;
        Reset_n = 1;
        #2000;
        #20000000;
        $stop;
    end
endmodule

仿真波形如下:

TFT显示屏开始接收的数据波形图:

TFT显示屏最后接收的数据波形图:

7,总结

在本博客中实现了串口接收图像写入RAM并读出在TFT显示屏上显示的这样一个实验。这个实验中使用的时FPGA中片内RAM,所以只能显示一个256*256大小的图片。如果能够将存储器的容量扩大,比如DDR4存储器,那这个时候就可以用串口传输一整幅图像,就可以将完整图片显示在整个显示屏上去。再其次把串口接收到的数据改为摄像头采集到的实时的数据流,那就可以做一个摄像采集头图像,存储,实时显示的应用。再者,对采集到的图像数据。进行一定的各种滤波算法,检测算法等等,就可以实现图像处理功能。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1496306.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

理解循环神经网络(RNN)

文章目录 1. 引言&#xff1a;什么是RNN以及它的重要性RNN简介RNN在机器学习中的作用和应用场景 2. RNN的工作原理神经网络基础RNN的结构和运作方式循环单元的作用 3. RNN的关键特点与挑战参数共享长期依赖问题门控机制&#xff08;例如LSTM和GRU&#xff09;代码示例&#xff…

【Vue】vue3 在图片上渲染 OCR 识别后的文本框、可复制文本组件

需求 后面返回解析后的文本和四角坐标&#xff0c;在图片上渲染成框&#xff0c;并且可复制。图片还可以缩放、拖拽 实现 这里要重点讲下关于OCR文本框的处理&#xff1a; 因为一些文字可能是斜着放的&#xff0c;所有我们要特殊处理&#xff0c;根据三角函数来计算出它的偏…

openEuler学习——部署MGR集群

本文介绍如何利用GreatSQL 8.0.25构建一个三节点的MGR集群。 1.安装准备 IP端口角色192.168.20.1103306mgr1192.168.20.1113306mgr2192.168.20.1123306mgr3 配置hosts解析 [rootMGR1 ~]# cat >> /etc/hosts << EOF > 192.168.20.110 MGR1 > 192.168.20.1…

小程序商城营业执照办哪种类型的?

在数字化浪潮的推动下&#xff0c;越来越多的商家选择通过微信小程序商城来拓展线上业务。但在启动小程序商城之前&#xff0c;有一项关键性的准备工作不可忽视——那就是营业执照的办理。本文将为您详细解读小程序商城营业执照的办理类型及相关流程步骤&#xff0c;帮助您顺利…

虚拟机时间同步主机

1.查看是否设置同步 2.查看时区 date -R 0800 表示时区东八区 明显不对 执行指令&#xff1a; tzselect &#xff1b;找到亚洲-中国-北京 3.覆盖一下文件 复制文件到 /etc/localtime 目录下&#xff1a;#sudo cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime 4.重现查…

【DAY08 软考中级备考笔记】机组:计算机组成和数据转换

机组&#xff1a;计算机组成和数据转换 3月2日 – 天气&#xff1a;晴 1. 计算机的基本组成结构 计算机的硬件由运算器&#xff0c;控制器&#xff0c;存储器&#xff0c;输入和输出设备组成其中&#xff0c;控制器和运算器成为CPU控制器又分为了内部存储器和外部存储器。内部…

Python与FPGA——膨胀腐蚀

文章目录 前言一、膨胀腐蚀二、Python实现腐蚀算法三、Python实现膨胀算法四、Python实现阈值算法五、FPGA实现腐蚀算法总结 前言 腐蚀是指周围的介质作用下产生损耗与破坏的过程&#xff0c;如生锈、腐烂等。而腐蚀算法也类似一种能够产生损坏&#xff0c;抹去部分像素的算法。…

FX110网:判断行情是真突破还是假突破?用这几招就够了

众所周知&#xff0c;在交易过程中&#xff0c;趋向线的突破对买入、卖出时机等选择具有重要的分析意义。因此&#xff0c;搞清趋势线何时突破&#xff0c;是有效的突破还是非有效的突破&#xff0c;于投资者而言是至关重要的。 本文将提供一些对于趋向线突破的判断方法和市场原…

学习Java的第三天

如何使用IDEA工具编写Java语言 上一节课已经讲过了&#xff0c;如何使用文本文档写出代码并在管理员控制台打印出来 接下来给大家分享的是使用IntelliJ IDEA工具 一、如何将IntelliJ IDEA设置成中文 1、点击右上角的图标&#xff0c;有人的图标会不一样&#xff0c;但位置是…

停工待料,责任真的全在PMC吗?天行健深度剖析背后的原因

在现代制造业中&#xff0c;停工待料的现象时有发生&#xff0c;这不仅影响了生产进度&#xff0c;还增加了企业的运营成本。很多人会自然而然地将责任归咎于生产物料控制&#xff08;PMC&#xff09;部门&#xff0c;认为是他们没有做好物料计划和管理。但事实上&#xff0c;停…

【Web】浅浅地聊SnakeYaml反序列化两条常见利用链

目录 关于Yaml 关于SnakeYaml SnakeYaml反序列化利用 JdbcRowSetImpl链 ScriptEngineManager链 复现 基本原理 继续深入 关于Yaml 学过SpringBoot开发的师傅都知道&#xff0c;YAML和 Properties 文件都是常见的配置文件格式&#xff0c;用于存储键值对数据。 这里举…

公车5.0优化内容

1、首屏加载速度慢&#xff0c;原因是commons重复打包了&#xff0c;删除即可&#xff0c;首屏加载速度提升了10几秒&#xff0c;本地打包速度提升了2分钟 2、删除$dogShanXi重复方法&#xff0c;并全局替换dogShanXi方法 3、Tab打开太多页面卡死&#xff0c;设置最多打开10个 …

2024小红书商家投放策略怎么制定?广告形式有哪些

据平台的消息&#xff0c; 截止2021年11月&#xff0c;小红书月活已达到2亿。其中 有72%为90后&#xff0c;超50%来自一二线城市。如何充分把握好这一趋势&#xff0c;这就需要一些行之有效的小红书投放策略。今天我们和大家分享下2024小红书商家投放策略怎么制定&#xff0c;广…

【C++庖丁解牛】C++内存管理 | new和delete的使用以及使用原理

&#x1f4d9; 作者简介 &#xff1a;RO-BERRY &#x1f4d7; 学习方向&#xff1a;致力于C、C、数据结构、TCP/IP、数据库等等一系列知识 &#x1f4d2; 日后方向 : 偏向于CPP开发以及大数据方向&#xff0c;欢迎各位关注&#xff0c;谢谢各位的支持 目录 1. C/C内存分布2. C语…

Go程序是如何编译并运行起来的(图文详解)

Go程序是如何编译的 从hello RdrB1te开始 package main import "fmt" func main() { fmt.Println("hello RdrB1te") }不实际编译它&#xff0c;只输出它的编译过程&#xff1a; go build -n简单的编译过程分析&#xff1a; 上面的过程确认了两个…

打印机扫描无法识别u盘怎么办?

相信不少朋友经常会有打印或者扫描的经历&#xff0c;特别是用公司的那种硕大的打印机。 打印的时候还好说&#xff0c;扫描的时候就老会出问题。 如果按正常的流程&#xff0c;先把文稿放在面板上&#xff0c;盖上盖儿。然后在控制屏幕上选择扫描&#xff0c;然后插入u盘。正…

查看kafka消息消费堆积情况

查看主题命令 展示topic列表 ./kafka-topics.sh --list --zookeeper zookeeper_ip:2181描述topic ./kafka-topics.sh --describe --zookeeper zookeeper_ip:2181 --topic topic_name查看topic某分区偏移量最大&#xff08;小&#xff09;值 ./kafka-run-class.sh kafka.too…

【格与代数系统】基本概念和性质

【格与代数系统】偏序关系、偏序集与全序集 格 设是一个偏序集&#xff0c;若对任意&#xff0c;的上、下确界都存在&#xff0c;则称是一个格&#xff0c;用表示格。 偏序关系偏序集 偏序集上下确界格 代数系统 若是格&#xff0c;则由格的定义&#xff0c;对任意&#xff0…

EMC测试整改:提升产品合规性和市场竞争力?|深圳比创达电子

在当前的产品研发和制造领域&#xff0c;电磁兼容&#xff08;EMC&#xff09;测试是确保产品符合法规要求并能够在各种电磁环境下正常工作的重要环节。然而&#xff0c;很多企业在进行EMC测试时可能会遇到一些问题和不合格情况&#xff0c;因此需要进行整改来提升产品的合规性…

timezoneinfo的裁剪移植之uclibc/gclibc/openwrt的最详细实战版!

1.需求背景 因为项目需要&#xff0c;产品售卖到国外各个地区&#xff0c;需要能适配各个国家的不同时区&#xff0c;一些国家可能会有多个不同时区&#xff0c;并且还存在冬夏令时问题&#xff0c;都需要做到一次性的兼容。而目前板子上可用的flash空间也已经不足200KB&#…