FPGA模块——以太网(1)MDIO读写

news2024/11/24 2:44:41

FPGA模块——以太网MDIO读写

  • MDIO接口介绍
  • MDIO接口代码
    • (1)MDIO接口驱动代码
    • (2)使用MDIO驱动的代码

MDIO接口介绍

MDIO是串行管理接口。MAC 和 PHY 芯片有一个配置接口,即 MDIO 接口,可以配置 PHY 芯片的工作模式以及获取 PHY 芯片的若干状态信息。

1.MDIO部分的接口结构
在这里插入图片描述

2.千兆以太网在接口上兼容百兆和十兆以太网。
在这里插入图片描述
在这里插入图片描述
3.YT8511 是一个千兆以太网物理层收发器,支持 1000/100/10Mbps 通信速率,该芯片内部的参数可以通过MDIO接口进行配置。
在这里插入图片描述

MDIO接口代码

MDIO接口主要是控制三根接口线,进行驱动和读写。
在这里插入图片描述

(1)MDIO接口驱动代码

mdio_dri文件:输入一些读写开始等等控制信号,输出读到的数据和控制芯片的时钟

module mdio_dri #(
    parameter  PHY_ADDR = 5'b00100,//PHY地址
    parameter  CLK_DIV  = 6'd10    //分频系数
   )
    (
    input                clk       , //时钟信号
    input                rst_n     , //复位信号,低电平有效
    input                op_exec   , //触发开始信号
    input                op_rh_wl  , //低电平写,高电平读
    input        [4:0]   op_addr   , //寄存器地址
    input        [15:0]  op_wr_data, //写入寄存器的数据
    output  reg          op_done   , //读写完成
    output  reg  [15:0]  op_rd_data, //读出的数据
    output  reg          op_rd_ack , //读应答信号 0:应答 1:未应答
    output  reg          dri_clk   , //驱动时钟
    
    output  reg          eth_mdc   , //PHY管理接口的时钟信号
    inout                eth_mdio    //PHY管理接口的双向数据信号
    );

//parameter define
localparam st_idle    = 6'b00_0001;  //空闲状态
localparam st_pre     = 6'b00_0010;  //发送PRE(前导码)
localparam st_start   = 6'b00_0100;  //开始状态,发送ST(开始)+OP(操作码)
localparam st_addr    = 6'b00_1000;  //写地址,发送PHY地址+寄存器地址
localparam st_wr_data = 6'b01_0000;  //TA+写数据
localparam st_rd_data = 6'b10_0000;  //TA+读数据

//reg define
reg    [5:0]  cur_state ;
reg    [5:0]  next_state;

reg    [5:0]  clk_cnt   ;  //分频计数                      
reg   [15:0]  wr_data_t ;  //缓存写寄存器的数据
reg    [4:0]  addr_t    ;  //缓存寄存器地址
reg    [6:0]  cnt       ;  //计数器
reg           st_done   ;  //状态开始跳转信号
reg    [1:0]  op_code   ;  //操作码  2'b01(写)  2'b10(读)                  
reg           mdio_dir  ;  //MDIO数据(SDA)方向控制
reg           mdio_out  ;  //MDIO输出信号
reg   [15:0]  rd_data_t ;  //缓存读寄存器数据

//wire define
wire          mdio_in    ; //MDIO数据输入
wire   [5:0]  clk_divide ; //PHY_CLK的分频系数

assign eth_mdio = mdio_dir ? mdio_out : 1'bz; //控制双向io方向
assign mdio_in = eth_mdio;                    //MDIO数据输入
//将PHY_CLK的分频系数除以2,得到dri_clk的分频系数,方便对MDC和MDIO信号操作
assign clk_divide = CLK_DIV >> 1;

//分频得到dri_clk时钟
always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        dri_clk <=  1'b0;
        clk_cnt <= 1'b0;
    end
    else if(clk_cnt == clk_divide[5:1] - 1'd1) begin
        clk_cnt <= 1'b0;
        dri_clk <= ~dri_clk;
    end
    else
        clk_cnt <= clk_cnt + 1'b1;
end

//产生PHY_MDC时钟
always @(posedge dri_clk or negedge rst_n) begin
    if(!rst_n)
        eth_mdc <= 1'b1;
    else if(cnt[0] == 1'b0)
        eth_mdc <= 1'b1;
    else    
        eth_mdc <= 1'b0;  
end

//(三段式状态机)同步时序描述状态转移
always @(posedge dri_clk or negedge rst_n) begin
    if(!rst_n)
        cur_state <= st_idle;
    else
        cur_state <= next_state;
end  

//组合逻辑判断状态转移条件
always @(*) begin
    next_state = st_idle;
    case(cur_state)
        st_idle : begin
            if(op_exec)
                next_state = st_pre;
            else 
                next_state = st_idle;   
        end  
        st_pre : begin
            if(st_done)
                next_state = st_start;
            else
                next_state = st_pre;
        end
        st_start : begin
            if(st_done)
                next_state = st_addr;
            else
                next_state = st_start;
        end
        st_addr : begin
            if(st_done) begin
                if(op_code == 2'b01)                //MDIO接口写操作  
                    next_state = st_wr_data;
                else
                    next_state = st_rd_data;        //MDIO接口读操作  
            end
            else
                next_state = st_addr;
        end
        st_wr_data : begin
            if(st_done)
                next_state = st_idle;
            else
                next_state = st_wr_data;
        end        
        st_rd_data : begin
            if(st_done)
                next_state = st_idle;
            else
                next_state = st_rd_data;
        end                                                                          
        default : next_state = st_idle;
    endcase
  end

//时序电路描述状态输出
always @(posedge dri_clk or negedge rst_n) begin
    if(!rst_n) begin
        cnt <= 5'd0;
        op_code <= 1'b0;
        addr_t <= 1'b0;
        wr_data_t <= 1'b0;
        rd_data_t <= 1'b0;
        op_done <= 1'b0;
        st_done <= 1'b0; 
        op_rd_data <= 1'b0;
        op_rd_ack <= 1'b1;
        mdio_dir <= 1'b0;
        mdio_out <= 1'b1;
    end
    else begin
        st_done <= 1'b0 ;                            
        cnt     <= cnt +1'b1 ;          
        case(cur_state)
            st_idle : begin
                mdio_out <= 1'b1;                     
                mdio_dir <= 1'b0;                     
                op_done <= 1'b0;                     
                cnt <= 7'b0;  
                if(op_exec) begin
                    op_code <= {op_rh_wl,~op_rh_wl}; //OP_CODE: 2'b01(写)  2'b10(读) 
                    addr_t <= op_addr;
                    wr_data_t <= op_wr_data;
                    op_rd_ack <= 1'b1;
                end     
            end 
            st_pre : begin                          //发送前导码:32个1bit 
                mdio_dir <= 1'b1;                   //切换MDIO引脚方向:输出
                mdio_out <= 1'b1;                   //MDIO引脚输出高电平
                if(cnt == 7'd62) 
                    st_done <= 1'b1;
                else if(cnt == 7'd63)
                    cnt <= 7'b0;
            end            
            st_start  : begin
                case(cnt)
                    7'd1 : mdio_out <= 1'b0;        //发送开始信号 2'b01
                    7'd3 : mdio_out <= 1'b1; 
                    7'd5 : mdio_out <= op_code[1];  //发送操作码
                    7'd6 : st_done <= 1'b1;
                    7'd7 : begin
                               mdio_out <= op_code[0];
                               cnt <= 7'b0;  
                           end    
                    default : ;
                endcase
            end    
            st_addr : begin
                case(cnt)
                    7'd1 : mdio_out <= PHY_ADDR[4]; //发送PHY地址
                    7'd3 : mdio_out <= PHY_ADDR[3];
                    7'd5 : mdio_out <= PHY_ADDR[2];
                    7'd7 : mdio_out <= PHY_ADDR[1];  
                    7'd9 : mdio_out <= PHY_ADDR[0];
                    7'd11: mdio_out <= addr_t[4];  //发送寄存器地址
                    7'd13: mdio_out <= addr_t[3];
                    7'd15: mdio_out <= addr_t[2];
                    7'd17: mdio_out <= addr_t[1];  
                    7'd18: st_done <= 1'b1;
                    7'd19: begin
                               mdio_out <= addr_t[0]; 
                               cnt <= 7'd0;
                           end    
                    default : ;
                endcase                
            end    
            st_wr_data : begin
                case(cnt)
                    7'd1 : mdio_out <= 1'b1;         //发送TA,写操作(2'b10)
                    7'd3 : mdio_out <= 1'b0;
                    7'd5 : mdio_out <= wr_data_t[15];//发送写寄存器数据
                    7'd7 : mdio_out <= wr_data_t[14];
                    7'd9 : mdio_out <= wr_data_t[13];
                    7'd11: mdio_out <= wr_data_t[12];
                    7'd13: mdio_out <= wr_data_t[11];
                    7'd15: mdio_out <= wr_data_t[10];
                    7'd17: mdio_out <= wr_data_t[9];
                    7'd19: mdio_out <= wr_data_t[8];
                    7'd21: mdio_out <= wr_data_t[7];
                    7'd23: mdio_out <= wr_data_t[6];
                    7'd25: mdio_out <= wr_data_t[5];
                    7'd27: mdio_out <= wr_data_t[4];
                    7'd29: mdio_out <= wr_data_t[3];
                    7'd31: mdio_out <= wr_data_t[2];
                    7'd33: mdio_out <= wr_data_t[1];
                    7'd35: mdio_out <= wr_data_t[0];
                    7'd37: begin
                        mdio_dir <= 1'b0;
                        mdio_out <= 1'b1;
                    end
                    7'd39: st_done <= 1'b1;           
                    7'd40: begin
                               cnt <= 7'b0;
                               op_done <= 1'b1;      //写操作完成,拉高op_done信号 
                           end    
                    default : ;
                endcase    
            end
            st_rd_data : begin
                case(cnt)
                    7'd1 : begin
                        mdio_dir <= 1'b0;            //MDIO引脚切换至输入状态
                        mdio_out <= 1'b1;
                    end
                    7'd2 : ;                         //TA[1]位,该位为高阻状态,不操作             
                    7'd4 : op_rd_ack <= mdio_in;     //TA[0]位,0(应答) 1(未应答)
                    7'd6 : rd_data_t[15] <= mdio_in; //接收寄存器数据
                    7'd8 : rd_data_t[14] <= mdio_in;
                    7'd10: rd_data_t[13] <= mdio_in;
                    7'd12: rd_data_t[12] <= mdio_in;
                    7'd14: rd_data_t[11] <= mdio_in;
                    7'd16: rd_data_t[10] <= mdio_in;
                    7'd18: rd_data_t[9] <= mdio_in;
                    7'd20: rd_data_t[8] <= mdio_in;
                    7'd22: rd_data_t[7] <= mdio_in;
                    7'd24: rd_data_t[6] <= mdio_in;
                    7'd26: rd_data_t[5] <= mdio_in;
                    7'd28: rd_data_t[4] <= mdio_in;
                    7'd30: rd_data_t[3] <= mdio_in;
                    7'd32: rd_data_t[2] <= mdio_in;
                    7'd34: rd_data_t[1] <= mdio_in;
                    7'd36: rd_data_t[0] <= mdio_in;
                    7'd39: st_done <= 1'b1;
                    7'd40: begin
                        op_done <= 1'b1;             //读操作完成,拉高op_done信号          
                        op_rd_data <= rd_data_t;
                        rd_data_t <= 16'd0;
                        cnt <= 7'd0;
                    end
                    default : ;
                endcase   
            end                
            default : ;
        endcase               
    end
end                    

endmodule

(2)使用MDIO驱动的代码

mdio_ctrl文件:对寄存器进行读写配置,主要还是读取状态,用于显示

1.基本控制寄存器地址:0x00
代码里面配置为16’h9140 即1001_0001_0100_0000
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.基本状态寄存器地址:0x01
用来读出转态信息
在这里插入图片描述
在这里插入图片描述

3.特定状态寄存器地址:0x11
在这里插入图片描述

module mdio_ctrl(
    input                clk           ,
    input                rst_n         ,
    input                soft_rst_trig , //软复位触发信号
    input                op_done       , //读写完成
    input        [15:0]  op_rd_data    , //读出的数据
    input                op_rd_ack     , //读应答信号 0:应答 1:未应答
    output  reg          op_exec       , //触发开始信号
    output  reg          op_rh_wl      , //低电平写,高电平读
    output  reg  [4:0]   op_addr       , //寄存器地址
    output  reg  [15:0]  op_wr_data    , //写入寄存器的数据
    output       [1:0]   led             //LED灯指示以太网连接状态
    );

//reg define
reg          rst_trig_d0;    
reg          rst_trig_d1;    
reg          rst_trig_flag;   //soft_rst_trig信号触发标志
reg  [23:0]  timer_cnt;       //定时计数器 
reg          timer_done;      //定时完成信号
reg          start_next;      //开始读下一个寄存器标致
reg          read_next;       //处于读下一个寄存器的过程
reg          link_error;      //链路断开或者自协商未完成
reg  [2:0]   flow_cnt;        //流程控制计数器 
reg  [1:0]   speed_status;    //连接速率 

//wire define
wire         pos_rst_trig;    //soft_rst_trig信号上升沿

//采soft_rst_trig信号上升沿
assign pos_rst_trig = ~rst_trig_d1 & rst_trig_d0;
//未连接或连接失败时led赋值00
// 01:10Mbps  10:100Mbps  11:1000Mbps 00:其他情况
assign led = link_error ? 2'b00: speed_status;
//对soft_rst_trig信号延时打拍
always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        rst_trig_d0 <= 1'b0;
        rst_trig_d1 <= 1'b0;
    end
    else begin
        rst_trig_d0 <= soft_rst_trig;
        rst_trig_d1 <= rst_trig_d0;
    end
end

//定时计数
always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        timer_cnt <= 1'b0;
        timer_done <= 1'b0;
    end
    else begin
        if(timer_cnt == 24'd1_000_000 - 1'b1) begin
            timer_done <= 1'b1;
            timer_cnt <= 1'b0;
        end
        else begin
            timer_done <= 1'b0;
            timer_cnt <= timer_cnt + 1'b1;
        end
    end
end    

//根据软复位信号对MDIO接口进行软复位,并定时读取以太网的连接状态
always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        flow_cnt <= 3'd0;
        rst_trig_flag <= 1'b0;
        speed_status <= 2'b00;
        op_exec <= 1'b0; 
        op_rh_wl <= 1'b0; 
        op_addr <= 1'b0;       
        op_wr_data <= 1'b0; 
        start_next <= 1'b0; 
        read_next <= 1'b0; 
        link_error <= 1'b0;
    end
    else begin
        op_exec <= 1'b0; 
        if(pos_rst_trig)                      
            rst_trig_flag <= 1'b1;             //拉高软复位触发标志
        case(flow_cnt)
            2'd0 : begin
                if(rst_trig_flag) begin        //开始对MDIO接口进行软复位
                    op_exec <= 1'b1; 
                    op_rh_wl <= 1'b0; 
                    op_addr <= 5'h00; 
                    op_wr_data <= 16'h9140;    // Bit[15]=1'b1,表示软复位
                    flow_cnt <= 3'd1;
                end
                else if(timer_done) begin      //定时完成,获取以太网连接状态
                    op_exec <= 1'b1; 
                    op_rh_wl <= 1'b1; 
                    op_addr <= 5'h01; 
                    flow_cnt <= 3'd2;
                end
                else if(start_next) begin       //开始读下一个寄存器,获取以太网通信速度
                    op_exec <= 1'b1; 
                    op_rh_wl <= 1'b1; 
                    op_addr <= 5'h11;
                    flow_cnt <= 3'd2;
                    start_next <= 1'b0; 
                    read_next <= 1'b1; 
                end
            end    
            2'd1 : begin
                if(op_done) begin              //MDIO接口软复位完成
                    flow_cnt <= 3'd0;
                    rst_trig_flag <= 1'b0;
                end
            end
            2'd2 : begin                       
                if(op_done) begin              //MDIO接口读操作完成
                    if(op_rd_ack == 1'b0 && read_next == 1'b0) //读第一个寄存器,接口成功应答,
                        flow_cnt <= 3'd3;                      //读第下一个寄存器,接口成功应答
                    else if(op_rd_ack == 1'b0 && read_next == 1'b1)begin 
                        read_next <= 1'b0;
                        flow_cnt <= 3'd4;
                    end
                    else begin
                        flow_cnt <= 3'd0;
                     end
                end    
            end
            2'd3 : begin                     
                flow_cnt <= 3'd0;          //链路正常并且自协商完成
                if(op_rd_data[5] == 1'b1 && op_rd_data[2] == 1'b1)begin
                    start_next <= 1;
                    link_error <= 0;
                end
                else begin
                    link_error <= 1'b1;  
               end           
            end
            3'd4: begin
                flow_cnt <= 3'd0;
                if(op_rd_data[15:14] == 2'b10)
                    speed_status <= 2'b11; //1000Mbps
                else if(op_rd_data[15:14] == 2'b01) 
                    speed_status <= 2'b10; //100Mbps 
                else if(op_rd_data[15:14] == 2'b00) 
                    speed_status <= 2'b01; //10Mbps
                else
                    speed_status <= 2'b00; //其他情况  
            end
        endcase
    end    
end    

endmodule

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

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

相关文章

前端手动部署与自动化部署

连接服务器 先购买服务器 安装vscode插件 连接服务器 连接成功 手动部署 安装nginx 启动nginx systemctl start nginx systemctl status nginx systemctl enable nginx启动 检查状态 开机就启动nginx 开始手动部署 配置nginx 成功

flutter自定义地图Marker完美展示图片

世人都说雪景美 寒风冻脚无人疼 只道是一身正气 结论 参考Flutter集成高德地图并添加自定义Maker先实现自定义Marker。如果自定义Marker中用到了图片&#xff0c;那么会碰到图片没有被绘制到Marker的问题&#xff0c;此时需要通过precacheImage来预加载图片&#xff0c;从而解…

DC-磁盘配额

2023年全国网络系统管理赛项真题 模块B-Windows解析 题目 在DC2驱动器C:\上设置磁盘配额&#xff0c;限制磁盘空间为5G&#xff0c;警告等级为3G&#xff0c;超出配额限制时记录事件&#xff0c;超出警告等级时记录事件。 配置步骤 验证 查看DC2驱动器C:\的磁盘配额&#xf…

WPF组合控件TreeView+DataGrid之TreeView封装-粉丝专栏

wpf的功能非常强大&#xff0c;很多控件都是原生的&#xff0c;但是要使用TreeViewDataGrid的组合&#xff0c;就需要我们自己去封装实现。 我们需要的效果如图所示&#xff1a; 这2个图都是第三方控件自带的&#xff0c;并且都是收费使用。 现在我们就用原生的控件进行封装一…

APP应用加固指南:如何有效辨别,网络上伪造的地理位置?

目录 地理位置数据的来源 伪造地理位置数据的危害 如何有效辨别模拟器作弊行为&#xff1f; App加固有效防控地理伪造 在数字互联时代&#xff0c;已经离不开地理位置数据。地理位置数据不仅仅是一个简单的坐标&#xff0c;更是一种数字足迹&#xff0c;描绘了人们在数字世界中…

隧道LED照明技术见证大国交通发展,三思陶瓷散热技术强势突围

隧道灯&#xff0c;顾名思义&#xff0c;就是用于公路隧道中照明的灯。随着我们社会经济的不断进步&#xff0c;公路交通网越来越发达&#xff0c;隧道越来越多&#xff0c;隧道中的照明也越来越受到重视。 很多人会想当然地认为&#xff0c;隧道照明和公路、街道照明应该差不…

QpushButton菜单设置 和 右键菜单

一、前言 ​ 在PyQt中&#xff0c;可以通过QMenu和QAction类来创建和管理菜单。QMenu用于定义具体的菜单&#xff0c;而QAction则代表菜单中的具体操作项。 二、点击QPushButton&#xff0c;显示菜单 API QPushButton操作菜单的相关Api QMenu自身相关Api 代码演示 代码&…

你以为出现NoClassDefFoundError错误会是什么原因?

你以为出现NoClassDefFoundError错误会是什么原因&#xff1f; 1、概述2、事情经过3、总结 1、概述 大家好&#xff0c;我是欧阳方超&#xff0c;可以关注我的公众号“欧阳方超”&#xff0c;后续内容将在公众号首发。 同样的错误&#xff0c;非一样的解决方式。NoClassDefFou…

CComboBoxEx

很久以前写的一段代码感觉比较有意思记录下 一、前面是bmp的图像后面是文字 BOOL bRe Img.Create(IDB_BITMAP_Chamfer, 50, 8, RGB(255, 0, 0));mComBoxChamfer.SetImageList(&Img);COMBOBOXEXITEM cbexItem;cbexItem.mask CBEIF_IMAGE | CBEIF_SELECTEDIMAGE | CBEIF_O…

【算法】【动规】最长定差子序列,大数组优化!!

跳转汇总链接 &#x1f449;&#x1f517;动态规划算法汇总链接 优化在后面&#xff01; 2.5 最长定差子序列 &#x1f517;题目链接 给你一个整数数组 arr 和一个整数 difference&#xff0c;请你找出并返回 arr 中最长等差子序列的长度&#xff0c;该子序列中相邻元素之间…

【CF闯关练习】—— 800分段

&#x1f30f;博客主页&#xff1a;PH_modest的博客主页 &#x1f6a9;当前专栏&#xff1a;cf闯关练习 &#x1f48c;其他专栏&#xff1a; &#x1f534;每日一题 &#x1f7e1; C跬步积累 &#x1f7e2; C语言跬步积累 &#x1f308;座右铭&#xff1a;广积粮&#xff0c;缓…

WPF组合控件TreeView+DataGrid之TreeView封装

&#xff08;关注博主后&#xff0c;在“粉丝专栏”&#xff0c;可免费阅读此文&#xff09; wpf的功能非常强大&#xff0c;很多控件都是原生的&#xff0c;但是要使用TreeViewDataGrid的组合&#xff0c;就需要我们自己去封装实现。 我们需要的效果如图所示&#x…

云上查看容器日志

有时候在云上希望查看容器日志&#xff0c;但web UI界面上看不到日志&#xff0c;怎么办&#xff1f;可以登入容器查看。 该做法适用于各种云上平台&#xff0c;包括华为云、腾讯云等。 首先用ssh登陆宿主机 [rootxxx ~]# 然后用docker列举所有容器&#xff0c;找到你想查看的…

科普-电子合同签署,这三步不能忽视

关于电子合同&#xff0c;许多人认为我自己直接内部发送邮件/传真等发送电子版合同或者我自己创建一个电子合同平台&#xff0c;这种怎么不属于电子合同呢&#xff1f; 在这里给大家科普一个知识点&#xff1a;签电子合同&#xff0c;需要经过这“三个步骤”。 根据《电子签名…

PYthon Pandas 时间序列数据重采样-resample()方法(第23讲)

PYthon Pandas 时间序列数据重采样-resample()方法(第23讲)         🍹博主 侯小啾 感谢您的支持与信赖。☀️ 🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔…

12、Qt:用QProcess类启动外部程序:简单使用

一、说明 简单使用&#xff1a;在一个函数中&#xff0c;使用QProcess类的临时对象调用可执行文件exe&#xff0c;只有这个exe执行完了&#xff0c;这个函数才往下执行&#xff0c;一次性打印出exe所有输出信息&#xff1b;复杂使用&#xff1a;创建QProcess类的全局对象&…

代码随想录算法训练营Day6 | 454.四数相加||、383.赎金信、35.三个之和、18.四数之和

LeetCode 454 四数相加 || 本题思路&#xff1a; 如果使用暴力的话就是 4 层 for 循环&#xff0c;这个时间复杂度就是 O(n^4) 了。 所以我们可以使用 map &#xff0c;来解决这道题&#xff0c;和之前的两数之和一样&#xff0c;之前是 遍历一个&#xff0c;存进去一个。 如果…

IIC使用方法

IIC模块简介 iic是stm32芯片上的一个外设 有两个外设接口 其中iic1可以重映射 iic2不可以重映射 寄存器组和内部结构 因为iic外设挂载在APB1总线上 所以时钟也是来自于APB1总线 时钟控制寄存器就是控制开关的 发送数据和接收数据都是经过了双缓冲区&#xff08;串行转行 接收 …

蓝桥杯专题-真题版含答案-【扑克牌排列】【取球博弈】【古堡算式】【泊松分酒】

Unity3D特效百例案例项目实战源码Android-Unity实战问题汇总游戏脚本-辅助自动化Android控件全解手册再战Android系列Scratch编程案例软考全系列Unity3D学习专栏蓝桥系列ChatGPT和AIGC &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff0c;以及各种资源分…

南京航空航天大学-高等计算机网络复习

计算机网络复习 计算机网络 通信网络 网络提供信息传递服务&#xff08;端用户角度&#xff09; 通信介质&#xff1a;电子和光子&#xff0c;传输介质&#xff1a;fiber……&#xff0c;交换方式&#xff0c;协议&#xff0c;算法&#xff0c;功能&#xff0c;应用 通信网…