『FPGA通信接口』串行通信接口-IIC(1)接口协议

在这里插入图片描述

文章目录

  • 1.IIC简介
    • 1.1 IIC概述
    • 1.2 总线结构
  • 2.IIC通信协议
    • 2.1消息种类
    • 2.2通信过程
  • 3.开发思路
  • 4.仿真分析
  • 5.传送门

1.IIC简介

1.1 IIC概述

IIC即 Inter-Integrated Circuit(集成电路总线),是由 Philips 半导体公司在八十年代初设计出来的一种简单、双向、二线制总线标准。多用于主机和从机在数据量不大且传输距离短的场合下的主从通信。主机启动总线,并产生时钟用于传送数据,此时任何接收数据的器件均被认为是从机。

传输速率标准模式下可以达到100kb/s,快速模式下可以达到 400kb/s,高速模式下可达 3.4Mbit/s,具体使用要看设备的支持情况。IIC接口只需要两条总线线路,即 SCL(串行时钟线)、SDA(串行数据线),IIC 总线是半双工通信。本篇解决的问题就是使用FPGA驱动这两根线实现标准IIC协议,但要清楚使用IIC接口于某设备通信要同样遵守设备的要求,例如IIC接口的EEPROM,会要求现发送读写地址,发送读写指示等,这个例程将在下一篇给出,下一篇连接在文末。

与UART不同的是,IIC总线上可以挂载若干个从机(一对多)通过主机下发的器件地址选择从机进行通信,并且需要有双向IO的支持,抗干扰能力较弱。每个连接在总线上的 IIC 器件都有一个唯一的器件地址,在通信的时候就是靠这个地址来握手的。而UART为异步串行通信,可称为点对点通信,较为复杂,需要有波特率,即数据传输的间隔要相等,以及接收和发送两根线可实现全双工。

IIC传输时,按照从高到低的位序进行传输,即采用大端模式。大端模式:就是低位字节排放在内存的低地址端,高位字节排放在内存的高地址端。小端模式:是高位字节排放在内存的低地址端,低位字节排放在内存的高地址端。

1.2 总线结构

总线(Bus),是指计算机设备和设备之间传输信息的公共数据通道。总线是连接计算机硬件系统内多种设备的通信线路,它的一个重要特征是由总线上的所有设备共享,可以将计算机系统内的多种设备连接到总线上。如果是某两个设备或设备之间专用的信号连线,就不能称之为总线。IIC总线,结构如图所示。
​​​​在这里插入图片描述
每个 IIC 器件都应该有一个器件地址,不同器件定义地址的方式是不同的,有的是软件定义,有的是硬件定义。例如某些单片机的 IIC接口作为从机时,其器件地址是可以通过软件修改从机地址寄存器确定的。而对于一些其他器件,如 CMOS 图像传感器、EEPROM 存储器,其器件地址在出厂时就已经完全或部分设定好了,具体情况可以在对应器件的数据手册中查到。

严格讲,主机不是直接向从机发送地址,而是主机往总线上发送地址,所有的从机都能接收到主机发出的地址,然后每个从机都将主机发出的地址与自己的地址比较,如果匹配上了,这个从机就会向总线发出一个响应信号。主机收到响应信号后,开始向总线上发送数据, 与这个从机的通讯就建立起来了。如果主机没有收到响应信号,则表示寻址失败。

需要注意的是,对于 i2c 总线,要求连接到总线上的输出端必须是开漏输出结构,给不了高电平,所以总线上所有的高电平应该是由上拉电阻上拉达到效果的,而不是由主机直接给总线赋值 1 就能实现, 本例中需要输出高电平时,输出高阻状态。

2.IIC通信协议

2.1消息种类

在这里插入图片描述
IIC 协议规定,在时钟(SCL)为高电平的时候,数据总线(SDA)必须保持稳定,数据总线(SDA)在时钟(SCL)为低电平的时候才能改变。因此,当SCL为高电平时,改变SDA的值,这些情况被赋予了特殊的含义,主机向从机发送的信息种类有启动信号、停止信号、7位地址码、读/写控制位、10位地址码(地址扩展)、数据字节、重启动信号、应答信号、时钟脉冲。而从机向主机发送的信息种类有应答信号、数据字节、时钟低电平(时钟拉伸)。
1.空闲状态:在空闲状态下SDA与SCL均为高电平;
2.起始信号:在时钟(SCL)为高电平的时候,数据总线(SDA)由高到低的跳变;
3.停止信号:在时钟(SCL)为高电平的时候,数据总线(SDA)由低到高的跳变;
在这里插入图片描述
4. 重新开始信号:在IIC总线上,由主机发送一个开始信号启动一次通信后,在首次发送停止信号之前,主机通过发送重新开始信号,可以转换与当前从机的通信模式,或是切换到与另一个从机通信。当SCL为高电平时,SDA由高电平向低电平跳变,产生重新开始信号,它的本质就是一个开始信号。
在这里插入图片描述
5.应答位IIC总线上的所有数据都是以8位字节传送的,发送器每发送一个字节,就在第9个时钟脉冲期间释放数据线,由接收器反馈一个应答信号。 应答信号为低电平时,规定为有效应答位(ACK简称应答位),表示接收器已经成功地接收了该字节;应答信号为高电平时,规定为非应答位(NACK),一般表示接收器接收该字节没有成功。因此一个完整的字节数据传输需要9个时钟脉冲。如果从机作为接收方向主机发送非应答信号,主机方就认为此次数据传输失败;如果是主机作为接收方,在从机发送器发送完一个字节数据后,向从机发送了非应答信号,从机就认为数据传输结束,并释放SDA线。不论是以上哪种情况都会终止数据传输,这时主机或是产生停止信号释放总线或是产生重新开始信号,开始一次新的通信。

6.插入等待时间:如果被控器需要延迟下一个数据字节开始传送的时间,则可以通过把时钟线SCL电平拉低并且保持,使主控器进入等待状态。一旦被控器释放时钟线,数据传输就得以继续下去,这样就使得被控器得到足够时间转移已经收到的数据字节,或者准备好即将发送的数据字节。
在这里插入图片描述
7.器件地址:任何IIC设备都有一个7位地址,理论上,现实中只能有127种不同的IIC设备。实际上,已有IIC的设备种类远远多于这个限制,在一条总线上出现相同的地址的IIC设备的概率相当高。为了突破这个限制,很多设备使用了双重地址——7位地址加引脚地址(external configuration pins)。主机向从机发送的第一个字节为器件地址加1Bit读写位,0代表写操作,1代表读操作。

2.2通信过程

写过程
在这里插入图片描述

①主机设置SDA为输出;
②主机发起起始信号;
③主机传输器件地址字节,其中最低位为 0,表明为写操作;
④主机设置 SDA 为三态门输入,读取从机应答信号;
⑤读取应答信号成功,主机设置 SDA 为输出,传输待写入的数据;
⑥设置 SDA 为三态门输入,读取从机应答信号;
⑦读取应答信号成功,主机产生 STOP 位,终止传输。
读过程
在这里插入图片描述

①主机设置 SDA 为输出;
②主机发起起始信号;
③主机传输器件地址字节,其中最低位为 1,表明为读操作;
④设置 SDA 为三态门输入,读取从机应答信号;
⑤读取应答信号成功,主机设置SDA为三态门输入,读取SDA总线上的一个字节的数据;
⑥主机收到数据后向从机反馈一个应答信号;
⑦从机收到应答信号后再向主机发送下一个数据;
⑧当主机完成接收数据后,向从机发送一个“非应答信号(ACK=1)”,从机收到ACK=1 的非应答信号后便停止发送;
⑨主机发送非应答信号后,再发送一个停止信号,释放总线结束通信。

3.开发思路

IIC协议虽然只有两根线,协议规定也简明清晰,但是要使用HDL实现,并不是一件“愉快”的事情,因为思路很难理清楚,可能会导致代码臃肿,资源浪费的情况出现。如下图所示为iic_driver模块,IIC协议规定每8bit数据为一个传输单位,需要有一个ACK信号,基于此,将所有的IIC消息分为带起始位写8bit,不带起始位写8bit,带停止位写8bit,不带起始位和停止位读8bit,带停止位的读五种操作类型,默认都带有应答位。因此创建IIC驱动模块的主要思路就是,保持读或写8bit的主体结构,区分五种命令以区分是否带起始位、是否带停止位、是否有ACK、是读还是写。当针对不同的设备器件写入不同的器件地址,或者是不同器件有不同的操作要求时,可在此驱动之上写一个模块用来满足器件要求,称此模块为iic_ctrl模块。例如,某型eeprom的一条写入数据命令依次为,带起始信号写入器件地址和写请求,不带起始位写入EEPROM内部地址,带停止位写入要写入的8bit数据,完成写入操作,iic_ctrl的任务就是将此写入命令拆分成了3个8bit主体,然后“调用”驱动模块完成写入操作。本节仅介绍驱动模块的编写,如下图所示。clk和rst分别为该模块的时钟和脉冲信号;iic_en为输入脉冲信号,拉高一次代表执行一次“8bit操作”,cmd表征了具体执行哪一个“8bit”操作,cmd[0] 1为读操作,0为写操作。cmd[1] 1为带起始位,0为不带起始位。cmd[2] 1为带停止位,0为不带停止位。cmd[3] 1为ACK,0为NOACK(在带停止位的读或者写操作中可以不要ACK信号)。Trans_data为要传入的8bit数据,不同的操作可能包含了器件地址、读写指示等。矩形框右侧为输出信号,iic_busy代表驱动模块正在忙,无法相应当前请求。Ack_fail标识是否有相应失败的情况,reci分别是读取到的数据和该数据的同步信号。
在这里插入图片描述

4.仿真分析

iic_sim文件如下:

module iic_sim();
 
reg clk_50;
reg rst_n;
reg iic_en;
reg [3:0]cmd;
reg [7:0]trans_data;
 
wire iic_busy;
wire ack_fail;
wire [7:0]reci_data;//接收数据
wire reci_dvalid;//接收数据同步信号
wire iic_clk;
wire iic_data;//使用force
initial begin
    clk_50 = 0;
    rst_n = 0;
    iic_en = 0;
    cmd = 0;
    trans_data = 0;
    #1000
    rst_n = 1;
    #100
    //仿真写过程:向某器件地址中写入data1和data2
    //写起始位+器件地址+读写指示+ACK
    do_iic(1'b1,4'b1010,8'b11001010);
    #20
    iic_en = 0;
    @(negedge iic_busy)
    #10
    //写8bit数据1+ACK
    do_iic(1'b1,4'b1000,8'b00110011);
    #20
    iic_en = 0;
    @(negedge iic_busy)
    #10
    //写8bit数据2+ACK+停止位
    do_iic(1'b1,4'b1100,8'b01011010);
    #20
    iic_en = 0;
    @(negedge iic_busy)
    #110
    //仿真 8bit读 过程
    do_iic(1'b1,4'b1001,8'b0);
    #20
    iic_en = 0;
end
always #10 begin
    clk_50 = ~clk_50;
end
task do_iic;
    input user_en;
    input [3:0]user_cmd;
    input [7:0]user_data;
    begin
        iic_en <= user_en;
        cmd <= user_cmd;
        trans_data <= user_data;
    end
endtask
//将一次eeprom动作拆解成多个iic动作
iic_driver sub_for_one_iic(
    .clk_50     (clk_50),
    .rst_n      (rst_n),
    .iic_en     (iic_en),
    .cmd        (cmd), //3:0
    .trans_data (trans_data),
    .iic_busy   (iic_busy),
    .ack_fail   (ack_fail),
    .reci_data  (reci_data),
    .reci_dvalid(reci_dvalid),
    .iic_clk    (iic_clk),
    .iic_data   (iic_data)
);
endmodule

iic_driver文件如下:

module iic_driver(
    input clk_50,
    input rst_n,
    input iic_en,
    input [3:0]cmd,
    input [7:0]trans_data,
    output reg iic_busy,
    output reg ack_fail,
    output reg [7:0]reci_data,//接收数据
    output reg reci_dvalid,//接收数据同步信号
    output reg iic_clk,
    inout  iic_data  
    );
 
 
//系统时钟采用50MHz
parameter SYS_CLOCK = 50_000_000;
//SCL总线时钟采用400kHz
parameter SCL_CLOCK = 400_000;
//产生时钟SCL计数器最大值
localparam SCL_CNT_M = SYS_CLOCK/SCL_CLOCK/4 - 1;
 
reg[3:0]state;
reg[3:0]sub_cmd;
reg[7:0]sub_data;
reg sub_ack;
always@(posedge clk_50 or negedge rst_n)
    if(!rst_n)begin
        sub_cmd <= 4'd0;
        sub_data<= 8'd0;
    end else if(iic_en)begin
        sub_cmd <= cmd;
        sub_data<= trans_data;
    end
reg en_div;
reg [19:0]div_cnt;
always@(posedge clk_50 or negedge rst_n)
	if(!rst_n)
		div_cnt <= 20'd0;
	else if(en_div)begin
		if(div_cnt < SCL_CNT_M)
			div_cnt <= div_cnt + 1'b1;
		else
			div_cnt <= 0;
	end
	else
		div_cnt <= 0;
 
wire imp_node;
reg  out_oe; //1代表写 , 0代表读.
reg  out_10;//代表输出高地电平
reg  [5:0]rd_cnt;
assign imp_node = div_cnt == SCL_CNT_M;
reg [1:0]cnt;
//时钟生成 iic_clk信号
always@(posedge clk_50 or negedge rst_n)
    if(!rst_n)begin
        iic_clk <= 0;
    end else if(en_div)begin
        if(imp_node)begin
            cnt <= cnt + 1;
            case (cnt)
                0:iic_clk <= 0;
                1:iic_clk <= 1;
                2:iic_clk <= 1;
                3:iic_clk <= 0;
                default: iic_clk <= 0;
            endcase
        end 
    end
assign iic_data = !out_10 && out_oe ? 1'b0:1'bz; //IIC上拉电阻,高电平无需输出
always@(posedge clk_50 or negedge rst_n)
    if(!rst_n)begin
        state <= 0;
        en_div<= 0;
        cnt <= 0;
        out_10 <= 1;
        out_oe <= 0; 
        rd_cnt <= 0;
        reci_dvalid <= 0;
        sub_ack <= 0;
        ack_fail <= 0;
        iic_busy<=0;
        reci_data <=0;
    end else begin
        case (state)
            0:begin //接收指令,进入选择选项
               ack_fail <= 0;
               if(iic_en)begin
                  en_div<=1;
                  iic_busy<=1;
                  state <= state + 1; 
               end else begin
                  en_div<=0;
               end
            end 
            1:begin//根据不同指令分发
            //cmd[0] 1为读操作,0为写操作
            //cmd[1] 1为带起始位,0为不带起始位
            //cmd[2] 1为带停止位,0为不带停止位
            //cmd[3] 1为ACK,0为NOACK
                if(sub_cmd[1])
                    state <= 2;
                else if(sub_cmd[0])
                    state <= 3;
                else 
                    state <= 4;
            end
            2:begin //生成起始位 START
            if(imp_node)begin
                case(cnt)
					0:begin out_10 <= 1; out_oe <= 1'd1;end //keep high(clk=0)
					1:;//data high and clk=1
					2:begin out_10 <= 0; end//data high  clk=0 产生起始位
					3:;
					default:begin out_10 <= 1;end
				endcase
                if(cnt==3)begin
                   if(sub_cmd[0]) //读操作
                      state <= 3;
                   else
                      state <= 4; //写操作
                end
            end
            end
            3:begin //读操作 
                if(imp_node)begin
                    case(cnt)
					    0:begin out_oe <= 1'd0;end
					    1:;
					    2:begin reci_data <= {reci_data[6:0],iic_data}; end
					    3:begin
                            if(rd_cnt<7)
                                rd_cnt <= rd_cnt + 1;
                            else begin
                                rd_cnt <= 0;
                                state <= 6;
                                reci_dvalid <= 1;
                            end
                        end
					    default:begin out_10 <= 1;end
				    endcase 
                end 
            end
            4:begin //写操作
               if(imp_node)begin
                    case(cnt)
					    0:begin out_10 <= sub_data[7-rd_cnt];out_oe<=1'b1;end
					    1:;
					    2:;
					    3:begin
                            if(rd_cnt<7)
                                rd_cnt <= rd_cnt + 1;
                            else begin
                                rd_cnt <= 0;
                                state <= 5;
                            end
                        end
					    default:begin out_10 <= 1;end
				    endcase 
                end  
            end
            5:begin //获取应答
               if(imp_node)begin
                    case(cnt)
					    0:begin out_oe<=1'b0;end
					    1:;
					    2:sub_ack <= iic_data;
					    3:begin
                            //状态跳转
                            if(sub_cmd[2])
                                state <= 7; //产生终止位
                            else begin
                                state <= 0;
                                iic_busy <= 0;
                            end
 
                            //收到错误应答
                            if(sub_ack)
                                ack_fail <= 1;
                        end
					    default:begin out_10 <= 1;end
				    endcase 
                end   
            end
            6:begin //生成应答
                reci_dvalid <= 0;
                if(imp_node)begin
                    case(cnt)
					    0:begin
                            out_oe<=1'b1;
                            if(sub_cmd[3])//应答
                               out_10 <=0;
                            else 
                               out_10 <=1; 
                            end
					    1:;
					    2:;
					    3:begin
                          if(sub_cmd[2])
                            state <= 7;
                          else begin
                            iic_busy <= 0;
                            state <= 0;
                          end
                        end
					    default:begin out_10 <= 1;end
				    endcase 
                end  
            end
            7:begin //产生终止信号
                ack_fail <= 0;
                if(imp_node)begin
                    case(cnt)
					    0:begin out_10 <= 0;out_oe<=1'b1;end
					    1:;
					    2:begin out_10 <= 1; end
					    3:begin
                          iic_busy <= 0;
                          state <= 0;
                        end
					    default:begin out_10 <= 1;end
				    endcase 
                end  
            end
            default: state <= 0;
        endcase
    end
endmodule

模拟写入某器件过程为带起始位写入7bit器件地址和1bit读写指令,随后写入一个8bit,在带停止位写入一个8bit,仿真结果如下图所示。
在这里插入图片描述
代码中关于读8bit的仿真结果如下图所示。仿真结果正确。
在这里插入图片描述

5.传送门

  • 我的主页
  • FPGA通信接口专栏汇总导航
  • 『FPGA通信接口』串行通信接口-IIC(2)IIC实战
END

🔈文章原创,首发于CSDN论坛。
🔈欢迎点赞❤❤收藏⭐⭐打赏💴💴!
🔈欢迎评论区或私信指出错误❌,提出宝贵意见或疑问❓。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

字节跳动(社招)三面算法原题

TikTok 喘息 继上月通过强制剥离 TikTok 法案后&#xff0c;美国众议院在当地时间 20 日下午以 360 票赞成 58 票反对通过了新的法案&#xff1a;剥离 TikTok 的期限由生效后 165 天调整至 270 天之内&#xff0c;即今年 11 月的美国总统大选后。 之前我们讲过&#xff0c;TikT…

【文件上传与包含漏洞综合利用】DVWA-文件上传-难度:High

实验过程和结果 步骤1&#xff1a;尝试直接上传php木马&#xff0c;失败&#xff0c;截图如下&#xff1a; 步骤2&#xff1a;将php木马后缀改为jpeg尝试上传&#xff0c;依旧失败&#xff0c;截图如下&#xff1a; 步骤3&#xff1a;将真实的jpeg图片1.jpeg上传&#xff0c;成…

云原生Service Mesh服务网格简单介绍

serviceMesh是什么 Service Mesh是一个用于处理服务间通信的基础设施层&#xff0c;旨在实现云原生应用复杂服务拓扑中的可靠请求传递。其基本构成是一组与应用一起部署的轻量级网络代理&#xff0c;这些代理对应用来说是透明的。Service Mesh通过统一的方式来控制和处理服务间…

基于openwrt交叉编译opencv4.9.0版本

源码包的获取 源码获取有两种方式&#xff0c;一种是通过编译时在makefile指定它的git地址&#xff0c;在编译时下载&#xff0c;这种很依赖网速&#xff0c;网速不好时&#xff0c;编译会失败。另一种是我们将源码的压缩包下载到本地&#xff0c;放到我们的SDK中&#xff0c;…

UltraScale+的10G/25G Ethernet Subsystem IP核使用

文章目录 前言一、设计框图1.1、xxv_ethernet_01.2、xxv_ethernet_0_sharedlogic_wrapper1.3、xxv_ethernet_0_clocking_wrapper1.4、xxv_ethernet_0_common_wrapper 二、IP核配置三、仿真四、上板测速五、总结 前言 前面我们学习了很多基于XILINX 7系列的高速接口使用&#x…

CC攻击频发,企业如何做好网络安全,该怎么防护能免遭CC攻击?

在当前网络现状下&#xff0c;随着信息技术的飞速发展&#xff0c;网络攻击手段也愈发多样化和复杂化。其中&#xff0c;CC攻击作为一种针对Web应用层的拒绝服务攻击&#xff0c;其危害日益凸显&#xff0c;对企业和个人造成了严重的威胁。下面我们就从多个角度详细分享关于CC攻…

SpringCloudAlibaba入门学习笔记20240408~20240424

跟学b站“图灵架构师”SpringCloudAlibaba入门教程 系统架构演化进程 单体应用架构>垂直应用架构>分布式架构>SOA架构>微服务架构 1、针对微服务架构&#xff1a; 如何管理众多小服务&#xff1f;(服务治理 注册中心[服务注册 发现 剔除])nacos 众多小服务之间如…

智能驾驶+网络安全

在智能驾驶场景下&#xff0c;安全问题一直是一个持续热点。 针对车机模块不被黑客利用Linux的漏洞攻击&#xff0c;可以采取以下几种方式来提高安全性&#xff1a; 安全设计和防护&#xff1a;在设计车机模块时&#xff0c;需要考虑安全性&#xff0c;并采取相应的安全防护措施…

【Yolov系列】Yolov5学习(一):大致框架

一、Yolov5网络结构 Yolov5特点&#xff1a; 合适于移动端部署&#xff0c;模型小&#xff0c;速度快 Yolov5骨干结构&#xff1a;CSPDarknet53网络Yolov5主要有Yolov5s、Yolov5m、Yolov5l、Yolov5x四个版本。这几个模型的结构基本一样&#xff0c;不同的是depth_multiple模型…

C++ | Leetcode C++题解之第42题接雨水

题目&#xff1a; 题解&#xff1a; class Solution { public:int trap(vector<int>& height) {int n height.size();if (n 0) {return 0;}vector<int> leftMax(n);leftMax[0] height[0];for (int i 1; i < n; i) {leftMax[i] max(leftMax[i - 1], he…

SpringMVC 源码剖析

SpringMVC 源码剖析 0 从源码角度分析SpringMVC执行流程 // 前端控制器&#xff0c;SpringMVC最核心的类 public class DispatcherServlet extends FrameworkServlet {// 前端控制器最核心的方法&#xff0c;这个方法是负责处理请求的&#xff0c;一次请求&#xff0c;调用一次…

数据类型总结

1 引言 在计算机的世界里&#xff0c;数据类型是被人类定义出来的&#xff0c;方便人去更好地理解、辨别数据。计算机只能识别二进制数&#xff0c;不可能要求写代码时&#xff0c;只是输入一些0/1的东西。通过定义数据类型&#xff0c;可以让人和计算机更好地“沟通”&#x…

图像处理|关于二维傅里叶变换的学习笔记(实用版)

因为图像至少是2D的&#xff0c;所以在数字图像处理中使用的都是2D-傅里叶变换。 1.什么是傅里叶变换(DFT)&#xff1f;傅里叶变换是将图像从空间域转换到频域&#xff0c;其逆变换是将图像从频域转到空间域。 物理意义是&#xff1a; 2.频谱图怎么看&#xff1f;傅里叶频谱图…

亚马逊、ozon、美客多等平台的测评技术核心:提升跨境电商业绩的关键要素

现今&#xff0c;越来越多的跨境卖家开始深入了解测评自养号这一领域&#xff0c;他们希望通过优化运营来降低成本并增加利润。在整个测评工作中&#xff0c;测评技术是非常关键的一环。只有不断学习、保持冷静&#xff0c;我们才能不断提升测评能力&#xff0c;从而获得更多机…

Bentley二次开发教程22-文件及模型管理-材质、图层

材质 材质主要用于对元素进行材质贴图&#xff0c;以表现实际的材料样式。材质表中包含材质表&#xff0c;材质面板以及材质。而其属性记录了反射等多种属性以表达实际材质效果。 创建材质 当我们需要创建自定义的材质时&#xff0c;对应的&#xff0c;需要依次创建材质表&…

JavaScript:js实现在线五子棋人机(人人)对弈

在线五子棋人机对弈 全部使用前端技术,使用HTML,CSS以及JS进行实现. 棋盘在后端就是一个15*15的二维数组 页面设计 页面设计的比较粗糙 主要使用js自带的canvas画布进行绘画 HTML代码如下: <div class"outer"><canvas id"canvas" height&qu…

男生一般穿什么裤子好看?五大爆款男装精选测评!

男生裤子要怎么选才能找到适合自己的裤子呢&#xff1f;这肯定是大家选裤子时经常出现的一个疑问了&#xff0c;现在的市面上虽然款式风格非常多&#xff0c;但是由于品牌鱼龙混杂的原因&#xff0c;不同的裤子质量也参差不齐。为了帮助各位男同胞能选到适合自己的裤子&#xf…

centos7使用源码安装方式redis

安装编译源码的工具gcc yum install -y gcc下载源码 源码下载地址 https://download.redis.io/releases/ 注意事项 不建议安装最新版本redis&#xff0c;所以我这里选择6.2.6版本 下载 wget https://download.redis.io/releases/redis-6.2.6.tar.gz解压 tar -zxvf redis-…

工业相机和镜头参数和选型

工业相机和镜头参数和选型 文章目录 工业相机和镜头参数和选型前言一、相机参数解释和选型1.相机参数1.1快门-shutter1.2曝光-exposure1.3增益-gain1.4 感光芯片类型&#xff08;CCD/CMOS&#xff09;1.5 感光芯片&#xff08;靶面&#xff09;尺寸1.6 分辨率1.7 像元尺寸1.8 帧…

【点量云流】国内首家适配国产信创的实时云渲染解决方案,助力国产化信创新体验!

一、背景 随着信息技术的广泛应用&#xff0c;信息安全与自主可控成为国家发展的重要保障。近年来&#xff0c;国产化信创的发展&#xff0c;为推动信息技术产业自主创新&#xff0c;实现关键技术和产品的自主可控&#xff0c;对于保障国家信息安全、促进产业发展有着重要意义。…