EEPROM读写实验——FPGA学习笔记18

一、EEPROM简介

        Electrically Erasable Progammable Read Only Memory:是指带电可擦可编程只读存储器,是一种常用的非易失性存储器(掉电数据不丢失)

EEPROM发展历史

        我们这次实验所用的AT24C64存储容量为64Kbit,内部分成256页,每页32字节,共有8192个字节,且其读写操作都是以字节为基本单位。可以把AT24C64看作一本书,那么这本书有256页,每页有32行,每行有8个字,总共有256*32*8=65536个字,对应着AT24C6464*1024=65536bit。
        读是从起始读到最大,回到起始; 写是写到一页的结束;

24C02:

片内地址寻址:

读写操作:

二、IIC简介

1、简介

        IIC即Inter-Integrated Circuit(集成电路总线),是由Philips半导体公司(现在的NXP半导体公司)在八十年代初设计出来的一种简单、双向、二线制总线标准。

2、 IIC结构示意

3、IIC协议时序

时钟线为低电平可以变化数据,时钟线为高电平不允许变化数据,只能保持。

 4、器件地址

5、字寄存器地址 (24C64)

6、单次写(字节写)

7、连续写(页写)

8、读当前地址:

9、任意地址单次读(随机读)

10、从xxx地址开始连续读

三、试验任务

        本节的实验任务是先向E2PROMAT24C64)的存储器地址0255分别写入数据0~255;写完之后再读取存储器地址0~255中的数据,若读取的值全部正确则LED灯常亮,否则LED灯闪烁。

四、程序设计

 1、整体框图

2、IIC_my

状态机:

代码:

`timescale 1ns / 1psmodule iic_my#(parameter integer WMEN_LEN = 8'd1   ,   //写长度,以字节为单位,包含器件地址parameter integer RMEN_LEN = 8'd0   ,   //读长度,以字节为单位,不包含器件地址parameter integer CLK_DIV  = 16'd499    //IIC时钟分频系数
)
(
input   wire                            I_clk               ,       //系统时钟输入
input   wire                            I_rstn              ,       //系统复位,低电平有效
output  reg                             O_iic_scl = 1'b0    ,       //I2C时钟SCL
inout   wire                            IO_iic_sda          ,       //I2C 数据总线
input   wire    [WMEN_LEN*8-1'b1:0]     I_wr_data           ,       //写数据寄存器,其中WMEN_LEN设置了最大支持的数据字节数,越大占用的FPGA资源越多
input   wire    [7:0]                   I_wr_cnt            ,       //写数据计数器,代表写了多少个字节
output  reg     [RMEN_LEN*8-1'b1:0]     O_rd_data = 0       ,       //读数据寄存器,其中RMEN_LEN设置了最大支持的数据字节数,越大占用的FPGA资源越多
input   wire    [7:0]                   I_rd_cnt            ,       //读数据计数器
input   wire                            I_iic_req           ,       //I_iic_req == 1 使能I2C传输
input   wire                            I_iic_mode          ,       //I_iic_mode = 1 随机读   I_iic_mode = 0 读当前寄存器或者页读
output  reg                             O_iic_busy = 1'b0   ,       //I2C控制器忙
output  reg                             O_iic_bus_error     ,       //I2C总线,无法读到正确ACK出错
output  reg                             IO_iic_sda_dg               //数据总线上的数据
);localparam IDLE     =    4'd0   ;       //I2C 总线空闲状态
localparam START    =    4'd1   ;       //I2C 总线启动
localparam W_WAIT   =    4'd2   ;       //I2C 总线等待写完成
localparam W_ACK    =    4'd3   ;       //I2C 总线等待写WACK
localparam R_WAIT   =    4'd4   ;       //I2C 总线等待读完成 
localparam R_ACK    =    4'd5   ;       //I2C 总线等待读RACK 
localparam STOP1    =    4'd6   ;       //I2C 总线产生停止位
localparam STOP2    =    4'd7   ;       //I2C 总线产生停止位   localparam SCL_DIV  =   CLK_DIV/2   ;localparam OFFSET   =   SCL_DIV - SCL_DIV/4 ;   //设置I2C总线的SCL时钟的偏移,以满足SCL和SDA的时序要求,外部的SCL延迟内部的半周期的四分之三reg         [2:0 ]  IIC_S   =   4'd0    ;   //I2C 状态机
//generate  scl 
reg         [15:0]  clkdiv  =   16'd0   ;   //I2C 时钟分频寄存器
reg                 scl_r   =   1'b1    ;   //I2C控制器的SCL内部时钟
reg                 sda_o 	=   1'b0    ;   //I2C控制器的SDA
reg                 scl_clk =   1'b0    ;   //I2C控制器内部SCL时钟,与外部时钟存在OFFSET参数设置的相位偏移
reg         [7:0]   sda_r   =   8'd0    ;   //发送寄存器
reg         [7:0]   sda_i_r =   8'd0    ;   //接收寄存器
reg         [7:0]   wcnt    =   8'd0    ;   //发送数据计数器,以byte为单位
reg         [7:0]   rcnt    =   8'd0    ;   //接收数据计数器,以byte为单位
reg         [2:0]   bcnt    =   3'd0    ;   //bit计数器
reg                 rd_req  =   1'b0    ;   //读请求,当判断到需要读数据,内部状态机中设置1
wire                sda_i               ;   //sda 输入
wire                scl_offset          ;   //scl 时钟偏移控制assign  sda_i       = (IO_iic_sda == 1'b0)  ?  1'b0 : 1'b1  ;       //读总线 
assign  IO_iic_sda  = (sda_o == 1'b0)       ?  1'b0 : 1'bz  ;       //写总线,1'bz代表高阻,I2C外部通过上拉电阻,实现总线的高电平PULLUP PULLUP_inst (.O(iic_sda));//仅对仿真有效,仿真设计iic_sda状态为高阻,模拟上拉电阻 //scl 时钟分频器
always@(posedge I_clk)beginif(clkdiv < SCL_DIV)    clkdiv <= clkdiv + 1'b1;else beginclkdiv <= 16'd0; scl_clk <= !scl_clk;end
endassign  scl_offset  =   (clkdiv == OFFSET)    ;   //设置scl_offset的时间参数always @(posedge I_clk)beginO_iic_scl <=  scl_offset ?  scl_r : O_iic_scl; //O_iic_scl延迟scl_offset时间的scl_r
end//当IIC_S状态机处于,同时空闲状态,设置SCL为高电平,同时也是空闲,停止状态,用于产生起始位和停止位时序,否则寄存scl_clk时钟
always @(*) beginif(IIC_S == IDLE || IIC_S == STOP1 || IIC_S == STOP2)scl_r <= 1'b1;else scl_r <= scl_clk;
end//当进入IIC_S状态为启动、停止设置sda=0,结合scl产生起始位,或者(IIC_S == R_ACK && (rcnt != I_rd_cnt) sda=0,用于产生读操作的ACK
always @(*) beginif(IIC_S == START || IIC_S == STOP1 || (IIC_S == R_ACK && (rcnt != I_rd_cnt)))beginsda_o <= 1'b0;endelse if(IIC_S == W_WAIT)beginsda_o <= sda_r[7]; endelse beginsda_o <= 1'b1;                          //否则其他状态都为1,当(IIC_S == R_ACK && (rcnt == I_rd_cnt) 产生一个NACK end
end//I2C数据发送模块,所有的写数据都通过此模块发送
always @(posedge scl_clk) beginif(IIC_S == W_ACK || IIC_S == START)begin   //IIC_S=START和W_ACK,把需要发送的数据,寄存到sda_rsda_r <= I_wr_data[(wcnt*8) +: 8];      //寄存需要发发送的数据到sda_rif( rd_req ) beginsda_r <= {I_wr_data[7:1],1'b1};     //对于读操作,rd_req由内部代码产生,当写完第一个数据(器件地址),后通过判断I_rd_cnt,确认是否数据需要读endendelse if(IIC_S == W_WAIT)begin               //当W_WAT状态,通过移位操作,把数据发送到数据总线sda_r <= {sda_r[6:0],1'b1};             //移位操作endelse beginsda_r <= sda_r;end
end//I2C数据接收模块,I2C读期间,把数据通过移位操作,移入O_rd_data
always @(negedge scl_clk)beginif(IIC_S == R_WAIT ) begin                  //当IIC_S == R_WAIT ||IIC_S == W_ACK(如果读操作,第1个BIT是W_ACK这个状态读)启动移位操作sda_i_r <= {sda_i_r[6:0],sda_i};endelse if(IIC_S == R_ACK) begin               //当IIC_S == R_ACK,完成一个BYTE读,把数据保存到O_rd_dataO_rd_data[((rcnt-1'b1)*8) +: 8] <= sda_i_r[7:0];endelse if(IIC_S == IDLE)begin                 //空闲状态,重置sda_i_rsda_i_r <= 8'd0;end
end//总线忙状态
always @(posedge scl_clk or negedge I_rstn )beginif(I_rstn == 1'b0)beginO_iic_busy <= 1'b0; endelse beginif((I_iic_req == 1'b1 || rd_req == 1'b1 || O_iic_bus_error))begin//I_iic_req == 1'b1 || rd_req == 1'b1总线进入忙状态O_iic_busy <= 1'b1; endelse if(IIC_S == IDLE)beginO_iic_busy <= 1'b0;endend 		
end//总线错误状态
always @(negedge scl_clk or negedge I_rstn )beginif(I_rstn == 1'b0)beginO_iic_bus_error <= 1'b0;end  	else beginif(IIC_S  == W_ACK && sda_i == 1'b1)begin//I_iic_req == 1'b1 || rd_req == 1'b1总线进入忙状态O_iic_bus_error <= 1'b1; endelse if(I_iic_req == 0)beginO_iic_bus_error <= 1'b0;endend 		
end//状态机
always @(posedge scl_clk or negedge I_rstn) beginif (!I_rstn) beginwcnt    <=  8'd0    ;rcnt    <=  8'd0    ;rd_req  <=  1'd0    ;IIC_S   <=  IDLE    ;end else begincase (IIC_S)                        //sda = 1   scl = 1IDLE:beginif ((I_iic_req == 1'b1)||(rd_req == 1'b1) )begin    //当I_iic_req == 1'b1代表启动传输 当 rd_req == 1'b1 代表读操作需要产生repeated start 重复启动  IIC_S <= START;         //进入总线启动end else beginwcnt <= 8'd0;rcnt <= 8'd0;endend START:begin                     //这个状态,前面的代码,先设置sda = 0,scl_offset参数设置了scl_clk时钟的偏移,之后 scl_clk =0 即scl =0 产生起始位或者重复起始位bcnt <= 3'd7;               //设置bcnt的初值IIC_S <= W_WAIT;            //进入发送等待end         W_WAIT:begin                    //等待发送完成,这里发送8bits 数据,写器件地址,写寄存器地址,写数据,都在这个状态完成if (bcnt > 3'd0) begin      //如果8bits没发送完,直到发送完bcnt <= bcnt - 1'b1;    //bcnt计数器,每发送1bit减1end else begin                  //8bits发送完毕wcnt <= wcnt + 1'b1;    //wcnt计数器,用于记录已经写了多少字节IIC_S <= W_ACK;         //进入W_ACK状态endend W_ACK:begin                     //等待WACK,此阶段,也判断是否有读操作if (wcnt < I_wr_cnt) begin  //判断是否所有数据发送(写)完成bcnt <= 3'd7;           //如果没有写完,重置bcntIIC_S <= W_WAIT;        //继续回到W_WAIT等待数据发送(写)完成end else if(I_rd_cnt > 3'd0)beginif ((rd_req == 1'b0) && (I_iic_mode == 1'b1)) beginrd_req  <=  1'b1  ;     //请求读操作IIC_S   <=  IDLE  ;     //设置状态进入IDLE,根据rd_req的值会重新产生一次为读操作进行的repeated重复startend else beginIIC_S   <=  R_WAIT  ;   //进入读等待bcnt    <=  3'd7    ;   endendelse beginIIC_S <= STOP1;             //如果所有的发送完成,也没数据需要读,进入停止状态endend R_WAIT:beginrd_req  <=  1'b0        ;       //重置读请求 bcnt    <=  bcnt - 1'b1 ;if (bcnt == 3'd0) beginrcnt    <=  ( rcnt < I_rd_cnt ) ? ( rcnt + 1'b1 ) : rcnt ; //判断是否还有数据需要读IIC_S   <=  R_ACK ;endend R_ACK:beginbcnt    <=  3'd7 ;                                             //重置读请求bcnt计数器IIC_S   <=  ( rcnt < I_rd_cnt ) ? R_WAIT : STOP1    ;           //如果所有数据读完,进入停止状态 end STOP1:begin //产生停止位 sda = 0 scl = 1rd_req  <=  1'b0    ;   IIC_S   <=  STOP2   ;   end STOP2:begin //产生停止位  sda = 1 scl = 1IIC_S <= IDLE;end default:begin                 IIC_S <= IDLE;endendcaseend
endendmodule

3、

状态机:

代码

`timescale 1ns / 1psmodule eeprom_rt
(input   wire            I_sysclk    ,   //系统时钟输入output  wire            O_iic_scl   ,   // I2C SCL时钟inout   wire            IO_iic_sda  ,   //I2C SDA数据总线output  wire    [3:0]   test_led    ,   //测试LEDoutput  wire            led             //error LED
);localparam  SYSCLKHZ    =   100_000_000;
localparam  T500MS_CNT  =   (SYSCLKHZ / 2 - 1) ;reg     [8 :0] 	    rst_cnt   	 = 9'd0     ;   //延迟复位计数器
reg     [25:0]      t500ms_cnt	 = 26'd0    ;   //500ms计数器
reg     [19:0]      delay_cnt 	 = 20'd0    ;   //eeprom每次读写完后,延迟操作计数器
reg     [2 :0]	    TS_S 	  	 = 2'd0     ;   // 读写EEPROM状态机
reg     		    iic_req 	 = 1'b0     ;   //i2c总线,读/写请求信号
reg     [31:0]	    wr_data   	 = 32'd0    ;   //写数据寄存器
reg     [7 :0]	    wr_cnt 	  	 = 8'd0     ;   //写数据计数器
reg     [7 :0]	    rd_cnt 	  	 = 8'd0     ;   //读数据计数器
wire     		    iic_busy                ;   // i2c总线忙信号标志
wire    [31:0]      rd_data                 ;   // i2c读数据
wire    		    t500ms_en               ;   // 500ms延迟到使能wire                IO_iic_sda_dg           ;
wire                iic_bus_error           ;   //i2c总线错误
reg                 iic_error = 1'b0        ;   //i2c 读出数据有错误assign  test_led    =   rd_data[3:0]            ;//测试LED输出
assign  led         =   iic_error               ;//通过LED显示错误标志
assign  t500ms_en   =   (t500ms_cnt==T500MS_CNT);//500ms 使能信号//系统复位计数器
always @(posedge I_sysclk ) beginif (!rst_cnt[8]) beginrst_cnt <= rst_cnt + 1'b1;end
end//I2C总线延迟间隔操作,该时间约不能低于500us,否则会导致EEPROM操作失败
always@(posedge I_sysclk) beginif(!rst_cnt[8])begindelay_cnt <= 0;endelse if((TS_S == 3'd0 || TS_S == 3'd2 )) begindelay_cnt <= delay_cnt + 1'b1;endelse begin delay_cnt <= 0;end
end//每间隔500ms状态机运行一次
always@(posedge I_sysclk) beginif(!rst_cnt[8])begint500ms_cnt <= 0;endelse if(t500ms_cnt == T500MS_CNT) begint500ms_cnt <= 0;endelse begin t500ms_cnt <= t500ms_cnt + 1'b1;end
end//状态机实现每次写1字节到EEPROM然后再读1字节
always @(posedge I_sysclk ) beginif (!rst_cnt[8]) beginiic_req     <=  1'b0    ;wr_data     <=  32'd0   ;rd_cnt      <=  8'd0    ;wr_cnt      <=  8'd0    ;iic_error   <=  1'b0    ;TS_S        <=  3'd0    ;end else begincase (TS_S)0:begin     if (!iic_busy) begin        //当总线不忙,可以开启一次IIC数据操作iic_req <=  1'b1    ;   //请求发送数据//数据寄存器中8'b10100000代表需要写的器件地址,第一个wr_data[15:8]代表了EEPROM内存地址,第二个wr_data[15:8]代表了写入数据   wr_data <= {8'hfe,wr_data[15:8],wr_data[15:8],8'b10100000}; rd_cnt  <=  8'd0    ;   //不需要读数据wr_cnt  <=  8'd3    ;   //需要写入3个BYTES数据,包含一个器件地址,1个EEPROM寄存器地址,一个数据TS_S    <=  3'd1    ;        endend1:beginif (iic_busy == 1'b1) beginiic_req <=  1'b0    ;TS_S    <=  3'd2    ;end end2:beginif ((!iic_busy) && (delay_cnt[19] == 1'b1)) begin//当总线非忙,可以开始一次I2C数据操作,该时间约不能低于500us,否则会导致EEPROM操作失败iic_req <=  1'b1    ;   //请求接收数据rd_cnt  <=  8'd1    ;   //需要读取一个字节wr_cnt  <=  8'd2    ;   //需要写两个byte  一个器件地址8’d1010_0000 一个寄存器地址 wr_data[15:8] (I2C控制器会自定设置读写标志位)TS_S    <=  3'd3    ;    end end3:beginif (iic_busy == 1'b1) beginiic_req <=  1'b0    ;TS_S    <=  3'd4    ;endend4:beginif (!iic_busy) begin        //当总线非忙,代表前面读数据完成       if (wr_data[23:16] != rd_data[7:0]) begin   //对比数据是否正确iic_error   <=  1'b1    ;end else beginiic_error   <=  1'b0    ;endwr_data[15:8]   <=  wr_data[15:8] + 1'b1    ;   //地址和数据都加1TS_S            <=  3'd5    ;endend5:beginif(t500ms_en == 1'b1)beginTS_S    <=  3'd0;endenddefault: TS_S   <=  3'd0;endcaseend
end// 以下代码为在线逻辑分析仪观察调试部分
reg scl_r = 1'b0;
always @(posedge I_sysclk)begin //对O_iic_scl寄存1次scl_r <= O_iic_scl; 
end//产生一个触发时钟,这个时钟是系统时钟的512倍分频,这样抓取总线的时候,可以看到更多I2C的有效信号
reg [8:0] dg_clk_cnt;
wire dg_clk = (dg_clk_cnt==0);//用scl_dg即O_iic_scl的跳变沿作为触发信号
always@(posedge I_sysclk) begindg_clk_cnt <= dg_clk_cnt+ 1'b1;
endila_0 ila_debug (.clk(I_sysclk),//在线逻辑分析仪的时钟.probe0({rd_data[7:0],wr_data[23:0],TS_S,iic_error,iic_req,scl_r,IO_iic_sda_dg,iic_bus_error,dg_clk,t500ms_en}) // 需要观察的调试信号
);//例化I2C控制模块
iic_my#
(
.WMEN_LEN   (4              )   ,   //最大支持一次写入4BYTE(包含器件地址)
.RMEN_LEN   (4              )   ,   //最大支持一次读出4BYTE(包含器件地址)
.CLK_DIV    (SYSCLKHZ/100000)       //100KHZ I2C总线时钟
)
u_iic_my
(.I_clk              (I_sysclk       )   ,   //系统时钟.I_rstn             (rst_cnt[8]     )   ,   //系统复位.O_iic_scl          (O_iic_scl      )   ,   //I2C SCL总线时钟.IO_iic_sda         (IO_iic_sda     )   ,   //I2C SDA数据总线.I_wr_data          (wr_data        )   ,   //写数据寄存器.I_wr_cnt           (wr_cnt         )   ,   //需要写的数据BYTES.O_rd_data          (rd_data        )   ,    //读数据寄存器.I_rd_cnt           (rd_cnt         )   ,   //需要读的数据BYTES.I_iic_req          (iic_req        )   ,   //I2C控制器请求.I_iic_mode         (1'b1           )   ,   //读模式.O_iic_busy         (iic_busy       )   ,   //I2C控制器忙.O_iic_bus_error    (iic_bus_error  )   ,   //总线错误信号标志.IO_iic_sda_dg      (IO_iic_sda_dg  )       //debug IO_iic_sda
); endmodule

五、仿真验证

发送器件地址:

发送片内地址:

随机读:

六、上板验证

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java--IO高级流

缓冲流 缓冲流,也叫高效流&#xff0c;是对4个基本的FileXxx 流的增强&#xff0c;所以也是4个流&#xff0c;按照数据类型分类&#xff1a; 字节缓冲流&#xff1a;BufferedInputStream&#xff0c;BufferedOutputStream 字符缓冲流&#xff1a;BufferedReader&#xff0c;Buf…

【2024】uniapp 接入声网音频RTC【H5+Android】Unibest模板下Vue3+Typescript

需求 最近开发一个项目&#xff0c;需要实现声网的接入。由于采用uniapp模式&#xff0c;按照最佳实践采用优先开发H5再适配的模式。因此实现了H5和Android两种模式的接入&#xff0c;Android里采用离线打包自定义基座来进行调试。怕自己忘记了&#xff0c;在这里详细的记录完…

Hadoop之WordCount测试

1、Hadoop简介&#xff1a; Hadoop是Apache旗下的一个用Java语言实现的开源软件框架&#xff0c;是一个开发和运行处理大规模数据的软件平台。 Hadoop的核心组件包括Hadoop分布式文件系统&#xff08;HDFS&#xff09;和MapReduce编程模型。HDFS是一个高度容错的系统&#xf…

OpenGL笔记十九之相机系统

OpenGL笔记十九之相机系统 —— 2024-10-02 晚上 bilibili赵新政老师的教程看后笔记 code review! 文章目录 OpenGL笔记十九之相机系统1.运行1.1.游戏相机1.2.轨迹球相机 2.游戏相机与轨迹球相机切换3.博主笔记本要运行需要更改的文件更改1:28_OpenGL_CameraSystem/applicat…

基于SpringBoot的学习资源共享平台

运行环境: jdk8tomcat9mysqlIntelliJ IDEAmavennodejs 设计选用前后端分离的单体架构方式 后端&#xff1a;SpringBootMybatis-PluslogbackElasticsearchRedisMySQLJwtsmtp阿里云OSS 前端&#xff1a;WebPackVueJsAnt Designaxios 主要模块&#xff1a;反馈管理、资源管理、…

GitLab flow工作流及其使用

问题背景 Git flow和Github flow及其问题 使用GitLab flow 目录 什么是GitLab工作流 功能分支 生产分支 使用GitLab flow环境分支 使用GitLab flow发布分支 使用GitLab flow合并/拉取请求 使用GitLab flow进行问题跟踪 链接和关闭合并请求中的问题 用rebase压缩提交…

实战案例:结合大模型与爬虫技术实现12306智能查票系统

大语言模型&#xff0c;例如 GPT-4&#xff0c;拥有强大的知识储备和语言理解能力&#xff0c;能够进行流畅的对话、创作精彩的故事&#xff0c;甚至编写代码。然而&#xff0c;它们也面临着一些难以克服的困境&#xff0c;就像一个空有知识却无法行动的巨人 信息滞后&#xf…

[ESP32]ESP-IDF使用组件添加U8g2图形库

U8g2 在ESP32使用u8g2的时候可以使用添加component的方式进行, 由于官方的component库没有, 这里我找到了一个可以使用的github库, 使用git的方式进行添加这一个库 具体的原理可以看[官方手册](https://docs.espressif.com/projects/esp-idf/zh_CN/stable/esp32/api-guides/to…

使用seata管理分布式事务

做应用开发时&#xff0c;要保证数据的一致性我们要对方法添加事务管理&#xff0c;最简单的处理方案是在方法上添加 Transactional 注解或者通过编程方式管理事务。但这种方案只适用于单数据源的关系型数据库&#xff0c;如果项目配置了多个数据源或者多个微服务的rpc调用&…

C语言 | Leetcode C语言题解之第459题重复的子字符串

题目&#xff1a; 题解&#xff1a; bool kmp(char* query, char* pattern) {int n strlen(query);int m strlen(pattern);int fail[m];memset(fail, -1, sizeof(fail));for (int i 1; i < m; i) {int j fail[i - 1];while (j ! -1 && pattern[j 1] ! pattern…

63.5 注意力提示_by《李沐:动手学深度学习v2》pytorch版

系列文章目录 文章目录 系列文章目录注意力提示生物学中的注意力提示查询、键和值注意力的可视化使用 show_heatmaps 显示注意力权重代码示例 代码解析结果 小结练习 注意力提示 &#x1f3f7;sec_attention-cues 感谢读者对本书的关注&#xff0c;因为读者的注意力是一种稀缺…

在Linux系统安装Nginx

注意&#xff1a;Nginx端口号是80(云服务器要放行) 我的是基于yum源安装 安装yum源(下面这4步就好了) YUM源 1、将源文件备份 cd /etc/yum.repos.d/ && mkdir backup && mv *repo backup/ 2、下载阿里源文件 curl -o /etc/yum.repos.d/CentOS-Base.repo ht…

LabVIEW机床加工监控系统

随着制造业的快速发展&#xff0c;机床加工的效率与稳定性成为企业核心竞争力的关键。传统的机床监控方式存在效率低、无法远程监控的问题。为了解决这些问题&#xff0c;开发了一种基于LabVIEW的机床加工监控系统&#xff0c;通过实时监控机床状态&#xff0c;改进生产流程&am…

安卓 /proc 目录详解:从内核到进程的桥梁

在安卓系统中&#xff0c;/proc 目录是开发者、调试者、甚至是普通用户深入了解系统状态、性能及行为的一个重要入口。这个虚拟文件系统不仅包含了丰富的内核信息&#xff0c;还反映了运行中的每个进程的状态。 /proc 文件系统 /proc 文件系统&#xff08;procfs&#xff09;是…

振动分析-30-振动信号的幅值概率密度函数CWRU西楚大学轴承数据(实战)

文章目录 1 背景2 幅值概率密度函数3 实现流程3.1 自定义函数3.2 模拟正弦信号4 CWRU轴承数据4.1 加载数据4.2 相同工况不同故障4.3 相同数据不同份数5 参考附录1 背景 很多初学者刚接触故障诊断可能觉得很简单,套用深度学习模型进行训练,分类准确率达到99%即可。 在写论文时…

AL生成文章标题指定路径保存:创新工具助力内容创作高效启航

在信息爆炸的时代&#xff0c;一个吸引人的标题是文章成功的第一步。它不仅要准确概括文章内容&#xff0c;还要能激发读者的好奇心&#xff0c;促使他们点击阅读。随着人工智能技术的飞速发展&#xff0c;AL生成文章标题功能正逐渐成为内容创作者的新宠&#xff0c;看看它是如…

Python基本库的使用--urllib

开篇 本篇文章旨在总结urlib基本库的一些常用用法。 相关方法 urlopen 用户打开和读取URL。 import urllib.requestresponse urllib.request.urlopen(https://www.python.org) print(response.read().decode(utf-8))带data参数 import urllib.parse import urllib.requestda…

队列的实现与讲解

一.概念与结构 1.概念 只允许在⼀端进行插⼊数据操作&#xff0c;在另⼀端进行删除数据操作的特殊线性表&#xff0c;队列具有先进先出FIFO(First In First Out) ​ 入队列&#xff1a;进⾏插⼊操作的⼀端称为队尾 ​ 出队列&#xff1a;进⾏删除操作的⼀端称为队头 注意&…

WebRTC Connection Negotiate解决

最近有个项目 &#xff0c;部署之后一直显示&#xff0c;查了一些资料还是没有解决&#xff0c;无奈只有自己研究解决&#xff1f; 什么是内网穿透&#xff1f; 我们访问我们自己的官网产品页面&#xff0c;我们的服务器是一个单独的个体&#xff0c;有独立的公网ip&#xf…

2024年10月6日历史上的今天大事件早读

23年10月06日西汉“新莽政权”领袖王莽被刺身亡 1866年10月06日清政府批准筹设天津机器局 1905年10月06日俄国爆发铁路工人大罢工 1913年10月06日中、英西姆拉会商“西藏问题” 1927年10月06日阿尔-乔尔森主演第一部有声电影 1940年10月06日新四军获黄桥决战胜利 1949年1…