FPGA学习—通过数码管实现电子秒表模拟
文章目录
- 一、数码管简介
- 二、项目分析
- 三、项目源码及分析
- 四、实现效果
- 五、总结
一、数码管简介
请参阅博主以前写过的一篇电子时钟模拟,在此不再赘述。
https://blog.csdn.net/qq_54347584/article/details/130402287
二、项目分析
- 项目说明:本次项目是为了通过数码管实现秒表模拟。其中,六位数码管分别显示秒表的分位,秒位,毫秒位(由于毫秒有三位,在此只取百位和十位),其中分位和秒位,秒位和毫秒位之间用小数点隔开
- 本次项目拟设置四个模块,分别为:按键消抖模块,计数模块,数码管驱动模块,以及顶层模块
- 按键消抖模块要求:传出两个按键的脉冲信号,一个用来暂停/开始秒表的计数,一个用来清空秒表的计数
- 计数模块要求:能传出秒表的各位值以及小数点位置
- 数码管驱动模块要求:能正常显示秒表各位值
三、项目源码及分析
数码管驱动模块:
代码分析:
- 由于本开发板有六位数码管,每位数码管设置显示0-F,因此在此模块中,博主定义了一个24位的din信号(六位每位能显示十六个字符(因此每位需要四位位宽))以此来给每位数码管赋值
- 同时博主将八段式数码管拆分为七段加一段小数点,因此设计了一个六位的point_n以此来控制小数点的显示
- 其余代码与博主以前写的数码管动态显示0-F类似,在此不再赘述(如果是FPGA初学者,没有数码管开发经验,请仔细阅读博主动态显示及电子时钟两篇博客!!)
/**************************************功能介绍***********************************
Date : 2023-08-01 11:08:11
Author : majiko
Version : 1.0
Description: 动态数码管模块(动态扫描)
*********************************************************************************///---------<模块及端口声名>------------------------------------------------------
module seg_driver( input clk ,input rst_n ,input [23:0] din ,//输入6位数码管显示数据,每位数码管占4位input [5:0] point_n ,//输入小数点控制位output reg [5:0] seg_sel ,//输出位选output reg [7:0] seg_dig //输出段选
);
//---------<参数定义>--------------------------------------------------------- parameter TIME_1MS = 50_000;//1ms//数码管显示字符编码localparam NUM_0 = 7'b100_0000,//0NUM_1 = 7'b111_1001,//1NUM_2 = 7'b010_0100,//NUM_3 = 7'b011_0000,//NUM_4 = 7'b001_1001,//NUM_5 = 7'b001_0010,//NUM_6 = 7'b000_0010,//NUM_7 = 7'b111_1000,//NUM_8 = 7'b000_0000,//NUM_9 = 7'b001_1000,//A = 7'b000_1000,//B = 7'b000_0011,//bC = 7'b100_0110,//D = 7'b010_0001,//dE = 7'b000_1110,//E替换为FF = 7'b011_1111,//F替换为--DIV = 7'b011_1111;//---------<内部信号定义>-----------------------------------------------------reg [15:0] cnt_1ms ;//1ms计数器(扫描间隔计数器)wire add_cnt_1ms ;wire end_cnt_1ms ;reg [3:0] disp_data ;//每一位数码管显示的数值reg point_n_r ;//每一位数码管显示的小数点//****************************************************************
//--cnt_1ms
//****************************************************************always @(posedge clk or negedge rst_n)begin if(!rst_n)begincnt_1ms <= 'd0;end else if(add_cnt_1ms)begin if(end_cnt_1ms)begin cnt_1ms <= 'd0;endelse begin cnt_1ms <= cnt_1ms + 1'b1;end endend assign add_cnt_1ms = 1'b1;//数码管一直亮assign end_cnt_1ms = add_cnt_1ms && cnt_1ms == TIME_1MS - 1;//****************************************************************
//--seg_sel
//****************************************************************always @(posedge clk or negedge rst_n)begin if(!rst_n)beginseg_sel <= 6'b111_110;//循环移位实现时,需要给位选赋初值end else if(end_cnt_1ms)begin seg_sel <= {seg_sel[4:0],seg_sel[5]};//循环左移end end//****************************************************************
//--disp_data
//****************************************************************always @(posedge clk or negedge rst_n)begin if(!rst_n)begindisp_data <= 'd0;point_n_r <= 1'b1;end else begin case (seg_sel)6'b111_110 : begin disp_data <= din[3:0] ; point_n_r <= point_n[0]; end//第一位数码管显示的数值6'b111_101 : begin disp_data <= din[7:4] ; point_n_r <= point_n[1]; end6'b111_011 : begin disp_data <= din[11:8] ; point_n_r <= point_n[2]; end6'b110_111 : begin disp_data <= din[15:12]; point_n_r <= point_n[3]; end6'b101_111 : begin disp_data <= din[19:16]; point_n_r <= point_n[4]; end6'b011_111 : begin disp_data <= din[23:20]; point_n_r <= point_n[5]; enddefault: disp_data <= 'd0;endcaseend end//****************************************************************
//--seg_dig
//****************************************************************// always @(posedge clk or negedge rst_n)begin // if(!rst_n)begin// seg_dig <= 8'hff;//数码管的段选如何赋值好?// end // else begin // case (disp_data)// 0 : seg_dig <= {point_n_r,NUM_0};// 1 : seg_dig <= {point_n_r,NUM_1};// 2 : seg_dig <= {point_n_r,NUM_2};// 3 : seg_dig <= {point_n_r,NUM_3};// 4 : seg_dig <= {point_n_r,NUM_4};// 5 : seg_dig <= {point_n_r,NUM_5};// 6 : seg_dig <= {point_n_r,NUM_6};// 7 : seg_dig <= {point_n_r,NUM_7};// 8 : seg_dig <= {point_n_r,NUM_8};// 9 : seg_dig <= {point_n_r,NUM_9};// 10 : seg_dig <= {point_n_r,A };// 11 : seg_dig <= {point_n_r,B };// 12 : seg_dig <= {point_n_r,C };// 13 : seg_dig <= {point_n_r,D };// 14 : seg_dig <= {point_n_r,E };// 15 : seg_dig <= {point_n_r,F };// default: seg_dig <= 8'hff;// endcase// end // endalways @(*)begin case (disp_data)0 : seg_dig <= {point_n_r,NUM_0};1 : seg_dig <= {point_n_r,NUM_1};2 : seg_dig <= {point_n_r,NUM_2};3 : seg_dig <= {point_n_r,NUM_3};4 : seg_dig <= {point_n_r,NUM_4};5 : seg_dig <= {point_n_r,NUM_5};6 : seg_dig <= {point_n_r,NUM_6};7 : seg_dig <= {point_n_r,NUM_7};8 : seg_dig <= {point_n_r,NUM_8};9 : seg_dig <= {point_n_r,NUM_9};10 : seg_dig <= {point_n_r,A };11 : seg_dig <= {point_n_r,B };12 : seg_dig <= {point_n_r,C };13 : seg_dig <= {point_n_r,D };14 : seg_dig <= {point_n_r,E };15 : seg_dig <= {point_n_r,F };16 : seg_dig <= {point_n_r,DIV };default: seg_dig <= 8'b1101_1111;endcaseendendmodule
计数器模块:
代码分析:
- 由项目分析可以得出,由于数码管资源有限,毫秒位只能实现百位和十位的显示,因此我们不妨设置一个基准单位为10ms,每当计数到10ms时,毫秒计数器才进行加一(这样毫秒计数器只需加到100次即可)
- 除此之外,秒位计数器和分位计数器的技术条件分别为毫秒计数器计满和秒位计数器计满
- 由于本次项目需要引入按键信号进行秒表的暂停、继续以及清空,因此博主引入了两位按键信号。
- 一位按键控制秒表的暂停与继续。由上述分析可知,如果想要暂停秒表的计数,我们只需暂停基准单位10ms的计数即可(其余三个计数器,均要在10ms计数器工作的前提下才能逐级工作),因此我们只需要引入一个中间信号flag,用flag作为其计数的条件即可(博主将flag初值设为0不计数,按键按下后flag反转为1开始计数,再次按下再次反转,停止计数)
- 剩余一位按键用于四个计数器的清零,一旦四个计数器全部清零,传出的数码管数据自然为0
- 在代码的最后博主将毫秒,秒,分计数器的值赋给dout,再将其传入数码管驱动模块即可(之所以是这个顺序是因为博主前面数码管驱动模块对位选信号赋值好像写反了,不过影响不大)
module counter (input wire clk ,input wire rst_n ,input wire [1:0] key_in ,//按键信号输入output wire [23:0] dout ,//数码管各位值输出output wire [5:0] point_out //小数点输出
);//内部参数定义
parameter TIME_10ms = 19'd500_000;//10ms计数器,计满秒表毫秒位加1
parameter TIME_990ms = 7'd100 ;//计数器毫秒位,以10ms为单位
parameter TIME_1s = 6'd60 ;//计数器秒位,计满清零
parameter TIME_1min = 6'd60 ;//计数器分位,计满清零//内部信号定义
reg [18:0] cnt_10ms ;//10毫秒计数器寄存器
reg [6:0] cnt_99ms ;//毫秒位计数寄存器
reg [5:0] cnt_1s ;//秒位计数器寄存器
reg [5:0] cnt_1min ;//分位计数器寄存器wire add_cnt_10ms ;
wire end_cnt_10ms ;wire add_cnt_990ms ;
wire end_cnt_990ms ;wire add_cnt_1s ;
wire end_cnt_1s ;wire add_cnt_1min ;
wire end_cnt_1min ;reg flag ;//运行/暂停标志信号寄存器
reg flag_0 ;//清零信号标志寄存器//10毫秒计数器
always @(posedge clk or negedge rst_n)beginif(!rst_n)begincnt_10ms <= 1'b0;endelse if(add_cnt_10ms)beginif(end_cnt_10ms)begincnt_10ms <= 1'b0;endelse begincnt_10ms <= cnt_10ms + 1'b1;endendelse begincnt_10ms <= cnt_10ms;end
endassign add_cnt_10ms = 1'b1 && flag;//运行标志位有效
assign end_cnt_10ms = (add_cnt_10ms && cnt_10ms == TIME_10ms - 1'b1) || key_in[1];//按下清零按键也会清零//毫秒位计数器
always@(posedge clk or negedge rst_n)beginif(!rst_n)begincnt_99ms <= 1'b0;endelse if(add_cnt_990ms)beginif(end_cnt_990ms)begincnt_99ms <= 1'b0;endelse begincnt_99ms <= cnt_99ms + 1'b1;endendelse begincnt_99ms <= cnt_99ms;end
endassign add_cnt_990ms = end_cnt_10ms;
assign end_cnt_990ms = (add_cnt_990ms && cnt_99ms == TIME_990ms - 1'b1) || key_in[1];//秒位计数器
always@(posedge clk or negedge rst_n)beginif(!rst_n)begincnt_1s <= 1'b0;endelse if(add_cnt_1s)beginif(end_cnt_1s)begincnt_1s <= 1'b0;endelse begincnt_1s <= cnt_1s + 1'b1;endendelse begincnt_1s <= cnt_1s;end
endassign add_cnt_1s = end_cnt_990ms;
assign end_cnt_1s = (add_cnt_1s && cnt_1s == TIME_1s - 1'b1) || key_in[1];//分位计数器
always@(posedge clk or negedge rst_n)beginif(!rst_n)begincnt_1min <= 1'b0;endelse if(add_cnt_1min)beginif(end_cnt_1min)begincnt_1min <= 1'b0;endelse begincnt_1min <= cnt_1min + 1'b1;endendelse begincnt_1min <= cnt_1min;end
endassign add_cnt_1min = end_cnt_1s;
assign end_cnt_1min = (add_cnt_1min && cnt_1min == TIME_1min - 1'b1) || key_in[1];//flag信号控制秒表运行/暂停
always@(posedge clk or negedge rst_n)beginif(!rst_n)beginflag <= 1'b0;endelse if(key_in[0])beginflag <= ~flag;endelse beginflag <= flag;end
end//输出值赋值
assign dout[23:20] = cnt_99ms % 10;
assign dout[19:16] = cnt_99ms / 10;
assign dout[15:12] = cnt_1s % 10;
assign dout[11:8] = cnt_1s / 10;
assign dout[7:4] = cnt_1min % 10;
assign dout[3:0] = cnt_1min / 10;
assign point_out = 6'b110_101 ;endmodule
按键消抖模块:
代码分析:请详细参阅博主所写的按键消抖模块博文,在此不再赘述
module key_filter#(parameter WIDTH = 2)//参数化按键位宽
(input wire clk ,input wire rst_n ,input wire [WIDTH - 1:0] key_in ,//按键输入信号output reg [WIDTH - 1:0] key_out //输出稳定的脉冲信号
);parameter MAX = 20'd1_000_000;reg [19:0] cnt_delay ; //20ms延时计数寄存器
wire add_cnt_delay ; //开始计数的标志
wire end_cnt_delay ; //结束计数的标志reg [WIDTH - 1:0] key_r0 ; //同步
reg [WIDTH - 1:0] key_r1 ; //打一拍
reg [WIDTH - 1:0] key_r2 ; //打两拍wire [WIDTH - 1:0] nedge ; //下降沿寄存器//同步打拍
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_delay <= 1'b0;endelse if(add_cnt_delay )beginif(nedge)begin //检测到下降沿从0开始计数cnt_delay <= 1'b0;endelse if(cnt_delay == MAX - 1'b1)begincnt_delay <= cnt_delay; //计数计满结束后保持,避免产生多个输出脉冲endelse begincnt_delay <= cnt_delay + 1'b1;endendelse begincnt_delay <= 1'b0;end
endassign nedge = ~key_r1 & key_r2; //下降沿检测
assign add_cnt_delay = 1'b1;
assign end_cnt_delay = add_cnt_delay && cnt_delay == MAX - 1'b1;//key_out脉冲信号赋值
always@(posedge clk or negedge rst_n)beginif(!rst_n)beginkey_out <= 'd0;endelse if(cnt_delay == MAX - 2'd2)begin //计数计满前一个脉冲时产生按键脉冲key_out <= ~key_in;endelse beginkey_out <= 'd0;end
endendmodule
顶层模块:
/****
项目说明:本次项目是为了通过数码管实现秒表模拟。其中,六位数码管分别显示秒表的分位,秒位,毫秒位(百位和十位)。本次项目拟设置四个模块,分别为:按键消抖模块,计数模块,数码管驱动模块,以及顶层模块。本项目按键消抖模块要求传出两个按键的脉冲信号,一个用来暂停/开始秒表的计数,一个用来清空秒表的计数。本项目计数模块要求能传出秒表的各位值以及小数点位置本项目数码管驱动模块要求能正常显示秒表各位值
****/
module top(input wire clk ,input wire rst_n ,input wire [1:0] key_in ,output wire [5:0] sel ,output wire [7:0] seg
);wire [1:0] key_out ;
wire [23:0] din ;
wire [5:0] point_n ;seg_driver u_seg_driver( .clk (clk ),.rst_n (rst_n ),.din (din ),.point_n (point_n),.seg_sel (sel ),.seg_dig (seg )
);key_filter u_key_filter(.clk (clk ),.rst_n (rst_n ),.key_in (key_in ),.key_out (key_out)
);counter u_counter(.clk (clk ),.rst_n (rst_n ),.key_in (key_out ),.dout (din ),.point_out (point_n )
);endmodule
四、实现效果
五、总结
本项目主要锻炼了FPGA的数码管开发和计数器编写,实际仍未FPGA学习基础,博主学习时常常被数码管位选信号的段选信号的赋值绕晕,解决方法也只有自己亲自编写几遍,否则仍然无法理解余晖效应和动态扫面是如何让数码管同时显示不同字符的。后续对于基础部分的学习博主应该还会写几篇关于蜂鸣器的博文,至此算是基础语法学习结束。
再往后博主学习到IP核HLS,通讯协议时,也许会继续编写博客,但也要看博主是否有足够的精力,以及能否自己理解并讲解清楚,否则话的还是请各位自行上网寻找视频教学资料,不管是野火还是正点原子,都有针对的FPGA学习视频。
学海无涯,大家有缘再见。
相关文章:

FPGA学习—通过数码管实现电子秒表模拟
文章目录 一、数码管简介二、项目分析三、项目源码及分析四、实现效果五、总结 一、数码管简介 请参阅博主以前写过的一篇电子时钟模拟,在此不再赘述。 https://blog.csdn.net/qq_54347584/article/details/130402287 二、项目分析 项目说明:本次项目…...

区块链媒体发稿:区块链媒体宣发常见问题解析
据统计,由于区块链应用和虚拟货币的兴起,越来越多媒体对区块链领域开展报导,特别是世界各国媒体宣发全是热火朝天。但是,随着推卸责任媒体宣发的五花八门,让很多人因而上当受骗,乃至伤害一大笔资产。身为投…...

openGauss学习笔记-28 openGauss 高级数据管理-NULL值
文章目录 openGauss学习笔记-28 openGauss 高级数据管理-NULL值28.1 IS NOT NULL28.2 IS NULL openGauss学习笔记-28 openGauss 高级数据管理-NULL值 NULL值代表未知数据。无法比较NULL和0,因为它们是不等价的。 创建表时,可以指定列可以存放或者不能存…...
DAO和XML文件参数和返回值
①MyBatis中resultType和resultMap的区别 1.使用MyBatis查询数据库记录时,返回类型常用的有两种:resultType和resultMap。那么两者之间有什么区别呢? 如果只是返回一个值,简单类型,比如说String或者int,那…...

vue 浏览器右侧可拖拽小组件
目录 0. 使用场景 1. 动图示例 2. 实现方式 2.1 创建drag.js 2.2 使用v-drag 3. 结尾 0. 使用场景 很多网页在浏览器右侧有"导航"或者“智能助手”的悬浮小气泡框,比如我们的csdn☞ 作为页面友好型的引导标注,某些场景下这些小气泡可以…...
SpringMvc学习笔记五
Restful 风格路由 1. 配置类 1.1、SpringMvcConfig配置类 Configuration ComponentScan({"com.itheima.controller", "com.itheima.config"}) 方式1.2 添加com.itheima.config 扫描目录 EnableWebMvc public class SpringMvcConfig { } 1.2、ServletCo…...
ORACLE-DG总结
述 当主库的某些日志没有成功传送到备库,那么这时候就发生了归档裂缝(Archive Gap)。目前Oracle提供了两种日志GAP的检测和处理机制,分别是自动GAP处理(Automatic Gap Resolution)和FAL进程GAP处理(FAL Gap Resolution)。自动GAP处理即主库上的ARCn进程会每分钟检查备库…...
机器学习中的 K-均值聚类算法及其优缺点
K-均值聚类算法是一种常用的无监督学习算法,用于将相似的数据点分组为聚类。 其步骤如下: 1. 初始化:选择聚类数K,随机选取K个聚类中心。 2. 计算距离:计算每个数据点与K个聚类中心的距离,将其分配到距离最…...
【数据化分析和建模】一般步骤(个人工作经验总结)
近期关于【数据化分析和建模】一般步骤的思考如下。 以终为始,要解决什么问题,实现什么效果? 数据可视化分析的首要目标是通过将数据以可视化图表的形式真实、完整地呈现业务现状,为发现业务问题打好基础,包括实时的…...

视频安防监控EasyCVR平台海康大华设备国标GB28181告警布防的报文说明
TSINGSEE青犀视频监控综合管理平台EasyCVR基于云边端协同,可支持海量视频的轻量化接入与汇聚管理。平台既具备传统安防视频监控的能力,比如:视频监控直播、云端录像、云存储、录像检索与回看、告警上报、平台级联、云台控制、语音对讲等&…...

T31开发笔记:librtmp拉流测试
若该文为原创文章,转载请注明原文出处。 T31使用librtmp拉流并保存成FLV文件或H264和AAC文件。 librtmp编译在前面有教程,自行编译。 实现的目的是想要获取获取rtmp的AAC流并播放,实时双向对讲功能。 一、硬件和开发环境 1、硬件࿱…...
2308C++概念化
原文 库 //概念化(需要C20) struct 可画 {void 画(小出流 &out) const {te::call([](auto const &s, auto &out)-> decltype(s.画(out)) { s.画(out); }, *this, out);} }; struct 方形 {void 画(小出流 &out) const { out << "方形"; } }…...
flutter开发实战-实现自定义按钮类似UIButton效果
flutter开发实战-实现自定义按钮类似UIButton效果 最近开发过程中需要实现一下UIButton效果的flutter按钮,这里使用的是监听手势点击事件。 一、GestureDetector GestureDetector属性定义 GestureDetector({super.key,this.child,this.onTapDown,this.onTapUp,t…...
深度优先搜索|1034, 1020, 1254
深度优先搜索|1034. 边界着色, 机器人的运动范围,529. 扫雷游戏 边界着色机器人的运动范围扫雷问题 边界着色 把这个题分段了,先找到包括 (row, col) 的连通分量,然后再去找符合条件的边界,找到以后涂上颜色就行。 c…...

都市信息供求网servlet+jsp新闻广告出售java源代码mysql
本项目为前几天收费帮学妹做的一个项目,Java EE JSP项目,在工作环境中基本使用不到,但是很多学校把这个当作编程入门的项目来做,故分享出本项目供初学者参考。 一、项目描述 都市信息供求网servletjsp 系统1权限:管理…...
kubeadm init:failed to pull image registry.k8s.io/pause:3.6
错误信息: Unfortunately, an error has occurred: timed out waiting for the condition This error is likely caused by: - The kubelet is not running - The kubelet is unhealthy due to a misconfiguration of the node in some way…...
设计模式之简单工厂模式、工厂模式、抽象工厂模式
参考: 设计模式笔记 简单工厂模式 ● 将类的创建过程交给工厂类实现,如果需要一个类对象,则直接通过工厂创建一个类。 ● 简单工厂模式不符合开闭原则 ● 适用场景:工厂类负责创建的对象比较少;客户端只知道传入工厂…...

C# 控制台彩色深度打印 工具类
文章目录 前言Nuget 环境安装代码使用打印结果 总结 前言 有时候我们想要靠打印获得程序信息,因为Dubeg模式需要一点一点断点进入进出,但是我们觉得断点运行实在是太慢了,还是直接打印后找结果会好一点。 Nuget 环境安装 想自己写的话可以看…...
Pytorch Tensor维度变换方法
1.torch.reshape()、torch.view()可以调整Tensor的shape 2.torch.unsqueeze(index)可以为Tensor增加一个维度 3.squeeze()可以删减维度 4.expand()扩展维度 5.repeat()维度重复,不常用 6.transpose(dim1, dim2)交换dim1与dim2࿰…...

微信小程序之点击文字文字自动转语音进行播放,微信小程序文字识别转语音播放
需求 一堆题目,题干需要在点击的时候进行语音朗读,不做音频上传,不然不便于维护 解决方案 点击查看微信官方文档:微信同声传译 使用流程 后台配置 mp.weixin.qq.com 设置 > 第三方设置 > 插件管理 小程序插件使用流…...
Vim 调用外部命令学习笔记
Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...

Linux 文件类型,目录与路径,文件与目录管理
文件类型 后面的字符表示文件类型标志 普通文件:-(纯文本文件,二进制文件,数据格式文件) 如文本文件、图片、程序文件等。 目录文件:d(directory) 用来存放其他文件或子目录。 设备…...

RocketMQ延迟消息机制
两种延迟消息 RocketMQ中提供了两种延迟消息机制 指定固定的延迟级别 通过在Message中设定一个MessageDelayLevel参数,对应18个预设的延迟级别指定时间点的延迟级别 通过在Message中设定一个DeliverTimeMS指定一个Long类型表示的具体时间点。到了时间点后…...

聊聊 Pulsar:Producer 源码解析
一、前言 Apache Pulsar 是一个企业级的开源分布式消息传递平台,以其高性能、可扩展性和存储计算分离架构在消息队列和流处理领域独树一帜。在 Pulsar 的核心架构中,Producer(生产者) 是连接客户端应用与消息队列的第一步。生产者…...

Cinnamon修改面板小工具图标
Cinnamon开始菜单-CSDN博客 设置模块都是做好的,比GNOME简单得多! 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...

Psychopy音频的使用
Psychopy音频的使用 本文主要解决以下问题: 指定音频引擎与设备;播放音频文件 本文所使用的环境: Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...
【JavaSE】绘图与事件入门学习笔记
-Java绘图坐标体系 坐标体系-介绍 坐标原点位于左上角,以像素为单位。 在Java坐标系中,第一个是x坐标,表示当前位置为水平方向,距离坐标原点x个像素;第二个是y坐标,表示当前位置为垂直方向,距离坐标原点y个像素。 坐标体系-像素 …...

学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2
每日一言 今天的每一份坚持,都是在为未来积攒底气。 案例:OLED显示一个A 这边观察到一个点,怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 : 如果代码里信号切换太快(比如 SDA 刚变,SCL 立刻变&#…...
嵌入式常见 CPU 架构
架构类型架构厂商芯片厂商典型芯片特点与应用场景PICRISC (8/16 位)MicrochipMicrochipPIC16F877A、PIC18F4550简化指令集,单周期执行;低功耗、CIP 独立外设;用于家电、小电机控制、安防面板等嵌入式场景8051CISC (8 位)Intel(原始…...
文件上传漏洞防御全攻略
要全面防范文件上传漏洞,需构建多层防御体系,结合技术验证、存储隔离与权限控制: 🔒 一、基础防护层 前端校验(仅辅助) 通过JavaScript限制文件后缀名(白名单)和大小,提…...