(STM32F4) 精準的Delay不透過Timer
时间: 2024-02-12 09:05:57 浏览: 104
可以使用CPU的循环延时方式来实现精准的Delay。具体实现方式是通过计算CPU的时钟频率以及所需要延时的时间来确定需要循环的次数,从而实现精确延时。代码示例如下:
```c
void delay_us(uint32_t us)
{
uint32_t ticks = us * (SystemCoreClock / 1000000);
for (uint32_t i = 0; i < ticks; i++) {
__NOP();
}
}
void delay_ms(uint32_t ms)
{
for (uint32_t i = 0; i < ms; i++) {
delay_us(1000);
}
}
```
其中,delay_us函数实现微秒级延时,delay_ms函数实现毫秒级延时。在delay_us函数中,通过计算所需延时的CPU时钟周期数来进行循环延时,每个循环中执行一个空操作指令__NOP(),以消耗一个CPU时钟周期。在delay_ms函数中,通过调用delay_us函数实现毫秒级的延时。需要注意的是,使用循环延时方式实现Delay时,需要确保CPU时钟频率是固定的,否则会影响延时的精度。
相关问题
STM32F4系列芯片 标准库如何写delay
STM32F4系列芯片通常使用 HAL (Hardware Abstraction Layer) 或者 CMSIS (Cortex-M System Interface Software) 模块来编写中断延迟函数。这些库提供了API来实现低级硬件相关的操作,包括延时。
如果你想使用HAL库来实现简单的时间延迟,可以使用`HAL_Delay()`函数。这个函数的基本用法如下:
```c
#include "stm32f4xx_hal.h"
void delay_ms(uint32_t ms)
{
HAL_Delay(ms * 1000);
}
```
这里,`ms`参数是要等待的毫秒数,函数会将该时间转换成微秒(因为`HAL_Delay()`需要的是微秒),然后调用底层提供的延时功能。
如果你需要更精确的定时,可以使用RTC (Real-Time Clock) 中的延时机制,或者通过定时器(Timer)设置计数器来实现自定义延时。
```c
void delay_us(uint32_t us)
{
TIM_HandleTypeDef htim;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIMx, ENABLE); // 配置定时器时钟
htim.Instance = TIMx; // 替换为实际的TIMx外设
htim.Init.Prescaler = (系统频率 / 1000000) - 1; // 计算分频后的预分频值
htim.Init.CounterMode = TIM_COUNTERMODE_UP;
htim.Init.Period = us; // 设置定时器周期等于所需延迟的us数
HAL_TIM_Base_Init(&htim);
HAL_TIM_Base_Start(&htim); // 开始定时器
while (HTIM_GetFlagStatus(htim, HTIM_FLAG_Update) == RESET) {
// 等待定时器更新标志被触发
}
HAL_TIM_Base_Stop(&htim); // 停止定时器
}
```
stm32f4延时 10s
STM32F4系列微控制器中,要实现10秒的延时,你可以通过几种方式来完成:
1. **定时器中断法**:
STM32F4有许多内置的高级定时器,如TIM1、TIM2等,可以配置定时器计数到预设值,然后设置相应的中断,在中断服务函数里更新标志位。当计数达到预定值时,系统会自动跳转并触发中断,此时可以检查是否超过10秒。
```c
void timer_init(void) {
TIM_TimeBaseInitTypeDef.TIM_Prescaler = ...; // 配置定时器分频系数
TIM_TimeBaseInitTypeDef.TIM_Period = 10 * (SystemCoreClock / TimerPrescaler); // 计算10秒周期
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseInitTypeDef);
TIM_ITConfig(TIM1, TIM_IT_Update, ENABLE); // 开启溢出中断
TIM_Cmd(TIM1, ENABLE); // 启动定时器
}
void interrupt_service Routine() {
if (TIM_GetFlagStatus(TIM1, TIM_FLAG_Update)) {
TIM_ClearFlag(TIM1, TIM_FLAG_Update); // 清除中断标志
if (elapsed_time > 10 * 1000) { // elapsed_time是计数变量
// 延时结束处理
}
}
}
```
2. **软件延时函数**:
如果对精确度要求不高,也可以使用循环加上延时函数(比如` HAL_Delay()`)来实现。但是这种方法效率较低,并不适合长时间延时。
```c
#include "main.h"
#define DELAY_US(x) for(uint32_t i = 0; i < x; i++)
void delay_10s(void) {
DELAY_US(10000000); // 10秒,大约1000万次循环
}
```
阅读全文