STM32延时函数的三种方法——最好掌握第三种

发布者:落霞与孤鹜最新更新时间:2018-12-21 来源: eefocus关键字:STM32  延时函数 手机看文章 扫描二维码
随时随地手机看文章

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


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.SysTick 定时器延时


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


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


a.中断方式

 如下,定义延时时间time_delaySysTick_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--;
}

b.非中断方式

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

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; //清空计数器
}


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


关键字:STM32  延时函数 引用地址:STM32延时函数的三种方法——最好掌握第三种

上一篇:stm32系统滴答定时器使用
下一篇:STM32串口USART通讯

推荐阅读最新更新时间:2024-03-16 16:21

Keil MDK STM32系列(五) 使用STM32CubeMX创建项目基础结构
概述 从前面介绍的STM32开发可以感受到, 虽然SPL对于纯寄存器方式开发已经是很大的进步, SPL将大部分寄存器配置做了很好的封装, 配置项简单易读, 但是外设与输出脚的映射关系, 配置项的数量, 配置之间的关联都使得配置难度并未降低, 在项目启动阶段依然要通过不断查阅MCU的用户手册去修改方案, 各种情况下的代码例程直接借鉴容易出错, 需要反复尝试, 往往在调通外设这一步就已经耗费了开发人员的大量时间. 所以ST将开发库的重心迁移到了HAL上, 配合HAL的就是STM32CubeMX这个图形化配置工具. 通过图形化界面, 通过预设的逻辑辅助生成代码模板. 这样可以将底层寄存器和外设的复杂定义和逻辑包装在工具界面之下, 避
[单片机]
STM32学习手记-TIM3上溢出定时
TIM3是属于通用定时器,程序中采用APB1的时钟(PCLK1),72MHz。 程序中TIM3采取上溢出,即0—ARR时溢出。 上述程序的TIM3的频率为(PCLK1*2)/(36000-1+1)=2KHz,其中PCLK1为36MHz,故计数2000次为1s 使用定时器定时的步骤: 1、在RCC里打开相应的定时器时钟 2、在NVIC里打开相应的中断 3、在TIMx_Configuration()进行相应的设置,大致步骤为 a)TIM_TimeBaseStructure.TIM_Period = 2000-1; // 自动重装载寄存器周期的值(定时时间) 累计 2000个频率后产生个更新或者中断(也是说定时时间到),也就是ARR
[单片机]
STM32之中断管理
关于STM32的中断,相信大家玩过单片机的朋友就知道,中断是MCU的一大优点,使MUC工作能够分清事情的”轻重缓急“ ,从而达到处理事情井井有条; 今天就讲解下STM32-Cortex-M3内核的中断管理机制,其他处理器的也类似;M3中F103系列的有60个可屏蔽的中断和16个内核级别的中断; 大家知道,操作一款MCU 其实实质就是操作的寄存器,而寄存器有机的结合起来就实现了特定的功能;中断系统也不例外,下面来认识一下中断系统中的几个重要的寄存器; 1. ISER (Interrupt Set-Enable Registers),就是中断使能寄存器组,这个数组有8个成员,每个成员是32位的寄存器;写1有效,写0无效;
[单片机]
stm32的TIM定时器HAL库函数的使用
相关具体内容参考 stm32f4xx_hal_time.h 几种模式函数的类型都差不多,包括基本类型(Base),输出比较(OC),输入捕获(IC),pwm(PWM),单脉冲(One_Pulse)和编码器(Encoder)。 /****** xxx使用上述几种模式的英文替换即可*******/ HAL_TIM_xxx_Init HAL_TIM_xxx_DeInit HAL_TIM_xxx_MspInit HAL_TIM_xxx_MspDeInit /***轮询方式启动/停止/ HAL_TIM_xxx_Start HAL_TIM_xxx_Stop /***中断方式启动/停止/ HAL_TIM_xxx_Start_IT HAL_TIM
[单片机]
使用STM32CubeMX 图形配置工具生成STM32 工程代码
STM32CubeMX 教程 简介: STM32CubeMX 是 ST 意法半导体近几年来大力推荐的 STM32 芯片图形化配置工具,允许用户使用图形化向导生成 C 初始化代码。 其特性如下: 直观的选择 MCU 型号,可指定系列、封装、外设数量等条件; 微控制器图形化配置; 自动处理引脚冲突; 动态设置时钟树,生成系统时钟配置代码; 可以动态设置外围和中间件模式和初始化; 功耗预测; C 代码工程生成器覆盖了 STM32 微控制器初始化编译软件,如 IAR,KEIL,GCC; 可以独立使用或者作为 Eclipse 插件使用。 注意:STM32Cube包含 STM32CubeMX 图形工具和 STM32Cube 库两个部分
[单片机]
使用STM32CubeMX 图形配置工具生成<font color='red'>STM32</font> 工程代码
STM32学习三:下载标准外设库(Standard Peripherals Library )
要想进行STM32编程,一是直接操作寄存器,这在上节有介绍,另一个办法是使用官方提供的标准外设库(Standard Peripherals Library )。 其实这也没什么好说的,按说既然是官方外设库,应该在官网直接可以下载,可能原来是这样的,只是我按网上提供的方法进入官网得到的结果是这样的。 并没有STM32F1系列MCU的标准外设库,其中第一个STSW-STM32023进去下载后是个EXE文件,运行后是个命令行界面,按解释应该是将2.0的库迁移到3.0的工具。那么网上流传的STM32F1系列的V3.5库在官网是不是没有下载?反正我一时找不着,当然,如果你不较真的话,通过度娘一搜,有很多下载链接,随便用。 最后,
[单片机]
<font color='red'>STM32</font>学习三:下载标准外设库(Standard Peripherals Library )
stm32ADC的DMA模式
//变量定义 __IO uint16_t ADCConvertedValue ; //ADC 外设的数据寄存器 #define ADC1_DR_Address ((uint32_t)0x4001244C) //ADC_DR(ADC规则数据寄存器),偏移量=0x4c ADC1(0x40012400-0x400127ff) //ADC1_GPIO配置 void ADC1_GPIO_Configuration(void) { GPIO_InitTypeDef GPIO_InitStructure; /* Configure PC.01 (ADC Channel11) as analog inpu
[单片机]
STM32基础知识:中断系统
中断系统 1 数据传输方式 无条件传输 :处理器不必了解外部设备状态,直接进行数据传输,用于指示灯和按键等简单设备.。 查询方式 :传输前,一方先查询另一方的状态,若已经准备好就传输,否则就继续查询。 中断方式 :一方通过申请中断的方式与另一方进行数据传输,收发双方可以并行工作。 直接存储器访问 :处理器内部建立片内外设和内存之间的数据传输通道,传输过程不需要处理器参与。 2 中断系统的基本概念 2.1 中断全过程 中断发生: 当CPU在处理某一事件A时,发生了另一事件B,请求CPU迅速去处理。 中断处理: CPU暂停当前的工作,转去处理事件B。 中断返回: 当CPU将事件B处理完毕后,再回到事件A中被暂停的地方继
[单片机]
<font color='red'>STM32</font>基础知识:中断系统
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved