【STM32-HAL库】实现微秒、毫秒、纳秒延时。(STM32F4系列)(附带工程下载链接)

使用了本代码后不能使用HAL库自带的HAL_Delay函数

使用了本代码后不能使用HAL库自带的HAL_Delay函数

使用了本代码后不能使用HAL库自带的HAL_Delay函数

一、新建工程

 可以参考我的新建工程系列教程

stm32-HAL库+cubeMX新建工程教程系列icon-default.png?t=O83Ahttps://blog.csdn.net/qq_39150957/article/details/143087351?fromshare=blogdetail&sharetype=blogdetail&sharerId=143087351&sharerefer=PC&sharesource=qq_39150957&sharefrom=from_link

二、移植代码

delay.h

#ifndef __DELAY_H__
#define __DELAY_H__

/* 包含头文件 ----------------------------------------------------------------*/
#include "stm32f4xx_hal.h"
#include "main.h"
void delay_init(uint8_t SYSCLK);
void delay_us(int32_t nus);
void delay_xms(uint16_t nms);
void delay_ms(int32_t nms);
#endif

delay.c

#include "delay.h"
/*
适用于STM32F407系列
*/
static uint8_t  fac_us=0;							//us延时倍乘数			   
static uint16_t fac_ms=0;							//ms延时倍乘数,在os下,代表每个节拍的ms数

//初始化延迟函数
//SYSTICK的时钟固定为AHB时钟的1/8
//SYSCLK:系统时钟频率
void delay_init(uint8_t SYSCLK)
{
	HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK_DIV8);
	fac_us=SYSCLK/8;						//不论是否使用OS,fac_us都需要使用
	fac_ms=(uint16_t)fac_us*1000;				//非OS下,代表每个ms需要的systick时钟数   
}								    
 /****************************
 ** 定时us
 ** nus: 需要定时的微秒数
 **延时nus
 **nus为要延时的us数.	
 **注意:nus的值,不要大于798915us(最大值即2^24/fac_us@fac_us=21)
 *****************************/
void delay_us(int32_t nus) 
 {
	uint32_t temp;	    	 
	SysTick->LOAD=nus*fac_us; 				//时间加载	  		 
	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;       				//清空计数器 
 }

 //延时nms
 //注意nms的范围
 //SysTick->LOAD为24位寄存器,所以,最大延时为:
 //nms<=0xffffff*8*1000/SYSCLK
 //SYSCLK单位为Hz,nms单位为ms
 //对168M条件下,nms<=798ms 
void delay_xms(uint16_t nms)
{
	uint32_t temp;
	SysTick->LOAD=(uint32_t)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;     		  		//清空计数器	  	    
} 
 
 /****************************
 ** 定时ms
 ** nms: 需要定时的毫秒数
 *****************************/
 void delay_ms(int32_t nms) 
 {
	uint8_t repeat=nms/540;						//这里用540,是考虑到某些客户可能超频使用,
											//比如超频到248M的时候,delay_xms最大只能延时541ms左右了
	uint16_t remain=nms%540;
	while(repeat)
	{
		delay_xms(540);
		repeat--;
	}
	if(remain)delay_xms(remain); 
 }

三、使用代码

main.c中

  /* USER CODE BEGIN 2 */

//传入参数为当前芯片频率
delay_init(168);

  /* USER CODE END 2 */

之后就可以使用函数delay_ms(毫秒延时)、delay_xms(纳秒延时)、delay_us(微秒延时)了

传入参数为延时事件。

例如延时一秒

delay_ms(1000);//延时1秒
delay_us(1000000);//延时1秒
delay_xms(1000000000);//延时1秒

四、工程下载

通过百度网盘分享的文件:delay_us.zip提取码:6666icon-default.png?t=O83Ahttps://pan.baidu.com/s/1I--gUvHxdVqrnnhkqF07AQ

STM32CubeMX 是一款由 ST Microelectronics 开发的集成设计环境工具,它能自动创建基本的 STM32 微控制器应用,简化了系统配置、内存管理、外设初始化等功能,帮助用户快速启动项目。 ### 配置 SYsTIck 和纳秒延时函数 在 STM32 的微处理器中,`SysTick` 是一种定时器,常用于生成周期性的中断事件,通常用于执行一些周期性任务或计数等操作。要在 STM32CubeMX 中设置 `SysTick` 及其纳秒延时功能,可以按照以下步骤操作: #### 通过 STM32CubeMX 配置 `SysTick` 1. **打开 STM32CubeMX 并选择目标 STM32 芯片**(例如 STM32H7)以及相应的系列版本。 2. **在项目窗口中选择 `System`** 来编辑系统部分。在这里,你可以找到 `SysTick` 相关的配置选项。 3. **勾选启用 `SysTick` 定时器**。然后可以选择 `Tick` 时间长度和预分频值,这将影响每秒钟的中断次数。通常,使用默认设置即可满足需求。 4. **配置 `SysTick` 作为周期性的中断源**,这通常已经在默认设置中完成。 5. **保存配置**,完成后,STM32CubeMX 将自动生成必要的代码和配置文件。 #### 实现纳秒延时函数 虽然 `SysTick` 提供的是毫秒级别的中断,但通过循环等待特定次数的 `SysTick` 中断,我们可以模拟出纳秒级别的时间延迟。下面是一个简单的示例代码段来演示如何使用 `SysTick` 进行纳秒级时间延迟: ```c #include "stm32h7xx_hal.h" #include "stm32h7xx_hal_msp.h" // 假定 SysTick 每次中断间隔大约为 0.001 秒 const uint32_t TICKS_PER_SECOND = 1000; uint32_t delay_ns = 1; // 延迟时间为 1 纳秒 void SystemClock_Config(void); void DelayNanoseconds(uint32_t ns); void __attribute__((interrupt("WWDG"))) WWDG_IRQHandler() { if (delay_ns > 0) { delay_ns--; } } int main() { HAL_Init(); SystemClock_Config(); RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA | RCC_AHBPeriph_GPIOB | RCC_AHBPeriph_GPIOD, ENABLE); // 初始化 GPIO 引脚 HAL_NVIC_EnableIRQ(WWDG_IRQn); // 启动 WWDG 中断 HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_SET); // 示例 GPIO 控制 while(1) { DelayNanoseconds(TICKS_PER_SECOND * 1000 * 1000); // 延迟 1 微秒 HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_0); } return 0; } void DelayNanoseconds(uint32_t ns) { for (; ns > 0; ns--) { while (HAL_GetTick() % TICKS_PER_SECOND != 0) { ; } } } ``` 此代码首先设置了一个无限循环,在循环内部通过 `DelayNanoseconds()` 函数实现纳秒级的延迟。`DelayNanoseconds()` 函数通过检查当前时间是否等于一个完整的毫秒来决定是否递减延迟计数器 `ns`。 ####
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值