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

MATLAB编程的计时器应用设计

基于MATLAB编程的计时器应用设计,可实现计时

提到MATLAB,很多人第一反应是算数值、画图、做仿真,但其实它写个轻量小工具真的挺顺手——比如这个我折腾过的极简计时器,本来是大三GUI课的作业,改改之后放实验室当倒计时用,现在跑个10分钟的表征实验,盯着它比看手机靠谱多了。

先讲最基础的需求:就是普通的计时工具,能开始、暂停、重置,显示到毫秒就行,最好窗口别挡着别的操作。很多新手一开始会踩坑,比如写个while循环硬刷新UI,结果直接把MATLAB界面卡死,今天咱们就用正经的写法来做。

先搭个UI架子

首先创建窗口和时间显示标签,纯代码就能搞定,不用拖控件:

fig = uifigure('Title','简易MATLAB计时器','Position',[100 100 350 180]); timeLabel = uilabel(fig,'Position',[50 100 250 50],'FontSize',28,'Text','00:00:00.00');

这段就是建了个350x180的窗口,加了个超大号的文本标签,初始显示标准的时分秒毫秒格式,字体调大到28号,实验室屏幕远也能看清。

核心计时逻辑,别踩卡死的坑

很多新手上来会写这种笨代码:

% 别这么写!会卡死UI while true elapsedTime = elapsedTime + 0.01; drawnow; end

这个while循环会把MATLAB的UI线程锁死,点按钮根本没反应,直到循环停了才行。正确的做法是用MATLAB自带的timer对象,它会在单独的线程里定时触发回调,完全不会阻塞主界面。

基于MATLAB编程的计时器应用设计,可实现计时

接下来写定时更新时间的回调函数:

function updateTimer(~,~) if isRunning elapsedTime = toc(startTime); hrs = floor(elapsedTime/3600); mins = floor(mod(elapsedTime,3600)/60); secs = floor(mod(elapsedTime,60)); frac = round(mod(elapsedTime,1)*100); timeLabel.Text = sprintf('%02d:%02d:%02d.%02d',hrs,mins,secs,frac); end end

这里用tictoc来算流逝时间,比自己手动计数准多了,不会因为UI更新慢导致时间飘。sprintf('%02d:...')是为了补零,比如1分2秒会显示成01:02:03.45,看着整整齐齐。

加按钮和交互逻辑

接下来加两个按钮,开始/暂停和重置,位置我调了好久刚好卡在窗口底部:

startPauseBtn = uibutton(fig,'Position',[50 40 120 40],'Text','开始计时',... 'ButtonPushedFcn',@toggleTimer); resetBtn = uibutton(fig,'Position',[180 40 120 40],'Text','重置',... 'ButtonPushedFcn',@resetTimer);

然后写按钮的回调函数,这里用嵌套函数比全局变量省心多了,不用到处声明变量:

function toggleTimer(~,~) if ~isRunning if isempty(startTime) startTime = tic; else % 暂停后继续的小技巧:不用重新tic,补上暂停的时间差 startTime = tic - toc(startTime); end startPauseBtn.Text = '暂停计时'; isRunning = true; else startPauseBtn.Text = '继续计时'; isRunning = false; end end

这里有个细节:如果暂停之后再继续,不是重新tic,而是用tic - toc(startTime),这样暂停的时间不会被算进去,比如你暂停了5秒,继续之后时间会接着之前的走,不会跳掉那5秒,比直接停timer对象自然多了。

重置函数就更简单了,把状态清零就行:

function resetTimer(~,~) isRunning = false; startTime = []; timeLabel.Text = '00:00:00.00'; startPauseBtn.Text = '开始计时'; end

收尾:别忘了清理内存

最后要记得在窗口关闭的时候删掉timer对象,不然它会一直在后台跑,占内存还停不下来:

set(fig,'CloseRequestFcn',@(~,~)cleanup(t,fig)); function cleanup(t,fig) stop(t); delete(t); delete(fig); end

完整代码直接用

把所有代码整合起来,就是一个可以直接运行的完整脚本:

function simpleTimer % 初始化UI和计时器 fig = uifigure('Title','简易MATLAB计时器','Position',[100 100 350 180]); timeLabel = uilabel(fig,'Position',[50 100 250 50],'FontSize',28,'Text','00:00:00.00'); % 按钮布局 startPauseBtn = uibutton(fig,'Position',[50 40 120 40],'Text','开始计时',... 'ButtonPushedFcn',@toggleTimer); resetBtn = uibutton(fig,'Position',[180 40 120 40],'Text','重置',... 'ButtonPushedFcn',@resetTimer); % 状态变量 isRunning = false; startTime = []; % 计时器对象,0.01秒更新一次,足够显示毫秒级精度 t = timer('Period',0.01,'ExecutionMode','fixedRate','TimerFcn',@updateTimer); start(t); % 窗口关闭时自动清理计时器 set(fig,'CloseRequestFcn',@(~,~)cleanup(t,fig)); % 嵌套函数:更新时间显示 function updateTimer(~,~) if isRunning elapsedTime = toc(startTime); hrs = floor(elapsedTime/3600); mins = floor(mod(elapsedTime,3600)/60); secs = floor(mod(elapsedTime,60)); frac = round(mod(elapsedTime,1)*100); timeLabel.Text = sprintf('%02d:%02d:%02d.%02d',hrs,mins,secs,frac); end end % 切换开始暂停 function toggleTimer(~,~) if ~isRunning if isempty(startTime) startTime = tic; else startTime = tic - toc(startTime); end startPauseBtn.Text = '暂停计时'; isRunning = true; else startPauseBtn.Text = '继续计时'; isRunning = false; end end % 重置计时器 function resetTimer(~,~) isRunning = false; startTime = []; timeLabel.Text = '00:00:00.00'; startPauseBtn.Text = '开始计时'; end % 清理计时器避免内存泄漏 function cleanup(t,fig) stop(t); delete(t); delete(fig); end end

自己玩的小改动

我自己用的时候还加了两个小优化:

  1. 把窗口设成永远置顶,只需要在uifigure里加个参数'WindowStyle','alwaysOnTop',做实验的时候不用切窗口就能看时间
  2. 加了倒计时提醒功能,输入总时间之后到点自动响一声,不用一直盯着看

其实这个小工具没啥技术含量,但胜在完全贴合实验室的使用场景,毕竟是自己写的小工具,用着都顺手一点。感兴趣的可以自己改改,比如加个计次 lap 按钮,把每次的计时结果存下来导出到Excel里,玩法挺多的。

http://www.jsqmd.com/news/573453/

相关文章:

  • 嵌入式看门狗服务:复位源识别与Nucleo深度适配
  • 英伟达与Marvell达成新协议,抢夺AI控制层主导权
  • Hvac一次卡顿问题分析
  • 基于位置闭环的神经网络自抗扰(RBF-ADRC)控制永磁同步电机研究(有推导公式)研究(Simulink仿真实现)
  • 网站URL优化的原则有哪些_如何利用声音搜索优化网站 SEO
  • 基于 hctsa 的脑电(EEG)复杂性核心指标筛选研究
  • 为什么一个视频能让全国人民同时秒开?
  • Mojo主控+Python微服务协同部署(单节点双Runtime热容灾设计):某自动驾驶公司已稳定运行217天的SRE运维白皮书
  • Mixly+MAX30102心率监测实战:从接线到串口数据可视化(附完整代码)
  • Linux下C程序编译与构建系统详解
  • OpenClaw内存优化:千问3.5-9B在4GB设备上的运行方案
  • Ubuntu 24.04 内核 Kernel Panic 问题排查与解决流程(第二次出现该问题后,永久性解决)
  • ai赋能react开发:描述需求即可获得高质量数据可视化组件代码
  • 诗词在线app上线带来的启发和展望
  • 大模型如何“思考”:一文读懂从输入到输出的完整逻辑,小白也能学会收藏!
  • Windows任务栏美化工具TranslucentTB完全指南
  • 用Proteus和Keil C51复刻经典:STC89C51单片机红绿灯仿真全流程(附紧急制动与手动切换)
  • c++编程:多组数据求和
  • APRSPacketLib:嵌入式C库实现APRS协议编解码
  • 谷歌SEO新手入门:以SEO为主、GEO为辅,精准打造高转化内容与用户人群
  • 【51单片机实战指南】从零构建多功能波形发生器:正弦、矩形、三角、锯齿波全解析
  • Tomato-Novel-Downloader:解决小说离线阅读痛点的全场景方案
  • BMP280气压计实战:从硬件接线到数据采集的完整指南(附STM32代码)
  • 【2026年最新600套毕设项目分享】springboot鸣珮乐器销售网站(14301)
  • 希尔排序算法原理与嵌入式应用实践
  • 湖南石材结晶公司
  • OpenClaw+Qwen3-32B内容创作:自动化生成技术博客与配图实践
  • 用AI重新定义中文字体设计:从3000个字符到完整字库的智能飞跃
  • 医疗大数据数据上报失败问题完整排查复盘
  • 混合ai开发新思路:快马生成项目演示云端与d盘本地ollama协同编程