FPGA开发(4)——AXI_LITE总线协议

news2024/11/20 3:18:38

一、AXI总线简介

对于axi总线的学习我主要是参考了赛灵思的ug1037文档以及arm的INI0022D手册,对其中的内容做了总结。在这里插入图片描述
AXI是amba总线的一种,包含三种,axi full、axi lite和axi stream。
在这里插入图片描述
在这里插入图片描述
AXI工作:axi接口包含了五组通道,分别是读地址、写地址、读数据、写数据以及写响应。数据可以在主机和从机中双向传输,AXI4支持最大256突发读写,AXI-lite只不支持突发读写。
在这里插入图片描述
在这里插入图片描述
1、axi支持数据突发传输,读和写通道可同时工作。Axi-lite则不支持突发传输,axi-stream可支持任意突发长度传输
2、其次,axi和axi-lite是地址映射的,axi-stream不是地址映射。Axi和axi-stream还可以结合起来,例如DMA等。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
AXI接口:
1、赛灵思官方本身提供很多带axi接口的ip,有axi、axistream等
2、自行封装带有axi接口的ip,axi协议自动生成,添加DIY代码即可
3、外部添加axi-接口IP
4、HLS
5、axi for dsp
……
在这里插入图片描述
Vivado中axi互联
主要有interconnect和smartconnect,其中smart更精密,inter适用于所有。两种都作为axi ip核与arm axi接口之间转换的功能接口。
Inter和smart都是地址映射,axi-stream无法连接,但是axi-stream可以连接axis-inter,然后转换为地址映射
在这里插入图片描述
Axi互联核心提供1对多、多对1和多对多的接口。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
包含了五组信号,写通道和读通道可以同时进行数据的传输
在这里插入图片描述
1、每一个独立的通道都包含valid和ready这样的握手机制
2、读通道和写通道数据传输最后会有一个last信号
3、读地址和写地址
4、读数据通道,数据支持多种位宽,然后读响应说明读的状态。
5、写数据通道,多种带宽,每个字节信号有一个频闪信号,用来说明数据有效。
6、写响应通道,从机用写响应通道反馈写的状态

二、AXI总线五组接口介绍

在这里插入图片描述
对于写地址通道,有这么一些关键的接口
1、写地址
2、写长度
3、写大小
4、写突发,有三种模式,固定、自增、回环
5、valid
6、ready
在这里插入图片描述
对于写数据通道,有这么一些关键的接口
1、写数据
2、频闪信号,表示数据有效
3、last,表示传输数据最后一个的标志
4、valid
5、ready
在这里插入图片描述
对于写响应通道,有这么一些关键的接口
1、bresp,代表了从机对主机写的回应,判断是否写入成功
2、valid
3、ready
在这里插入图片描述
在这里插入图片描述
读地址和读数据通道,与写相似

三、AXI信号约束

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

信号约束
共用时钟线,上升沿数据采样,在上升沿之后数据才可以变化。
低电平复位,复位时主机控制写地址、读地址和写数据的valid,从机控制读数据和写响应的valid。
在这里插入图片描述
在这里插入图片描述
信号约束
说明了五组信号中valid和ready信号的关系
当源端的数据或者地址或者控制信号有效时,拉高valid信号。然后这个valid信号要一直保持高电平直到ready信号为高并采样为止。
在这里插入图片描述
读地址和读数据的信号先后关系
1、主机arvaild信号不必等从机的arready
2、从机的arready可以等主机的arvalid
3、从机的arready可以先于主机的arvalid
4、从机的rvalid一定要在arvalid和arready之后才出现(重要)
5、从机的rvalid不必等主机的rready
6、主机的rready可以等从机的rvalid
7、主机的rready可以先于从机的rvalid
在这里插入图片描述
写地址和写通道类似前面读的过程
要注意一点,主机valid不要等待从机ready,否则有可能会引发死锁的产生。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在非高带宽应用场景,axi-lite接口是很常用的,比axi4少了很多信号。其有以下的特点:
1、不支持突发传输
2、传输的位宽位32或者64位
3、传输无缓存,不可配置
4、不支持独立访问
这边主要来学习axi-lite协议。

四、AXI-LITE信号时序图

在这里插入图片描述
首先上面这张图是输入信号的时序图。
在这里插入图片描述在这里插入图片描述
上面两张图是我根据看的两个手册画的axi-lite协议的时序图。

五、AXI-LITE的verilog代码

根据上面的时序图写了下述的代码,其内容也很简单就是定义了19组信号。这19个信号分为五组,分别是写地址、写数据、读地址、读数据以及写响应。每一组数据都含有valid和ready信号,基于握手机制传输数据。代码并不复杂,根据时序图就能很快写出来。

module axi_test(
    //aclk and reset_n
    input s_axi_aclk,
    input s_axi_aresetn,
    //write addr
    input [3:0] s_axi_awaddr,
    input [2:0] s_axi_awprot,
    input s_axi_awvalid,
    output s_axi_awready,
    //write data
    input [31:0] s_axi_wdata,
    input [3:0] s_axi_wstrb,
    input s_axi_wvalid,
    output s_axi_wready,
    //write response
    output [1:0] s_axi_bresp,
    output s_axi_bvalid,
    input s_axi_bready,
    //read addr
    input [3:0] s_axi_araddr,
    input [2:0] s_axi_arprot,
    input s_axi_arvalid,
    output s_axi_arready,
    //read data
    output [31:0] s_axi_rdata,
    output [1:0] s_axi_rresp,
    output s_axi_rvalid,
    input s_axi_rready,
    //output signal
    output axi_test
);


//axi4_lite signal
reg [3:0] axi_awaddr;
reg [3:0] axi_araddr;

reg axi_awready;
reg axi_wready;
reg axi_bvalid;
reg [1:0] axi_bresp;
reg axi_arready;
reg axi_rvalid;
reg [31:0] axi_rdata;
reg [1:0] axi_rresp;

//slave registers to save data
reg [31:0] slv_reg0;
reg [31:0] slv_reg1;
reg [31:0] slv_reg2;
reg [31:0] slv_reg3;
reg [31:0] reg_data_out;
reg aw_en;
integer byte_index;
wire slv_reg_rden;
wire slv_reg_wren;

//axi4-lite signal define
assign s_axi_awready=axi_awready;
assign s_axi_wready=axi_wready;
assign s_axi_bvalid=axi_bvalid;
assign s_axi_bresp=axi_bresp;
assign s_axi_arready=axi_arready;
assign s_axi_rdata=axi_rdata;
assign s_axi_rvalid=axi_rvalid;
assign s_axi_rresp=axi_rresp;

//awready signal
//aresetn:0
//~awready & awvalid & wvalid & awen:1
//bready & bvalide:0
//other:0
always @(posedge s_axi_aclk) begin
    if(~s_axi_aresetn)begin
      aw_en<=1'b1;
      axi_awready<=1'b0;
    end
    else begin
      if(~axi_awready && aw_en && s_axi_awvalid && s_axi_wvalid)begin
        aw_en<=1'b0;
        axi_awready<=1'b1;
      end
      else if(s_axi_bready && axi_bvalid)begin
        aw_en<=1'b1;
        axi_awready<=1'b0;
      end
      else begin
        axi_awready<=1'b0;
      end
    end
end

//awaddr signal
//aresetn:0
//~awready & awvalid & wvalid & awen:1
//other:same 
always @(posedge s_axi_aclk) begin
    if(~s_axi_aresetn)begin
      axi_awaddr<=4'd0;
    end
    else begin
      if(~axi_awready && aw_en && s_axi_awvalid && s_axi_wvalid)begin
        axi_awaddr<=s_axi_awaddr;
      end
    end
end

//axi_wready signal 
//aresetn:0
//~awready & awvalid & wvalid & awen:1
//other:0
always @(posedge s_axi_aclk) begin
    if(~s_axi_aresetn)begin
      axi_wready<=1'b0;
    end
    else begin
      if(~axi_awready && aw_en && s_axi_awvalid && s_axi_wvalid)begin
        axi_wready<=1'b1;
      end
      else begin
        axi_wready<=1'b0;
      end
    end
end

//wren signal
//awready && awvalid && wready && wvalid:1
//other:0
assign slv_reg_wren=s_axi_awvalid && s_axi_wvalid && axi_awready && axi_wready;

//write data to reg0 to reg3
always @(posedge s_axi_aclk) begin
    if(~s_axi_aresetn)begin
      slv_reg0<=32'd0;
      slv_reg1<=32'd0;
      slv_reg2<=32'd0;
      slv_reg3<=32'd0;
    end
    else begin
      if(slv_reg_wren)begin
        case(axi_awaddr[3:2])
            //reg0
            2'h0:begin
              for(byte_index=0;byte_index<=3;byte_index=byte_index+1)begin
                if(s_axi_wstrb[byte_index]==1'b1)begin
                  slv_reg0[(byte_index*8) +: 8]<=s_axi_wdata[(byte_index*8) +: 8];
                end
              end
            end
            //reg1
            2'h1:begin
              for(byte_index=0;byte_index<=3;byte_index=byte_index+1)begin
                if(s_axi_wstrb[byte_index]==1'b1)begin
                  slv_reg1[(byte_index*8) +: 8]<=s_axi_wdata[(byte_index*8) +: 8];
                end
              end
            end
            //reg2
            2'h2:begin
              for(byte_index=0;byte_index<=3;byte_index=byte_index+1)begin
                if(s_axi_wstrb[byte_index]==1'b1)begin
                  slv_reg2[(byte_index*8) +: 8]<=s_axi_wdata[(byte_index*8) +: 8];
                end
              end
            end
            //reg3
            2'h3:begin
              for(byte_index=0;byte_index<=3;byte_index=byte_index+1)begin
                if(s_axi_wstrb[byte_index]==1'b1)begin
                  slv_reg3[(byte_index*8) +: 8]<=s_axi_wdata[(byte_index*8) +: 8];
                end
              end
            end
            //no reg 
            default:begin
              slv_reg0<=slv_reg0;
              slv_reg1<=slv_reg1;
              slv_reg2<=slv_reg2;
              slv_reg3<=slv_reg3;
            end
        endcase
      end
    end
end

//breasp and bvalid signal
//aresetn:0
//awready && wready && awvalid && wvalid && ~bvalid:1
//bvalid && bready:1
always @(posedge s_axi_aclk) begin
    if(~s_axi_aresetn)begin
      axi_bvalid<=1'b0;
      axi_bresp<=2'd0;
    end
    else begin
      if(axi_awready && axi_wready && s_axi_wvalid && s_axi_awvalid && ~axi_bvalid)begin
        axi_bvalid<=1'b1;
        axi_bresp<=2'd0;
      end
      else if(s_axi_bready && axi_bvalid)begin
        axi_bvalid<=1'b0;
      end
    end
end

//arready signal 
//araddr save
//arsetn:0
//~arready && arvalid:1
//other:0
always @(posedge s_axi_aclk) begin
    if(~s_axi_aresetn)begin
      axi_arready<=1'b0;
      axi_araddr<=4'd0;
    end
    else begin
      if(~axi_arready && s_axi_arvalid)begin
        axi_arready<=1'b1;
        axi_araddr<=s_axi_araddr;
      end
      else begin
        axi_arready<=1'b0;
      end
    end
end

//rvalid and rresp signal 
//aresetn:0
//arready && arvalid && ~rvalid:1
//rvalid & rready:0
//other:0
always @(posedge s_axi_aclk) begin
    if(~s_axi_aresetn)begin
      axi_rvalid<=1'b0;
      axi_rresp<=2'd0;
    end
    else begin
      if(axi_arready && s_axi_arvalid && ~axi_rvalid)begin
        axi_rvalid<=1'b1;
        axi_rresp<=2'd0;
      end
      else if(axi_rvalid && s_axi_rready)begin
        axi_rvalid<=1'b0;
      end
    end
end

//read data from reg0 to reg3
assign slv_reg_rden=axi_arready && s_axi_arvalid && ~axi_rvalid;
always @(*) begin
    case(axi_araddr[3:2])
        2'h0:reg_data_out<=slv_reg0;
        2'h1:reg_data_out<=slv_reg1;
        2'h2:reg_data_out<=slv_reg2;
        2'h3:reg_data_out<=slv_reg3;
        default:reg_data_out<=32'd0;
    endcase
end

//output data
always @(posedge s_axi_aclk) begin
    if(~s_axi_aresetn)begin
      axi_rdata<=32'd0;
    end
    else begin
      if(slv_reg_rden)begin
        axi_rdata<=reg_data_out;
      end
    end
end

//axi_test
breath_led u_breath_led(
    .sys_clk            ( s_axi_aclk            ),
    .sys_rst_n          ( s_axi_aresetn         ),
    .sw_ctrl            ( slv_reg0[0]           ),
    .set_en             ( slv_reg1[31]          ),
    .set_freq_step      ( slv_reg1[9:0]         ),
    .led                ( axi_test              )
);


endmodule 

六、AXI-LITE测试——ps与pl互通

下面是我的block design,作为参照,我还使用vivado自带封装AXI接口的ip核封装了一个呼吸灯的代码,然后两个IP完成的功能是一样的,都是可以控制呼吸灯的闪烁,然后都可以从ps读取pl寄存器的值。
在这里插入图片描述
下面是我的ps端的C代码,主要完成功能就是对两个IP分别读写寄存器,来控制呼吸灯。还有另外一部分不想关,是我对是个数据的读取个判断,是第三个IP。

#include "math.h"
#include "stdio.h"
#include "breathLED.h"
#include "xparameters.h"
#include "xil_io.h"

//baseaddr define
#define breath_led_baseaddr XPAR_BREATHLED_0_S00_AXI_BASEADDR
#define axi_test_baseaddr XPAR_AXI_TEST_0_BASEADDR
#define axi_num_recog_baseaddr XPAR_AXI_NUM_RECOG_TEST_0_BASEADDR

int main()
{
	//led test signal
	int a1;
	int a2;
	int a1_1;
	int a2_1;
	//data read from PL
	int data[10];
	//data change to double
	double data_lf[10];
	//find max data and cnt
	u32 i;
	u32 cnt;
	double max;
	//calculate the number probability
	double pro_all=0;
	double pro_num[10];

	//led control test
  	Xil_Out32(breath_led_baseaddr+BREATHLED_S00_AXI_SLV_REG0_OFFSET,0x00000001);
  	Xil_Out32(breath_led_baseaddr+BREATHLED_S00_AXI_SLV_REG1_OFFSET,0x80000050);
  	a1=Xil_In32(breath_led_baseaddr+BREATHLED_S00_AXI_SLV_REG0_OFFSET);
  	a2=Xil_In32(breath_led_baseaddr+BREATHLED_S00_AXI_SLV_REG1_OFFSET);
  	Xil_Out32(axi_test_baseaddr+0,0x00000001);
  	Xil_Out32(axi_test_baseaddr+4,0x80000050);
  	a1_1=Xil_In32(axi_test_baseaddr+0);
  	a2_1=Xil_In32(axi_test_baseaddr+4);
  	//data read
  	for(i=0;i<10;i++)
  	{
  		data[i]=Xil_In32(axi_num_recog_baseaddr+i*4);
  	}
  	//data change
  	for(i=0;i<10;i++)
  	{
  		data_lf[i]=data[i];
  	}
  	//find max data and cnt
  	max=data_lf[0];
  	cnt=0;
  	for(i=0;i<10;i++)
  	{
  		if(max<=data_lf[i])
  		{
  			max=data_lf[i];
  			cnt=i;
  		}
  	}
  	Xil_Out32(axi_num_recog_baseaddr+10*4,cnt);
  	//calculate the probability
  	for(i=0;i<10;i++)
  	{
  		data_lf[i]=data_lf[i]/max*10;
  	}
  	for(i=0;i<10;i++)
  	{
  		pro_all=pro_all+exp(data_lf[i]);
  	};
  	for(i=0;i<10;i++)
  	{
  		pro_num[i]=exp(data_lf[i])/pro_all;
  	}

  	printf("breath led test\n");
  	printf("a1=%d\n",a1);
  	printf("a2=%d\n",a2);
  	printf("\n");

  	printf("breath led  DIY test\n");
  	printf("a1_1=%d\n",a1_1);
  	printf("a2_1=%d\n",a2_1);
  	printf("\n");

  	printf("read num data test\n");
  	for(i=0;i<10;i++)
  	{
  	  	printf("data_%d=%d\n",i,data[i]);
  	}
  	printf("\n");

  	printf("output number and probability\n");
  	for(i=0;i<10;i++)
  	{
  		printf("The probability of the number %d is %f\n",i,pro_num[i]);
  	}
  	printf("the number is %d\n",cnt);


	return 0;
}

最终通过串口也可以得到,两个IP可以接收到的数据是一样的。说明自己写的axi-lite接口可以实现ps与pl之间的互通。
在这里插入图片描述

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

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

相关文章

如何快速用一条命令配置好本地yum源(6/7/8版本)

一&#xff0c;挂载ISO安装镜像 挂载方式分两种&#xff1a; 1.上传iso安装镜像到服务器主机的指定目录&#xff0c;比如/setup/os为例 mount -o loop /setup/os/iso镜像包名称 /mnt 2.直接虚拟机或者物理主机挂载iso安装镜像 mount /dev/cdrom /mnt mount/dev/sr0 /mnt 3.挂载…

【计算机网络】网络层:路由器的构成

路由器工作在网络层&#xff0c;用于互连网络&#xff0c;主要工作是转发分组。 把某个输入端口收到的分组&#xff0c;按照分组要去的目的网络&#xff0c;把该分组从路由器的某个合适的输出端口转发给下一跳路由器。 &#xff08;根据目的网络的IP地址转发分组&#xff09;…

[附源码]java毕业设计学生档案管理系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

使用Umi 遇到的错误

今天想使用ui&#xff0c;出现了很多错误&#xff0c;刚开始安装的时候没有一点事&#xff0c;就是运行的时候报错&#xff0c;好像和umi版本不匹配了&#xff0c;后来又把umi删除了又安装一遍&#xff0c;然后还是运行不了&#xff0c;后来我又把umijs/preset-ui卸了&#xff…

通过制作4个游戏学习Python

前言 学习编程最好玩的方法 你会学到什么 &#xff08;文末送读者福利&#xff09; 您将学习如何有效地使用Python 您将创建一个python游戏组合 你将学会如何管理好大型项目 你将学习面向对象编程 您将学习并实现高级Python特性 你将对Python有一个透彻的理解 类型:电…

Spark并行度和任务调度

文章目录并行度如何设置并行度如何规划我们自己群集环境的并行度&#xff1f;Spark的任务调度并行度 Spark之间的并行就是在同一时间内&#xff0c;有多少个Task在同时运行。并行度也就是并行能力的设置&#xff0c;假设并行度设置为6&#xff0c;就是6个task在并行跑&#xf…

蒙特卡洛原理及实例(附Matlab代码)

文章目录一、理论基础1.1 伯努利大数定理1.2 辛钦大数定理1.3 切比雪夫大数定理1.4 三者区别和联系二、蒙特卡洛法2.1 蒙特卡洛的起源2.2 蒙特卡洛的解题思路2.2 蒙特卡洛法的应用三、几个小栗子3.1 求解定积分3.1.1 解析法3.1.2 蒙特卡洛法3.2 求解六边形面积3.2.1 解析法3.2.…

[附源码]SSM计算机毕业设计基于的高校学生考勤管理系统JAVA

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

支持向量机

目录 支持向量机 0. 由来 1. 核心思想 2. 硬间隔支持向量机 2.1 间隔最大化 2.1.1 函数间隔2.1.2 几何间隔2.1.2 间隔最大化 2.2 转换为拉格朗日对偶问题 2.2.1 拉格朗日对偶问题2.2.2 将问题转换为拉格朗日对偶问题 3. 软间隔支持向量机 4. 泛函基础 4.1 度量&#xff…

Flutter 8 个优秀动画 Packages

Flutter 8 个优秀动画 Packages 前言 动画对于使移动应用程序的用户界面感觉自然流畅至关重要。加上交互式元素和平滑的过渡&#xff0c;它们使应用程序简单易用。 正文 Flutter Animate 组件 Package https://pub.dev/packages/flutter_animate 一个 performant 库&#xff0c…

springboot simple (9) springboot jpa(Hibernate)

返回目录 1 JPA Hibernate Hibernate是一个全自动的ORM框架&#xff08;Object Relational Mapping ,对象关系映射&#xff09;。 Spring Data JPA&#xff1a; 是Spring Data的子模块&#xff0c;JPA默认使用hibernate作为ORM实现。 2 springboot继承Hibernate 第1步&…

【Servlet】7:监听器和过滤器的原理和应用

目录 | 监听器 监听器 基本概述 ServletContextListener监听器 ServletContextAttributeListener监听器 监听器的应用场景 | 过滤器 过滤器 基本概述 过滤器 实现步骤 过滤器 应用场景 本文章属于后端全套笔记的第三部分 &#xff08;更新中&#xff09;【后端入门到入…

leetcode 494.目标和 动态规划背包问题 (c++版本)

题目描述 说白了就是让一部分数减去剩下的一部数使得差值为target&#xff0c;计算有多少中组合的方法 下面来个数学公式推导一下 leftrightsumleft−righttargetleftsum−lefttargetleft(sumtarget)/2leftright sum\\ left-righttarget\\ leftsum-lefttarget\\ left(sumtarge…

用户行为分析-如何用数据驱动增长

用户行为分析-如何用数据驱动增长 2022-11-22 看完书才知道是 GrowingIO 公司出的一本书&#xff0c;干货还是挺多的。 第一章从商业进化的角度认识用户行为数据的重要性&#xff0c;帮助大家了解什么是用户行为数据&#xff0c;以及用户行为数据怎么发挥价值。接着四章详细…

【操作系统】2.2 操作系统的调度

2.2.1 操作系统之处理机调度的概念及层次 2.2.1操作系统之处理机调度的概念及层次_StudyWinter的博客-CSDN博客_操作系统调度的层次 高级调度&#xff08;作业调度&#xff09;&#xff1a;外存-》内存 中级调度&#xff08;内存调度&#xff09;&#xff1a;外存-》内存 低…

用最少的代码模拟gRPC四种消息交换模式

我们知道&#xff0c;建立在HTTP2/3之上的gRPC具有四种基本的通信模式或者消息交换模式&#xff08;MEP&#xff1a; Message Exchange Pattern&#xff09;&#xff0c;即Unary、Server Stream、Client Stream和Bidirectional Stream。本篇文章通过4个简单的实例演示它们在.NE…

HTML+CSS大作业 格林蛋糕(7个页面) 餐饮美食网页设计与实现

&#x1f380; 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业…

编写第一个Qt程序和分析第一个Qt程序

文章目录编写第一个Qt程序新建一个项目项目的文件组成和管理项目的编译、调试与运行分析第一个Qt程序创建项目1) main.cpp2) mainwindow.h和mainwindow.cpp编码实现简易的窗口界面编写第一个Qt程序 已剪辑自: http://c.biancheng.net/view/1817.html 学习一种编程语言或编程环…

最漂亮:yWorks yFiles Diagramming SDK 5.4.0.2

yWorks yfiles Diagramming SDK 5.4.0.2 卓越的 绘图 SDK 使用 yFiles 自动布局的图表 您的数据可视化软件开发套件 yFiles是行业领先的 图表软件库。20 多年来&#xff0c;公司和机构一直在使用此 SDK 来 描述、编辑和分析他们的连接数据。 准备好探索自动布局和交互式图形组…

Qt-OpenCV学习笔记--人脸识别--基于Haar特征的cascade分类器

概述 基于Haar特征的cascade分类器(classifiers) 是Paul Viola和 Michael Jone在2001年&#xff0c;论文”Rapid Object Detection using a Boosted Cascade of Simple Features”中提出的一种有效的物品检测(object detect)方法。它是一种机器学习方法&#xff0c;通过许多正…