SysTick定时器与delay延时函数的实现
- 格式:pdf
- 大小:995.84 KB
- 文档页数:5
c延时函数delay延时函数(delay function)是一种在程序中用来暂停一段时间的函数。
在C语言中,延时函数通常用于需要控制时间间隔的应用程序中,例如时钟、定时器、动画等。
在C语言中,实现延时函数有多种方法,下面将介绍两种常用的方法。
1.使用循环计数法延时函数最常见的实现方式之一是使用循环计数法。
具体步骤如下:-接收一个参数,表示延时的毫秒数;-将参数转换为循环需要的次数。
在现代计算机中,循环一次通常需要几十纳秒到几百纳秒的时间,因此需要将毫秒数转换为相应的循环次数;-使用一个循环来延时,每次循环后递减计数器,直到计数器为0。
下面是一个使用循环计数法实现的延时函数的示例代码:```c#include <stdio.h>#include <stdlib.h>void delay(int milliseconds)for(int i = 0; i < iterations; i++)//什么都不做,只是进行循环迭代}printf("Before delay\n");delay(1000); // 延时1秒printf("After delay\n");return 0;```2.使用标准库函数- `sleep(`函数:使程序休眠指定的秒数。
参数是休眠的秒数。
下面是使用`usleep(`函数实现延时的示例代码:```c#include <stdio.h>#include <stdlib.h>#include <unistd.h>void delay(int milliseconds)usleep(milliseconds * 1000); // 将毫秒转换为微秒int maiprintf("Before delay\n");delay(1000); // 延时1秒printf("After delay\n");```无论是使用循环计数法还是使用标准库函数,延时函数都有一定的局限性。
delay函数原理
delay函数是一种用于延迟执行代码的方法。
它可以暂停程序的执行一段特定的时间,然后再继续执行后续的代码。
在常见的编程语言中,delay函数通常是通过调用系统提供的计时器或定时器来实现的。
当调用delay函数时,程序会暂时停止在该函数调用处执行的指令,然后进入一个等待状态,等待一段特定的时间。
延迟的时间可以通过给delay函数传递参数来设置,通常以毫秒为单位。
例如,delay(1000)表示暂停程序执行1秒钟。
在延迟时间结束后,程序会从delay函数调用处继续执行后续的代码。
这个过程可以看作是一个计时器到期后触发的事件,类似于定时器的工作原理。
需要注意的是,delay函数通常是阻塞式的,即在延迟期间,程序无法进行其他操作。
这意味着如果在延迟期间有其他任务需要执行,它们会被暂时阻塞,直到延迟时间结束。
需要特别注意的是,在某些情况下,使用delay函数可能会导致程序变得不响应或出现卡顿的现象。
这是因为在延迟期间,程序无法处理其他的任务,如果延迟时间过长,就会导致程序看起来像是被冻结了一样。
为了避免这种情况的发生,可以考虑使用异步编程或者多线程
等机制,使得程序在延迟期间仍然能够同时执行其他任务,而不会出现阻塞的情况。
STM32HAL库实现US微秒延时函数STM32HAL库是STMicroelectronics公司为STM32系列微控制器提供的一套软件库,它提供了丰富的API和功能以简化开发人员在STM32上的编程工作。
其中包括了实现微秒级延时函数的功能。
实现微秒延时函数的一种常见方法是使用STM32的系统计时器(SysTick)模块。
SysTick是STM32微控制器上的一个24位倒数计数器,它可以在固定的间隔内递减,并在递减到0时产生中断。
在HAL库中,可以使用SysTick模块和相关的HAL函数来实现微秒级延时函数。
以下是一个示例代码:首先,需要配置SysTick模块的时钟源和计数器值。
在初始化函数中添加以下代码:```c```然后,可以编写一个名为`delay_us`的延时函数。
这个函数使用了SysTick模块的计数器来进行延时操作。
在这个函数中,当计数器减为0时,表示经过了指定的微秒数,延时结束。
```cvoid delay_us(uint32_t us)uint32_t start = HAL_GetTick(;while((HAL_GetTick( - start) < us);```这个函数使用`HAL_GetTick`函数获取当前的系统滴答数。
每个滴答数对应一个毫秒,所以可以通过计算差值来实现微秒级的延时。
这里是一个完整的使用STM32HAL库实现微秒延时的示例:```c#include "stm32f4xx_hal.h"void SystemClock_Config(void);void MX_GPIO_Init(void);void delay_us(uint32_t us);int main(void)HAL_Init(;SystemClock_Config(;MX_GPIO_Init(;while (1)HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5); // 切换LED状态}void SystemClock_Config(void)RCC_OscInitTypeDef RCC_OscInitStruct;RCC_ClkInitTypeDef RCC_ClkInitStruct;__HAL_RCC_PWR_CLK_ENABLE(;__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1 );RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;RCC_OscInitStruct.HSIState = RCC_HSI_ON;RCC_OscInitStruct.HSICalibrationValue = 16;RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;RCC_OscInitStruct.PLL.PLLM = 16;RCC_OscInitStruct.PLL.PLLN = 336;RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV4;RCC_OscInitStruct.PLL.PLLQ = 7;if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)while (1);}RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK ,RCC_CLOCKTYPE_SYSCLKRCC_CLOCKTYPE_PCLK1,RCC_CLOCKTYPE_PCLK2RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)while (1);}void MX_GPIO_Init(void)GPIO_InitTypeDef GPIO_InitStruct;__HAL_RCC_GPIOA_CLK_ENABLE(;GPIO_InitStruct.Pin = GPIO_PIN_5;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);void delay_us(uint32_t us)uint32_t start = HAL_GetTick(;while((HAL_GetTick( - start) < us);```在这个示例中,我们配置了SysTick模块为1微秒的计数频率,并使用`delay_us`函数实现了一秒钟的延时。
SysTick定时器介绍,SysTick定时器寄存器
SysTick定时器介绍
SysTick定时器也叫SysTick滴答定时器,它是Cortex-M3内核的一个外设,被嵌入在NVIC 中。
它是一个24 位向下递减的定时器,每计数一次所需时间为1/SYSTICK,SYSTICK 是系统定时器时钟,它可以直接取自系统时钟,还可以通过系统时钟8 分频后获取,本套程序中我们采用后者,即每计数一次所需时间为1/(72/8)us,换句话说在1us 的时间内会计数9 次。
当定时器计数到0 时,将从LOAD 寄存器中自动重装定时器初值,重新向下递减计数,如此循环往复。
如果开启SysTick 中断的话,当定时器计数到0,将产生一个中断信号。
因此只要知道计数的次数就可以准确得到它的延时时间。
SysTick 定时器通常应用在操作系统中,为其提供时钟周期。
SysTick定时器操作
在STM32F1 库函数中,并没有提供相应的SysTick 定时器配置函数,。
学习笔记:STM32的SysTick定时器SysTick定时器是一个系统定时器,该定时器是个24位的倒计数定时器,该定时器的最大用处在于可以提供一个操作系统任务切换所需要的“时钟滴答”。
该定时器是STM32中功能最简单的定时器,提供倒计数、中断两个功能,类似与8051的定时器。
SysTick是包含在Cortex-M3内核中的一个简单的定时器。
因为所有的CM3芯片都带有这个定时器,软件在不同芯片生产厂商的CM3器件间的移植工作就得以简化。
该定时器的时钟源可以是内部时钟(FCLK,CM3上的自由运行时钟),或者是外部时钟(CM3处理器上的STCLK信号)。
不过,STCLK的具体来源则由芯片设计者决定,因此不同产品之间的时钟频率可能大不相同。
因此,需要阅读芯片的使用手册来确定选择什么作为时钟源。
在STM32中SysTick以外部时钟HCLK(AHB时钟)或HCLK/8作为运行时钟。
SysTick工作分析SysTick是一个24位的定时器,即一次最多可以计数2^24个时钟脉冲,这个脉冲的计数值被保存到当前计数值寄存器STK_VAL中,只能向下计数,每接收到一个时钟脉冲STK_VAL 的值就向下减1,直到为0。
当STK_VAL的值被减至0时,由硬件自动把重载寄存器STK_LOAD 中保存的数值加载到STK_VAL中,STK_VAL又重新向下计数……当使能中断时,STK_VAL的值减至0时,触发中断,就可以在中断服务函数中处理定时事件了。
当然,要使SysTick进行以上工作必须要进行SysTick配置。
它的控制配置很简单,只有三个控制位和一个标志位,都位于寄存器STK_CTRL中。
STK_CTRL是一个32位的寄存器,该寄存器与SysTick有关的位分别为Bit0(ENABLE)、Bit1(TICKINT)、Bit2(CLKSOURCE)、Bit16(COUNTFLAG)。
Bit0(ENABLE):SysTick的使能位,此位为1的时候使能SysTick定时器,为0的时候关闭SysTick定时器。
STM32入门教程系统时钟SysTickSTM32 入门教程系统时钟 SysTick(一) 背景介绍在传统的嵌入式系统软件按中通常实现 Delay(N) 函数的方法为:for(i = 0; i <= x; i ++);x --- 对应于对应于 N 毫秒的循环值对于STM32系列微处理器来说,执行一条指令只有几十个ns,进行 for 循环时,要实现 N 毫秒的 x 值非常大,而且由于系统频率的宽广,很难计算出延时 N 毫秒的精确值。
针对 STM32 微处理器,需要重新设计一个新的方法去实现该功能,以实现在程序中使用Delay(N)。
(二) STM32 SysTick 介绍Cortex-M3 的内核中包含一个 SysTick 时钟。
SysTick 为一个 24 位递减计数器,SysTick 设定初值并使能后,每经过 1 个系统时钟周期,计数值就减 1。
计数到 0 时,SysTick 计数器自动重装初值并继续计数,同时内部的COUNTFLAG 标志会置位,触发中断(如果中断使能情况下)。
在 STM32 的应用中,使用 Cortex-M3 内核的 SysTick 作为定时时钟,设定每一毫秒产生一次中断,在中断处理函数里对N 减一,在Delay(N) 函数中循环检测 N 是否为 0,不为 0 则进行循环等待;若为0 则关闭 SysTick 时钟,退出函数。
注:全局变量 TimingDelay , 必须定义为 volatile 类型 , 延迟时间将不随系统时钟频率改变。
(三) ST SysTick 库文件使用ST的函数库使用systick的方法1、调用SysTick_CounterCmd() -- 失能SysTick计数器2、调用SysTick_ITConfig () -- 失能SysTick中断3、调用SysTick_CLKSourceConfig() -- 设置SysTick时钟源。
4、调用SysTick_SetReload() -- 设置SysTick重装载值。
正点原子systick 延时32bit 溢出-回复"正点原子systick 延时32bit 溢出" 的主题是关于延时函数和计时器的使用。
在本文中,我们将介绍正点原子systick 延时函数的原理、32bit 溢出的影响以及如何解决这个问题。
延时函数是在嵌入式系统中常用的功能之一。
它可以让程序在一段时间内暂停执行,以实现定时等待的效果。
正点原子是一家专注于嵌入式开发的公司,提供了一系列的硬件和软件解决方案,其中包括systick 延时函数。
这个函数使用了系统中的一个计时器来实现精确的延时功能。
systick 是ARM Cortex-M 架构中的一个系统定时器,它可以提供一个可编程的定时中断。
在正点原子的开发板上,systick 定时中断的频率被设置为1 毫秒。
也就是说,每隔1 毫秒,系统都会触发一次systick 中断。
延时函数通过在systick 中断中进行计数,实现了精确的时间控制。
然而,由于计时器的位数是有限的,当计时器的值超过它的上限时,会发生溢出。
在正点原子的systick 延时函数中,计时器使用了32 位的无符号整数来进行计数,所以当计时器的值超过2^32-1 时,会发生溢出。
也就是说,当计时器的值从0 开始计数,达到最大值后又回到了0。
这种溢出会导致延时函数产生错误的结果。
为了解决这个问题,正点原子提供了一种处理溢出的方法。
在systick 中断中,延时函数会检查计时器的值是否发生了溢出。
如果发生了溢出,延时函数会将溢出的次数记录下来,并在计算延时时间时考虑到这个溢出次数。
具体来说,延时函数会将溢出的次数乘以计时器的上限2^32,然后再加上当前的计时器的值。
这样,我们在计算延时时间时就可以考虑到溢出的影响,得到准确的结果。
接下来,我们将通过一个例子来说明延时函数的使用和处理溢出的方法。
假设我们需要延时10 秒钟,我们可以使用如下的代码片段来实现:#include "systick.h"void delay_seconds(uint32_t seconds) {uint32_t start = systick_get_tick(); 获取当前的计时器值while (systick_get_tick() - start < seconds * 1000); 检查延时时间是否到达}int main() {systick_init(); 初始化systick 定时器delay_seconds(10); 延时10 秒钟以下是延时后的逻辑代码...}在上述代码中,我们使用了systick_get_tick() 函数来获取当前计时器的值。
@TOC
1.SysTick定时器介绍
SysTick定时器也叫SysTick滴答定时器,它是Cortex-M4内核的一个外设,被嵌入在 NVIC 中。
它是一个24 位向下递减的定时器,每计数一次所需时间为1/SYSTICK,SYSTICK是系统定时器时钟,它可以直接取自系统时钟,还可以通过系统时钟8分频后获取。
当定时器计数到0时,将从LOAD 寄存器中自动重装定时器初值,重新向下递减计数,如此循环往复。
如果开启SysTick中断的话,当定时器计数到0,将产生一个中断信号。
因此只要知道计数的次数就可以准确得到它的延时时间。
2.SysTick定时器寄存器
(1)CTRL寄存器
CTRL是SysTick定时器的控制及状态寄存器。
其相应位功能如下:
(2)LOAD寄存器
LOAD是SysTick定时器的重装载数值寄存器。
其相应位功能如下:
(3)VAL寄存器
VAL是SysTick定时器的当前数值寄存器。
其相应位功能如下:
(4)CALIB寄存器
CALIB是SysTick定时器的校准数值寄存器。
其相应位功能如下:3.SysTick定时器配置步骤
5.编程。