三、SysTick系统节拍定时器

3.1 SysTick简介

系统节拍定时器SysTick是ARM Cortex-M0内核提供的一个24位递减定时器,当计数值达到0时产生中断,可以为操作系统和其他管理软件提供固定时间的中断。

当系统节拍定时器被被使能时,定时器从重装值递减计数,到0进中断,再继续从重装值递减,循环往复。

3.2 寄存器

3.2.1 系统定时器控制和状态寄存器 STCTRL

|----|---------------------------|
| 位 | 功能 |
| 0 | 1计数器使能,0计数器禁能 |
| 1 | 1中断使能,0中断禁能 |
| 16 | 标志位,倒计数到0该标志置位,读一下该位置标志清零 |

所以用的时候0-1位都给1就行了

3.2.2 系统定时器重载值寄存器 STRELOAD

|------|-------------|
| 位 | 功能 |
| 23:0 | 倒计数到0时装入计数器 |

就是用该寄存器设置倒计时初始值,注意这里位数范围,说明倒计时起始最大值为2^24 - 1 = 16,777,215 然而不够48MHz,想想怎么计数1s。答案是中断里写循环,也整个计数器。

对于周期为N的倒计数,LOAD置N-1即可。

3.2.3 系统定时器当前值寄存器 STCURR

|------|--------------------------------------|
| 位 | 功能 |
| 23:0 | 读的时候返回当前计数值 写的时候清零计数器,清零STCRL中16位标志位 |

3.2.4 系统定时器校准值寄存器 STCALIB

校准特性,没用过。

3.3 使用方法

首先定时器中断时间间隔 T = (初始计数值 + 1)/ 系统时钟 =

LPC1114用的48MHz,如果要定时1ms,那么直接初始值设置48000 -1 = 47999即可

对于代码书写,基本配置已经有现成函数了,就在core_cm0.h中

cpp 复制代码
__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
{
  if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk)
  {
    return (1UL);                                                   /* Reload value impossible */
  }

  SysTick->LOAD  = (uint32_t)(ticks - 1UL);                         /* set reload register */
  NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */
  SysTick->VAL   = 0UL;                                             /* Load the SysTick Counter Value */
  SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk |
                   SysTick_CTRL_TICKINT_Msk   |
                   SysTick_CTRL_ENABLE_Msk;                         /* Enable SysTick IRQ and SysTick Timer */
  return (0UL);                                                     /* Function successful */
}

我们要做的就是知道怎么用就行,在代码里,我们发现要输入的数已经进行了减一操作,那么输入值ticks就是load + 1 ,就是计数周期。

配置时,还有一个巧妙办法得到需要的值,就是,先不管系统时钟具体值(当然还是需要知道以防止初始值过大溢出),直接将需要的时间取倒数乘以SystemCoreClock即可。

对于避免溢出的处理方法,只要周期足够小即可,剩下的靠中断里循环去扩大周期,具体见下面的3.4。

3.4 实现1s定时

1s定时,那么根据公式就需要 1 * FCLK = 48M = 4.8 * 10^7 , 而计数值上文计算过只有十几兆,那么求其次实现10ms计时足够了,4.8*10^5 < 16,777,215 填入函数值的就是 (FCLK/100)

现在开始实现。

首先我们复制一下上次的工程,换个文件名SysTick

然后main.c如下

cpp 复制代码
#include <LPC11xx.h>
#include "LED.h"

// 粗糙的delay函数
void delay_1s()
{
	uint16_t i,j;
	
	for(i=0;i<30000;i++)
		for(j=0;j<200;j++);
}

int main()
{
	LED_Init();
	LED_ON();
	
	SysTick_Config(SystemCoreClock / 100); // 10ms
	
	while(1)
	{

	}
}

void SysTick_Handler() /// 系统节拍定时器中断函数
{
	static unsigned long ticks;
	if(ticks++ >= 99)
	{
		ticks = 0;
		LED_G_Toggle();
	}
}

中断函数SysTick_Handler这个名字记住就行,里面ticks是个静态变量,每次调用函数时不会更新,当中断进入99次,执行相关操作,10ms * 100 = 1s,实现了1s定时。

结果就是蓝灯BLINKY常亮,RGB中G灯一秒一换状态闪烁。

相关推荐
国科安芯1 小时前
ASP4644芯片低功耗设计思路解析
网络·单片机·嵌入式硬件·安全
充哥单片机设计1 小时前
【STM32项目开源】基于STM32的智能厨房火灾燃气监控
stm32·单片机·嵌入式硬件
CiLerLinux8 小时前
第四十九章 ESP32S3 WiFi 路由实验
网络·人工智能·单片机·嵌入式硬件
时光の尘8 小时前
【PCB电路设计】常见元器件简介(电阻、电容、电感、二极管、三极管以及场效应管)
单片机·嵌入式硬件·pcb·二极管·电感·三极管·场效应管
Lu Zelin8 小时前
单片机为什么不能跑Linux
linux·单片机·嵌入式硬件
宁静致远20219 小时前
stm32 freertos下基于hal库的模拟I2C驱动实现
stm32·嵌入式硬件·freertos
Wave84514 小时前
STM32--智能小车
stm32·单片机·嵌入式硬件
wdfk_prog16 小时前
[Linux]学习笔记系列 -- lib/timerqueue.c Timer Queue Management 高精度定时器的有序数据结构
linux·c语言·数据结构·笔记·单片机·学习·安全
充哥单片机设计20 小时前
【STM32项目开源】基于STM32的智能家居环境(空气质量)检测系统
stm32·单片机·嵌入式硬件
夜月yeyue20 小时前
ART 加速器、流水线与指令预测的关系详解
linux·服务器·c语言·单片机·嵌入式硬件·性能优化·嵌入式高阶技巧