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

GD32利用Systick实现高精度μs与ms延时函数的设计与优化

1. Systick定时器基础原理在嵌入式开发中精准延时是每个工程师都会遇到的基础需求。GD32作为国产ARM Cortex-M内核单片机其内置的Systick定时器就是我们实现微秒(μs)和毫秒(ms)级延时的利器。不同于通用定时器Systick是Cortex-M内核自带的一个24位递减计数器它最大的优势就是不占用额外的定时器资源。Systick的工作原理其实很简单它从重装载值(LOAD)开始递减当减到0时会产生中断如果使能同时会将控制状态寄存器(CTRL)的COUNTFLAG位置1。这个过程中有两个关键参数需要关注时钟源选择和分频系数。GD32通常提供两种时钟源选项内核时钟HCLK内核时钟的8分频HCLK/8假设我们的GD32F1x0系列芯片运行在72MHz主频下如果选择HCLK/8作为时钟源那么Systick的实际计数频率就是9MHz72MHz/8。这意味着每个计数周期的时间是1/9,000,000 ≈ 111ns这个基础时间单位就是我们实现高精度延时的关键。2. 硬件配置与初始化要让Systick正常工作我们需要先完成硬件初始化配置。下面是一个典型的Systick初始化函数void systick_config(void) { /* 选择HCLK/8作为Systick时钟源 */ systick_clksource_set(SYSTICK_CLKSOURCE_HCLK_DIV8); /* 计算1us和1ms需要的计数值 */ count_1us (float)SystemCoreClock/8000000; count_1ms (float)count_1us * 1000; }这段代码做了三件重要的事情通过systick_clksource_set()函数设置时钟源为HCLK/8计算1微秒对应的计数值SystemCoreClock/8000000计算1毫秒对应的计数值1us计数值×1000这里特别要注意的是count_1us和count_1ms这两个静态变量。它们被定义为volatile static float类型volatile关键字告诉编译器不要优化这些变量因为它们可能在中断中被修改static限定作用域只在当前文件float类型确保在72MHz等非整除数频率下也能得到精确结果在实际项目中我遇到过因为忘记加volatile而导致延时不准的问题。当编译器优化掉这些变量时延时函数就完全失控了这个坑大家一定要注意避开。3. 查询方式实现精准延时查询方式是使用Systick实现延时最基础也最可靠的方法。它的核心思想是通过轮询CTRL寄存器的COUNTFLAG位来判断计时是否完成。下面是具体的实现代码3.1 微秒级延时实现void delay_1us(uint32_t count) { uint32_t ctl; /* 设置重装载值 */ SysTick-LOAD (uint32_t)(count * count_1us); /* 清除当前计数值 */ SysTick-VAL 0x0000U; /* 启动Systick */ SysTick-CTRL SysTick_CTRL_ENABLE_Msk; /* 等待计时完成 */ do { ctl SysTick-CTRL; } while((ctl SysTick_CTRL_ENABLE_Msk) !(ctl SysTick_CTRL_COUNTFLAG_Msk)); /* 关闭Systick */ SysTick-CTRL ~SysTick_CTRL_ENABLE_Msk; /* 清除计数值 */ SysTick-VAL 0x0000U; }这段代码的工作流程非常清晰根据需要的延时时间计算并设置LOAD寄存器清零当前计数值VAL寄存器使能Systick开始计时循环检查COUNTFLAG位直到计时完成关闭Systick并清理现场在实际测试中这种方式的精度可以做到±1us以内完全满足大多数外设驱动对时序的要求。我曾经用逻辑分析仪实测过在72MHz主频下10us延时的实际误差不超过0.1us。3.2 毫秒级延时实现毫秒级延时的实现与微秒级几乎相同只是使用了不同的计数值void delay_1ms(uint32_t count) { uint32_t ctl; SysTick-LOAD (uint32_t)(count * count_1ms); SysTick-VAL 0x0000U; SysTick-CTRL SysTick_CTRL_ENABLE_Msk; do { ctl SysTick-CTRL; } while((ctl SysTick_CTRL_ENABLE_Msk) !(ctl SysTick_CTRL_COUNTFLAG_Msk)); SysTick-CTRL ~SysTick_CTRL_ENABLE_Msk; SysTick-VAL 0x0000U; }虽然代码结构相同但有几点需要注意毫秒级延时使用了count_1ms作为计算基准长时间延时超过几百毫秒时建议使用硬件定时器而非Systick在RTOS环境中毫秒级延时通常会触发任务调度4. 中断方式实现延时除了查询方式我们还可以利用Systick中断来实现延时。这种方式更适合在RTOS中作为系统心跳时钟使用。下面是中断方式的典型实现4.1 中断服务函数配置首先需要配置中断服务函数volatile uint32_t ticks 0; void SysTick_Handler(void) { ticks; }4.2 中断方式延时函数然后实现基于中断的延时函数void delay_ms(uint32_t ms) { uint32_t start ticks; while((ticks - start) ms); }这种方式看似简单但有几点需要特别注意需要在Systick初始化时使能中断变量ticks必须声明为volatile延时精度受中断响应时间影响在中断嵌套场景下可能会有误差我在一个实际项目中对比过两种方式发现中断方式在负载较重时可能会有几十微秒的抖动而查询方式则稳定得多。所以如果对精度要求高还是建议使用查询方式。5. 性能优化技巧经过多年的项目实践我总结出几个Systick延时函数的优化技巧5.1 避免浮点运算前面的示例代码使用了浮点数计算这在没有FPU的MCU上效率较低。我们可以改用定点数运算// 原浮点版本 count_1us (float)SystemCoreClock/8000000; // 优化为整数运算 count_1us SystemCoreClock/8000000; count_remainder SystemCoreClock%8000000;5.2 循环展开对于短延时可以展开循环减少开销void delay_10us(void) { SysTick-LOAD 90; // 9MHz * 10us SysTick-VAL 0; SysTick-CTRL SysTick_CTRL_ENABLE_Msk; while(!(SysTick-CTRL SysTick_CTRL_COUNTFLAG_Msk)); SysTick-CTRL 0; }5.3 动态时钟源切换根据延时需求动态切换时钟源微秒级延时使用HCLK更高精度毫秒级延时使用HCLK/8更低功耗void delay_us(uint32_t us) { if(us 100) { systick_clksource_set(SYSTICK_CLKSOURCE_HCLK); // ...使用HCLK实现短延时 } else { systick_clksource_set(SYSTICK_CLKSOURCE_HCLK_DIV8); // ...使用HCLK/8实现长延时 } }6. 常见问题与解决方案在实际使用Systick的过程中我遇到过不少坑这里分享几个典型问题的解决方法6.1 延时时间不准确现象延时时间比预期长很多原因忘记设置时钟源使用了默认的低速时钟系统时钟配置错误实际主频与预期不符解决方案确认SystemCoreClock的值是否正确检查时钟树配置使用示波器测量实际延时时间6.2 在RTOS中无法使用现象在FreeRTOS等系统中无法正常使用Systick原因RTOS已经接管了Systick作为系统时钟解决方案使用RTOS提供的延时函数如vTaskDelay如果必须使用裸机延时可以改用通用定时器6.3 长时间延时失效现象延时超过几百毫秒时出现异常原因24位计数器溢出最大计数16,777,215解决方案分段延时多次调用短延时函数改用32位通用定时器结合计数器溢出中断实现长延时7. 不同型号GD32的适配虽然GD32各系列都基于Cortex-M内核但在使用Systick时还是有一些差异需要注意7.1 GD32F1x0系列最大主频108MHz需要特别注意时钟树配置提供完整的Systick驱动库7.2 GD32F4x0系列最大主频200MHz支持浮点单元(FPU)可以使用更精确的浮点计算7.3 GD32E23x系列最大主频72MHz超低功耗设计Systick在低功耗模式下行为可能不同针对不同型号建议在代码中使用宏定义进行区分#if defined(GD32F1x0) #define SYSTICK_CLK_SOURCE SYSTICK_CLKSOURCE_HCLK_DIV8 #elif defined(GD32F4x0) #define SYSTICK_CLK_SOURCE SYSTICK_CLKSOURCE_HCLK #endif在项目移植过程中我发现GD32的Systick实现与STM32高度兼容这大大降低了迁移成本。但在高精度应用中还是建议重新验证延时精度因为时钟树配置可能存在细微差别。

相关文章:

GD32利用Systick实现高精度μs与ms延时函数的设计与优化

1. Systick定时器基础原理 在嵌入式开发中,精准延时是每个工程师都会遇到的基础需求。GD32作为国产ARM Cortex-M内核单片机,其内置的Systick定时器就是我们实现微秒(μs)和毫秒(ms)级延时的利器。不同于通用定时器,Systick是Cortex-M内核自带…...

VMware ESXi上玩转Proxmox VE:家庭实验室搭建全记录(附OpenWrt配置)

VMware ESXi与Proxmox VE混合虚拟化实战:打造高性能家庭实验室 在家庭环境中搭建多功能虚拟化平台,已经成为越来越多技术爱好者的新选择。将成熟的商业虚拟化方案VMware ESXi与开源的Proxmox VE结合使用,既能发挥各自优势,又能在…...

菊厂员工家属吐槽:42 岁老公越干越起劲,牛马当久了形成意识了,周末不加班他也是五六点早起,晚上一两点睡,让他休息都不干!

前段时间刷到一个菊厂员工家属的讨论集合帖。有位 42 岁员工喊着要离职,却卡在进退两难的关口:提前走,保留股票要打折,多年奋斗的财富会缩水。继续熬吧,身体和精力早已被工作透支。一边是提前退休要打折股票的现实压力…...

N76E003开发环境搭建避坑指南:从Keil C-51安装到Nu-Link驱动配置

N76E003开发环境搭建避坑指南:从Keil C-51安装到Nu-Link驱动配置 对于初次接触N76E003开发的工程师来说,搭建一个稳定可靠的开发环境是项目成功的第一步。本文将深入解析从Keil C-51安装到Nu-Link驱动配置的全流程,特别针对那些容易让人"…...

小白程序员必备:收藏这份AI Agent设计模式指南,轻松入门大模型开发

AI Agent的设计模式正在经历从学术概念到工业标准的关键转折。 ReAct、Planning、单智能体和多智能体四种核心模式构成了当前Agent系统的技术基座,而Anthropic在其"Building Effective Agents"指南中反复强调的核心原则——“从最简单的方案开始&#xff…...

科研小白必看:如何用学校邮箱快速注册Reaxys数据库(附常见问题解答)

科研新手高效注册Reaxys数据库的完整指南与实战技巧 刚踏入科研领域时,获取权威数据库的使用权限往往是第一个需要跨越的门槛。作为Elsevier旗下的核心化学数据库,Reaxys以其海量的化合物信息和反应数据成为众多研究者的首选工具。但对于初次接触的同学来…...

【2024唯一权威实测报告】:Python 3.15异步HTTP客户端QPS突破142,000,但93%开发者尚未启用这3个关键配置!

第一章:Python 3.15异步HTTP客户端性能跃迁全景图Python 3.15正式将httpx.AsyncClient深度集成至标准库asyncio.http模块,并引入零拷贝响应流、协程级连接复用池与自适应超时调度器三大底层优化机制。基准测试显示,在万级并发GET请求场景下&a…...

别再只会用FFT了!用MATLAB玩转信号功率谱分析:从周期图到Welch法的保姆级实战

别再只会用FFT了!用MATLAB玩转信号功率谱分析:从周期图到Welch法的保姆级实战 当你面对一段嘈杂的工业振动信号,或是夹杂着环境噪声的脑电数据时,快速准确地识别其中的频率成分往往成为解决问题的关键。传统教学中强调的FFT变换虽…...

E2E自驾规控30讲:导论

欢迎来到端到端(End-to-End)自动驾驶与机器人控制的世界!这也是目前工业界和学术界最具挑战、也最激动人心的技术前沿。一、 端到端规划控制概述:打破“接力赛”在传统的自动驾驶或机器人系统中,架构通常是高度模块化的…...

如何安全解锁华为设备Bootloader:面向普通用户的完整指南

如何安全解锁华为设备Bootloader:面向普通用户的完整指南 【免费下载链接】PotatoNV Unlock bootloader of Huawei devices on Kirin 960/95х/65x/620 项目地址: https://gitcode.com/gh_mirrors/po/PotatoNV 对于许多华为设备用户来说,Bootload…...

照着用就行:毕业论文全流程神器——千笔·降AIGC助手

你是否正为论文选题发愁?是否在文献整理中手忙脚乱?是否因查重率高而焦虑?千笔AI,专为毕业论文全流程打造,助你高效完成写作,轻松应对学术挑战。千笔AI(官网直达入口) :https://www.qianbixiezu…...

MySQL 事务锁冲突排查

MySQL事务锁冲突排查:高效定位数据库并发瓶颈 在数据库高并发场景中,事务锁冲突是导致性能下降的常见原因。当多个事务同时竞争同一资源时,可能引发阻塞、超时甚至死锁,影响业务响应速度。如何快速定位并解决锁冲突,是…...

RAGFlow保姆级安装指南:从零配置到成功部署(附常见问题排查)

RAGFlow深度部署实战:从环境搭建到高阶配置全解析 在人工智能技术快速迭代的今天,检索增强生成(RAG)系统正成为企业知识管理的核心基础设施。RAGFlow作为一款开源RAG引擎,凭借其深度文档理解能力和灵活的架构设计&…...

PP-DocLayoutV3部署案例:中小企业电子档案系统非平面文档预处理集成

PP-DocLayoutV3部署案例:中小企业电子档案系统非平面文档预处理集成 1. 项目背景与需求场景 在中小企业电子档案管理系统中,经常需要处理各种非平面文档,比如弯曲的发票、倾斜的合同、折叠的报告等。这些文档在扫描或拍照后往往存在变形、倾…...

告别Pygame!用Pyglet从零搭建你的第一个游戏窗口(附Hello World完整代码)

告别Pygame!用Pyglet从零搭建你的第一个游戏窗口(附Hello World完整代码) 在Python游戏开发领域,Pygame长期占据着入门首选库的地位。但如果你正在寻找一个更轻量、更现代的替代方案,Pyglet值得你深入了解。作为一个纯…...

小白也能搞定!Clawdbot汉化版快速部署指南,免费私有AI助手开箱即用

小白也能搞定!Clawdbot汉化版快速部署指南,免费私有AI助手开箱即用 1. 什么是Clawdbot? Clawdbot是一个可以让你在任何地方与AI对话的智能助手,就像ChatGPT一样,但有四个关键优势: 微信/WhatsApp/Telegr…...

Llama Factory保姆级入门:可视化界面微调ChatGLM/Qwen,告别复杂代码

Llama Factory保姆级入门:可视化界面微调ChatGLM/Qwen,告别复杂代码 1. 为什么选择Llama Factory? 1.1 传统微调方式的痛点 想象一下,你想让ChatGLM或Qwen模型学会某个特定领域的知识(比如医疗咨询或法律问答&#…...

如何使用Java完成简单的电子邮件发送程序

使用Java完成一个简单的电子邮件发送程序的核心依赖是 JavaMail API。它允许你通过 SMTP 协议连接电子邮件服务器并发送电子邮件。下面一步一步地解释如何实现它。增加必要的依赖性 如果你使用 Maven 项目,在 pom.xml 加入以下依赖:javax.mail 包括发送邮…...

深信服AF8.0防火墙新手必看:从开箱到上网配置全流程(附常见问题排查)

深信服AF8.0防火墙实战指南:从开箱到策略优化的全链路配置 第一次接触企业级防火墙的运维工程师,面对机架上的深信服AF设备时,往往既兴奋又忐忑。这款承载着企业网络安全重任的硬件设备,其配置过程远比家用路由器复杂得多。本文将…...

零基础通关Linux!从入门到精通全攻略,IT人必备的核心技能指南

零基础通关Linux!从入门到精通全攻略,IT人必备的核心技能指南 Hello 各位小伙伴们大家好! 欢迎来到Linux从入门到进阶的保姆级攻略。接下来,我会带着大家完成从零基础小白,到Linux技术达人的完整蜕变。话不多说&#x…...

基于微信小程序的中小型企业员工电子档案借阅管理系统的设计与实现

目录需求分析与系统设计技术选型与架构搭建核心功能模块开发安全与性能优化测试与部署上线运营与数据分析项目技术支持源码获取详细视频演示 :文章底部获取博主联系方式!同行可合作需求分析与系统设计 明确中小型企业员工电子档案借阅管理的核心需求&am…...

5个关键问题:如何构建高可靠分布式智能体通信系统?

5个关键问题:如何构建高可靠分布式智能体通信系统? 【免费下载链接】MiroFish A Simple and Universal Swarm Intelligence Engine, Predicting Anything. 简洁通用的群体智能引擎,预测万物 项目地址: https://gitcode.com/GitHub_Trending…...

Qwen2.5-32B-Instruct保姆级教程:Ubuntu20.04环境部署

Qwen2.5-32B-Instruct保姆级教程:Ubuntu20.04环境部署 1. 引言 最近大语言模型越来越火,特别是阿里云开源的Qwen2.5系列,其中32B版本在代码能力和多语言支持上表现相当不错。不过很多朋友在部署时遇到了各种问题,特别是环境配置…...

3大核心功能解析:从零开始掌握Ryujinx模拟器实战技巧

3大核心功能解析:从零开始掌握Ryujinx模拟器实战技巧 【免费下载链接】Ryujinx 用 C# 编写的实验性 Nintendo Switch 模拟器 项目地址: https://gitcode.com/GitHub_Trending/ry/Ryujinx 作为一款用C#编写的开源Nintendo Switch模拟器,Ryujinx以其…...

快速部署次元画室:基于Qwen3-32B的动漫角色设计终端,开箱即用

快速部署次元画室:基于Qwen3-32B的动漫角色设计终端,开箱即用 1. 次元画室简介与核心价值 次元画室是一款专为动漫创作者打造的一站式角色设计解决方案。基于强大的Qwen3-32B大模型,它能够将文字描述转化为完整的动漫角色设计方案&#xff…...

T5403气压传感器I²C驱动开发与嵌入式工程实践

1. SparkFun T5403气压传感器库技术解析与嵌入式工程实践1.1 传感器选型背景与工程价值T5403是EPCOS(现属TDK集团)推出的低成本、高精度IC数字气压传感器,专为消费电子与工业环境监测场景设计。其核心价值在于:在1 hPa&#xff08…...

TI CCS工程依赖总报错?手把手教你正确迁移和打包TMS320F28P55x的空工程(附避坑指南)

TMS320F28P55x工程迁移全攻略:彻底解决CCS依赖报错问题 每次从C2000Ware官方例程复制工程到新目录,编译时总会遇到各种路径报错?这个问题困扰过几乎所有TI MCU开发者。本文将深入解析CCS工程的依赖机制,并给出两种彻底解决方案——…...

论文降重破局指南:Paperxie 如何让 AI 生成内容顺利通过知网 / 维普检测

paperxie-免费查重复率aigc检测/开题报告/毕业论文/智能排版/文献综述https://www.paperxie.cn/weight?type1https://www.paperxie.cn/weight?type1 在本科毕业论文写作的最后冲刺阶段,不少同学都面临着同一个难题:用 AI 辅助写完的初稿,AI…...

Keras模型部署超简单

💓 博客主页:瑕疵的CSDN主页 📝 Gitee主页:瑕疵的gitee主页 ⏩ 文章专栏:《热点资讯》 Keras模型部署:从繁琐到超简单的革命性实践目录Keras模型部署:从繁琐到超简单的革命性实践 引言&#xf…...

轻量级无头浏览器的性能优化革命:Lightpanda自动化技术解析

轻量级无头浏览器的性能优化革命:Lightpanda自动化技术解析 【免费下载链接】browser The open-source browser made for headless usage 项目地址: https://gitcode.com/GitHub_Trending/browser32/browser 在当今数据驱动的时代,无头浏览器已成…...