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
}
}
delay.c文件与STM32单片机
1918

被折叠的 条评论
为什么被折叠?



