STM32F103C8T6的ns延时函数
时间: 2025-06-09 22:26:21 浏览: 32
### STM32F103C8T6 实现纳秒级延时函数的方法与代码示例
STM32F103C8T6 的核心时钟频率通常为 72MHz,这意味着每个时钟周期大约为 13.89 纳秒(1/72MHz)。基于此特性,可以利用简单的循环和空操作指令实现纳秒级延时。以下详细介绍几种方法及其实现代码。
---
#### 方法一:使用空操作指令(`__nop()`)实现纳秒级延时
通过嵌入式 C 提供的 `__nop()` 指令,可以在单个时钟周期内执行一次无操作命令。结合循环控制,可以实现精确的纳秒级延时。
```c
#include "stm32f10x.h"
void delay_ns(uint32_t n) {
while (n--) {
__nop(); // 每次调用占用约 13.89 纳秒
}
}
```
这种方法的优点是简单且不依赖外部硬件资源,但其精度受限于系统时钟频率[^3]。
---
#### 方法二:基于 SysTick 定时器实现纳秒级延时
SysTick 是一个 24 位递减计数器,工作在核心时钟频率下。通过配置 SysTick 的重装载值,可以实现高精度的延时功能。
```c
#include "stm32f10x.h"
void delay_ns(uint32_t ns) {
uint32_t reload = (ns * SystemCoreClock) / 1000000000UL; // 计算重装载值
if (reload == 0) reload = 1; // 防止重装载值为零
SysTick->LOAD = reload - 1; // 设置重装载值
SysTick->VAL = 0; // 清除当前值寄存器
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_ENABLE_Msk; // 启用 SysTick
while (!(SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk)); // 等待计数完成
SysTick->CTRL = 0; // 禁用 SysTick
}
```
此方法通过硬件定时器实现延时,具有较高的精度和稳定性,但会消耗一定的 CPU 资源[^2]。
---
#### 方法三:使用 TIM 定时器实现纳秒级延时
STM32 的通用定时器(TIM)支持更高的分辨率和更灵活的配置选项。通过设置合适的预分频器和自动重装载值,可以实现精确的纳秒级延时。
```c
#include "stm32f10x.h"
void TIM2_Init(void) {
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); // 使能 TIM2 时钟
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_TimeBaseStructure.TIM_Period = 0; // 自动重装载值
TIM_TimeBaseStructure.TIM_Prescaler = 0; // 预分频器
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
TIM_Cmd(TIM2, ENABLE); // 启用 TIM2
}
void delay_ns(uint32_t ns) {
uint32_t reload = (ns * SystemCoreClock) / 1000000000UL; // 计算重装载值
TIM_SetAutoreload(TIM2, reload - 1); // 设置自动重装载值
TIM_SetCounter(TIM2, 0); // 清零计数器
while (TIM_GetCounter(TIM2) < reload); // 等待计数完成
}
```
此方法利用硬件定时器实现延时,适合需要频繁调用延时函数的场景,但初始化过程较为复杂[^3]。
---
#### 方法四:结合 DMA 和 TIM 实现高效纳秒级延时
对于需要大量数据传输或高频信号生成的场景,可以结合 DMA 和 TIM 定时器实现高效的纳秒级延时控制。例如,在驱动 WS2812 LED 时,这种方法可以显著降低 CPU 占用率。
```c
#include "stm32f10x.h"
void TIM_DMA_Init(void) {
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
DMA_InitTypeDef DMA_InitStructure;
DMA_InitStructure.DMA_Channel = DMA_Channel_5;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&(TIM2->ARR);
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)delay_buffer;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
DMA_InitStructure.DMA_BufferSize = buffer_size;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel5, &DMA_InitStructure);
TIM_DMACmd(TIM2, TIM_DMA_Update, ENABLE);
DMA_Cmd(DMA1_Channel5, ENABLE);
}
```
此方法适用于高性能需求场景,但实现复杂度较高,需合理规划内存和外设资源。
---
### 注意事项
- 系统时钟频率直接影响延时精度,确保在程序初始化阶段正确配置系统时钟。
- 在使用硬件定时器时,需注意避免与其他外设冲突。
- 纳秒级延时函数的实际效果可能受编译器优化和硬件特性影响,建议通过实验验证其准确性。
---
阅读全文
相关推荐


















