STM32_systick定时器解述

2024-05-05 07:32
文章标签 stm32 定时器 systick 解述

本文主要是介绍STM32_systick定时器解述,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

先看Cotex-M3内核中对systick定时器的描述。

</pre><p><strong><span style="font-size:14px;"><span style="white-space: pre;">SysTick定时器被捆绑在NVIC中,用于产生SYSTICK异常(异常号:15)</span><span style="white-space: pre;">。</span></span></strong></p><p><span style="white-space:pre">在以前,大多操作系统需要一个硬件定时器来产生操作系统需要的滴答中断,作为整个系统的时基。例如,为多个任务许以不同数目的时间片,</span></p><p><span style="white-space:pre">确保没有一个任务能霸占系统;</span><span style="white-space:pre">或者把每个定时器周期</span><span style="white-space:pre">的某个时间范围赐予特定的任务等,还有操作系统提供的各种定时功能,都与这个滴答定</span></p><p><span style="white-space:pre">时器有关。因此,需要一个定时器来产生周期性的中断,而且最好还让用户程序不能随意访问</span><span style="white-space:pre">它的寄存器,以维持操作系统“心跳”的节律。 </span></p><p><span style="white-space:pre">Cortex‐M3处理器内部包含了一个简单的定时器。因为所有的CM3芯片都带有这个定时器,软件在不同  CM3器件间的移植工作得以化简。该</span></p><p><span style="white-space:pre">定时器的时钟源可以是内部时钟(FCLK,</span><span style="white-space:pre">CM3上的自由运行时钟),或者是外部时钟(  CM3处理器上的STCLK信号)。不过,STCLK的具体来源则</span></p><p><span style="white-space:pre">由芯片设计者决定,因此不同产品之间的时钟频率可能会大不相同,你需要检视</span><span style="white-space:pre">芯片的器件手册来决定选择什么作为时钟源。 </span></p><p><span style="white-space:pre">SysTick定时器能产生中断,CM3为它专门开出一个异常类型,并且在向量表中有它的一席之地。它使操作系统和其它系统软件在CM3器件间的</span></p><p><span style="white-space:pre">移植变得简单多了,因为在所有CM3</span><span style="white-space:pre">产品间对其处理都是相同的。  </span></p><span style="white-space:pre">有4个寄存器控制SysTick定时器,如表8.9至表8.12所示。 </span><p></p><p><img src="https://img-blog.csdn.net/20160317114228619?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" /></p><p>校准值寄存器提供了这样一个解决方案:它使系统即使在不同的CM3产品上运行,也能产生恒定的SysTick中断频率。最简单的作法就是:</p><p>直接把TENMS的值写入重装载寄存器,这样一来,只要没突破系统极限,就能做到每10ms来一次  SysTick异常。如果需要其它的SysTick异常周期,则可以根据TENMS的值加以比例计算。只不过,在少数情况下,CM3芯片可能无法准确地提供TENMS的值(如,CM3的校准输入</p><p>信号被拉低),所以为保险起见,最好在使用TENMS前检查器件的参考手册。  SysTick定时器除了能服务于操作系统之外,还能用于其它目的:如作为一个闹铃,用于测量时间等。要注意的是,当处理器在调试期间被喊</p><p>停(halt)时,则SysTick定时器亦将暂停运作。</p><p>下面的例子基于官方库函数,用systick实现简单的时间片用以调度任务(从libopencm3库移植而来)。</p><p>既然是时间片,我们先看时间片管理结构体:</p><p>类型声明是放在sys_time.h中:<pre name="code" class="cpp">typedef uint8_t tid_t; ///< sys_time timer id type
typedef void (*sys_time_cb)(uint8_t id);struct sys_time_timer {                                                      //时间片类型声明bool_t                in_use;sys_time_cb      cb;                                                           //时间片到了要执行的函数volatile bool_t  elapsed;                                            uint32_t            end_time;        ///< in SYS_TIME_TICKSuint32_t            duration;         ///< in SYS_TIME_TICKS
};struct sys_time {<span style="white-space:pre">								</span>     //系统时间片管理器类型声明volatile uint32_t nb_sec;                                                  ///< 系统启动后工作了的秒数volatile uint32_t nb_sec_rem;  <span style="white-space:pre">	</span> <span style="white-space:pre">			</span>  <span style="white-space:pre">	</span>     ///< remainder of seconds since startup in CPU_TICKSvolatile uint32_t nb_tick;      <span style="white-space:pre">					</span>     ///< 系统启动后“心跳”的次数struct sys_time_timer timer[SYS_TIME_NB_TIMER];      ///<时间片数组float resolution;               <span style="white-space:pre">						</span>     ///<系统时间(“心跳”)的周期                    //分辨率=1.0 / ticks_per_secuint32_t ticks_per_sec;         <span style="white-space:pre">					</span>     ///<系统每秒中“心跳”的次数,也即每秒SYSTICK的中断次数uint32_t resolution_cpu_ticks;  <span style="white-space:pre">					</span>     ///< systick定时器的“时基脉冲”的周期uint32_t cpu_ticks_per_sec;     <span style="white-space:pre">					</span>     ///< 每秒systick定时器计数的脉冲数
};
并在sys_time.c文件中声明实体:
struct sys_time sys_time;

下面是对系统时间片管理器的初始化:
<pre name="code" class="cpp">void sys_time_init(void)
{sys_time.nb_sec     = 0;sys_time.nb_sec_rem = 0;sys_time.nb_tick    = 0;sys_time.ticks_per_sec = SYS_TIME_FREQUENCY;            //< #define SYS_TIME_FREQUENCY 2000         //系统“心跳”的频率,也即systick每秒中断的次数sys_time.resolution = 1.0 / sys_time.ticks_per_sec;for (unsigned int i = 0; i < SYS_TIME_NB_TIMER; i++) {sys_time.timer[i].in_use     = FALSE;sys_time.timer[i].cb         = NULL;sys_time.timer[i].elapsed    = FALSE;sys_time.timer[i].end_time   = 0;sys_time.timer[i].duration   = 0;}sys_time_arch_init();
}
这里看sys_time_arch_init函数的定义:
/** Initialize SysTick.
* Generate SysTick interrupt every sys_time.resolution_cpu_ticks
*/
void sys_time_arch_init(void)
{
/* run cortex systick timer with 72MHz (FIXME only 72 or does it work with 168MHz???) */
#if USE_OCM3_SYSTICK_INIT
systick_set_clocksource(STK_CSR_CLKSOURCE_AHB);
#endif
sys_time.cpu_ticks_per_sec = AHB_CLK;                             //#define AHB_CLK 72000000
/* cpu ticks per desired sys_time timer step */
sys_time.resolution_cpu_ticks = (uint32_t)(sys_time.resolution * sys_time.cpu_ticks_per_sec + 0.5);     //四舍五入
#if USE_OCM3_SYSTICK_INIT
/* The timer interrupt is activated on the transition from 1 to 0,
* therefore it activates every n+1 clock ticks.
*/
systick_set_reload(sys_time.resolution_cpu_ticks - 1);
systick_interrupt_enable();
systick_counter_enable();
#endif
}


 

下面是对systick的初始化:
<pre name="code" class="cpp">/** Initialize SysTick.* Generate SysTick interrupt every sys_time.resolution_cpu_ticks*/
void sys_time_arch_init(void)
{/* run cortex systick timer with 72MHz (FIXME only 72 or does it work with 168MHz???) */
#if USE_OCM3_SYSTICK_INITsystick_set_clocksource(STK_CSR_CLKSOURCE_AHB);
#endifsys_time.cpu_ticks_per_sec = AHB_CLK;                             //#define AHB_CLK 72000000/* cpu ticks per desired sys_time timer step */sys_time.resolution_cpu_ticks = (uint32_t)(sys_time.resolution * sys_time.cpu_ticks_per_sec + 0.5);     //四舍五入#if USE_OCM3_SYSTICK_INIT/* The timer interrupt is activated on the transition from 1 to 0,* therefore it activates every n+1 clock ticks.*/systick_set_reload(sys_time.resolution_cpu_ticks - 1);systick_interrupt_enable();systick_counter_enable();
#endif
}


 


这篇关于STM32_systick定时器解述的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/961133

相关文章

【STM32】SPI通信-软件与硬件读写SPI

SPI通信-软件与硬件读写SPI 软件SPI一、SPI通信协议1、SPI通信2、硬件电路3、移位示意图4、SPI时序基本单元(1)开始通信和结束通信(2)模式0---用的最多(3)模式1(4)模式2(5)模式3 5、SPI时序(1)写使能(2)指定地址写(3)指定地址读 二、W25Q64模块介绍1、W25Q64简介2、硬件电路3、W25Q64框图4、Flash操作注意事项软件SPI读写W2

STM32(十一):ADC数模转换器实验

AD单通道: 1.RCC开启GPIO和ADC时钟。配置ADCCLK分频器。 2.配置GPIO,把GPIO配置成模拟输入的模式。 3.配置多路开关,把左面通道接入到右面规则组列表里。 4.配置ADC转换器, 包括AD转换器和AD数据寄存器。单次转换,连续转换;扫描、非扫描;有几个通道,触发源是什么,数据对齐是左对齐还是右对齐。 5.ADC_CMD 开启ADC。 void RCC_AD

STM32内部闪存FLASH(内部ROM)、IAP

1 FLASH简介  1 利用程序存储器的剩余空间来保存掉电不丢失的用户数据 2 通过在程序中编程(IAP)实现程序的自我更新 (OTA) 3在线编程(ICP把整个程序都更新掉) 1 系统的Bootloader写死了,只能用串口下载到指定的位置,启动方式也不方便需要配置BOOT引脚触发启动  4 IAP(自己写的Bootloader,实现程序升级) 1 比如蓝牙转串口,

FreeRTOS-基本介绍和移植STM32

FreeRTOS-基本介绍和STM32移植 一、裸机开发和操作系统开发介绍二、任务调度和任务状态介绍2.1 任务调度2.1.1 抢占式调度2.1.2 时间片调度 2.2 任务状态 三、FreeRTOS源码和移植STM323.1 FreeRTOS源码3.2 FreeRTOS移植STM323.2.1 代码移植3.2.2 时钟中断配置 一、裸机开发和操作系统开发介绍 裸机:前后台系

寻迹模块TCRT5000的应用原理和功能实现(基于STM32)

目录 概述 1 认识TCRT5000 1.1 模块介绍 1.2 电气特性 2 系统应用 2.1 系统架构 2.2 STM32Cube创建工程 3 功能实现 3.1 代码实现 3.2 源代码文件 4 功能测试 4.1 检测黑线状态 4.2 未检测黑线状态 概述 本文主要介绍TCRT5000模块的使用原理,包括该模块的硬件实现方式,电路实现原理,还使用STM32类

STM32 ADC+DMA导致写FLASH失败

最近用STM32G070系列的ADC+DMA采样时,遇到了一些小坑记录一下; 一、ADC+DMA采样时进入死循环; 解决方法:ADC-dma死循环问题_stm32 adc dma死机-CSDN博客 将ADC的DMA中断调整为最高,且增大ADCHAL_ADC_Start_DMA(&hadc1, (uint32_t*)adc_buffer, ADC_Buffer_Size); 的ADC_Bu

【Qt】定时器事件

定时器事件 在之前学习QTimer中实现了定时器的功能,而在QTimer背后是QTimerEvent定时器事件进行支撑的。在QObject中提供了一个timeEvent这个函数。 startTimer启动定时器killTimer关闭定时器 Qt 中在进⾏窗⼝程序的处理过程中,经常要周期性的执⾏某些操作,或者制作⼀些动画效果,使⽤定 时器就可以实现。所谓定时器就是在间隔⼀定时间后,去执⾏某⼀

独立按键单击检测(延时消抖+定时器扫描)

目录 独立按键简介 按键抖动 模块接线 延时消抖 Key.h Key.c 定时器扫描按键代码 Key.h Key.c main.c 思考  MultiButton按键驱动 独立按键简介 ​ 轻触按键相当于一种电子开关,按下时开关接通,松开时开关断开,实现原理是通过轻触按键内部的金属弹片受力弹动来实现接通与断开。  ​ 按键抖动 由于按键内部使用的是机

基于stm32的河流检测系统-单片机毕业设计

文章目录 前言资料获取设计介绍功能介绍具体实现截图参考文献设计获取 前言 💗博主介绍:✌全网粉丝10W+,CSDN特邀作者、博客专家、CSDN新星计划导师,一名热衷于单片机技术探索与分享的博主、专注于 精通51/STM32/MSP430/AVR等单片机设计 主要对象是咱们电子相关专业的大学生,希望您们都共创辉煌!✌💗 👇🏻 精彩专栏 推荐订阅👇🏻 单片机设计精品

STM32的使用方法一

注:我采用的是STM32F103RC芯片、相应的电路图和STM32CubeIDE软件这是在STM32CubeIDE软件定义芯片后,所给的必要的代码逻辑,加上了注释 #include "main.h"/* Private variables ---------------------------------------------------------*//* Private function