STM32 HAL us delay(微秒延时)的指令延时实现方式及优化

111 篇文章 58 订阅
订阅专栏

STM32 HAL us delay(微秒延时)的指令延时实现方式及优化

STM32的HAL库,直接提供了1ms延时的实现函数HAL_Delay()。其原理是系统在上电后时钟配置阶段,配置了1ms产生一次中断,然后对一个32位寄存器uwTick逐次加1。HAL_Delay(x)函数执行时,会读取当前的uwTick值,并循环读取不断增加的uwTick值,直到uwTick增加了x后退出循环。

要实现us级延时,可以从中断方式进行,如修改系统时钟中断配置,将系统时钟1ms中断改为1us中断,也可以用一个TIM定时器产生1us中断来计数实现1us级延时。但如果系统的业务时序比较紧张,太频繁的中断可能引入某些不良时序风险。在这种情况下,采用指令延时实现1us级延时是一种方式,但是需要注意,指令延时不是时钟延时,并非一个指令延时对应一个时钟延时,通常一个指令周期需要多个时钟周期实现,因此系统时钟的配置频率不同,也会影响一个指令周期的实现时间。采用循环语句进行指令延时的实现时,循环语句里的循环与否判断部分,也会产生指令周期的执行延时,需要综合考虑进去。因此,采用指令延时实现更精确1us级别延时需要进行特殊的设计。本代码采用的初步测定–优化–应用的方式:

us级延时设计

__IO float usDelayBase;
void PY_usDelayTest(void)
{
  __IO uint32_t firstms, secondms;
  __IO uint32_t counter = 0;

  firstms = HAL_GetTick()+1;
  secondms = firstms+1;

  while(uwTick!=firstms) ;

  while(uwTick!=secondms) counter++;

  usDelayBase = ((float)counter)/1000;
}

void PY_Delay_us_t(uint32_t Delay)
{
  __IO uint32_t delayReg;
  __IO uint32_t usNum = (uint32_t)(Delay*usDelayBase);

  delayReg = 0;
  while(delayReg!=usNum) delayReg++;
}

上面的设计,实现了基本的us级延时函数的设计,分为系数测定函数和延时函数,系数测定函数测定1ms内特定语句的执行次数。其中HAL_GetTick()就是读取uwTick值并作为返回值的函数,和直接调用uwTick一样。

在这里插入图片描述
其中,循环执行的语句包含uwTick的读取,secondms的读取,一次不等于的比较,一次counter的加法。退出循环后的counter对应延时1ms时间要执行这种指令类型的次数。usDelayBase则是对应延时1us时间要要执行这种指令类型的次数,暂时以浮点形式表现。

在延时实现函数里,将要延时的us数乘以usDelayBase,得到要执行的特定类型指令的次数。然后执行特定类型指令形式的延时,即下面的方式:
在这里插入图片描述
这样,就实现了1us级别的延时。

us级延时设计优化

实际上,上面1us延时的实现,还存在一点小的偏差,可以通过下面的函数设计和执行,对usDelayBase进行进一步校准优化。

void PY_usDelayOptimize(void)
{
  __IO uint32_t firstms, secondms;
  __IO float coe = 1.0;

  firstms = HAL_GetTick();
  PY_Delay_us_t(1000000) ;
  secondms = HAL_GetTick();

  coe = ((float)1000)/(secondms-firstms);
  usDelayBase = coe*usDelayBase;
}

上述校正原理是,采用us延时函数延时1000000即1秒,那么对应的系统时钟的1ms延时数理论值是1000,而存在us延时函数偏差累积时,得到的不是1000,这个时候可以产生偏差校正系数coe,从而用coe*usDelayBase得到矫正后的usDelayBase。

us延时函数优化

上述已实现的us延时函数,对1us的延时,已很接近1us,但并非100%等于1us,因此如延时数比较大,如30分钟20秒100毫秒50微秒的延时,就会产生一定的累积时间偏差。对于us级精度又要实现长时间延时,用下面的优化函数,原理是将大于等于1ms的部分,用系统时钟的1ms延时函数代替实现,将小于1ms的微秒部分,用微秒延时函数实现。

void PY_Delay_us(uint32_t Delay)
{
  __IO uint32_t delayReg;

  __IO uint32_t msNum = Delay/1000;
  __IO uint32_t usNum = (uint32_t)((Delay%1000)*usDelayBase);

  if(msNum>0) HAL_Delay(msNum);

  delayReg = 0;
  while(delayReg!=usNum) delayReg++;
}

这样,就保证了长延时和短延时都具有良好的us精度。

另外,HAL库的HAL_Delay()如果没有调整中断优先级,不能用在各中断的中断处理函数中,在没有长延时us级高精度要求情况下,可以把本文中的PY_Delay_us_t()函数用在任意场合包括各中断处理函数中,如PY_Delay_us_t(1000)等同于HAL_Delay(1)的非中断方式实现。

使用方式

  1. 先定义上述的全局变量usDelayBase和4个函数。
  2. 在main函数进入while循环之前,执行 PY_usDelayTest(); 和 PY_usDelayOptimize();
  3. 在需要进行us延时的时候,执行PY_Delay_us(x)或 PY_Delay_us_t(x); 其中x为要延时的微秒数。如执行PY_Delay_us(12) ; 为延时12微秒;PY_Delay_us(1020) ; 为延时1毫秒20微秒。

GPIO驱动注意事项

在利用延时进行GPIO驱动时(譬如定时进行GPIO输出翻转),需要注意GPIO的驱动延时,也即MCU从开始到执行完GPIO的管脚输出驱动有一定延时(几us),在这个延时后才会继续执行后面的代码。因此在采用TIM定时器中断和本方案指令延时驱动GPIO翻转时,就需要注意时序的区别,如果设置成像定时器中断里驱动GPIO翻转一样的延时,则采用指令延时的真实延时会加长,而解决办法就是相应的减少指令延时的时间,图示如下:
在这里插入图片描述
以STM32G030F6P6为例,主频设置为64MHz,驱动100us延时GPIO翻转的波形为:

	  HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_0);
	  PY_Delay_us_t(100);

在这里插入图片描述
驱动500us延时GPIO翻转的波形为:

	  HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_0);
	  PY_Delay_us_t(500);

在这里插入图片描述
可以看出有一个大约8us的GPIO输出延时,如果想要输出15us的翻转延时,则需要设置延时为15-8=7us:

	  HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_0);
	  PY_Delay_us_t(7);

波形验证:
在这里插入图片描述

易用性及扩展性

  1. 初始阶段执行 PY_usDelayTest() 和 PY_usDelayOptimize()是为了测得浮点参数值usDelayBase。实际上,如果要节约初始阶段的执行时间,可以单独用一个同样工程环境的测试工程,测试出usDelayBase,然后在正式工程中将usDelayBase定义为常量,则使用PY_Delay_us(x)或 PY_Delay_us_t(x)前不再产生初始阶段的时间占用,不需要定义和调用PY_usDelayTest()和 PY_usDelayOptimize()。 PY_Delay_us_t(x)的方式也应用于UCOS, FREE-RTOS, RT-THREAD等嵌入式操作系统的微秒延时实现,不受操作系统接管时钟系统的影响。为了避免操作系统调度打断延时过程,还可用__disable_irq()与__enable_irq()来保护延时过程PY_Delay_us_t(x)的执行精度。
  2. 在主频高的情况下,指令延时的规格精度可以继续升级,譬如半微秒级(semi-us)延时的函数设计就可以如下代码实现:
__IO float semiusDelayBase;
void PY_semiusDelayTest(void)
{
  __IO uint32_t firstms, secondms;
  __IO uint32_t counter = 0;

  firstms = HAL_GetTick()+1;
  secondms = firstms+1;

  while(uwTick!=firstms) ;

  while(uwTick!=secondms) counter++;

  semiusDelayBase = ((float)counter)/2000;
}

void PY_Delay_semius_t(uint32_t Delay)
{
  __IO uint32_t delayReg;
  __IO uint32_t semiusNum = (uint32_t)(Delay*semiusDelayBase);

  delayReg = 0;
  while(delayReg!=semiusNum) delayReg++;
}

void PY_semiusDelayOptimize(void)
{
  __IO uint32_t firstms, secondms;
  __IO float coe = 1.0;

  firstms = HAL_GetTick();
  PY_Delay_semius_t(2000000) ;
  secondms = HAL_GetTick();

  coe = ((float)1000)/(secondms-firstms);
  semiusDelayBase = coe*semiusDelayBase;
}

void PY_Delay_semius(uint32_t Delay)
{
  __IO uint32_t delayReg;

  __IO uint32_t msNum = Delay/2000;
  __IO uint32_t semiusNum = (uint32_t)((Delay%2000)*semiusDelayBase);

  if(msNum>0) HAL_Delay(msNum);

  delayReg = 0;
  while(delayReg!=semiusNum) delayReg++;
}

使用方式一致,通过执行 PY_semiusDelayTest(); 和 PY_semiusDelayOptimize();获得浮点参数值semiusDelayBase,就可以通过PY_Delay_semius(x)或 PY_Delay_semius_t(x)调用半微秒精度延时,如PY_Delay_semius_t(3)为延迟1.5微秒。

–End–

STM32实现微秒延时函数3种不同方式(含独创内容哈哈)
geniusChinaHN的博客
04-06 472
【代码】STM32实现微秒延时函数。
STM32F0延时函数,用于ms及us延时
12-17
STM32F0延时函数,用于ms及us延时
STM32+HAL微秒延时函数汇总
最新发布
共同进步!
05-09 547
STM32+HAL微秒延时函数汇总
STM32CubeIDE HAL微秒us的延时Delay实现
路过的熊的博客
08-14 2457
STM32CubeIDE HAL微秒us的延时Delay实现
STM32CubeMX | STM32 HAL方式微秒延时函数
热门推荐
^_^
11-06 3万+
STM32CUBEMX系列教程之HAL方式微秒延时函数 标准库一般是使用系统嘀嗒定时器来进行微妙级别的延时,而HAL库官方使用SysTick的地方非常多,改代码容易引起错乱。网上的代码使用定时器进行微秒级别延时(不知道该方式的请自行搜索),总是卡在__HAL_TIM_GET_COUNTER,所以自己实现一个微秒级别延时函数尤为重要。 #define CPU_FREQUENCY_MHZ ...
STM32实现延时(Systick+Tim)
qq_28576837的博客
06-24 3691
STM32实现延时
STM32使用内核System Tick定时器实现微秒延时
goodrenze的专栏
04-19 2900
使用内核System Tick定时器实现微秒延时实现方法详解。
STM32HAL微秒延时(μs)
mnwu522的博客
12-13 3915
STM32HAL微秒(μs)延时
HAL 库 uS 延时的 3 种实现方式
qq_16519885的博客
02-03 1万+
CUBEMX 可视化初始化配置,结合 HAL 库,给我们开发带来了很多便利,但 HAL 库封装的延时函数目前仅支持 ms 级别的延时,日常很多情况下会用到 us 延时,特别是一些传感器的数据读取过程,对时序要求比较严格,us 延时必不可少,基于此项需求,此次给大家介绍 3 种 uS 延时实现方式,方法同样适用标准库,不足之处,还请大佬指出。 实验目标 使用普通定时器实现 us 延时 使用 Systick 功能实现 us 延时 使用 for 循环实现 us 延时 1、普通定时
STM32延时函数的三种方法——最好掌握第三种
childboy的博客
01-04 1万+
https://blog.csdn.net/luodonghuan1/article/details/46573501 单片机编程过程中经常用到延时函数,最常用的莫过于微秒延时delay_us( )和毫秒级delay_ms( )。 1.普通延时法 这个比较简单,让单片机做一些无关紧要的工作来打发时间,经常用循环来实现,不过要做的比较精准还是要下一番功夫。下面的代码是在网上搜到的,经测试延时...
HAL基础实验源码07 stm32cubemx-F429IGT6_HAL库1us微秒延时产生方法例程.zip
10-19
本代码采用STMcubeMX5.30和MDK5版本的开发环境,包含cubeMX工程文件和MDK5工程文件,arm嵌入式 C语言源代码 附开发环境的版本说明,STM32F429igt6/f767igt6/h743iit6原理图及全部器件全套资料免费提供,教学视频免费提供
STM32 HAL延时函数 HAL_Delay 解析
01-06
下面我们列出HAL实现延时相关的函数。首先是功能配置函数: //调用 HAL_SYSTICK_Config 函数配置每隔 1ms 中断一次 __weak HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority) { /* 配置系统在 1ms 的时间...
STM32_DelayUs.zip_STM32标准库Delay_haldelayus_stm32 hal_stm32 us函数
07-13
STM32通用精确us延时函数;包含标准库和HAL库两种,直接声明调用即可。
stm32延时函数,毫秒延时微秒延时
02-20
stm32延时函数,毫秒延时是模仿HAL库的毫秒延时,利用systick时钟每1ms产生中断来计时。微秒延时是采用__nop()空指令延时
HAL实现Stm32延时与计时例程
07-11
HAL实现Stm32延时与计时例程 教程可参考:https://lindoglog.blog.csdn.net/article/details/107191273
关于STM32单片机延时微妙(delay_us)函数-hal
宁静致远的博客
04-08 3014
自己外部晶振为8M,查单片机对映的是时钟框图如下,可以看出时钟从外部HSE_OSC来的为8M,经过以一个选择器后,进入PLL锁相环,之后去了AHB PRESC,最后经过一个/8的分频后就是滴答定时器的频率。近段时间调试一个STM32带多个DS18B20传感器,发现这个传感器对时序要求特别高,而使用的固件是HAL库版的,里面没有专门微米级别的延时函数,通不过不断尝试,调通了延时函数,使DS18B20成功跑起来了。写此篇文章来记录本次调试。,所以放心的使用 delay_us 来实现 delay_ms,不。
STM32微秒延时实现方式
weixin_45682654的博客
11-02 2153
STM32中的微秒延时实现
STM32延时函数的四种方法
山上编程猿的博客
05-24 1万+
STM32延时函数的四种方法单片机编程过程中经常用到延时函数,最常用的莫过于微秒延时delay_us()和毫秒级delay_ms()。本文基于STM32F207介绍4种不同方式实现延时函数。\\\插播一条:我自己在今年年初录制了一套还比较系统的入门单片机教程,想要的同学找我私信,最近比较闲,带做毕设,带学生参加省级以上比赛///1、普通延时这种延时方式应该是大家在51单片机时候,接触最早的延时函数。这个比较简单,让单片机做一些无关紧要的工作来打发时间,经常用循环来实现,在某些编译器下,代码会被优化,导致
stm32hal微秒延时函数
05-19
STM32 HAL库中,可以使用以下代码来实现微秒延时函数: ```c void delay_us(uint32_t us) { uint32_t tickstart = HAL_GetTick(); uint32_t wait = us * (HAL_RCC_GetHCLKFreq() / 1000000); while ((HAL_GetTick() - tickstart) < wait); } ``` 其中,`HAL_GetTick()`函数返回当前系统的毫秒级时钟计数器值,`HAL_RCC_GetHCLKFreq()`函数返回系统时钟频率。在函数中,我们先记录下当前时钟计数器值,然后计算需要等待的时钟周期数,最后不断检查时钟计数器是否超过等待周期数,如果没有,就一直等待。 需要注意的是,这个延时函数是基于毫秒级时钟计数器实现的,因此如果需要更高的精度,可以考虑使用定时器或者其他更高精度的时钟源实现延时。同时,由于循环等待会占用CPU资源,因此在需要长时间延时的情况下,最好使用RTOS等系统级别的延时函数。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
写文章

热门文章

  • STM32 HAL us delay(微秒延时)的指令延时实现方式及优化 22956
  • STM32驱动全彩LED灯模块WS2812 15891
  • Electron Security Warning (Insecure Content-Security-Policy) 告警解决 15834
  • STM32 region `FLASH‘ overflowed by xxx bytes 问题解决 14730
  • STM32用超声波测距模块实现测距 11387

分类专栏

  • STM32 111篇
  • C/C++ 22篇
  • Electron 18篇
  • js/Node.js 22篇
  • ARAS PLM 20篇

最新评论

  • STM32 HAL 驱动I2C总线0.91寸OLED模块(基于SSD1306显示驱动芯片)

    ZPF333777: 大佬,我移植以后,可以显示内容,但是为啥刷新的速度很慢?

  • STM32 TIM PWM高阶操作:刹车及状态约束

    格里姆肖: 好文章,很全面,受教了

  • STM32存储左右互搏 I2C总线读写FRAM MB85RC16

    小白变形计: 写的很好,但是我发现MB85RC1M_Read函数里的读IIC中的ADDR是不是要加1 ,读不应该是0xa1嘛

  • STM32F407获取OV5640摄像头图像及上位机解码(一维码&二维码)

    Michalebanana: 倒序是因为他的接口D0到D7和stm32F407的DCMI的D0到D7完全反掉,所以按照芯片引脚定义连接模块就行

  • STM32模拟SPI时序控制双路16位数模转换(16bit DAC)芯片DAC8552电压输出

    电工小王: 博主为什么,我没有输出,一直打都是0,我想问,他输出端口和芯片的gnd是否是通的

大家在看

  • 驱动开发(二):创建字符设备驱动 343
  • Linux 【基础篇-vim编辑器 网络配置 远程登录】 1033
  • Java锁之舞:性能分析与优化之路 611
  • 1688跨境是淘系对抗拼多多Temu的一把尖刀吗?|1688开放API接口接入|1688跨境代采系统搭建
  • App UI 风格展现非凡创意

最新文章

  • STM32存储左右互搏 模拟U盘桥接SPI总线FATS读写FLASH W25QXX
  • STM32 UART串口数据接收策略
  • STM32存储左右互搏 USB接口FATS文件读写U盘
2024年11篇
2023年52篇
2022年39篇
2021年38篇
2020年20篇
2019年23篇

目录

目录

评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

PegasusYu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或 充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值

深圳SEO优化公司韶关建设网站雅安seo网站推广多少钱天水模板网站建设公司海西百姓网标王推广价格兰州阿里店铺托管价格延边百度网站优化推荐曲靖百度网站优化哪家好揭阳网站关键词优化推荐湘西网站开发公司信阳网站关键词优化永州网络广告推广多少钱莆田网页制作多少钱晋城百度网站优化排名多少钱白银企业网站制作报价阿坝网站设计模板公司和田阿里店铺运营推荐海北品牌网站设计清徐网站搜索优化多少钱安康网站优化软件公司普洱优秀网站设计价格木棉湾品牌网站设计公司辽源百度爱采购哪家好安康外贸网站制作价格玉溪优化六安网站seo优化多少钱铜仁网站建设公司新乡模板网站建设报价爱联外贸网站制作哪家好十堰网站搜索优化价格宜春建设网站多少钱歼20紧急升空逼退外机英媒称团队夜以继日筹划王妃复出草木蔓发 春山在望成都发生巨响 当地回应60岁老人炒菠菜未焯水致肾病恶化男子涉嫌走私被判11年却一天牢没坐劳斯莱斯右转逼停直行车网传落水者说“没让你救”系谣言广东通报13岁男孩性侵女童不予立案贵州小伙回应在美国卖三蹦子火了淀粉肠小王子日销售额涨超10倍有个姐真把千机伞做出来了近3万元金手镯仅含足金十克呼北高速交通事故已致14人死亡杨洋拄拐现身医院国产伟哥去年销售近13亿男子给前妻转账 现任妻子起诉要回新基金只募集到26元还是员工自购男孩疑遭霸凌 家长讨说法被踢出群充个话费竟沦为间接洗钱工具新的一天从800个哈欠开始单亲妈妈陷入热恋 14岁儿子报警#春分立蛋大挑战#中国投资客涌入日本东京买房两大学生合买彩票中奖一人不认账新加坡主帅:唯一目标击败中国队月嫂回应掌掴婴儿是在赶虫子19岁小伙救下5人后溺亡 多方发声清明节放假3天调休1天张家界的山上“长”满了韩国人?开封王婆为何火了主播靠辱骂母亲走红被批捕封号代拍被何赛飞拿着魔杖追着打阿根廷将发行1万与2万面值的纸币库克现身上海为江西彩礼“减负”的“试婚人”因自嘲式简历走红的教授更新简介殡仪馆花卉高于市场价3倍还重复用网友称在豆瓣酱里吃出老鼠头315晚会后胖东来又人满为患了网友建议重庆地铁不准乘客携带菜筐特朗普谈“凯特王妃P图照”罗斯否认插足凯特王妃婚姻青海通报栏杆断裂小学生跌落住进ICU恒大被罚41.75亿到底怎么缴湖南一县政协主席疑涉刑案被控制茶百道就改标签日期致歉王树国3次鞠躬告别西交大师生张立群任西安交通大学校长杨倩无缘巴黎奥运

深圳SEO优化公司 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化