365不让提款-日博365bet体育在线-网上365体育买球波胆提现

深度阅读体验

日博365bet体育在线

单片机:实现延时函数(附带源码)

延时函数的实现:单片机编程的核心需求 在嵌入式开发中,延时函数是一个非常常见的需求。在很多情况下,程序需要暂停执行一定时间,通常

单片机:实现延时函数(附带源码)

延时函数的实现:单片机编程的核心需求

在嵌入式开发中,延时函数是一个非常常见的需求。在很多情况下,程序需要暂停执行一定时间,通常是为了控制外设的工作周期,或者是为了实现定时功能。比如,控制LED闪烁、按键消抖、定时读取传感器数据等,往往需要利用延时函数来控制时间间隔。

实现延时函数通常有两种方式:

基于软件的空循环延时(Software Delay)基于硬件定时器的延时(Hardware Timer Delay)在本篇解读中,我们将聚焦于 软件延时 函数的实现,尤其是基于 空循环 来实现延时的原理。对于要求较高的精度和稳定性的应用,硬件定时器方式将是另一种更精确的方案,但在一些不复杂的任务中,空循环延时方式仍然是广泛应用的解决方案。

1. 延时函数实现的基本思路

延时函数的核心思想是通过执行一定数量的空操作指令(例如 NOP,即 No Operation 指令)来消耗时钟周期,达到延迟的效果。具体来说,通过控制 CPU 执行一个空循环,反复执行一些指令,从而消耗出一定数量的时钟周期,进而实现时间延迟。

延时函数的实现思路:

时钟频率计算: 单片机的时钟频率(如 16 MHz,72 MHz 等)决定了每个时钟周期的时间。通过知道每个时钟周期的时长,我们可以计算出一个指定延时时间(如 1 毫秒,1 微秒)所需要的循环次数。

空循环延时: 空循环延时是最简单的一种延时方式,CPU 执行的每一条指令会消耗一定的时钟周期,因此通过执行多次空指令(NOP 或其他无效指令),就可以累积消耗一定的时钟周期,进而控制延时时间。

控制延时时间: 通过计算系统时钟频率和所需的延时,我们可以通过编写一个循环,控制 NOP 指令的次数,来实现指定时间的延时。

2. 延时函数的工作原理与实现细节

2.1 延时函数的设计:

延时函数通常需要两个参数:

Delay_us:以微秒(us)为单位的延时函数。Delay_ms:以毫秒(ms)为单位的延时函数。在 C 语言中,这些函数的实现原理类似,但精度不同。微秒级的延时通常更精确,而毫秒级延时是通过调用多个微秒级延时函数来实现的。

Delay_us 函数设计:

为了设计 Delay_us(微秒延时),首先需要根据单片机的系统时钟频率来计算每次空循环的时间。假设单片机的时钟频率为 72 MHz,每个时钟周期的时长是:

时钟周期时间=172,000,000≈13.89 纳秒\text{时钟周期时间} = \frac{1}{72,000,000} \approx 13.89 \, \text{纳秒}时钟周期时间=72,000,0001​≈13.89纳秒

如果我们想实现 1 微秒的延时,那么我们需要让 CPU 执行大约 72 次空循环指令(72 * 1)。这样可以消耗大约 1 微秒的时间。

2.2 Delay_ms 函数设计:

对于 Delay_ms(毫秒延时),我们通过多次调用 Delay_us 来实现。每调用一次 Delay_us(1000),就相当于延时了 1 毫秒。因此,通过将 ms 作为参数传递,并递减 ms 值,可以实现所需的毫秒级延时。

3. 延时函数的代码实现

接下来,我们提供一个基于上述原理的具体代码实现:

#include "stm32f10x.h"

// 延时函数(单位:微秒)

void Delay_us(uint32_t us) {

// 假设系统时钟频率为 72 MHz(72,000,000 Hz)

// 每个时钟周期的时间 = 1 / 72,000,000 = 13.89 纳秒

// 为了实现微秒级延时,我们计算出需要多少个循环来实现目标延时。

uint32_t count = 72 * us / 10; // 系统时钟为 72 MHz,/10 来弥补编译器优化等因素

while (count--) {

__NOP(); // 执行空操作指令,消耗一个时钟周期

}

}

// 延时函数(单位:毫秒)

void Delay_ms(uint32_t ms) {

// 通过调用 Delay_us 实现毫秒级延时

while (ms--) {

Delay_us(1000); // 每次延时 1 毫秒(即 1000 微秒)

}

}

4. 代码解读:

Delay_us 函数解读:

Delay_us 函数接收一个参数 us,即希望延迟的微秒数。根据系统时钟频率,计算每个微秒延时需要执行多少次循环。这里我们假设系统时钟为 72 MHz,所以每个时钟周期为 13.89 纳秒。为了实现精准的微秒延时,我们通过 count = 72 * us / 10 来计算所需的循环次数。__NOP() 是一个空操作指令,它不会进行任何计算,但会消耗一个时钟周期,达到延时效果。

Delay_ms 函数解读:

Delay_ms 函数通过调用 Delay_us(1000) 来实现每次延时 1 毫秒。循环递减 ms,每次调用 Delay_us(1000),这样可以实现总的毫秒级延时。5. 延时函数的优化与问题

编译器优化问题:

在编写空循环延时函数时,编译器可能会进行优化,导致延时不准确。为了避免编译器优化掉空循环,我们使用了 volatile 关键字来声明 count 变量。这可以告诉编译器不要优化该变量,从而确保延时函数的正确性。

时钟频率问题:

系统时钟频率对延时精度有直接影响。如果系统时钟频率较低,延时函数的精度就会降低。反之,时钟频率越高,延时越精确。如果时钟频率过高,空循环的延时会变得非常短,可能会超出计算的精度范围。

延时精度问题:

空循环延时的精度较低,尤其在高频时钟下,延时误差可能会增加。因此,在一些对延时精度要求较高的应用中,建议使用硬件定时器来替代软件延时。

优化空循环:

在计算循环次数时,需要考虑编译器对代码的优化,因此通常会稍微增加循环次数(如 /10 的修正)来弥补编译器优化的误差。6. 延时函数的应用场景

延时函数在单片机开发中广泛应用,以下是一些典型应用场景:

LED 闪烁:

在嵌入式系统中,控制 LED 灯的闪烁是一项常见需求。通过调用延时函数,我们可以定时控制 LED 的开关,实现在固定时间间隔内闪烁的效果。

按键消抖:

按键输入的扫描通常会受到 抖动 的影响,延时函数常用于 按键消抖。通过延时函数,可以延时一段时间后再重新扫描按键,从而避免重复触发。

串口通信:

在串口通信中,延时函数用于控制数据的发送和接收。通过控制时间间隔,避免数据丢失或串口冲突。

传感器轮询:

延时函数常用于 传感器数据轮询。例如每隔一定时间读取一次温湿度传感器的值,或者在给定时间内等待传感器的响应。

蜂鸣器控制:

蜂鸣器的控制也常依赖延时函数,通过控制蜂鸣器的响铃时长和频率,可以实现报警、提示等功能。7. 总结与优化建议

延时函数在嵌入式系统中的作用非常重要,虽然通过空循环延时的方式简单易实现,但它也有一些局限性,特别是在高精度要求的场合。为了提高延时函数的精度,建议使用硬件定时器。此外,了解系统时钟频率、编译器优化等因素对于编写准确的延时函数非常重要。

相关阅读

日博365bet体育在线 绠套的意思

绠套的意思

yī tào 一套 常用pèi tào 配套 常用chéng tào 成套 常用shǒu tào 手套 常用quán tào 全套 常用wài tào 外套 常用quān tào 圈套 常用tào lù 套路 常用tà

365不让提款 百度地图全景多久更新一次?

百度地图全景多久更新一次?

921 iPhone_iPad_Mac_apple 百度地图全景多久更新一次? 百度地图全景作为一款帮助用户了解地理环境的工具,其更新频率对于用户而言至关重要。本

网上365体育买球波胆提现 腾讯应用宝为啥不行了?

腾讯应用宝为啥不行了?

文 | 南七道 从腾讯应用宝2011年推出,背靠着腾讯的大数据和大流量,应用宝在应用商店行业一路领先。根据iiMedia Research(艾媒咨询)发布的《2018-