STM32裸机系统采用滴答定时器延时

delay.c文件与STM32单片机

F1、F4延时
1.STM32F103
delay.h文件

#ifndef __DELAY_H
#define __DELAY_H

#include "stm32f10x.h"

//#define configTICK_RATE_HZ 1000		//时钟节拍频率,这里设置为1000,周期就是1ms

//void SysTick_Init(void);
void delay_init(void);
void delay_ms(u16 nms);
void delay_us(u32 nus);


#endif

delay.c文件
1.不开启中断只有精确延时功能

static u8  fac_us=0;                            //us延时倍乘数               
static u16 fac_ms=0;                            //ms延时倍乘数  
 
//初始化延迟函数
//SYSTICK的时钟固定为HCLK时钟的1/8,即SYSTICK=SYSCLK/8
//SYSCLK:系统时钟
void delay_init()
{
    SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);    //选择外部时钟  HCLK/8

    fac_us=SystemCoreClock/8000000;                          //SYSTICK时钟为9M(即8分频)时,fac_us=9,即SysTick倒数9个数,耗时1us
    fac_ms=(u16)fac_us*1000;                                 //非OS下,代表每个ms需要的systick时钟数   
}    

//查询SysTick->CTRL寄存器bit0是否为1,当为1时,说明倒计时时间到;
//整个延时方法中,不进入SysTick中断;
//延时nus
//nus为要延时的us数.                                               
void delay_us(u32 nus)
{        
    u32 temp;             
    SysTick->LOAD=nus*fac_us;                       //延时时间加载               
    SysTick->VAL=0x00;                              //清空计数器
    SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ;        //开始倒数      
 
    //do while 判断就是 systick 使能(bit0)位为 1 且(bit16)为1的时候等待结束
    do
    {
        temp=SysTick->CTRL;
    }while((temp&0x01)&&!(temp&(1<<16)));           //等待时间到达
 
    SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk;        //关闭计数器
    SysTick->VAL =0X00;                             //清空计数器     
}

//延时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|=SysTick_CTRL_ENABLE_Msk ;    //开始倒数  
    do
    {
        temp=SysTick->CTRL;
    }while((temp&0x01)&&!(temp&(1<<16)));        //等待时间到达   
    SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk;    //关闭计数器
    SysTick->VAL =0X00;                           //清空计数器              
}


2.开启SysTick中断并保留精确延时功能

volatile uint32_t TimingDelay = 0;  // 用于延时计数
volatile uint32_t systick_counter = 0; // 系统运行时间计数器(毫秒)

/**
 * @brief  初始化SysTick定时器并开启中断
 * @param  sysclk: 系统时钟频率(单位Hz)
 * @retval 无
 */
void delay_init(uint32_t sysclk)
{
    // 1. 配置时钟源为HCLK(72MHz)
    SysTick->CTRL |= SysTick_CTRL_CLKSOURCE_Msk; 
    
    // 2. 设置重装载值,产生1ms中断
    SysTick->LOAD = (sysclk / 1000) - 1;
    
    // 3. 设置中断优先级(较低优先级)
    NVIC_SetPriority(SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1);
    
    // 4. 使能SysTick中断和定时器
    SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk; // 开启中断
    SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;   // 启动定时器
    
    // 5. 清空当前值
    SysTick->VAL = 0;
}

/**
 * @brief  SysTick中断服务函数
 */
void SysTick_Handler(void)
{    
    // 1. 处理延时计数器
    if (TimingDelay != 0x00) {
        TimingDelay--;
    }
    
    // 2. 系统运行时间计数器
    systick_counter++;
    
    // 3. 这里可以添加其他周期性任务
    // 例如:按键扫描、状态检测等    
	if(systick_counter>10)
	{
		systick_counter = 0;
		Key_Scan();
	}
}

/**
 * @brief  毫秒级阻塞延时
 * @param  ms: 延时的毫秒数
 */
void delay_ms(uint32_t ms)
{
    TimingDelay = ms;
    while(TimingDelay != 0);
}

/**
 * @brief  微秒级精确延时(非中断方式)
 * @param  us: 延时的微秒数
 */
void delay_us(uint32_t us)
{
    uint32_t ticks = us * (SystemCoreClock / 1000000);
    SysTick->LOAD = (ticks & 0xFFFFFF) - 1;
    SysTick->VAL = 0;
    SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;
    while (!(SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk));
    SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
}

STM32F401

/**
 * @brief     初始化延迟函数
 * @param     sysclk: 系统时钟频率, 即CPU频率(rcc_c_ck), 84MHz
 * @retval    无
 */  
void delay_init(void)
{
    // 选择时钟源:AHB(84MHz for STM32F401)
    SysTick->CTRL |= SysTick_CTRL_CLKSOURCE_Msk; 

    // 关闭 SysTick 中断(仅用于延时,不需要中断)
    SysTick->CTRL &= ~SysTick_CTRL_TICKINT_Msk; 
}

//延时nus
//nus为要延时的us数.	
//由于 SysTick 是 24 位递减计数器(最大值 0xFFFFFF)
void delay_us(u32 us)
{		
    // 计算 ticks 数(84MHz时,1us = 84个周期)
    uint32_t ticks = us * (SystemCoreClock / 1000000); 

    // 设置重装载值(24位最大值限制)
    SysTick->LOAD = (ticks & 0xFFFFFF) - 1; 

    // 清空当前值并启动计数器
    SysTick->VAL = 0;
    SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;

    // 等待计数结束
    while (!(SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk));

    // 关闭 SysTick
    SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
}
//延时nms
//注意nms的范围
void delay_ms(u32 ms)
{	 		  	  
    while (ms--) 
	{
        delay_us(1000); // 1ms = 1000us
    }
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值