ZYNQ 7020 之 FPGA知识点重塑笔记一——串口通信

news2025/1/24 8:34:16

目录

一:串口通信简介

二:三种常见的数据通信方式—RS232串口通信

2.1 实验任务

2.2 串口接收模块的设计

2.2.1 代码设计

2.3 串口发送模块的设计

2.3.1 代码设计

2.4 顶层模块编写

2.4.1 代码设计

2.4.2 仿真验证代码

2.4.3 仿真结果

2.4.4 板上验证

一:串口通信简介

       通信方式一般分为串行通信并行通信并行通信是指多比特数据同时通过并行线进行传送。这种传输方式通信线多、成本高,故不宜进行远距离通信,通常传输距离小于 30 米。串行通信是指数据在一条数据线上,一比特接一比特地按顺序传送的方式。这种运输方式通常节省传输线,大大降低使用成本,但数据传送速度慢。综上可知,串行通信主要应用于长距离、低速率的通信场合。本次实验我们主要讲解下串行通信。

       串行通信一般有 2 种通信方式: 同步串行通信 异步串行通信 同步串行通信需要通信双方在同一时钟的控制下同步传输数据; 异步串行通信是指具有不规则数据段传送特性的串行数据传输。在常见的通信总线协议中,I2C,SPI 属于同步通信而 UART 属于异步通信。同步通信的通信双方必须先建立同步,即双方的时钟要调整到同一个频率,收发双方不停地发送和接收连续的同步比特流。异步通信在发送字符时,发送端可以在任意时刻开始发送字符,所以,在 UART 通信中,数据起始位和停止位是必不可少的。
       UART 串口通信需要两根信号线来实现,一根用于串口发送,另外一根负责串口接收,如下图所示。对于 PC 来说它的 TX 要和对于 FPGA 来说的 RX 连接,同样 PC RX 要和 FPGA TX 连接,如果是两个TX 或者两个 RX 连接那数据就不能正常被发送出去或者接收到。
          
UART 在发送或接收过程中的一帧数据由 4 部分组成,起始位、数据位、奇偶校验位和停止位,如下图所示。
           
起始位:当不传输数据时,UART 数据传输线通常保持高电平。若要开始数据传输,发送 UART 会将传输线从高电平拉到低电平并保持 1 个波特率周期。当接收 UART 检测到高到低电压跃迁时,便开始以波特率对应的频率读取数据帧中的位。
数据帧: 数据帧包含所传输的实际数据。如果使用奇偶校验位,数据帧长度可以是 5 位到 8 位。如果不使用奇偶校验位,数据帧长度可以是 9 位。在很多情况下,数据以最低有效位优先发送。
奇偶校验:奇偶性描述数字是偶数还是奇数。通过奇偶校验位,接收 UART 判断传输期间是否有数据发生改变。
停止位 为了表示数据包结束,发送 UART 将数据传输线从低电压驱动到高电压并保持 1 2 位时间。
波特率:即每秒传输的位数 (bit) 。一般选波特率都会有 9600 19200 115200等选项。其实意思就是每秒传输这么多个比特位数(bit)

二:三种常见的数据通信方式—RS232串口通信

rs232通信: RS-232 是单端输入输出,
RS-232 标准的串口最常见的接口类型为 DB9 ,样式如图 27.1.3 所示,工业控制领域中用到的工控机 一般都配备多个串口,很多老式台式机也都配有串口。但是笔记本电脑以及较新一点的台式机都没有串 口,它们一般通过 USB 转串口线(下图所示 )来实现与外部设备的串口通信。
         
DB9 接口定义以及各引脚功能说明如下图所示,我们一般只用到其中的 2 RXD )、 3 TXD )、 5 (GND)引脚,其他引脚在普通串口模式下一般不使用,如果大家想了解,可以自行百度下。
       

2.1 实验任务

      本节实验任务是上位机通过串口调试助手发送数据给zynq开发板,zynq开发板 PL 端通过 USB     
_UART 串口接收数据并将接收到的数据发送给上位机,完成串口数据环回实验。主要模块如下表所示:

2.2 串口接收模块的设计

      首先完成串口接收模块的设计,串口接收模块我们的输入信号主要有系统时钟信号、系统复位信号与串口接收端口。当我们将一帧的数据接收完成后,那么要告诉下级模块已经将一帧数据接收完了,所以输出为接收完成标志和串口接收数据信号。 模块接口框图如下所示:
                   
串口接收模块端口与功能描述如下表所示:
绘制波形图:
在绘制波形图之前,我们首先要确定串口通信的数据格式及波特率。在这里我们选择串口比较常用的 一种模式,数据位为 8 位,停止位为 1 位,无校验位,波特率为 115200bps 。则传输一帧数据的时序图如下图所示:

2.2.1 代码设计

//串转并
module zdyz_rs232_rx(
    input sys_clk , //系统时钟
    input sys_rst_n , //系统复位,低有效
    
    input uart_rxd , //UART 接收端口
    output reg uart_rx_done, //UART 接收完成信号
    output reg [7:0] uart_rx_data //UART 接收到的数据
);

parameter CLK_FREQ = 5000_0000; //系统时钟频率
parameter UART_BPS = 115200 ; //串口波特率
localparam BAUD_CNT_MAX = CLK_FREQ/UART_BPS; //为得到指定波特率,对系统时钟计数 BPS_CNT 次

reg uart_rxd_d0;
reg uart_rxd_d1;//定义两个D触发器进行异步打拍处理
reg rx_flag ; //接收过程标志信号
reg [3:0] rx_cnt ; //接收数据位计数器    
reg [15:0] baud_cnt ; //波特率计数器(位宽为16,防止溢出)
reg [7:0 ] rx_data_t ; //接收数据寄存器

wire start_flag;//开始接收的标志,下降沿到来。
    
//打两拍:波特率时钟和系统时钟不同步,为异步信号,所以要进行打拍处理,防止产生亚稳态  
always @(posedge sys_clk or negedge sys_rst_n) begin
    if(!sys_rst_n) begin
        uart_rxd_d0 <= 1'b0;
        uart_rxd_d1 <= 1'b0;
    end
    else begin
        uart_rxd_d0 <= uart_rxd;
        uart_rxd_d1 <= uart_rxd_d0;
    end
end  
    
assign start_flag = (uart_rxd_d0 == 0)&&(uart_rxd_d1 == 1);//下降沿到来的表示方法
// rx_flag接收信号的拉高与拉低   
always @(posedge sys_clk or negedge sys_rst_n) begin
    if(!sys_rst_n)
        rx_flag <= 1'b0;
    else if(start_flag) //检测到起始位
        rx_flag <= 1'b1; //接收过程中,标志信号 rx_flag 拉高
    //在停止位一半的时候,即接收过程结束,标志信号 rx_flag 拉低
    else if((rx_cnt == 4'd9) && (baud_cnt == BAUD_CNT_MAX/2 - 1))//rx_flag 要提前拉低,防止其影响下一帧数据的接收
        rx_flag <= 1'b0;
    else
        rx_flag <= rx_flag;
    end 
//波特率的计数器计数逻辑 
always @(posedge sys_clk or negedge sys_rst_n)begin 
    if(!sys_rst_n) 
        baud_cnt <= 0;      
    else if(rx_flag)begin
        if(baud_cnt == BAUD_CNT_MAX - 1)
            baud_cnt <= 0;
        else
            baud_cnt <= baud_cnt + 1;       
    end
    else
        baud_cnt <= 0;
end 
//位计数实现逻辑
always @(posedge sys_clk or negedge sys_rst_n)begin 
    if(!sys_rst_n)
        rx_cnt <= 0;   
    else if(rx_flag)begin
        if(baud_cnt == BAUD_CNT_MAX - 1)
            rx_cnt <= rx_cnt + 1;        
        else
            rx_cnt <= rx_cnt;
    end
    else
        rx_cnt <= 0;//其他情况下都为0,所以不用担心计数超过9,且其计数也不会超过9,当rx_flag为0时就不计数了
end
//根据 rx_cnt 来寄存 rxd 端口的数据
always @(posedge sys_clk or negedge sys_rst_n) begin
    if(!sys_rst_n)
        rx_data_t <= 0;    
    else if(rx_flag)begin   //系统处于接收过程时
        if(baud_cnt == BAUD_CNT_MAX/2 - 1)begin//判断 baud_cnt 是否计数到数据位的中间 
            case(rx_cnt)
                1:rx_data_t[0] <= uart_rxd_d1; //寄存数据的最低位
                2:rx_data_t[1] <= uart_rxd_d1;
                3:rx_data_t[2] <= uart_rxd_d1;
                4:rx_data_t[3] <= uart_rxd_d1;
                5:rx_data_t[4] <= uart_rxd_d1;
                6:rx_data_t[5] <= uart_rxd_d1;
                7:rx_data_t[6] <= uart_rxd_d1;
                8:rx_data_t[7] <= uart_rxd_d1;//寄存数据的高低位
                default:rx_data_t <= rx_data_t; 
            endcase
        end
        else 
            rx_data_t <= rx_data_t;
    end
    else
        rx_data_t <= 0; 
end
//给接收完成信号和接收到的数据赋值    
always @(posedge sys_clk or negedge sys_rst_n)begin 
    if(!sys_rst_n)begin    
        uart_rx_done <= 0;   
        uart_rx_data <= 0;
    end
    //当接收数据计数器计数到停止位,且 baud_cnt 计数到停止位的中间时
    else if((rx_cnt == 4'd9) && (baud_cnt == BAUD_CNT_MAX/2 - 1))begin
        uart_rx_done <= 1; //拉高接收完成信号
        uart_rx_data <= rx_data_t;//并对 UART 接收到的数据进行赋值
    end    
    else begin
        uart_rx_done <= 0; 
        uart_rx_data <= uart_rx_data;     
    end
end    
endmodule

2.3 串口发送模块的设计

串口发送模块我们的输入信号主要有系统时钟信号、系统复位信号以及发送使能信号和待发送数据, 输出信号主要有发送忙状态标志和串口发送端口。模块接口框图如下所示:
串口发送模块端口与功能描述如下表所示:

2.3.1 代码设计

module zdyz_rs232_tx(
   input sys_clk , //系统时钟
   input sys_rst_n , //系统复位,低有效
   input uart_tx_en , //UART 的发送使能(发送是有标志起始时间的,接收是根据下降沿到来就开始进入起始位)
   input [7:0] uart_tx_data, //UART 要发送的数据
   output reg uart_txd , //UART 发送端口 
   output reg uart_tx_busy //发送忙状态信号 
);
   
   //parameter define
   parameter CLK_FREQ = 50000000; //系统时钟频率
   parameter UART_BPS = 115200 ; //串口波特率
   localparam BAUD_CNT_MAX = CLK_FREQ/UART_BPS; //为得到指定波特率,对系统时钟计数 BPS_CNT 次    
    
   reg [7:0] tx_data_t; //发送数据寄存器 
   reg [3:0] tx_cnt ; //发送数据位计数器 
   reg [15:0] baud_cnt ; //波特率计数器 
   
 //当 uart_tx_en 为高时,寄存输入的并行数据(防止发生变化影响发送),并拉高 BUSY 信号  
always @(posedge sys_clk or negedge sys_rst_n) begin   
    if(!sys_rst_n)begin  
        tx_data_t <= 0;   
        uart_tx_busy <= 0;            
    end
    else if(uart_tx_en)begin
        tx_data_t <= uart_tx_data;   
        uart_tx_busy <= 1;
    end
    /*为了确保环回实验的成功,在程序的 36 行我们将 uart_tx_busy 提前 1/16 个停止位拉低。尽管串口发送数据只是接收数据的反过程,
    理论上在传输的时间上是一致的,但是考虑到我们模块里计算波特率会有较小的偏差,并且串口对端的通信设备(如电脑等)收发数据的波特率
    同样可能会出现较小的偏差,因此为了确保环回实验的成功,这里将发送模块的停止位略微提前结束。需要说明的是,较小偏差的波特率在
    串口通信时是允许的,同样可以保证数据可靠稳定的传输*/
else if((tx_cnt == 4'd9) && (baud_cnt == BAUD_CNT_MAX - BAUD_CNT_MAX/16))begin
        uart_tx_busy <= 0; 
        tx_data_t <= 0;
    end
else begin
        uart_tx_busy <= uart_tx_busy; 
        tx_data_t <= tx_data_t;    
    end         
end 

//波特率的计数器计数逻辑
always @(posedge sys_clk or negedge sys_rst_n)begin 
    if(!sys_rst_n) 
        baud_cnt <= 0;      
    else if(uart_tx_busy)begin //当处于发送过程时,波特率计数器(baud_cnt)进行循环计数
        if(baud_cnt == BAUD_CNT_MAX - 1)
            baud_cnt <= 0; //计数达到一个波特率周期后清零
        else
            baud_cnt <= baud_cnt + 1;       
    end
    else
        baud_cnt <= 0;//发送过程结束时计数器清零
end
//位计数实现逻辑
always @(posedge sys_clk or negedge sys_rst_n)begin 
    if(!sys_rst_n)
        tx_cnt <= 0;   
    else if(uart_tx_busy)begin//处于发送过程时 tx_cnt 才进行计数
        if(baud_cnt == BAUD_CNT_MAX - 1)//当波特率计数器计数到一个波特率周期时
            tx_cnt <= tx_cnt + 1;   //发送数据计数器加 1     
        else
            tx_cnt <= tx_cnt;
    end
    else
        tx_cnt <= 0;//其他情况下都为0,所以不用担心计数超过9,且其计数也不会超过9,当rx_flag为0时就不计数了
end

//根据 tx_cnt 来给 uart 发送端口赋值
always @(posedge sys_clk or negedge sys_rst_n)begin 
    if(!sys_rst_n)
        uart_txd <= 1 ;//空闲态为1
    else if(uart_tx_busy)begin
        case(tx_cnt)
            4'd0 : uart_txd <= 1'b0 ; //起始位
            4'd1 : uart_txd <= tx_data_t[0]; //数据位最低位
            4'd2 : uart_txd <= tx_data_t[1];
            4'd3 : uart_txd <= tx_data_t[2];
            4'd4 : uart_txd <= tx_data_t[3];
            4'd5 : uart_txd <= tx_data_t[4];
            4'd6 : uart_txd <= tx_data_t[5];
            4'd7 : uart_txd <= tx_data_t[6];
            4'd8 : uart_txd <= tx_data_t[7]; //数据位最高位
            4'd9 : uart_txd <= 1'b1 ; //停止位            
            default:uart_txd <= 1'b1 ;
        endcase
    end
    else
        uart_txd <= 1 ; //空闲时发送端口为高电平
end 
endmodule 

2.4 顶层模块编写

       在顶层模块中完成了对其余各个子模块的例化。本次实验我们需要设置 2 个参数变量,分别是系统时钟频率 CLK_FREQ 与串口波特率 UART_BPS ,大家使用时可以根据不同的系统时钟频率以及所需要的串口波特率设置这两个变量。zynq7020开发板上的系统时钟为 50MHz ,所以这里将 CLK_FREQ 参数设为50000000。在前文我们说过本次实验的波特率设为 115200 ,所以这里的参数 UART_BPS 就设为 115200 。我们可以尝试将串口波特率 UART_BPS 设置为其他值(如 9600 ),在模块例化时会将这个变量传递到串口接收与发送模块中,从而实现不同速率的串口通信。

2.4.1 代码设计


module top_uart(
    input sys_clk , //外部 50MHz 时钟
    input sys_rst_n, //系外部复位信号,低有效
    
    //UART 端口 
    input uart_rxd , //UART 接收端口(串行数据)
    output uart_txd //UART 发送端口
    );
    
    parameter CLK_FREQ = 50000000; //定义系统时钟频率
    parameter UART_BPS = 115200 ; //定义串口波特率
   
    //wire define
    wire uart_rx_done; //UART 接收完成信号
    wire [7:0] uart_rx_data; //UART 接收数据(并行数据)
    wire uart_tx_busy;
 //*****************************************************
 //**                      main code
 //***************************************************** 
 //串口接收
   zdyz_rs232_rx #(
       .CLK_FREQ (CLK_FREQ),
       .UART_BPS (UART_BPS)
   )zdyz_rs232_rx(
    .sys_clk(sys_clk) , //系统时钟
    .sys_rst_n(sys_rst_n) , //系统复位,低有效
    
    .uart_rxd(uart_rxd) , //UART 接收端口
    .uart_rx_done(uart_rx_done), //UART 接收完成信号
    .uart_rx_data(uart_rx_data)//UART 接收到的数据
); 
    
   zdyz_rs232_tx #(
       .CLK_FREQ (CLK_FREQ),
       .UART_BPS (UART_BPS)
   )zdyz_rs232_tx(
   .sys_clk(sys_clk) , //系统时钟
   .sys_rst_n(sys_rst_n) , //系统复位,低有效
   .uart_tx_en(uart_rx_done) , //UART 的发送使能
   .uart_tx_data(uart_rx_data), //UART 要发送的数据
   .uart_txd(uart_txd) , //UART 发送端口 
   .uart_tx_busy(uart_tx_busy) //发送忙状态信号 
); 
    
endmodule

2.4.2 仿真验证代码

 `timescale 1ns/1ns //仿真的单位/仿真的精度
 
 module tb_uart_loopback();
 
//parameter define
parameter CLK_PERIOD = 20;//时钟周期为 20ns

//reg define
 reg sys_clk ; //时钟信号
 reg sys_rst_n; //复位信号
 reg uart_rxd ; //UART 接收端口

 //wire define
 wire uart_txd ; //UART 发送端口

 //*****************************************************
 //** main code
 //*****************************************************

 //发送 8'h55 8'b0101_0101
 initial begin
 sys_clk <= 1'b0;
 sys_rst_n <= 1'b0;
 uart_rxd <= 1'b1;
 #200
 sys_rst_n <= 1'b1; 
 #1000
 uart_rxd <= 1'b0; //起始位
 #8680

 uart_rxd <= 1'b1; //D0
 #8680
 uart_rxd <= 1'b0; //D1
 #8680
 uart_rxd <= 1'b1; //D2
 #8680
 uart_rxd <= 1'b0; //D3
 #8680
 uart_rxd <= 1'b1; //D4
 #8680
 uart_rxd <= 1'b0; //D5
 #8680
 uart_rxd <= 1'b1; //D6
 #8680
 uart_rxd <= 1'b0; //D7 
 #8680
 uart_rxd <= 1'b1; //停止位
 #8680
 uart_rxd <= 1'b1; //空闲状态 
 end

 //50Mhz 的时钟,周期则为 1/50Mhz=20ns,所以每 10ns,电平取反一次
 always #(CLK_PERIOD/2) sys_clk = ~sys_clk;

 //例化顶层模块
 top_uart top_uart(
     .sys_clk (sys_clk ),
     .sys_rst_n (sys_rst_n),
     .uart_rxd (uart_rxd ),
     .uart_txd (uart_txd )
 );

 endmodule

2.4.3 仿真结果

2.4.4 板上验证

        上述程序已经经过板上验证了,代码正确,注意若发送和接受都选择了16进制的话,那么就输入0~F,如果不选择16进制的话,就可以任意输入阿拉伯数字和26个字母。

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

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

相关文章

小信跳房子的题解

原题描述&#xff1a; 时间&#xff1a;1s 空间&#xff1a;256M 题目描述&#xff1a; 小信在玩跳房子游戏&#xff0c;已知跳房子游戏的图表现为一颗完美的具有个节点的二叉树。从根节点依次编号为。节点的左子节点编号为&#xff0c;右子节点编号为。 小信从从节点出发&…

万字盘点 Android 领域在 2023 年的重要技术:AI, 14, Compose, 鸿蒙...

AICore 2022 年底横空出世的 GPT-3.5 引发了全球的大模型 LLM 狂潮。作为在 AI 领域耕耘多年的巨头&#xff0c;Google 自然不会坐视不管&#xff0c;于 2023 年底之际发布了超越 GPT-4 的 Gemini 系列模型&#xff0c;其在多模态领域的表现令无数人震撼。 而对于 Android 开发…

接口自动化测试实战经验分享(附教程)

作为测试&#xff0c;你可能会对以下场景感到似曾相识&#xff1a;开发改好的 BUG 反复横跳&#xff1b;版本兼容逻辑多&#xff0c;修复一个 BUG 触发了更多 BUG&#xff1b;上线时系统监控毫无异常&#xff0c;过段时间用户投诉某个页面无数据&#xff1b;改动祖传代码时如履…

HTML教程(1)——概述和第一个网页

一、什么是HTML HTML 是用来描述网页的一种语言。 HTML 指的是超文本标记语言 (Hyper Text Markup Language)HTML 不是一种编程语言&#xff0c;而是一种标记语言 (markup language)标记语言是一套标记标签 (markup tag)HTML 使用标记标签来描述网页 二、什么是HTML 标签 H…

你真的懂Hello World!吗?(编译与链接,静态链接与动态链接)

&#x1f4ab;Hello World! 对于大家来说Hello World!应该是最熟悉不过的一句话&#xff0c;我们从Hello World!走进了计算机的世界&#xff0c;但是你真的了解Hello World!吗&#xff1f;你又思考过它背后蕴含的机理吗&#xff1f;他是怎么从代码变成程序的你真的思考过吗&…

LINUX 抓包工具Tcpdump离线安装教程

本次教程基于内网环境无法访问网络使用安装包进行安装抓包工具 1、首先给大家看下一共有6个安装包&#xff0c;依次进行解压&#xff0c;包我就放到csdn上了&#xff0c;需要的可以联系我进行下载 2打包然后传到服务器任意一个目录下&#xff0c;进入到当前目录&#xff0c;然后…

第11章 访问维护

上一章讨论了在目标主机上提升权限的方法。本章将介绍在滲透测试过程的最后一个环节&#xff0c;即帮助我们随时进入目标主机的方法。 在完成了提升权限的阶段性工作之后&#xff0c;我们应当建立一种机制&#xff0c;以维持对目标主机的控制权。这样一来&#xff0c;即使我们…

GPT3.5 改用 GPT4 价格翻了30倍 如何破局? GPT 对话成本推演

场景介绍 假设你搭建了一个平台&#xff0c;提供 ChatGPT 3.5 的聊天服务。目前已经有一批用户的使用数据&#xff0c;想要测算一下如果更换 GPT 4.0 服务需要多少成本&#xff1f; 方案阐述 如果是全切&#xff0c;最简单粗暴的方案就是根据提供 ChatGPT 3.5 消费的金额乘…

Rust学习笔记004:Rust的所有权机制

内存相关的基础知识 不同语言的内存管理系统 栈和堆 堆和栈的使用 引出所有权方案 String类型 Rust 的所有权机制 Rust 的所有权机制是一种内存管理系统&#xff0c;它允许在编译时通过所有权、借用和生命周期来确保内存安全&#xff0c;同时避免了垃圾回收的运行时开销。这些…

2023-12-21 LeetCode每日一题(美丽塔 II)

2023-12-21每日一题 一、题目编号 2866. 美丽塔 II二、题目链接 点击跳转到题目位置 三、题目描述 给你一个长度为 n 下标从 0 开始的整数数组 maxHeights 。 你的任务是在坐标轴上建 n 座塔。第 i 座塔的下标为 i &#xff0c;高度为 heights[i] 。 如果以下条件满足&a…

软件工程PPT 笔记摘录(2)

分析软件需求 UML 提供了用例图来分析和描述用例视角的软件需求模型 UML 提供了交互图和状态图来描述行为视角的软件需求模型 UML 提供了类图来描述和分析业务领域的概念模型 顺序图&#xff1a;强调消息传递的时间序 通信图&#xff1a;突出对象间的合作 类图&#xff0…

【SAP-FICO】--总账标识配置路径OBXR

FICO业务需求&#xff1a; F-02&#xff0c;财务会计凭证填写09客户A时&#xff0c;带出的总账标识为可编辑。 需求截图&#xff1a; 第一步&#xff1a;了解需求 首先&#xff0c;我们要明白&#xff0c;财务凭证生成&#xff0c;是分多种类型&#xff08;不同类型的凭证&a…

【深度学习:Few-shot learning】理解深入小样本学习中的孪生网络

【深度学习&#xff1a;Few-shot learning】理解深入小样本学习中的孪生网络 深入理解孪生网络&#xff1a;架构、应用与未来展望小样本学习的诞生元学习小样本学习孪生网络的基本概念孪生网络的细节Triplet Loss架构特点关键组件训练过程主要应用领域未来展望示例图片结论 备注…

[JS设计模式]Prototype Pattern

Prototype pattern Prototype pattern可便于同类型的多个对象共享属性。原型&#xff08;prototype&#xff09;是JS原生的对象&#xff0c;其他对象可以通过原型链&#xff08;prototype chain&#xff09;来访问原型。单独看这句描述可能还是有点儿抽象&#xff0c;下面通过…

【HarmonyOS】ArkTS语言介绍与组件方式运用

从今天开始&#xff0c;博主将开设一门新的专栏用来讲解市面上比较热门的技术 “鸿蒙开发”&#xff0c;对于刚接触这项技术的小伙伴在学习鸿蒙开发之前&#xff0c;有必要先了解一下鸿蒙&#xff0c;从你的角度来讲&#xff0c;你认为什么是鸿蒙呢&#xff1f;它出现的意义又是…

OSG绘制视锥体

最近要来实现一个相机位姿态可视化的需求&#xff0c;不想使用pangolin&#xff0c;不好集成&#xff0c;想用osg来做可视化。以下是demo效果。 代码实现&#xff1a; // Cone_of_vision.cpp : 定义控制台应用程序的入口点。 //#include "stdafx.h" #include <os…

Angular进阶之六:Progressive rendering

简介 Progressive Rendering 是一种提高 Web 应用性能的方法&#xff0c;允许页面在加载过程中逐步呈现&#xff0c;以提高用户体验。在本文中&#xff0c;我们将探讨如何在 Angular 中通过自定义指令实现 Progressive Rendering&#xff0c;特别是处理从服务器获取大量数据的…

PAT 乙级 1046 划拳

划拳是古老中国酒文化的一个有趣的组成部分。酒桌上两人划拳的方法为&#xff1a;每人口中喊出一个数字&#xff0c;同时用手比划出一个数字。如果谁比划出的数字正好等于两人喊出的数字之和&#xff0c;谁就赢了&#xff0c;输家罚一杯酒。两人同赢或两人同输则继续下一轮&…

数据预处理时,怎样处理类别型特征?

1. 序号编码 序号编码通常用于处理类别间具有大小关系的数据。例如成绩&#xff0c;可以分为低、中、高三档&#xff0c;并且存在“高>中>低”的排序关系。序号编码会按照大小关系对类别型特征赋予一个数值ID&#xff0c;例如高表示为3、中表示为2、低表示为1&#xff0…

【网络安全 | MD5截断比较】PHP、Python脚本利用

前言 在解题中&#xff0c;当遇到类似 substr(md5(a),-6,6) 7788这样的MD5截断比较的题目时&#xff0c;只有求出a的值才能进行接下来的操作。 一个一个去猜是不可能的&#xff0c;通常使用脚本解决&#xff0c;文末给出实战案例。 PHP循环脚本 <?phpfor($i1;$i<9…