[米联客-XILINX-H3_CZ08_7100] FPGA程序设计基础实验连载-21读写I2C接口EEPROM实验

news2024/9/27 17:36:26

软件版本:VIVADO2021.1

操作系统:WIN10 64bit

硬件平台:适用 XILINX A7/K7/Z7/ZU/KU 系列 FPGA

实验平台:米联客-MLK-H3-CZ08-7100开发板

板卡获取平台:https://milianke.tmall.com/

登录“米联客”FPGA社区 http://www.uisrc.com 视频课程、答疑解惑!

目录

1概述

2 EEPROM-24C02介绍

3用户程序设计

3.1用户接口时序

3.2 RTC用户读写程序设计

3.2.1 状态机介绍

3.2.2 用户接口程序源码

4 FPGA工程

5 RTL仿真

5.1仿真激励文件

5.2仿真结果

6在线仿真

7下载演示

7.1硬件连接

7.2运行结果 


1概述

前面的课程中,我们学习了I2C总线协议,以及介绍了米联客I2C Master控制器的实现原理、内部状态机、I2C时序产生、外部控制接口。本文开始,后面所涉及的I2C总线相关内容都会使用该控制器实现。本实验使用米联客的uii2c控制器实现对EEPROM的访问。

2 EEPROM-24C02介绍

如下图,A0-A2是EEPROM I2C器件地址,SDA和SCL是EEPROM I2C总线SLAVE接口,WP是保护脚,一般接VCC。

24LXX 器件地址如下图

我们看下24C02的写时序,可以看到,支持单个字节的写,以及多个字节的写。首先发送器件的地址,然后发送需要写EEPROM存储空间的地址,之后就是数据,对于读操作一次可以写1个字节或者多个字节。

写字节操作BYTE WRITE

在起始位产生后,先写器件地址,再写芯片内存地址,再写入数据,最后产生停止位,每写一个字节都要产生ACK位。

页写PAGE WRITE

页写和字节写差不多,在字节写的基础上,连续写入数据,最后产生停止位。

我们看下24C02的读时序,可以看到,支持单个字节的读,以及多个字节的读。以下支持3种读的方式:

读当前地址CURRENT ADDRESS READ

只要发送器件地址就能读当前内存地址所指向的地址空间数据,最后的读数据可以不需要发送ACK

随机读RANDOM READ

需要发送器件地址,然后发送内存地址,之后再发送器件地址并且读取到数据,最后的读数据可以不需要发送ACK。

连续读SEQUENTIAL READ

可以从第一种和第二种读方式启动后,连续读取,但是需要注意的时候除最后一个读数据,其他的读主机都需要发送ACK。

I2C起始停止时序

I2C时序参数

3用户程序设计

3.1用户接口时序

先温习下前面课程内容中关于I2C控制器的功能模块接口信号:

IO_sda为I2C双向数据总线

O_scl为I2C时钟

I_wr_cnt写数据字节长度,包含了器件地址,发送I_iic_req前,预设该值

I_rd_cnt读数据字节长度,仅包含读回有效部分,发送I_iic_req前,预设该值

I_wr_data写入的数据

O_rd_data读出的数据,如果是读请求,当O_iic_busy从高变低代表数据读回有效

I_iic_req I2C操作请求,根据I_rd_cnt是否大于0决定是否有读请求

I_iic_mode是否支持随机读写,发送I_iic_req前,预设该值

O_iic_busy总线忙

请求一次I2C传输的控制时序如下:

首先在O_iic_busy=0即I2C总线空闲情况下,设置I_wr_cnt,I_rd_cnt,I_wr_data,并且设置I_iic_req=1,启动I2C传输。当O_iic_busy=1说明I2C控制器开始传输,这时候可以设置I_iic_req=0,结束本次请求,并且等待O_iic_busy=0,当O_iic_busy=0代表本次传

传输结束.如果发送的是读请求(当I_rd_cnt>0),则此时O_rd_data有效可以读走数据。

3.2 RTC用户读写程序设计

3.2.1 状态机介绍

3.2.2 用户接口程序源码
/*******************************eeprom_test*********************
--1.本实验目的用于验证米联客I2C控制器
--2.通过写入数据到EEPROM并且读出比对数据,确认I2C控制器是否工作正常
--3.本实验也演示了,如何使用米联客I2C控制器的信号接口
*********************************************************************/
`timescale 1ns / 1ns//仿真时间间隔/精度

module eeprom_test
(
input  wire I_sysclk_p,
input  wire I_sysclk_n,//系统时钟输入
output wire O_iic_scl,// I2C SCL时钟
inout  wire IO_iic_sda,//I2C SDA数据总线
output wire [3:0]O_test_led,//测试LED
output wire O_led //error LED
);
//localparam SYSCLKHZ     =  100_000_00; //仿真用系统时钟
localparam SYSCLKHZ     =  100_000_000; //定义系统时钟100MHZ
localparam T500MS_CNT   = (SYSCLKHZ/2-1); //定义每500ms访问一次EEPROM
wire I_clk;
IBUFGDS CLK_U(
.I(I_sysclk_p),
.IB(I_sysclk_n),
.O(I_clk)
);
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 iic_sda_dg;
wire iic_bus_error;  //i2c总线错误
reg iic_error = 1'b0; //i2c 读出数据有错误
assign O_test_led = rd_data[3:0];//测试LED输出
assign O_led = iic_error;//通过LED显示错误标志
assign t500ms_en = (t500ms_cnt==T500MS_CNT);//500ms 使能信号       
//通过内部计数器实现复位
always@(posedge I_clk) begin
    if(!rst_cnt[8]) 
        rst_cnt <= rst_cnt + 1'b1;
end

//I2C总线延迟间隔操作,该时间约不能低于500us,否则会导致EEPROM操作失败
always@(posedge I_clk) begin
    if(!rst_cnt[8])
        delay_cnt <= 0;
    else if((TS_S == 3'd0 || TS_S == 3'd2 )) 
        delay_cnt <= delay_cnt + 1'b1;
    else 
        delay_cnt <= 0;
end

//每间隔500ms状态机运行一次
always@(posedge I_clk) begin
    if(!rst_cnt[8])
        t500ms_cnt <= 0;
    else if(t500ms_cnt == T500MS_CNT) 
        t500ms_cnt <= 0;
    else 
        t500ms_cnt <= t500ms_cnt + 1'b1;
end

//状态机实现每次写1字节到EEPROM然后再读1字节
always@(posedge I_clk) begin
    if(!rst_cnt[8])begin
        iic_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 begin
        case(TS_S)
        0:if(!iic_busy)begin//当总线非忙,可以开始一次I2C数据操作
            iic_req <= 1'b1;//请求发送数据
            wr_data <= {8'hfe,wr_data[15:8],wr_data[15:8],8'b10100000};//数据寄存器中8'b10100000代表需要写的器件地址,第一个wr_data[15:8]代表了EEPROM内存地址,第二个wr_data[15:8]代表了写入数据
            rd_cnt  <= 8'd0; //不需要读数据
            wr_cnt  <= 8'd3; //需要写入3个BYTES数据,包含1个器件地址,1个EEPROM 寄存器地址 1个数据   
            TS_S     <= 3'd1;//进入下一个状态      
        end
        1:if(iic_busy)begin 
            iic_req  <= 1'b0; //重置iic_req=0
            TS_S     <= 3'd2;
        end
        2:if(!iic_busy&&delay_cnt[19])begin //当总线非忙,可以开始一次I2C数据操作,该时间约不能低于500us,否则会导致EEPROM操作失败
            iic_req  <= 1'b1;//请求接收数据
            rd_cnt  <= 8'd1; //需要读1个BYTE
            wr_cnt  <= 8'd2; //需要些2个BYTE(1个器件地址8'b10100000,和1个寄存器地址wr_data[15:8])(I2C控制器会自定设置读写标志位)
            TS_S    <= 3'd3;  //进入下一个状态
        end     
        3:if(iic_busy)begin 
            iic_req  <= 1'b0; //重置iic_req=0
            TS_S     <= 3'd4;
        end    
        4:if(!iic_busy)begin//当总线非忙,代表前面读数据完成
            if(wr_data[23:16] != rd_data[7:0])//比对数据是否正确
                iic_error <= 1'b1;//如果有错误,设置iic_error=1
            else 
                iic_error <= 1'b0;//如果有错误,设置iic_error=0
                wr_data[15:8] <= wr_data[15:8] + 1'b1;//wr_data[15:8]+1 地址和数据都加1
            TS_S    <= 3'd5;
        end
        5:if(t500ms_en)begin//延迟操作后进入下一个状态
            TS_S    <= 3'd0; 
        end 
        default:
            TS_S    <= 3'd0;
    endcase
   end
end

// 以下代码为在线逻辑分析仪观察调试部分
reg scl_r = 1'b0;
always @(posedge I_clk)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_clk) begin
    dg_clk_cnt <= dg_clk_cnt+ 1'b1;
end

ila_0 ila_debug (
    .clk(I_clk),//在线逻辑分析仪的时钟
    .probe0({rd_data[7:0],wr_data[23:0],TS_S,iic_error,iic_req,scl_r,iic_sda_dg,iic_bus_error,dg_clk,t500ms_en}) // 需要观察的调试信号
);
//例化I2C控制模块
uii2c#
(
.WMEN_LEN(4),//最大支持一次写入4BYTE(包含器件地址)
.RMEN_LEN(4),//最大支持一次读出4BYTE(包含器件地址)
.CLK_DIV(SYSCLKHZ/100000)//100KHZ I2C总线时钟
)
uii2c_inst
(
.I_clk(I_clk),//系统时钟
.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(iic_sda_dg)//debug IO_iic_sda
);  
endmodule

4 FPGA工程

fpga工程的创建过程不再重复

米联客的代码管理规范,在对应的FPGA工程路径下创建uisrc路径,并且创建以下文件夹

01_rtl:放用户编写的rtl代码

02_sim:仿真文件或者工程

03_ip:放使用到的ip文件

04_pin:放fpga的pin脚约束文件或者时序约束文件

05_boot:放编译好的bit或者bin文件(一般为空)

06_doc:放本一些相关文档(一般为空)

5 RTL仿真

5.1仿真激励文件

eeprom仿真模型

`define timeslice 20
module eeprom(
input scl,
inout sda);
reg out_flag;
reg [7:0] memory[2047:0];
reg[10:0] address;
reg[7:0] memory_buf;
reg [7:0] sda_buf;
reg [7:0] shift;
reg [7:0] addr_byte;
reg [7:0] ctrl_byte;
reg [1:0] State;
integer i;

// ----------------------------------------------
parameter r7=8'b10101111,w7=8'b10101110,
          r6=8'b10101101,w6=8'b10101100,
             r5=8'b10101011,w5=8'b10101010,
             r4=8'b10101001,w4=8'b10101000,
             r3=8'b10100111,w3=8'b10100110,
          r2=8'b10100101,w2=8'b10100100,
             r1=8'b10100011,w1=8'b10100010,
             r0=8'b10100001,w0=8'b10100000;
             
//---------------------------------------------------

assign sda= (out_flag == 1)?sda_buf[7]:1'bz;
//--------------------寄存器和存储器初始化------------------------------
initial
begin
addr_byte   =0;
ctrl_byte   =0;
out_flag    =0;
sda_buf     =0;
State       =2'b00;
memory_buf  =0;
address     =0;
shift       =0;
for(i=0;i<=2047;i=i+1)
memory[i]=0;
end

//--------------启动信号检测--------------
always @(negedge sda)
            if(scl == 1)
             begin
                State=State+1;
                if(State==2'b11)
                 disable write_to_eeprm;
             end                
 /-------------------主状态机-----------------------
always @(posedge sda)
                if(scl == 1)
                stop_W_R;
                else
                begin
                casex(State)  
                2'b01:
                begin
                read_in;
                    if(ctrl_byte == w7||ctrl_byte == w6|| ctrl_byte == w5
                    || ctrl_byte == w4 || ctrl_byte == w3 || ctrl_byte == w2 ||ctrl_byte == w1 ||ctrl_byte == w0)
                     begin
                        State = 2'b10;
                        write_to_eeprm;
                     end
                     else 
                        State = 2'b00;
                end
                     
                2'b11:
                     read_from_eeprm;
                     default:
                           State=2'b00;
                     endcase
                     end

                
//--------------操作停止------------------
task stop_W_R;
       begin
         
         State = 2'b00;
         addr_byte  =0;
         ctrl_byte  =0;
         out_flag   =0;
         sda_buf   =0;
         end
    endtask
//----------------读进控制字和存储单元地址-------------------
    task read_in;
    begin
    shift_in(ctrl_byte);
    shift_in(addr_byte);
    end
    endtask
    //-------------EEPROM--------------------
    task write_to_eeprm;
    begin
    shift_in(memory_buf);
    address    ={ctrl_byte[3:1],addr_byte};
    memory[address]  = memory_buf;
    $display("eeprm---memory[%0h]=%0h",address,memory[address]);
    State= 2'b00;
    end
    endtask
    
    
    //-------------EEPROM读操作_______________________
    task read_from_eeprm;
    begin
    shift_in(ctrl_byte);
    if(ctrl_byte == r7 || ctrl_byte == r6 || ctrl_byte == r5 || ctrl_byte == r4 || ctrl_byte == r3 || ctrl_byte == r2
        || ctrl_byte == r1 || ctrl_byte == r0)
         begin
         address = {ctrl_byte[3:1],addr_byte};
         sda_buf =memory [address];
         shift_out;
         State = 2'b00;
    end
    end
    endtask
    
    // ---SDA 数据线上的数据存入寄存器 ,数据在SCL的高电平有效------------------
    task shift_in;
    output[7:0] shift;
    begin
    @(posedge scl) shift[7]=sda;
    @(posedge scl) shift[6]=sda;
    @(posedge scl) shift[5]=sda;
    @(posedge scl) shift[4]=sda;
    @(posedge scl) shift[3]=sda;
    @(posedge scl) shift[2]=sda;
    @(posedge scl) shift[1]=sda;
    @(posedge scl) shift[0]=sda;
    @(negedge scl) //ACK
    begin
    #`timeslice;//模拟芯片的延迟输出ACK
    out_flag = 1;
    sda_buf  =0;
    end
    @(negedge scl)//结束ACK
    #`timeslice out_flag  = 0;
    end
    endtask
    //----------EEPROM存储器中的数据通过SDA数据线输出,数据在SCL低电平时变化
   task shift_out;
    begin
    out_flag= 1;
    for(i=6;i>=0;i=i-1)
    begin
    
    @(negedge scl);
    # `timeslice;
    sda_buf = sda_buf<<1;
    end
   @(negedge scl) # `timeslice sda_buf[7]=1;
    @(negedge scl) # `timeslice out_flag=0;
    end
    endtask
    endmodule 

顶层调用接口仿真代码

`timescale 1ns / 1ns

module eeprom_test_tb;
reg I_sysclk_p = 1'b0;
reg I_sysclk_n = 1'b1;
wire O_iic_scl;
wire IO_iic_sda;

pullup( IO_iic_sda );

eeprom_test eeprom_test_inst
(
.I_sysclk_p(I_sysclk_p),
.I_sysclk_n(I_sysclk_n),
.O_iic_scl(O_iic_scl),
.IO_iic_sda(IO_iic_sda)
);
    
eeprom eeprom_inst(
.scl(O_iic_scl),
.sda(IO_iic_sda)
);    

always 
    begin
        #5 I_sysclk_p = ~I_sysclk_p;
        #5 I_sysclk_n = ~I_sysclk_n;
    end
 
endmodule

5.2仿真结果

启动后,右击需要观察的信号,添加到波形窗口,并仿真。

放大观察I2C时序,查看写操作START和ACK位置

放大观察I2C时序,查看写读操作Repeated START

6在线仿真

设置ila的采样深度为8192,越大观察的数据越多,但是消耗的Bram也越多,设置支持capture control模式

设置需要观察数据的总位宽

注意代码中,通过512分频器产生的信号作为capture信号

// 以下代码为在线逻辑分析仪观察调试部分
reg scl_r = 1'b0;
always @(posedge I_clk)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_clk) begin
    dg_clk_cnt <= dg_clk_cnt+ 1'b1;
end

ila_0 ila_debug (
   .clk(I_clk),//在线逻辑分析仪的时钟
   .probe0({rd_data[7:0],wr_data[23:0],TS_S,iic_error,iic_req,scl_r,iic_sda_dg,iic_bus_error,dg_clk,t500ms_en}) // 需要观察的调试信号
);

7下载演示

为了方便观察结果,使用LED观察,每间隔500ms完成一次读写操作

assign O_test_led = rd_data[3:0];//测试LED输出

下载程序前,先确保FPGA工程已经编译。

7.1硬件连接

(该教程为通用型教程,教程中仅展示一款示例开发板的连接方式,具体连接方式以所购买的开发板型号以及结合配套代码管脚约束为准。)

请确保下载器和开发板已经正确连接,另外需要把核心板上的2P模式开关设置到JTAG模式,即ON ON,并且开发板已经上电。(注意JTAG端子不支持热插拔,而USB接口支持,所以在不通电的情况下接通好JTAG后,再插入USB到电脑,之后再上电,以免造成JTAG IO损坏)

7.2运行结果 

(该教程为通用型教程,教程中仅展示一款示例开发板的上板现象,具体现象以所购买的开发板型号以及配套代码上板现象为准。)

1.通过LED观察I2C的读写结果,可以看到LED规律运行

2.通过ILA在线逻辑分析仪观察

Capure模式必须设置BASIC模式

用500ms作为触发信号

运行后抓到的波形如下

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

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

相关文章

B样条曲线法

1. B样条曲线法概述 1.1 B样条曲线法的定义与发展 B样条曲线法是一种基于控制点和节点向量的数学模型&#xff0c;用于几何建模和曲线设计。该方法由Paul de Casteljau和Pierre Bezier等人在20世纪60年代提出&#xff0c;并迅速发展成为一种广泛应用于计算机辅助设计&#xf…

Docker php文件本地包含--pearcmd.php利用

目录 前言 环境搭建 pearcmd.php巧妙利用 渗透 前言 docker包含日志文件&#xff0c;基本不可能&#xff0c;就以我自身的一个项目来说&#xff0c;在尝试包含日志文件时发现&#xff0c;客户将他的日志文件从定向到了设备文件&#xff0c;而php没有包含设备文件的权限 然…

【Python Web开发】Flask+HTML学习笔记

目录 Flask框架一、安装flask库二、运行一个网页三、库函数及变量 HTML标签语言一、基本格式二、标签2.1 块级标签2.1.1 标题2.1.2 div2.1.3 图片2.1.4 列表2.1.5 表格 2.2 行内标签2.2.1 span2.2.2 超链接2.2.3 输入 2.3 其他标签2.3.1 提交表单 Flask框架 一、安装flask库 …

Unity 3D学习资料集合

本文包含了unity3D 游戏开发相关的学习资料&#xff0c;包含了入门、进阶、性能优化、面试和书籍等学习资料&#xff0c;含金量非常高&#xff0c;在这里分享给大家&#xff0c;欢迎收藏。 学习社区 1.Unity3D开发者 Unity3D开发者论坛是一个专注于Unity引擎的开发者社区。在这…

国内AI工具分类大盘点,这些神器你都用过了吗?

AI爆发到现成已经快2年了&#xff0c;基本上我自己也使用了近2年的AI产品。国内、外的AI产品体验了很多。 从最初文本聊天类的gpt、new bing、文心一言、通义千问&#xff0c;到后面绘图类Midjourney、Stable Diffusion、文心一格、通义万相等等。 在这里来分享我自己使用的一…

游戏设计师:创造虚拟世界的艺术家

游戏设计师&#xff0c;这个听起来富有创造性和趣味的职业&#xff0c;正逐渐成为数字娱乐行业中备受瞩目和追捧的角色。他们是虚拟世界的建造者、体验的创造者和叙事的编织者。在电子游戏风靡全球的今天&#xff0c;游戏设计师的工作远不只是画画或编故事那么简单&#xff0c;…

如何设计接口测试用例?

&#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 接口测试是一种软件测试方法&#xff0c;用于验证软件系统中不同组件或模块之间的接口是否正常工作&#xff0c;主要关注于接口的输入和输出&#xff0c;以及接…

Linux的远程登录教程(超详细)

我们在进行远程登录时要用的一种协议叫SSH&#xff0c;那什么叫SSH呢&#xff1f; SSH&#xff08;Secure Shell&#xff09;是一种网络协议&#xff0c;用于在不安全的网络中提供安全的远程登录和其他网络服务。它通过加密技术确保数据在传输过程中的机密性和完整性&#xff…

ESP32-IDF http请求崩溃问题分析与解决

文章目录 esp32s3 http请求崩溃问题代码讨论修正后不崩溃的代码esp32相关文章 ESP32S3板子, 一运行http请求百度网站的例子, 就会panic死机, 记录下出现及解决过程. esp32s3 http请求崩溃 一执行http请求的perform就会崩溃, 打印如图 ESP32-IDF 的http请求代码是根据官方dem…

DDK拧紧控制器AFC1500维修_无法通讯问题怎么解决

‌DDK拧紧控制器在工业装配领域以其高效、精准的性能受到众多企业的青睐。特别是在汽车制造、航空航天、重型机械和其他需要大量螺栓紧固的行业。 ‌工具小巧 拧紧力范围广泛‌ 联网功能强大 配备扭矩和角度传感器 多回路控制器 一、检查电源及插头‌&#xff1a;首先应检…

2024公立医院绩效考核进行中,契约锁电子签章助力电子病历评级

2024年公立医院绩效考核正在进行中&#xff0c;由国家卫健委最新印发的《国家二级公立医院绩效考核操作手册&#xff08;2024版&#xff09;》以及《国家三级公立医院绩效考核操作手册&#xff08;2024版&#xff09;》将“电子病历应用功能水平分析应逐步提高”列为新增考核指…

【相似度计算 / 2】

题目 代码 #include <bits/stdc.h> using namespace std; unordered_set<string> s1, s2; int cnt1, cnt2, cnt; int n, m; void process(string& x) {for(char& c : x){if(c > a) continue;else c a - A;} } int main() {cin >> n >> m;…

加密软件的特殊功能有哪些

1.透明加密&#xff1a;在用户不感知的情况下自动对文件进行加密和解密&#xff0c;保证数据的安全性和使用的便捷性。 2.多种加密模式&#xff1a;提供多种加密模式&#xff0c;如透明加密、智能加密、只解密不加密等&#xff0c;满足不同场景下的数据保护需求。 3.应用加密…

基于协同过滤算法的电影推荐系统的设计与实现(论文+源码)_kaic

摘 要 现在观看电影已逐渐成为人们日常生活中最常见的一种娱乐方式&#xff0c;人们通常会在周末或在休息、吃饭时间不由自主地在各种视频软件中搜索当前火热的影视节目。但是现在的视频软件电影推荐功能不够完善&#xff0c;所以需要开发出一套系统来使用户只需要简单操作就能…

如何实现OpenHarmony的OTA升级

OTA简介 随着设备系统日新月异&#xff0c;用户如何及时获取系统的更新&#xff0c;体验新版本带来的新的体验&#xff0c;以及提升系统的稳定性和安全性成为了每个厂商都面临的严峻问题。OTA&#xff08;Over the Air&#xff09;提供对设备远程升级的能力。升级子系统对用户…

白嫖游戏指南,Epic喜加一:《野卡橄榄球》

前言 Epic喜加一&#xff1a;《野卡橄榄球》《野卡橄榄球》简介&#xff1a; 前言 接下来有时间会分享一些游戏相关可以白嫖的资源&#xff0c;包括游戏本体、游戏素材资源等等。 有需要的小伙伴可以关注这个专栏&#xff0c;不定期更新哦&#xff01; 专栏&#xff1a;白嫖…

微信小程序中Towxml解析Markdown及html

一、Towxml Towxml 是一个让小程序可以解析Markdown、HTML的解析库。 二、引入 2.1 clone代码 git clone https://github.com/sbfkcel/towxml.git2.2 安装依赖 npm install2.3 打包 npm run build2.4 引入文件 将dist文件复制到微信小程序根目录&#xff0c;改名为towx…

简化WPF开发:CommunityToolkit.Mvvm在MVVM架构中的实践与优势

文章目录 前言一、CommunityToolkit.Mvvm1.特点2.优点3.缺点 二、WPF项目应用1.引入到 WPF 项目2.使用示例 总结 前言 CommunityToolkit.Mvvm 是 Microsoft 提供的一个社区工具包&#xff0c;专为 MVVM&#xff08;Model-View-ViewModel&#xff09;模式设计&#xff0c;旨在帮…

基于Virtex UltraScale+ VU13P FPGA的4路FMC接口基带信号处理平台

Virtex UltraScale系列 FPGA处理器&#xff1a;XCVU13P-2FHGB2104I动态存储数量&#xff1a;2组DDR4 SDRAM动态存储容量&#xff1a;每组4GByte&#xff0c;每个颗粒为8GBit动态存储带宽&#xff1a;工作时钟1000MHz&#xff0c;数据率2000Mbps板载6路QSFP光纤接口板载4个FMC高…

echarts 柱状图_堆叠柱状图_数据分区_常用图表配置_数据可视化

Echarts 常用各类图表模板配置 注意&#xff1a; 这里主要就是基于各类图表&#xff0c;更多的使用 Echarts 的各类配置项&#xff1b; 以下代码都可以复制到 Echarts 官网&#xff0c;直接预览&#xff1b; 图标模板目录 Echarts 常用各类图表模板配置一、数据分区显示二、折…