历史上的今天
返回首页

历史上的今天

今天是:2024年09月11日(星期三)

正在发生

2018年09月11日 | STM32延时函数的四种方法

2018-09-11 来源:eefocus

单片机编程过程中经常用到延时函数,最常用的莫过于微秒级延时delay_us( )和毫秒级delay_ms( )。


1.普通延时法


(1)普通延时法1


这个比较简单,让单片机做一些无关紧要的工作来打发时间,经常用循环来实现,不过要做的比较精准还是要下一番功夫。下面的代码是在网上搜到的,经测试延时比较精准。


//粗延时函数,微秒

void delay_us(u16 time)

{    

   u16 i=0;  

   while(time--)

   {

      i=10;  //自己定义

      while(i--) ;    

   }

}

//毫秒级的延时

void delay_ms(u16 time)

{    

   u16 i=0;  

   while(time--)

   {

      i=12000;  //自己定义

      while(i--) ;    

   }

}

(2)普通延时法2


void delay(u16 num)

{

  u16 i,j;

  for(i=0;i

    for(j=0;j<0x800;j++);

}

2.SysTick 定时器延时


CM3 内核的处理器,内部包含了一个SysTick 定时器,SysTick 是一个24 位的倒计数定时器,当计到0 时,将从RELOAD 寄存器中自动重装载定时初值。只要不把它在SysTick 控制及状态寄存器中的使能位清除,就永不停息。SysTick 在STM32的参考手册里面介绍的很简单,其详细介绍,请参阅《Cortex-M3 权威指南》。


 这里面也有两种方式实现:


(1)中断方式 如下,定义延时时间time_delay,SysTick_Config()定义中断时间段,在中断中递减time_delay,从而实现延时。


volatile unsigned long time_delay; // 延时时间,注意定义为全局变量

//延时n_ms

void delay_ms(volatile unsigned long nms)

{

    //SYSTICK分频--1ms的系统时钟中断

    if (SysTick_Config(SystemFrequency/1000))

    {

   

        while (1);

    }

    time_delay=nms;//读取定时时间

    while(time_delay);

    SysTick->CTRL=0x00; //关闭计数器

    SysTick->VAL =0X00; //清空计数器

}

//延时nus

void delay_us(volatile unsigned long nus)

{

 //SYSTICK分频--1us的系统时钟中断

    if (SysTick_Config(SystemFrequency/1000000))

    {

   

        while (1);

    }

    time_delay=nus;//读取定时时间

    while(time_delay);

    SysTick->CTRL=0x00; //关闭计数器

    SysTick->VAL =0X00; //清空计数器

}

 

    //在中断中将time_delay递减。实现延时

 

void SysTick_Handler(void)

{

    if(time_delay)

        time_delay--;

}

(2)非中断方式


主要仿照原子的《STM32不完全手册》。SYSTICK 的时钟固定为HCLK 时钟的1/8,在这里我们选用内部时钟源72M,所以SYSTICK的时钟为9M,即SYSTICK定时器以9M的频率递减。SysTick 主要包含CTRL、LOAD、VAL、CALIB 等4 个寄存器。


CTRL: SysTick控制和状态寄存器

LOAD: SysTick重装载值寄存器

VAL:    SysTick当前值寄存器

CALIB:SysTick校准值寄存器


对这几个寄存器的操作被封装到core_cm3.h中:

SysTick->CTRL

位段

名称

类型

复位值

描述

16

COUNTFLAG

R

0

如果在上次读本寄存器后systick已为0,则该位为1,若 读该位自动清零

2

CLKSOURCE

RW

0

0:外部时钟源 1:内部时钟

1

TICKINT

RW

0

0:减到0无动作;1:减到0产生systick异常请求

0

ENABLE

RW

0

systick定时器使能位

 

SysTick-> LOAD

位段

名称

类型

复位值

描述

23:0

RELOAD

RW

0

减到0时被重新装载的值

SysTick-> VAL

位段

名称

类型

复位值

描述

23:0

CURRENT

RW

0

读取时返回当前倒计数的值,写则清零,同时还会清除在systick控制及状态寄存器中的COUNTFLAG标志

SysTick-> CALIB 不常用,在这里我们也用不到,故不介绍了。

程序如下,相当于查询法。

//仿原子延时,不进入systic中断

void delay_us(u32 nus)

{

 u32 temp;

 SysTick->LOAD = 9*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(u16 nms)

{

 u32 temp;

 SysTick->LOAD = 9000*nms;

 SysTick->VAL=0X00;//清空计数器

 SysTick->CTRL=0X01;//使能,减到零是无动作,采用外部时钟源

 do

 {

  temp=SysTick->CTRL;//读取当前倒计数值

 }while((temp&0x01)&&(!(temp&(1<<16))));//等待时间到达

    SysTick->CTRL=0x00; //关闭计数器

    SysTick->VAL =0X00; //清空计数器

}

三种方式各有利弊,第一种方式容易理解,但不太精准。第二种方式采用库函数,编写简单,由于中断的存在,不利于在其他中断中调用此延时函数。第三种方式直接操作寄存器,看起来比较繁琐,其实也不难,同时克服了以上两种方式的缺点,个人感觉比较好用。


推荐阅读

史海拾趣

EXCELTA公司的发展小趣事

近年来,随着环保意识的提高和可持续发展的理念深入人心,Excelta也积极响应这一趋势。公司不断优化生产工艺和材料选择,降低产品对环境的影响。同时,公司还积极参与环保公益活动和社会责任项目,为社会和环境贡献自己的力量。这一转变不仅提升了公司的社会形象,也为公司的长期发展奠定了坚实的基础。

Cincon公司的发展小趣事

创新是Cincon持续发展的动力。2003年,公司在台北设立了研发中心,专注于电源产品的技术创新和研发。这一举措极大地提升了公司的技术实力和产品创新能力。几年后,Cincon成功设计并制造了LED电源,进一步丰富了产品线,并满足了市场对高效节能照明解决方案的需求。

Compex Corporation公司的发展小趣事

为了进一步扩大市场份额,Compex Corporation开始实施全球化战略。公司积极开拓国际市场,与全球多个国家的客户建立了合作关系。同时,公司还在海外设立了生产基地和研发中心,以便更好地服务当地市场。这一战略的实施使得公司的业务范围不断扩大,国际影响力也逐渐增强。

Carling Technologies公司的发展小趣事

在发展过程中,Carling Technologies还通过收购其他企业来增强自身实力。例如,公司收购了Maretron品牌,将其纳入旗下,并充分利用其在船舶监控和控制解决方案方面的优势,为前沿产品和解决方案的持续开发提供支持。这种收购与品牌整合的策略不仅丰富了公司的产品线,也扩大了其在特定市场的影响力。

ARBOR公司的发展小趣事

ARBOR公司一直致力于电子技术的研发与创新。在某个时期,公司研发团队成功开发出一款具有颠覆性的电路板技术,这项技术在信号传输速度和稳定性上实现了重大突破。凭借这一技术,ARBOR公司迅速占领了高端电子市场,成为行业内的技术领导者。公司股价随之飙升,吸引了大量投资者的关注。

Brainboxes公司的发展小趣事

多年来,Brainboxes一直致力于技术创新和研发投入。公司拥有一支高素质的软件和硬件工程师团队,他们在产品设计和制造方面具有丰富的经验。凭借先进的设计和制造技术,Brainboxes在业界赢得了多项荣誉,如英国制造联合会颁布的“2007年度最佳企业”奖和欧洲电子工业奖的“2005年度制造商”。这些荣誉不仅证明了公司的技术实力,也提升了其在全球电子行业中的影响力。

问答坊 | AI 解惑

关于单片机的讨论

很久以来总是能看到关于单片机的各种讨论,又是这个不好啦,那个不好了,那个过时啦,这个先进啊,学什么什么没用啦! 我吧我看到的告诉大家 西门子S7-200 PLC   8051 单片机做的 西门子S7-300PLC    模拟量采集模板(正在大量使用 ...…

查看全部问答>

滤波电容的选择

滤波电容的选择滤波电容的选择 经过整流桥以后的是脉动直流,波动范围很大。后面一般用大小两个电容 大电容用来稳定输出,众所周知电容两端电压不能突变,因此可以使输出平滑 小电容是用来滤除高频干扰的,使输出电压纯净 电容越小,谐振频率越 ...…

查看全部问答>

PLC-(S7-200)系列心得--如何验证数据是否正确保存到了EEPROM中?

有两种方法可以验证数据是否正确保存到EEPROM中:    1)在“系统块-数据保持”设置中取消相应数据区(V存储区)的保持设置,则CPU在上电时会用EEPROM中相应区域的数值覆盖RAM中的数据,可以检查数据是否正确    2)使用Micro/WIN的Upload ...…

查看全部问答>

新人跪求电路图

跪求基于AT89C51&DS18B20的无线数字显示温度计设计的电路图。。。 哪位达人来帮帮我啊。。。…

查看全部问答>

单片机跟Android手机通信

为Android开发外接设备,让手机变成小场合的设备控制、数据采集中心, 单片机通过miniUSB跟Android通信,可行么。…

查看全部问答>

反激式电源如何提高效率

最近做了一个反激式电源,自己做的反激式变压器,利用PWM调节占空比来控制输出的。但是发现效率很低,希望有经验的设计者能提供一些参考意见来提高这种dcdc电源的效率  谢谢…

查看全部问答>

WINCE杂这么复杂?!!!!!!!!!!!!

看WINCE看得我头痛了!这个函数,那个函数,还有设备管理我始终不明白,恳请各路高手指教!我现在遇到了这样一个函数:AdvertiseInterface,不知道这个函数是干什么的?有什么作用?为什么要使用这个函数!什么情况下要使用这个函数!谢谢!…

查看全部问答>

上海比较好的做嵌入式软件开发的公司

请问上海有哪些比较好的做嵌入式软件开发的公司啊,本人是软件工程专业的…

查看全部问答>

WinCE6.0操作系统可以使用loadIcon函数么?

我使用loadicon加载图标不成功,返回0址,不知有没有什么好的方法可以在WinCE6.0下加载图标呀?…

查看全部问答>

74LS163不工作

分频器74LS163不工作,是什么原因呢?我把晶振产生的时钟信号通过74LS163,想通过它来分频,可是发现信号频率并没有变,到底是什么原因呢?请教各位大侠,谢谢!…

查看全部问答>