【数字电子技术课程设计】基于FPGA的高精度数字电子钟设计与实现

news2026/3/14 18:07:07
1. 从“搭积木”到“写代码”为什么FPGA是数字钟设计的未来我记得十年前第一次做数字电子钟课程设计那场景真是壮观。实验室的桌子上铺满了各种74系列芯片、电阻电容还有像蜘蛛网一样的杜邦线。一个小组五六个人忙活好几天最后能成功显示时间、能校时、能整点响一下那成就感别提多大了。但说实话那种用中小规模集成电路比如74LS390、CD4060搭出来的数字钟问题也不少电路板又大又笨重稍微碰一下线可能就不显示了想改个功能比如把24小时制改成12小时制带AM/PM显示那几乎等于重做一遍更头疼的是精度靠RC振荡或者简单的晶振分频走时精度总差那么一点意思。所以当我在后来的项目中接触到FPGA现场可编程门阵列时我立刻意识到这玩意儿简直是数字电路课程设计的“降维打击”工具。你不再需要和一大堆具体的芯片、复杂的布线打交道而是坐在电脑前用硬件描述语言比如Verilog HDL像写软件一样去“描述”你想要的硬件电路。这次我们就来聊聊怎么用FPGA做一个比传统方法更高精度、更灵活、功能更强大的数字电子钟。FPGA到底是什么你可以把它想象成一个“万能数字电路实验板”。它内部有成千上万个基本的逻辑单元像门电路、触发器、可编程的连线和专用的功能块。你需要什么电路——无论是计数器、分频器、还是复杂的状态机——都不用去找对应的物理芯片焊接了直接用代码“画”出来然后通过软件“烧录”到FPGA芯片里它内部的结构就会按照你的代码重新组织变成你专属的芯片。这种“可编程”的特性带来了几个碾压性的优势第一集成度极高。传统方案里秒计数器、分计数器、译码器、校时逻辑、报时逻辑各自需要一堆芯片。而在FPGA里所有这些功能模块都只是你代码里的几个“module”模块最终都集成在那一颗小小的FPGA芯片内部。电路板会变得非常简洁可靠性也大大提升。第二精度和稳定性飞跃。传统方案的石英晶体振荡器比如32768Hz晶振产生的频率会受温度、电源电压影响分频电路也可能引入误差。FPGA通常自带高精度、高稳定性的时钟管理单元如PLL锁相环。我们可以用一个外部的高频有源晶振比如50MHz然后通过FPGA内部的PLL进行精准的倍频、分频产生任意我们需要的时钟频率其稳定度远非简单RC或门电路振荡能比。第三灵活性与可扩展性无敌。这是FPGA最迷人的地方。你的数字钟不再只是一个简单的计时器。想增加一个万年历包括闰年判断加几十行代码。想用更省电、效果更炫的数码管动态扫描LED显示优化写个扫描驱动模块。想把整点报时改成自定义音乐铃声用状态机描述一个简单的音乐发生器。所有这些都不需要改动任何一根物理连线只需要修改和增加代码。调试也方便可以在电脑上先做完善的仿真确保逻辑百分百正确再下载到板子上成功率极高。所以无论你是正在为数字电子技术课程设计寻找一个亮眼的课题还是一个电子爱好者想挑战更有趣的项目基于FPGA的数字电子钟设计都是一个绝佳的起点。它不仅能让你巩固数字电路的核心知识计数器、分频、译码更能带你跨入现代数字系统设计的大门体验硬件编程的乐趣。接下来我就带你一步步从设计思路到代码实现把这个高精度的数字钟做出来。2. 核心设计思路把传统电路图“翻译”成Verilog模块传统数字钟的框图我们很熟悉振荡源 - 分频器 - 秒计数器 - 分计数器 - 时计数器 - 译码显示 - 校时/报时控制。用FPGA实现本质上就是把这个框图里的每一个方块都用硬件描述语言“建模”出来。我们的大脑需要从“连线思维”切换到“模块化描述思维”。2.1 精准的“心脏”时钟源与分频模块在传统设计中我们可能用一个32768Hz的晶振配合CD4060进行2^15次分频来得到1Hz的秒脉冲。在FPGA设计中我们有更优的方案。通常FPGA开发板会提供一个高稳定度的有源晶振比如50MHz。我们的第一步就是把这个50MHz的时钟变成精准的1Hz秒脉冲。直接进行50,000,000次分频理论上可以但会产生一个巨大的计数器而且灵活性差。更好的方法是使用FPGA内部的锁相环PLL资源。以Altera/Intel的Cyclone系列FPGA为例我们可以通过Quartus Prime软件中的PLL IP核轻松将50MHz输入时钟先倍频到比如200MHz然后再分频到1Hz。PLL的好处是产生的时钟信号抖动小、相位稳定是高质量时钟的保障。当然为了理解分频原理我们也可以先用一个计数器来实现简单的分频。下面是一个用Verilog实现的将50MHz分频到1Hz的模块同时产生一个用于数码管动态扫描的更高频率如1KHz的扫描时钟module clk_gen ( input wire clk_50m, // 输入50MHz主时钟 input wire rst_n, // 低电平复位信号 output reg clk_1s, // 输出1秒时钟 output reg clk_1k // 输出1KHz扫描时钟 ); // 用于生成1Hz时钟的计数器50,000,000分频 reg [25:0] cnt_1s; // 需要26位计数器 (2^26 50e6) parameter CNT_1S_MAX 26d49_999_999; // 从0计数到49,999,999 // 用于生成1KHz扫描时钟的计数器50,000分频 reg [15:0] cnt_1k; parameter CNT_1K_MAX 16d49_999; always (posedge clk_50m or negedge rst_n) begin if (!rst_n) begin cnt_1s 26d0; clk_1s 1b0; end else begin if (cnt_1s CNT_1S_MAX) begin cnt_1s 26d0; clk_1s ~clk_1s; // 每计满一次秒时钟翻转一次占空比50% end else begin cnt_1s cnt_1s 1b1; end end end always (posedge clk_50m or negedge rst_n) begin if (!rst_n) begin cnt_1k 16d0; clk_1k 1b0; end else begin if (cnt_1k CNT_1K_MAX) begin cnt_1k 16d0; clk_1k ~clk_1k; end else begin cnt_1k cnt_1k 1b1; end end end endmodule这个模块就是整个数字钟的“心跳”发生器。clk_1s将直接驱动后续的计时逻辑。在实际工程中我强烈推荐使用PLL IP核来生成clk_1s把上面的代码当作理解分频原理的练习。使用PLL时我们只需要在GUI中配置参数工具会自动生成可靠的分频时钟代码中直接使用这个时钟网络即可。2.2 计时核心秒、分、时计数器模块这是数字钟的逻辑核心对应传统电路中的74LS390。我们需要实现一个24进制时和两个60进制分、秒的计数器。用Verilog来描述计数器比用芯片搭电路直观太多了。关键点在于模块化设计。我们可以先设计一个通用的十进制计数器模块一个六进制计数器模块然后将它们组合。但更直接高效的方法是为秒、分、时分别编写一个计数器模块清晰明了。下面是一个包含秒、分、时计数并能产生进位信号的顶层计时模块module time_counter ( input wire clk_1s, // 1秒时钟输入 input wire rst_n, // 异步低电平复位 input wire en, // 计数使能正常为1校时时可置0 // 校时信号高电平有效按下时对应单位快速递增 input wire adj_sec, input wire adj_min, input wire adj_hour, // 当前时间输出每个单位用4位BCD码表示 output reg [3:0] sec_ones, // 秒个位 (0-9) output reg [3:0] sec_tens, // 秒十位 (0-5) output reg [3:0] min_ones, // 分个位 output reg [3:0] min_tens, // 分十位 output reg [3:0] hour_ones, // 时个位 output reg [3:0] hour_tens, // 时十位 (0-2) // 进位信号可用于触发报时等 output wire co_sec_to_min, // 秒到分进位 output wire co_min_to_hour // 分到时进位 ); // 内部信号秒、分、时的快速校时时钟由按键信号控制选择 wire sec_clk adj_sec ? clk_1s : (en ? clk_1s : 1b0); // 校秒时快速跳动 wire min_clk adj_min ? clk_1s : co_sec_to_min; // 校分时快速跳动否则由秒进位触发 wire hour_clk adj_hour ? clk_1s : co_min_to_hour; // 校时时快速跳动否则由分进位触发 // 秒计数器 (60进制) always (posedge sec_clk or negedge rst_n) begin if (!rst_n) begin sec_ones 4d0; sec_tens 4d0; end else begin if (sec_ones 4d9) begin // 个位满9 sec_ones 4d0; if (sec_tens 4d5) // 十位满5 sec_tens 4d0; else sec_tens sec_tens 1b1; end else begin sec_ones sec_ones 1b1; end end end // 秒进位条件秒计数为59时下一个时钟上升沿产生进位这里用组合逻辑判断当前状态 assign co_sec_to_min (sec_ones 4d9) (sec_tens 4d5); // 分计数器 (60进制)逻辑与秒计数器完全一致只是时钟源不同 always (posedge min_clk or negedge rst_n) begin if (!rst_n) begin min_ones 4d0; min_tens 4d0; end else begin if (min_ones 4d9) begin min_ones 4d0; if (min_tens 4d5) min_tens 4d0; else min_tens min_tens 1b1; end else begin min_ones min_ones 1b1; end end end assign co_min_to_hour (min_ones 4d9) (min_tens 4d5); // 时计数器 (24进制) always (posedge hour_clk or negedge rst_n) begin if (!rst_n) begin hour_ones 4d0; hour_tens 4d0; end else begin // 判断是否到达23:59:59的下一个脉冲即归零时刻 if ((hour_tens 4d2) (hour_ones 4d3)) begin // 当前是23 hour_ones 4d0; hour_tens 4d0; end else if (hour_ones 4d9) begin // 个位满9十位加1 hour_ones 4d0; hour_tens hour_tens 1b1; end else begin hour_ones hour_ones 1b1; end end end endmodule这段代码清晰地体现了硬件描述语言的精髓我们不是在写“执行步骤”而是在描述一组并行工作的硬件电路。三个always块是同时工作的分别描述了秒、分、时三个计数器电路。adj_sec、adj_min、adj_hour是校时按键输入当它们为高电平时对应的计数器直接由clk_1s驱动快速计数实现校时功能。这种设计比传统电路中使用门电路切换时钟源要简洁和可靠得多。3. 让时间“看得见”LED动态扫描显示驱动传统设计中我们使用74LS48这样的BCD-7段译码器驱动共阴极数码管每个数码管需要占用7个IO口6位数码管就是42个IO再加上位选端资源消耗很大。在FPGA项目中IO口是非常宝贵的资源。因此动态扫描显示技术几乎是必选项。动态扫描的原理是利用人眼的视觉暂留效应。在某一时刻我们只点亮一位数码管显示对应的数字然后以足够快的速度通常60Hz轮流点亮各位数码管。只要切换速度够快人眼看到的就是所有数字同时稳定显示。这个“足够快的速度”就是前面clk_gen模块中产生的clk_1k1KHz时钟。用1KHz扫描每位显示约1ms6位一个循环就是6ms刷新率约166Hz完全无闪烁。实现动态扫描需要两个核心部分段选译码和位选扫描。module led_display ( input wire clk_scan, // 扫描时钟如1KHz input wire rst_n, // 6位时间数据输入 (BCD码) input wire [3:0] hour_tens_in, input wire [3:0] hour_ones_in, input wire [3:0] min_tens_in, input wire [3:0] min_ones_in, input wire [3:0] sec_tens_in, input wire [3:0] sec_ones_in, // 输出到数码管 output reg [7:0] seg_data, // 段选信号 a,b,c,d,e,f,g,dp (假设共阴极1点亮) output reg [5:0] dig_sel // 位选信号低电平有效选中某一位 ); // 将6位时间数据合并到一个寄存器数组中方便索引 reg [3:0] time_data [5:0]; always (*) begin time_data[5] hour_tens_in; // 第6位时十位 time_data[4] hour_ones_in; // 第5位时个位 time_data[3] min_tens_in; // 第4位分十位 time_data[2] min_ones_in; // 第3位分个位 time_data[1] sec_tens_in; // 第2位秒十位 time_data[0] sec_ones_in; // 第1位秒个位 end // 位选扫描计数器 reg [2:0] scan_cnt; // 0~5循环 always (posedge clk_scan or negedge rst_n) begin if (!rst_n) scan_cnt 3d0; else scan_cnt (scan_cnt 3d5) ? 3d0 : (scan_cnt 1b1); end // 根据扫描计数器生成位选信号低电平有效假设数码管共阴极 always (*) begin case (scan_cnt) 3d0: dig_sel 6b111110; // 选中秒个位 3d1: dig_sel 6b111101; // 选中秒十位 3d2: dig_sel 6b111011; // 选中分个位 3d3: dig_sel 6b110111; // 选中分十位 3d4: dig_sel 6b101111; // 选中时个位 3d5: dig_sel 6b011111; // 选中时十位 default: dig_sel 6b111111; // 全灭 endcase end // BCD码到7段数码管译码器 (共阴极段信号高电平点亮) always (*) begin case (time_data[scan_cnt]) 4h0: seg_data 8b0011_1111; // 0, 点亮除g,dp外的段 4h1: seg_data 8b0000_0110; // 1 4h2: seg_data 8b0101_1011; // 2 4h3: seg_data 8b0100_1111; // 3 4h4: seg_data 8b0110_0110; // 4 4h5: seg_data 8b0110_1101; // 5 4h6: seg_data 8b0111_1101; // 6 4h7: seg_data 8b0000_0111; // 7 4h8: seg_data 8b0111_1111; // 8 4h9: seg_data 8b0110_1111; // 9 default: seg_data 8b0000_0000; // 其他情况全灭 endcase // 可以在这里增加小数点控制逻辑例如在秒个位和分个位之间点亮dp段作为分隔符 // if (scan_cnt 3d2 || scan_cnt 3d4) seg_data[7] 1b1; // 点亮dp段 end endmodule这个模块完美替代了传统方案中6片74LS48和复杂的位选驱动电路。它只用了14个IO口8个段选6个位选就驱动了6位数码管极大地节省了FPGA的引脚资源。在实际调试时如果发现数码管有闪烁或亮度不均可以调整clk_scan的频率或者尝试在段选和位选信号变化时加入短暂的消隐时间以消除鬼影。4. 智能化交互按键消抖与多功能校时/报时传统电路的校时和报时功能依赖于额外的比较器如74LS85和门电路设计复杂且功能固定。在FPGA里我们可以用状态机和逻辑判断实现更智能、更灵活的人机交互。4.1 按键消抖模块机械按键在按下和弹起时会产生持续数毫秒的抖动如果不处理会被误认为是多次按下。软件消抖是FPGA设计中的常用技巧。module key_debounce ( input wire clk, // 系统时钟比如50MHz input wire key_in, // 原始按键输入低电平表示按下 output reg key_out // 消抖后的稳定输出低电平有效 ); parameter CNT_MAX 20d999_999; // 50MHz时钟下计数20ms (50e6 * 0.02 1e6) reg [19:0] cnt; reg key_reg; always (posedge clk) begin key_reg key_in; // 同步打拍减少亚稳态影响 if (key_reg ! key_in) begin // 检测到按键状态变化 cnt 20d0; // 计数器清零重新计时 end else if (cnt CNT_MAX) begin cnt cnt 1b1; end else begin key_out key_reg; // 稳定20ms后输出当前稳定的按键状态 end end endmodule我们需要为adj_sec,adj_min,adj_hour三个校时按键分别实例化这个消抖模块确保每次按下只产生一个干净的脉冲信号。4.2 增强型校时逻辑有了干净的按键信号校时逻辑可以做得更友好。比如我们可以设计长按加速功能短按时时间单位按1递增长按超过1秒后开始快速递增方便快速调整。这只需要在time_counter模块的校时部分增加一个计时器和一个速度选择逻辑即可代码比用门电路搭建简单无数倍。4.3 可编程的整点报时与闹钟传统方案的整点报时通常利用分计数器的进位脉冲59分59秒跳转到00分00秒时触发蜂鸣器响一下。FPGA可以实现更丰富的报时模式。我们可以设计一个报时控制模块它监测计时模块输出的时间信息hour_tens/ones,min_tens/ones,sec_tens/ones和进位信号co_min_to_hour。对于整点报时可以在co_min_to_hour信号有效即分计数器从59归零且秒计数器也为0的时刻触发一个持续数秒的蜂鸣器驱动信号。你甚至可以设计一个简单的状态机让蜂鸣器发出“嘀-嘀-嘀-嘟”这样的四短一长音。对于闹钟功能则需要增加一个闹钟时间设置和存储模块。我们可以用FPGA内部的存储器如寄存器或RAM来存储用户设置的闹钟时、分。然后在计时模块的每个时钟周期将当前时间与存储的闹钟时间进行比较。如果完全匹配则触发闹钟。为了用户体验还可以加入“贪睡”功能闹钟响时按下一个键暂停几分钟后再响。这些复杂的功能在传统硬件电路上实现极其困难但在FPGA中只是多写几段状态机代码而已。蜂鸣器驱动很简单通常是一个GPIO口连接一个三极管来驱动无源或有源蜂鸣器。对于无源蜂鸣器你还需要一个PWM模块来产生不同频率的方波以发出不同音调。// 一个简单的整点报时例子 module hourly_beep ( input wire clk_1s, input wire rst_n, input wire co_min_to_hour, // 分到时的进位信号 input wire [3:0] sec_ones, // 秒个位用于判断整点时刻 output reg beep // 蜂鸣器控制信号1-响0-停 ); reg [1:0] state; parameter IDLE 2b00, BEEPING 2b01; reg [3:0] beep_cnt; // 控制蜂鸣时长 always (posedge clk_1s or negedge rst_n) begin if (!rst_n) begin state IDLE; beep 1b0; beep_cnt 4d0; end else begin case (state) IDLE: begin // 在59分59秒的下一跳即整点且秒为0时触发 if (co_min_to_hour (sec_ones 4d0)) begin state BEEPING; beep 1b1; beep_cnt 4d4; // 响4秒 end end BEEPING: begin if (beep_cnt 0) begin beep_cnt beep_cnt - 1b1; end else begin beep 1b0; state IDLE; end end endcase end end endmodule5. 系统集成、仿真与上板实战当我们把各个模块都编写、调试完毕后就需要将它们集成到一个顶层模块Top Module中并分配实际的FPGA引脚。5.1 顶层模块设计与引脚分配顶层模块就像电路的主板负责将所有子模块像芯片一样连接起来。module top_digital_clock ( // 时钟与复位 input wire clk_50m, // 板载50MHz晶振 input wire rst_n_in, // 复位按键低电平复位 // 校时按键低电平有效 input wire key_adj_sec, input wire key_adj_min, input wire key_adj_hour, // 数码管接口 output wire [7:0] seg, output wire [5:0] dig, // 蜂鸣器接口 output wire beep_out ); // 内部连线声明 wire clk_1s; wire clk_1k; wire key_sec_db, key_min_db, key_hour_db; // 实例化时钟生成模块 clk_gen u_clk_gen ( .clk_50m(clk_50m), .rst_n(rst_n_in), .clk_1s(clk_1s), .clk_1k(clk_1k) ); // 实例化三个按键消抖模块 key_debounce u_debounce_sec ( .clk(clk_50m), .key_in(key_adj_sec), .key_out(key_sec_db) ); key_debounce u_debounce_min ( .clk(clk_50m), .key_in(key_adj_min), .key_out(key_min_db) ); key_debounce u_debounce_hour ( .clk(clk_50m), .key_in(key_adj_hour), .key_out(key_hour_db) ); // 实例化计时核心模块 wire [3:0] h_tens, h_ones, m_tens, m_ones, s_tens, s_ones; wire co_min2hour; time_counter u_time_counter ( .clk_1s(clk_1s), .rst_n(rst_n_in), .en(1b1), // 始终使能计数 .adj_sec(key_sec_db), .adj_min(key_min_db), .adj_hour(key_hour_db), .sec_ones(s_ones), .sec_tens(s_tens), .min_ones(m_ones), .min_tens(m_tens), .hour_ones(h_ones), .hour_tens(h_tens), .co_sec_to_min(), // 悬空或连接到其他模块 .co_min_to_hour(co_min2hour) ); // 实例化显示驱动模块 led_display u_display ( .clk_scan(clk_1k), .rst_n(rst_n_in), .hour_tens_in(h_tens), .hour_ones_in(h_ones), .min_tens_in(m_tens), .min_ones_in(m_ones), .sec_tens_in(s_tens), .sec_ones_in(s_ones), .seg_data(seg), .dig_sel(dig) ); // 实例化报时模块 hourly_beep u_beep ( .clk_1s(clk_1s), .rst_n(rst_n_in), .co_min_to_hour(co_min2hour), .sec_ones(s_ones), .beep(beep_out) ); endmodule写完顶层模块后我们需要在Quartus Prime或Vivado等开发工具中进行引脚分配。这需要根据你使用的具体FPGA开发板的原理图来进行。例如clk_50m连接到板载晶振的专用时钟引脚key_adj_sec等连接到按键对应的GPIOseg和dig连接到数码管段选和位选网络beep_out连接到蜂鸣器驱动三极管的基极电阻。这一步至关重要分配错了硬件就无法工作。5.2 功能仿真在电脑上验证逻辑在把程序下载到板子之前一定要做仿真这是FPGA设计相比传统硬件焊接最大的优势之一。我们可以使用ModelSim等工具写一个测试平台Testbench。timescale 1ns / 1ps module tb_digital_clock(); reg clk_50m; reg rst_n; reg key_sec, key_min, key_hour; wire [7:0] seg; wire [5:0] dig; wire beep; // 实例化被测设计 top_digital_clock uut ( .clk_50m(clk_50m), .rst_n_in(rst_n), .key_adj_sec(key_sec), .key_adj_min(key_min), .key_adj_hour(key_hour), .seg(seg), .dig(dig), .beep_out(beep) ); // 生成50MHz时钟 initial clk_50m 0; always #10 clk_50m ~clk_50m; // 周期20ns即50MHz // 测试过程 initial begin // 初始化 rst_n 0; key_sec 1; key_min 1; key_hour 1; #100; // 等待100ns rst_n 1; // 释放复位 #2000000000; // 仿真运行2秒模拟时间观察计时是否从00:00:00开始 // 测试校时功能快速调整分钟 key_min 0; // 按下调分键 #20000000; // 按下20ms模拟长按 key_min 1; // 释放 #1000000000; // 再观察1秒 // 可以继续添加更多测试场景比如测试整点报时触发 // 通过观察波形图中的 seg, dig, beep 信号以及内部的时间计数器变量可以完整验证设计功能。 $stop; // 停止仿真 end endmodule在ModelSim中运行这个测试平台你可以看到所有信号的波形变化。你可以检查clk_1s是否精准地每秒产生一个脉冲时间计数器是否正确地60进制和24进制递增按下校时键时对应的时间单位是否快速增加以及在仿真时间到达整点时beep信号是否被触发。仿真通过意味着你的逻辑设计99%是正确的大大提高了上板一次成功的概率。5.3 上板调试与优化将编译好的.sof或.bit文件下载到FPGA开发板后真正的乐趣开始了。你可能会遇到一些问题这里分享几个我踩过的坑数码管显示暗淡或闪烁这通常是动态扫描的时钟clk_scan频率不合适导致的。频率太低如100Hz会看到明显的闪烁频率太高如10KHz每个数码管点亮时间太短平均电流太小导致亮度不足。1KHz-500Hz是一个不错的起点。另外检查位选和段选信号的驱动能力必要时可以在输出端口加上上拉电阻或使用IO的强电流驱动模式。按键响应不灵或连击首先确认消抖模块的参数如20ms延时是否合适。如果按键是低电平有效确保硬件电路上按键按下时确实能将FPGA引脚拉低。有时需要配置FPGA引脚的内部上拉电阻。对于“连击”检查消抖模块的输出是否在按键稳定期间只产生了一个稳定的电平变化而不是一串脉冲。计时不准这是最可能遇到的问题。如果使用内部计数器分频请确保计数器的最大值设置正确50MHz分1Hz是49999999不是50000000。最推荐的解决方案是使用PLL。在Quartus中调用PLL IP核输入50MHz直接输出1Hz的精准时钟可以彻底解决因分频计数器误差导致的累积误差。整点报时不响检查触发条件。我的代码里是在co_min_to_hour有效且sec_ones0的clk_1s上升沿触发。你需要确保co_min_to_hour这个信号在59分59秒跳转到00分00秒的那个clk_1s周期内是有效的。最好在仿真波形里仔细对照这个时刻附近各个信号的变化。当你看到数码管清晰地显示着时间按下按键能随心所欲地调整整点时蜂鸣器发出清脆的提示音那一刻的成就感远非拼凑一堆芯片所能比拟。这个基于FPGA的数字电子钟不仅仅是一个课程设计作业它更是一个可无限扩展的平台。你可以轻松地为它增加温度显示、秒表、倒计时、蓝牙手机校时等功能。从传统的“连线思维”升级到现代的“设计思维”这才是这个项目带给你的最大价值。

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

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

相关文章

SpringBoot-17-MyBatis动态SQL标签之常用标签

文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…

wordpress后台更新后 前端没变化的解决方法

使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…

网络编程(Modbus进阶)

思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…

UE5 学习系列(二)用户操作界面及介绍

这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…

利用最小二乘法找圆心和半径

#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…

XML Group端口详解

在XML数据映射过程中&#xff0c;经常需要对数据进行分组聚合操作。例如&#xff0c;当处理包含多个物料明细的XML文件时&#xff0c;可能需要将相同物料号的明细归为一组&#xff0c;或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码&#xff0c;增加了开…

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造&#xff0c;完美适配AGV和无人叉车。同时&#xff0c;集成以太网与语音合成技术&#xff0c;为各类高级系统&#xff08;如MES、调度系统、库位管理、立库等&#xff09;提供高效便捷的语音交互体验。 L…

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型

摘要 拍照搜题系统采用“三层管道&#xff08;多模态 OCR → 语义检索 → 答案渲染&#xff09;、两级检索&#xff08;倒排 BM25 向量 HNSW&#xff09;并以大语言模型兜底”的整体框架&#xff1a; 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后&#xff0c;分别用…

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析

1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具&#xff0c;该工具基于TUN接口实现其功能&#xff0c;利用反向TCP/TLS连接建立一条隐蔽的通信信道&#xff0c;支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式&#xff0c;适应复杂网…

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…

Linux应用开发之网络套接字编程(实例篇)

服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …

华为云AI开发平台ModelArts

华为云ModelArts&#xff1a;重塑AI开发流程的“智能引擎”与“创新加速器”&#xff01; 在人工智能浪潮席卷全球的2025年&#xff0c;企业拥抱AI的意愿空前高涨&#xff0c;但技术门槛高、流程复杂、资源投入巨大的现实&#xff0c;却让许多创新构想止步于实验室。数据科学家…

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…