当前位置: 首页 > news >正文

FPGA学习——FPGA利用状态机实现电子锁模拟

文章目录

  • 一、本次实验简介
  • 二、源码及分析
  • 三、总结

一、本次实验简介

本次是实验是为了利用状态机模拟电子锁,相关要求如下:

  • 顺序输入4位密码,密码为1234,用按键来键入密码
  • 用led灯指示键入第几位密码,(博主IDLE状态亮1个LED,输入第一位密码后亮2个,以此类推),若密码输入正确,让4个led闪烁(每间隔0.3s)
  • 用3个按键,按下key1,对应位的数值加1
  • 按下key2,对应位的数值减1
  • 按下按键key3,表示确认键入该数值

二、源码及分析

fsm_lock模块:

源码分析:

  • 博主为状态机设计了五个状态并采用独热码编码的方式(一般均建议状态机状态编码方式采用独热码):
    IDLE 空闲状态
    P1密码1输入正确状态
    P2 密码2输入正确状态
    P3密码3输入正确状态
    P4密码4输入正确后LED闪烁状态
  • 有题目可以看出,我们有四位的密码,博主的想法是设置四个密码寄存器,KEY1按下后计数值加1,KEY2按下时计数值减一,以此来存储键入密码值(当然每个密码寄存器的加1条件有些许不同,详细请看代码)。
  • 而除了最后一个状态,其他状态博主设置的跳转下一状态的条件均为状态机处于当前状态并且按下了KEY3(确认键)并且此时键入的值为密码值。
  • 对于最后一个状态,由于需要在P4闪烁LED灯,因此跳转状态设置为了LED闪烁结束。至于如何控制LED闪烁结束,博主设置了一个八位的次数寄存器,LED每完成一次闪烁,该计数器左移一位(初始值为8’d1),当闪烁完成时,该计数器的最高位为1,此时便可以将最高位作为跳转的控制条件。
/****
状态机模拟电子锁- 顺序输入4位密码,密码为1234,用按键来键入密码
- 用led灯指示键入第几位密码,(博主IDLE状态亮1个LED,输入第一位密码后亮2个,以此类推),若密码输入正确,让4个led闪烁(每间隔0.3s)
- 用3个按键,按下key1,对应位的数值加1
- 按下key2,对应位的数值减1
- 按下按键key3,表示确认键入该数值****/
module fsm_lock (input       wire                clk     ,input       wire                rst_n   ,input       wire    [2:0]       key_in  , //按键输入信号output      reg     [3:0]       led       //输出led
);//参数定义
parameter MAX = 15_000_000  ;//300ms计数器
parameter IDLE = 5'b00001   ,//空闲状态P1   = 5'b00010   ,//密码1输入正确状态 P2   = 5'b00100   ,//密码2输入正确状态P3   = 5'b01000   ,//密码3输入正确状态P4   = 5'b10000   ;//密码4输入正确LED闪烁状态//状态转移条件定义
wire            idle2p1     ;
wire            p12p2       ;
wire            p22p3       ;
wire            p32p4       ;
wire            p42idle     ;//内部信号定义
reg     [23:0]  cnt      ;//300ms计数寄存器
reg     [7:0]   cnt_8    ;//解锁成功后让LED闪烁4次reg     [4:0]   cstate   ;//现态
reg     [4:0]   nstate   ;//次态reg     [3:0]   cnt_key1 ;//密码计数器 计数当前按下的密码值
reg     [3:0]   cnt_key2 ;
reg     [3:0]   cnt_key3 ;
reg     [3:0]   cnt_key4 ;reg             led_light;//三段式状态机
//第一段时序逻辑,描述状态转移
always@(posedge clk or negedge rst_n)beginif(!rst_n)begincstate <= IDLE;endelse begincstate <= nstate;end
end//第二段组合逻辑,描述状态转移规律及状态转移条件
always@(*)begincase(cstate)IDLE    :   beginif(idle2p1)beginnstate = P1;endelse beginnstate = cstate;endendP1      :   beginif(p12p2)beginnstate = P2;endelse beginnstate = cstate;endendP2      :   beginif(p22p3)beginnstate = P3;endelse beginnstate = cstate;endendP3      :   beginif(p32p4)beginnstate = P4;endelse beginnstate = cstate;endendP4      :   beginif(p42idle)beginnstate = IDLE;endelse beginnstate = cstate;endenddefault :   nstate = IDLE;endcase
endassign idle2p1 = (cstate == IDLE) && (key_in[2]) && (cnt_key1 == 4'd1);
assign p12p2   = (cstate == P1  ) && (key_in[2]) && (cnt_key2 == 4'd2);
assign p22p3   = (cstate == P2  ) && (key_in[2]) && (cnt_key3 == 4'd3);
assign p32p4   = (cstate == P3  ) && (key_in[2]) && (cnt_key4 == 4'd4);
assign p42idle = (cstate == P4  ) && (cnt_8[7]);//led闪烁完成后跳转//第三段,时序逻辑,描述不同状态下的输出
always@(posedge clk or negedge rst_n)beginif(!rst_n)beginled <= 4'b0000;endelse begincase(cstate)IDLE    :   led <= 4'b0001      ;P1      :   led <= 4'b0011      ;P2      :   led <= 4'b0111      ;P3      :   led <= 4'b1111      ;P4      :   led <= led_light    ;default :   led <= 4'b0000      ;endcaseend
end//密码计数器1
always@(posedge clk or negedge rst_n)beginif(!rst_n)begincnt_key1 <= 1'b0;endelse if(key_in[0] && cstate == IDLE)begincnt_key1 <= cnt_key1 + 1'b1;endelse if(key_in[1] && (cnt_key1 != 1'b0))begincnt_key1 <= cnt_key1 - 1'b1;endelse if(cnt_8[7])begincnt_key1 <= 1'b0;endelse begincnt_key1 <= cnt_key1;end
end//密码计数器2
always@(posedge clk or negedge rst_n)beginif(!rst_n)begincnt_key2 <= 1'b0;endelse if(key_in[0] && cstate == P1)begincnt_key2 <= cnt_key2 + 1'b1;endelse if(key_in[1] && (cnt_key2 != 1'b0))begincnt_key2 <= cnt_key2 - 1'b1;endelse if(cnt_8[7])begincnt_key2 <= 1'b0;endelse begincnt_key2 <= cnt_key2;end
end//密码计数器3
always@(posedge clk or negedge rst_n)beginif(!rst_n)begincnt_key3 <= 1'b0;endelse if(key_in[0] && cstate == P2)begincnt_key3 <= cnt_key3 + 1'b1;endelse if(key_in[1] && (cnt_key3 != 1'b0))begincnt_key3 <= cnt_key3 - 1'b1;endelse if(cnt_8[7])begincnt_key3 <= 1'b0;endelse begincnt_key3 <= cnt_key3;end
end//密码计数器4
always@(posedge clk or negedge rst_n)beginif(!rst_n)begincnt_key4 <= 1'b0;endelse if(key_in[0] && cstate == P3)begincnt_key4 <= cnt_key4 + 1'b1;endelse if(key_in[1] && (cnt_key4 != 1'b0))begincnt_key4 <= cnt_key4 - 1'b1;endelse if(cnt_8[7])begincnt_key4 <= 1'b0;endelse begincnt_key4 <= cnt_key4;end
end//300ms计数器
always @(posedge clk or negedge rst_n)beginif(!rst_n)begincnt <= 1'b0;endelse if(cnt == MAX - 1'b1)begincnt <= 1'b0;endelse if(cstate == P4)begincnt <= cnt + 1'b1;endelse begincnt <= 1'b0;end
end//闪烁次数寄存器
always @(posedge clk or negedge rst_n) beginif(!rst_n)begincnt_8 <= 8'b00000001;end    else if(cnt == MAX -1'd1)begincnt_8 <= {cnt_8[6:0],cnt_8[7]};endelse if(cstate == IDLE)begincnt_8 <= 8'b00000001;endelse begincnt_8 <= cnt_8;end
end//led闪烁
always@(posedge clk or negedge rst_n)beginif(!rst_n)beginled_light <= 4'b1111;endelse if(cstate == P4 && cnt == MAX - 1'b1)beginled_light <= ~led_light;endelse beginled_light <= led_light;end
endendmodule

fsm_key模块(按键消抖模块):

如果有读者不了解按键消抖原理与代码细节的可以查看博主此篇博文,博主在此就不再赘述了

module fsm_key#(parameter WIDTH = 3) (input       wire                    clk     ,input       wire                    rst_n   ,input       wire   [WIDTH - 1:0]    key_in  ,//按键信号输入output      reg    [WIDTH - 1:0]    key_out  //消抖后稳定的脉冲信号输出
);//参数定义
parameter       IDLE        = 4'b0001;//空闲状态
parameter       FILTER_DOWN = 4'b0010;//按键按下抖动状态
parameter       HOLD_DOWN   = 4'b0100;//按键稳定状态
parameter       FILTER_UP   = 4'b1000;//按键释放抖动状态parameter MAX = 20'd1_000_000 ;//延时20ms采样//内部信号定义
reg         [19:0]               cnt_20ms    ;//20ms计数寄存器
reg         [WIDTH - 1:0]        key_r0      ;//同步
reg         [WIDTH - 1:0]        key_r1      ;//打一拍
reg         [WIDTH - 1:0]        key_r2      ;//打两拍reg         [3:0]                cstate      ;//现态寄存器
reg         [3:0]                nstate      ;//次态寄存器//状态转移条件定义
wire                             idle2down   ;
wire                             down2hold   ;
wire                             hold2up     ;
wire                             up2idle     ;  //计数器信号定义
wire                             add_cnt_20ms;//开始计时的标志
wire                             end_cnt_20ms;//结束计时的标志wire        [WIDTH - 1:0]        nedge       ;//下降沿寄存器
wire        [WIDTH - 1:0]        pedge       ;//上升沿寄存器//同步打拍
always @(posedge clk or negedge rst_n) beginif(!rst_n)beginkey_r0 <= {WIDTH{1'b1}};key_r1 <= {WIDTH{1'b1}};key_r2 <= {WIDTH{1'b1}};endelse beginkey_r0 <= key_in;key_r1 <= key_r0;key_r2 <= key_r1;end
end//20ms计数器
always@(posedge clk or negedge rst_n)beginif(!rst_n)begincnt_20ms <= 1'b0;endelse if(add_cnt_20ms)beginif(end_cnt_20ms)begincnt_20ms <= 1'b0;endelse begincnt_20ms <= cnt_20ms + 1'b1;endendelse begincnt_20ms <= 1'b0;end
endassign add_cnt_20ms = cstate == FILTER_DOWN || cstate == FILTER_UP;
assign end_cnt_20ms = add_cnt_20ms && cnt_20ms == MAX - 1'b1;//下降沿 上升沿检测
assign nedge = ~key_r1 & key_r2;
assign pedge = key_r1 & ~key_r2;//三段式状态机//第一段,时序逻辑,描述状态转移
always@(posedge clk or negedge rst_n)beginif(!rst_n)begincstate <= IDLE;endelse begincstate <= nstate;end
end//第二段,组合逻辑,状态转移规律及状态转移条件
always @(*)begincase (cstate)IDLE         : beginif(idle2down)beginnstate <= FILTER_DOWN;endelse beginnstate <= cstate;endendFILTER_DOWN  : beginif(down2hold)beginnstate <= HOLD_DOWN;endelse beginnstate <= cstate;endendHOLD_DOWN    : beginif(hold2up)beginnstate <= FILTER_UP;endelse beginnstate <= cstate;endendFILTER_UP    : beginif(up2idle)beginnstate <= IDLE;endelse beginnstate <= cstate;endenddefault     : nstate <= IDLE;endcase
endassign idle2down   = cstate == IDLE         && nedge        ;
assign down2hold   = cstate == FILTER_DOWN  && end_cnt_20ms ;
assign hold2up     = cstate == HOLD_DOWN    && pedge        ;
assign up2idle     = cstate == FILTER_UP    && end_cnt_20ms ;//第三段 时序逻辑或组合逻辑 描述输出
always@(posedge clk or negedge rst_n)beginif(!rst_n)beginkey_out <= {WIDTH{1'b0}};endelse if(down2hold)beginkey_out <= ~key_in;endelse beginkey_out <= {WIDTH{1'b0}};end
endendmodule

顶层模块:

module top_lock(input   wire            clk     ,input   wire            rst_n   ,input   wire    [2:0]   key_in  ,output  wire    [3:0]   led
);wire   [2:0]     key_out;fsm_lock u_fsm_lock(.clk   (clk    )  ,.rst_n (rst_n  )  ,.key_in(key_out)  ,.led   (led)   
);fsm_key u_fsm_key(.clk    (clk    ) ,.rst_n  (rst_n  ) ,.key_in (key_in ) ,.key_out(key_out)  
);endmodule

三、总结

本次实验较为简单,博主没有编写仿真文件跑仿真(其实是因为懒毕竟我觉得TB文件写起来真的很麻烦),功能实现也较为简单,感兴趣的读者可以自主添加其他功能,如:输入错误蜂鸣器鸣叫并自动跳转回到IDLE状态,或者利用数码管显示正在输入的密码位数与密码值等。

相关文章:

FPGA学习——FPGA利用状态机实现电子锁模拟

文章目录 一、本次实验简介二、源码及分析三、总结 一、本次实验简介 本次是实验是为了利用状态机模拟电子锁&#xff0c;相关要求如下&#xff1a; 顺序输入4位密码&#xff0c;密码为1234&#xff0c;用按键来键入密码用led灯指示键入第几位密码&#xff0c;&#xff08;博…...

Bert经典变体学习

ALBert ALBERT就是为了解决模型参数量大以及训练时间过长的问题。ALBERT最小的参数只有十几M, 效果要比BERT低1-2个点&#xff0c;最大的xxlarge也就200多M。可以看到在模型参数量上减少的还是非常明显的&#xff0c;但是在速度上似乎没有那么明显。最大的问题就是这种方式其实…...

uniapp checkbox radio 样式修改

文章目录 通过查看代码&#xff0c;发现 before部分是设置样式的主要属性 我们要设置的话&#xff0c;就要设置checkbox::before的属性。 其中的content表示内容&#xff0c;比如内部的对勾 那么我们设置的时候&#xff0c;比如设置disabletrue的时候或者checkedtrue的时候&…...

电脑重启后VScode快捷方式失效,找不到Code.exe

问题描述 下班回家关了部分程序就直接关机了&#xff0c;回家后重启电脑发现vscode的快捷方式就失效了&#xff0c;提示Code.exe已被移动或删除。 解决方法 查看你的vscode安装目录&#xff0c;Microsoft VS Code目录下大概率会存在一个名为_的文件夹&#xff0c;然后会发现…...

C语言实现扫雷游戏

test.c源文件 - 扫雷游戏测试 game.h头文件 - 扫雷游戏函数的声明 game.c源文件 - 扫雷游戏函数的实现 1.布置雷 -- 存放雷的雷盘 9*9 数组设计成11*11 上下左右方各多一行&#xff0c;保证周围8的范围 雷 - 1 不是雷 - 0 2.排查雷 主题测试源文件代码 &…...

蓝图节点编辑器

打印字符串 第02章 蓝图结构 03 -注释和重新路由_哔哩哔哩_bilibili 第02章 蓝图结构 04 - 变量_哔哩哔哩_bilibili 第03章 蓝图简易门 01 - 箱子碰撞_哔哩哔哩_bilibili 第03章 蓝图简易门 02 - 静态Mesh和箭头_哔哩哔哩_bilibili 第03章 蓝图简易门 03 - 设置相对旋转节点_哔…...

MySql 知识大汇总

数据库索引 数据库索引是一种数据结构&#xff0c;用于提高数据库查询的速度和效率。索引可以看作是表中一列或多列的值的快速查找方式&#xff0c;类似于书籍的目录。通过创建索引&#xff0c;可以减少数据库的扫描量&#xff0c;加快数据的检索速度。 常见的索引类型 常见…...

深入浅出Pytorch函数——torch.sum

分类目录&#xff1a;《深入浅出Pytorch函数》总目录 相关文章&#xff1a; 深入浅出Pytorch函数——torch.Tensor 函数torch.sum有两种形式&#xff1a; torch.sum(input, *, dtypeNone)&#xff1a;返回输入张量input所有元素的和。torch.sum(input, dim, keepdimFalse, *,…...

Git克隆文件不显示绿色勾、红色感叹号等图标

1、问题 Git和TorToiseGit安装后&#xff0c;Git克隆的文件不会显示绿色勾、红色感叹号等图标。 2、检查注册表 2.1、打开注册表 (1)WinR打开运行窗口&#xff0c;输入regedit&#xff0c;点击确定&#xff0c;打开注册表编辑器。 2.2、找如下路径 (1)找到路径 计算机\HKEY_…...

SOC FPGA之HPS模型设计(一)

目录 一、建立HPS硬件系统模型 1.1 GHRD 1.2 从0开始搭建HPS 1.2.1 FPGA Interfaces 1.2.1.1 General 1.2.1.2 AXI Bridge 1.2.1.3 FPGA-to-HPS SDRAM Interface 1.2.1.4 DMA Peripheral Request 1.2.1.5 Interrupts 1.2.1.6 EMAC ptp interface 1.2.2 Peripheral P…...

解决openstack重启swift服务后报错

swift重启报错 问题描述解决办法 问题描述 swift服务正常状态如下 [rootcontroller ~]# swift statAccount: AUTH_8bde12ff804e42498661b7454994c446Containers: 0Objects: 0Bytes: 0X-Put-Timestamp: 1690507907.67931X-Timestamp: 1690507907.67931X-Trans-Id: tx56d22fa13…...

[Linux]进程控制详解!!(创建、终止、等待、替换)

hello&#xff0c;大家好&#xff0c;这里是bang___bang_&#xff0c;在上两篇中我们讲解了进程的概念、状态和进程地址空间&#xff0c;本篇讲解进程的控制&#xff01;&#xff01;包含内容有进程创建、进程等待、进程替换、进程终止&#xff01;&#xff01; 附上前2篇文章…...

全面适配 | 走近openGauss数据库+鲲鹏欧拉操作系统

引入 全面适配 | openEuler操作系统 openGauss数据库 开篇 1、openEuler欧拉操作系统 百度百科&#xff1a;openEuler是覆盖全场景的创新平台&#xff0c;在引领内核创新&#xff0c;夯实云化基座的基础上&#xff0c;面向计算架构互联总线、存储介质发展新趋势&#xff0c;…...

2023Robocom CAIP省赛 第四题 相对论大师

原题链接&#xff1a; PTA | 程序设计类实验辅助教学平台 题面&#xff1a; 在某个直播间里&#xff0c;观众常常会发送类似这样的弹幕&#xff1a; 鱼越大&#xff0c;鱼刺越大&#xff1b;鱼刺越大&#xff0c;肉越少&#xff1b;肉越少&#xff0c;鱼越小&#xff1b;所以鱼…...

【TypeScript】TS入门级基础学习(一)

【TypeScript】TS入门级基础学习&#xff08;一&#xff09; 一、前言 TypeScript 是一种用于应用程序规模的 JavaScript 语言。 TypeScript 向 JavaScript 添加了可选类型&#xff0c;支持用于任何浏览器、任何主机、任何操作系统的大规模 JavaScript 应用程序的工具。 Type…...

jenkins执行jmeter时,报Begin size 1 is not equal to fixed size 5

jenkins执行jmeter脚本的时候一直提示如下错误&#xff1a; Tidying up ... Fri Jul 28 17:03:53 CST 2023 (1690535033178) Error generating the report: org.apache.jmeter.report.dashboard.GenerationException: Error while processing samples: Consumer failed wi…...

在 “小小容器” WasmEdge 里运行小小羊驼 llama 2

昨天&#xff0c;特斯拉前 AI 总监、OpenAI 联合创始人 Andrej Karpathy 开源了 llama2.c 。 只用 500 行纯 C 语言就能训练和推理 llama 2 模型的框架&#xff0c;没有任何繁杂的 python 依赖。这个项目一推出就受到大家的追捧&#xff0c;24 小时内 GitHub 收获 4000 颗星&am…...

【C#】async和await 续

前言 在文章《async和await》中&#xff0c;我们观察到了一下客观的规律&#xff0c;但是没有讲到本质&#xff0c;而且还遗留了一个问题: 这篇文章中&#xff0c;我们继续看看这个问题如何解决! 我们再看看之前写的代码&#xff1a; static public void TestWait2() {var t…...

【Matlab】基于粒子群优化算法优化BP神经网络的数据回归预测(Excel可直接替换数据)

【Matlab】基于粒子群优化算法优化 BP 神经网络的数据回归预测(Excel可直接替换数据) 1.模型原理2.数学公式3.文件结构4.Excel数据5.分块代码5.1 fun.m5.2 main.m6.完整代码6.1 fun.m6.2 main.m7.运行结果1.模型原理 基于粒子群优化算法(Particle Swarm Optimization, PSO)…...

QPainter绘制雷达界面

文章目录 功能实现定义的结构体定义的函数效果图gitee源码链接 功能实现 相较于上一版&#xff0c;这一版添加的功能有&#xff1a; 1、自适应窗口 2、扫描方式&#xff08;圆周扫描、扇形扫描&#xff08;指定起始角度和结束角度&#xff09;&#xff09; 3、扫描方向&#x…...

浅谈 React Hooks

React Hooks 是 React 16.8 引入的一组 API&#xff0c;用于在函数组件中使用 state 和其他 React 特性&#xff08;例如生命周期方法、context 等&#xff09;。Hooks 通过简洁的函数接口&#xff0c;解决了状态与 UI 的高度解耦&#xff0c;通过函数式编程范式实现更灵活 Rea…...

大数据学习栈记——Neo4j的安装与使用

本文介绍图数据库Neofj的安装与使用&#xff0c;操作系统&#xff1a;Ubuntu24.04&#xff0c;Neofj版本&#xff1a;2025.04.0。 Apt安装 Neofj可以进行官网安装&#xff1a;Neo4j Deployment Center - Graph Database & Analytics 我这里安装是添加软件源的方法 最新版…...

利用ngx_stream_return_module构建简易 TCP/UDP 响应网关

一、模块概述 ngx_stream_return_module 提供了一个极简的指令&#xff1a; return <value>;在收到客户端连接后&#xff0c;立即将 <value> 写回并关闭连接。<value> 支持内嵌文本和内置变量&#xff08;如 $time_iso8601、$remote_addr 等&#xff09;&a…...

五年级数学知识边界总结思考-下册

目录 一、背景二、过程1.观察物体小学五年级下册“观察物体”知识点详解&#xff1a;由来、作用与意义**一、知识点核心内容****二、知识点的由来&#xff1a;从生活实践到数学抽象****三、知识的作用&#xff1a;解决实际问题的工具****四、学习的意义&#xff1a;培养核心素养…...

2021-03-15 iview一些问题

1.iview 在使用tree组件时&#xff0c;发现没有set类的方法&#xff0c;只有get&#xff0c;那么要改变tree值&#xff0c;只能遍历treeData&#xff0c;递归修改treeData的checked&#xff0c;发现无法更改&#xff0c;原因在于check模式下&#xff0c;子元素的勾选状态跟父节…...

解决本地部署 SmolVLM2 大语言模型运行 flash-attn 报错

出现的问题 安装 flash-attn 会一直卡在 build 那一步或者运行报错 解决办法 是因为你安装的 flash-attn 版本没有对应上&#xff0c;所以报错&#xff0c;到 https://github.com/Dao-AILab/flash-attention/releases 下载对应版本&#xff0c;cu、torch、cp 的版本一定要对…...

rnn判断string中第一次出现a的下标

# coding:utf8 import torch import torch.nn as nn import numpy as np import random import json""" 基于pytorch的网络编写 实现一个RNN网络完成多分类任务 判断字符 a 第一次出现在字符串中的位置 """class TorchModel(nn.Module):def __in…...

安卓基础(aar)

重新设置java21的环境&#xff0c;临时设置 $env:JAVA_HOME "D:\Android Studio\jbr" 查看当前环境变量 JAVA_HOME 的值 echo $env:JAVA_HOME 构建ARR文件 ./gradlew :private-lib:assembleRelease 目录是这样的&#xff1a; MyApp/ ├── app/ …...

JVM虚拟机:内存结构、垃圾回收、性能优化

1、JVM虚拟机的简介 Java 虚拟机(Java Virtual Machine 简称:JVM)是运行所有 Java 程序的抽象计算机,是 Java 语言的运行环境,实现了 Java 程序的跨平台特性。JVM 屏蔽了与具体操作系统平台相关的信息,使得 Java 程序只需生成在 JVM 上运行的目标代码(字节码),就可以…...

嵌入式学习笔记DAY33(网络编程——TCP)

一、网络架构 C/S &#xff08;client/server 客户端/服务器&#xff09;&#xff1a;由客户端和服务器端两个部分组成。客户端通常是用户使用的应用程序&#xff0c;负责提供用户界面和交互逻辑 &#xff0c;接收用户输入&#xff0c;向服务器发送请求&#xff0c;并展示服务…...