STM32的三种延时方法的代码实现_纯软件延时, 系统定时器延时, 定时器延时

发布者:自由思想最新更新时间:2024-10-21 来源: cnblogs关键字:STM32  延时方法  定时器延时 手机看文章 扫描二维码
随时随地手机看文章

/* 外部调用:

    delay_init(72);    //系统主频, 单位为MHZ, 仅对 SYSTICK_DELAY 有效

    delay_ms(1000);

*/


#include 'stm32f10x.h'


//#define SOFT_DELAY        //纯软件延时

//#define SYSTICK_DELAY    //系统定时器延时

#define TIMER_DELAY            //定时器延时


#ifdef TIMER_DELAY


#define TIMER_DELAY                                    TIM4

#define TIMER_DELAY_PERIOD                    1000

#define TIMER_DELAY_PRESCALER                72

#define TIMER_DELAY_CLOCK                        RCC_APB1Periph_TIM4

#define TIMER_DELAY_IRQ_HANDLER            TIM4_IRQHandler


#define TIMER_DELAY_PREEMPTION_PRIORITY        2

#define TIMER_DELAY_SUB_PRIORITY                    2

#define TIMER_DELAY_IRQ_CHANNEL                        TIM4_IRQn


static __IO u16    counter_delay_ms;

#endif


//-----------------------------------------------------------------

#ifdef SOFT_DELAY


void delay_init(u8 SYSCLK)

{}


#if 1

void delay_us(u32 Number)

{

    u32 i=0;


     while(Number--){

      i=12; while(i--);

     }

}


void delay_ms(u16 Number)

{

    u32 i;


     while(Number--){

      i=12000; while(i--);

    }

}


#else

unsigned char MULTIPLE8M = 9;

void delay_us(u32 usNum)

{

  unsigned short kk, i;


  for(i=usNum; i>0; i--)

  {

    kk = 2*MULTIPLE8M - 1; //0x080003AA 4C06 LDR r4,[pc,#24] ; @0x080003C4 2clk

    do

    { //0x080003AC BF00 NOP 1clk

      kk--; //0x080003AE 1E64 SUBS r4,r4,#1 1clk

    } while(kk); //0x080003B0 2C00 CMP r4,#0x00 1clk

                    //0x080003B2 D1FC BNE 0x080003AE jump:2clk, no jump:1clk

  }

}


void delay_ms(u16 usNum)

{

  unsigned short kk, i;


  for(i=usNum; i>0; i--)

  {

    if (i % 100 == 0) {

        //FEEDDOG;

    }

    kk = 2000*MULTIPLE8M - 1; //0x080003AA 4C06 LDR r4,[pc,#24] ; @0x080003C4 2clk

    do

    { //0x080003AC BF00 NOP 1clk

      kk--; //0x080003AE 1E64 SUBS r4,r4,#1 1clk

    } while(kk); //0x080003B0 2C00 CMP r4,#0x00 1clk

                    //0x080003B2 D1FC BNE 0x080003AE jump:2clk, no jump:1clk

  }

}

#endif

#endif


//---------------------------------------------------------------------------


#ifdef SYSTICK_DELAY

//参考原子的代码. 修正了中断中调用出现死循环的错误, 防止延时不准确,采用do

static u8 fac_us = 0;    //us延时倍乘数

static u16 fac_ms = 0;    //ms延时倍乘数


//初始化延迟函数, SYSTICK的时钟固定为HCLK时钟的1/8, SYSCLK:系统时钟, 单位为MHZ

void delay_init(u8 SYSCLK)

{

    SysTick->CTRL &= 0xfffffffb;    //bit2清空,选择外部时钟 HCLK/8

    fac_us = SYSCLK/8;

    fac_ms = (u16)fac_us*1000;

}


//延时nms, 注意nms的范围

//SysTick->LOAD为24位寄存器,所以,最大延时为:nms<=0xffffff*8*1000/SYSCLK

//SYSCLK单位为Hz,nms单位为ms, 对72M条件下,nms<=1864

void delay_ms(u16 nms)

{

    u32 temp;


    SysTick->LOAD = (u32)nms*fac_ms;//时间加载(SysTick->LOAD为24bit)

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

    SysTick->CTRL = 0x01 ; //开始倒数

    do {

        temp = SysTick->CTRL;

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

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

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

}


//延时nus, nus为要延时的us数.

void delay_us(u32 nus)

{

    u32 temp;


    SysTick->LOAD = nus*fac_us; //时间加载

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

    SysTick->CTRL = 0x01 ; //开始倒数

    do{

        temp = SysTick->CTRL;

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

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

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

}

#endif

//-------------------------------------------------------------------


#ifdef TIMER_DELAY


void decrement_delay(void)

{

    if(counter_delay_ms != 0)

    {

        /* Decrement the counter */

        counter_delay_ms--;

    }

}


void delay_init(u8 SYSCLK)

{

    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;

    NVIC_InitTypeDef NVIC_InitStructure;


    RCC_APB1PeriphClockCmd(TIMER_DELAY_CLOCK, ENABLE);


    TIM_TimeBaseStructure.TIM_Period                 = TIMER_DELAY_PERIOD;

    TIM_TimeBaseStructure.TIM_Prescaler         = TIMER_DELAY_PRESCALER;

    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;

    TIM_TimeBaseStructure.TIM_CounterMode     = TIM_CounterMode_Up;

    TIM_TimeBaseInit(TIMER_DELAY, &TIM_TimeBaseStructure);


    TIM_UpdateRequestConfig(TIMER_DELAY, TIM_UpdateSource_Global);

    TIM_ClearITPendingBit(TIMER_DELAY, TIM_IT_Update);


    /* Enable TIMER Update interrupt */

    TIM_ITConfig(TIMER_DELAY, TIM_IT_Update, ENABLE);


    // Disable timers

    TIM_Cmd(TIMER_DELAY, DISABLE);


    /* Enable and set TIMER IRQ used for delays */

    NVIC_InitStructure.NVIC_IRQChannel                                          = TIMER_DELAY_IRQ_CHANNEL;

    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority     = TIMER_DELAY_PREEMPTION_PRIORITY;

    NVIC_InitStructure.NVIC_IRQChannelSubPriority                  = TIMER_DELAY_SUB_PRIORITY;

    NVIC_InitStructure.NVIC_IRQChannelCmd                                 = ENABLE;

    NVIC_Init(&NVIC_InitStructure);

}


void delay_ms(uint16_t delay)

{

    counter_delay_ms = delay;


    TIM_SetCounter(TIMER_DELAY, 0);

    /* TIM4 enable counter */

  TIM_Cmd(TIMER_DELAY, ENABLE);

    /* Wait for 'delay' milliseconds */

    while(counter_delay_ms != 0);

    /* TIM4 disable counter */

    TIM_Cmd(TIMER_DELAY, DISABLE);

}


void TIMER_DELAY_IRQ_HANDLER(void)

{

    /* Clear TIMER update interrupt flag */

    TIM_ClearITPendingBit(TIMER_DELAY, TIM_IT_Update);


    decrement_delay();

}


#endif


当然运行RTOS时, 一般系统定时器延时就不能用了. 


关键字:STM32  延时方法  定时器延时 引用地址:STM32的三种延时方法的代码实现_纯软件延时, 系统定时器延时, 定时器延时

上一篇:stm32中的NVIC_Configuration(void)函数
下一篇:STM32 通用底层函数集锦, 自用

推荐阅读最新更新时间:2024-11-16 22:56

stm32 中空编码器tim4初始化
#include stm32f10x.h #include encode.h #include misc.h #include nvic.h #include sys.h #include delay.h void TIM4_Mode_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_ICInitTypeDef TIM_ICInitStructure; //PB6 ch1 A,PB7 ch2 RCC_APB1PeriphClockCmd(RCC_APB1Periph_
[单片机]
STM32使用TIM触发ADC,CUBEMX配置
上一篇博客讲到,要采集准确的电机电流值,需要在PWM发波的高电平中间,或中间靠后进行ADC采样 这样可以确定采样出来的电流是真实的电机电流,应该是会比平均电流大写的。因为我这边PWM产生是用TIM1的互补PWM通道,而TIM1又是由TIM3的COM事件来触发的,现在我需要有另外一个定时器来产生一个跟TIM1周期相同,但是PWM的值是TIM1的一半的波形,这里我选择的是TIM15,因此需要保证TIM15的CCR寄存器的值为TIM1的一半,因此,可以直接在TIM1的溢出中断的回调函数中更新TIM15的CCR寄存器的值: 接下来就是要保证TIM1与TIM15同步了,因为TIM1是TIM3(霍尔定
[单片机]
<font color='red'>STM32</font>使用TIM触发ADC,CUBEMX配置
stm32单片机检测12V电路
1.先通过采样电路,分压得到3.3V的电压 2.然后使用电压跟随器,将3.3V的大阻抗信号电压变为3.3V的小阻抗驱动电压,此电压直接可以接到stm32的ADC引脚 3.注意:运放芯片LM358的供电电压一定要比3.3V大3~4V左右,这样才能使得跟谁的电压能够达到3.3v 12V衰减到3.3V的电路如下: 然后单片机根据才几点到的数字,反推算回去,看是多少V
[单片机]
<font color='red'>stm32</font>单片机检测12V电路
STM32学习记录8:DMA
官方的例子:STM32F10x_StdPeriph_Lib_V3.1.2\Project\STM32F10x_StdPeriph_Examples\DMA\FLASH_RAM /* DMA1 channel6 configuration */ DMA_DeInit(DMA1_Channel6); //peripheral base address 外设地址是自己的一个定义 //例如#define SPI1_DR_Addr ( (u32)0x4001300C ) DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)SRC_Const_Buffer; //memory base
[单片机]
<font color='red'>STM32</font>学习记录8:DMA
基于RT-Thread和STM32的数码相框的设计方案
  1.引言   近年来,随着数码相机的普及,一种以数码照片的保存、回放和浏览为核心功能的产品,数码相框应运而生,它以其独特的设计理念和美妙的欣赏效果倍受市场青睐。数码相框采用传统普通相框的外观造型,把传统普通相框的中间照片部分换成液晶显示屏,配上电源,控制器,存储介质等部件,可以直接展示数码照片。同时,数码相框也可以在同一个相框内循环展示不同照片,解决了需要使用电脑才能查看数码相片的缺陷,给日益增多的数码照片和喜好照片的人们提供一个更好的展示照片的平台和空间。基于此,本系统设计了基于RT-Thread和STM32的数码相框。   本系统采用STM32为主控芯片,利用源代码开放的嵌入式RT-Thread操作系统和人机交互界面μ
[单片机]
基于RT-Thread和<font color='red'>STM32</font>的数码相框的设计方案
Stm32 外部中断EXTI使用说明
硬件情况:采用PA11管脚 需要明确的是,PxN管脚共用外部中断线EXTIN和外部中断向量EXTIN_IRQn和中断服务程序入口EXTIN_IRQHandler,但是需要注意的是 共用EXTI9_5_IRQn和EXTI9_5_IRQHandler、 共用EXTI15_10_IRQn和EXTI15_10_IRQHandler 基本过程: 1、设置时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE); 注意需要打开AFIO时钟 2、配置GPIO GPIO_InitStructure.GPIO_Pin = GPIO_Pin_
[单片机]
再造STM32---第十二部分:启动文件详解
本章参考资料《STM32F4xx 中文参考手册》第十章-中断和事件:表 46.STM32F42xxx 和 STM32F43xxx 的向量表; MDK 中的帮助手册—ARM Development Tools:用来查询 ARM 的汇编指令和编译器相关的指令。 12.1 启动文件简介: 启动文件由汇编编写,是系统上电复位后第一个执行的程序。主要做了以下工作: 1、 初始化堆栈指针 SP=_initial_sp 2、 初始化 PC 指针=Reset_Handler 3、 初始化中断向量表 4、 配置系统时钟 5、 调用 C 库函数_main 初始化用户堆栈,
[单片机]
再造STM32---第十二部分:启动文件详解
STM32的SPI接口、cubeMX软件配置SPI接口和分析SPI相关代码
本文主要介绍STM32的SPI接口、cubeMX软件配置SPI接口和分析SPI相关代码。 STM32之SPI简介: SPI协议【Serial Peripheral Interface】 串行外围设备接口,是一种高速全双工的通信总线。主要用在MCU与FLASHADCLCD等模块之间的通信。 SPI信号线 SPI 共包含 4 条总线。 SS(Slave Select):片选信号线,当有多个SPI 设备与 MCU 相连时,每个设备的这个片选信号线是与 MCU 单独的引脚相连的,而其他的 SCK、MOSI、MISO 线则为多个设备并联到相同的 SPI 总线上,低电平有效。 SCK (Serial Clock):时钟信号线,由主通信设备
[单片机]
<font color='red'>STM32</font>的SPI接口、cubeMX<font color='red'>软件</font>配置SPI接口和分析SPI相关代码
小广播
设计资源 培训 开发板 精华推荐

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

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

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

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