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

STM32的四种延时方法

单片机编程过程中经常用到延时函数,最常用的莫过于微秒级延时delay_us()和毫秒级delay_ms()。本文基于STM32F207介绍4种不同方式实现的延时函数。

一:普通延时

这种延迟方式应该是每个人在51台单片机时接触最早的延迟函数。这个比较简单,让单片机做一些无关紧要的工作来打发时间,经常通过循环来实现。在一些编译器下,代码会被优化,导致精度低,用于一般延迟和对精度不敏感的应用场景。

//微秒级的延时
void delay_us(uint32_t delay_us) {volatile unsigned int num;volatile unsigned int t;for (num = 0; num < delay_us; num++) {t = 11;while (t != 0) {t--;}}
}
//毫秒级的延时
void delay_ms(uint16_t delay_ms) {volatile unsigned int num;for (num = 0; num < delay_ms; num++) {delay_us(1000);}
}

二:定时器中断

定时器精度很高,可以配置定时器中断,比如配置1ms中断一次,然后间接判断进入中断的次数,达到精确延迟的目的。这种方法的精度可以保证,但是系统一直在中断,不利于在其他中断中调用这个延迟函数。有些高精度的应用场景不适合,比如其他外部设备输出,不允许中断。

STM32任何定时器都可以实现,下面我们以SysTick 定时器为例介绍:

初始化SysTick 定时器:

/* 配置SysTick为1ms */
RCC_GetClocksFreq(&RCC_Clocks);
SysTick_Config(RCC_Clocks.HCLK_Frequency / 1000);

中断服务函数:

void SysTick_Handler(void) {TimingDelay_Decrement();
}void TimingDelay_Decrement(void) {if (TimingDelay != 0x00) {TimingDelay--;}
}

延时函数:

void Delay(__IO uint32_t nTime) {TimingDelay = nTime;while(TimingDelay != 0);
}

三:查询定时器

为了解决定时器频繁中断的问题,我们可以使用定时器,但不使能中断,可以通过查询延迟,既可以解决频繁中断的问题,又可以保证精度。

STM32任何定时器都可以实现,下面我们以SysTick 定时器为例介绍。

STM32的CM3核心处理器包括SysTick计时器,SysTick是24位倒计数计时器,计算到0时,从RELOAD存储器自动重新加载计时初始值。如果不清除SysTick控制和状态存储器中的使能位置,就不会停止。

SYSTICK的时钟固定为HCLK时钟的1/8,在这里我们选用内部时钟源120M,所以SYSTICK的时钟为(120/8)M,即SYSTICK定时器以(120/8)M的频率递减。SysTick 主要包含CTRL、LOAD、VAL、CALIB 等4 个寄存器。

void delay_us(uint32_t nus) {uint32_t temp;SysTick->LOAD = RCC_Clocks.HCLK_Frequency/1000000/8*nus;SysTick->VAL=0X00;//清空计数器  SysTick->CTRL=0X01;//使能,减到零是无动作,采用外部时钟源  do {temp=SysTick->CTRL;//读取当前倒计数值}while((temp&0x01)&&(!(temp&(1<<16))));//等待时间到达SysTick->CTRL=0x00;//关闭计数器 SysTick->VAL =0X00;//清空计数器
}
void delay_ms(uint16_t nms) {uint32_t temp;SysTick->LOAD = RCC_Clocks.HCLK_Frequency/1000/8*nms;SysTick->VAL=0X00;//清空计数器SysTick->CTRL=0X01;//使能,减到零是无动作,采用外部时钟源  do {temp=SysTick->CTRL;//读取当前倒计数值}while((temp&0x01)&&(!(temp&(1<<16))));//等待时间到达  SysTick->CTRL=0x00;//关闭计数器  SysTick->VAL =0X00;//清空计数器}

四:汇编指令

如果系统硬件资源紧张,或者没有额外的定时器提供,又不想方法1的普通延时,可以使用汇编指令的方式进行延时,不会被编译优化且延时准确。

/*! *  @brief   软件延时  *  @param  ulCount:延时时钟数 *  @return none *  @note   ulCount每增加1,该函数增加3个时钟 */
void SysCtlDelay(unsigned long ulCount) {__asm("    subs    r0, #1\n"          "    bne.n   SysCtlDelay\n"          "    bx      lr");
}

这3个时钟指的是CPU时钟,也就是系统时钟。120MHZ,也就是说1s有120M的时钟,一个时钟也就是1/120 us,也就是周期是1/120 us。3个时钟,因为执行了3条指令。

使用这种方式整理ms和us接口,在Keil和IAR环境下都测试通过。

从理论上讲:汇编方式的延迟也是不准确的,有可能被其它中断打断,最好使用us和ms级的延迟,使用for循环延迟的函数也是如此。理论上,使用定时器延迟也可能是不准确的,定时器延迟是准确的,但在判断语句时,如if语句,判断延迟是否到达时,就在判断时,被中断打断执行其他代码,返回时已经过了一小段时间。但是汇编方式和定时方式,只是理论上不准确,在实际项目中,这两种方式的精度已经足够高了。

http://www.dtcms.com/a/525679.html

相关文章:

  • 手机网站怎么制作织梦网站备份几种方法
  • 网站设计答辩ppt大宗贸易平台
  • 【大模型与OCR】配合应用的示例demo
  • 门户网站内容建设岗位职责国家单位网站建设要多久
  • 辽宁自适应网站建设公司ps做景观有哪些素材网站
  • 服务器网站过多对排名建网站空间
  • 福州官网建站厂自己建网站还是淘宝
  • 空对象模式(Null Object Pattern)
  • 需求资产管理:从混沌到有序的数字化变革之路
  • dedecms图片网站模板开发做网站公司
  • 曲阜官方建设局网站安全之要
  • 【NestJS】依赖注入(DI) 的模块系统、`imports`、`@Module`、`providers` 之间的关系彻底搞清楚
  • Vibe Coding 小白上手指南
  • 洞察:当前Crypto大环境正需要Solana这种工程化实用主义
  • 做空机构的网站拌合站建站方案
  • wordpress搭建教育网站三只松鼠网络营销案例分析
  • FongMi 蜂蜜影视播放器TVBOX衍生版 V4.6.2支持安卓手机和电视附100+配置地址接口
  • 免费自助建站哪个好上海短视频制作
  • 北京好用的h5建站一般建站公司用什么cms
  • Xshell连接kali系统
  • 做网站 图片 文件夹 放哪儿网页升级访问紧急通通知
  • 赋能智慧水利:视频汇聚平台EasyCVR智慧水利工程视频管理系统解决方案
  • CentOS7.9部署Mysql8(二进制方式)
  • 太原网站建设推广驻马店哪家做网站好
  • 音乐网站设计源码网页制作知识点归纳
  • Linux POSIX信号量与线程池
  • 微网站和普通网站区别重庆建设科技培训中心官方网站
  • 网站做受网站做计算机网站有哪些功能
  • 网站有没有做301搬瓦工vps建设网站
  • GPIO重点