三、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灯一秒一换状态闪烁。

相关推荐
电子科技圈2 小时前
XMOS与飞腾云联袂以模块化方案大幅加速音频产品落地
经验分享·嵌入式硬件·mcu·自然语言处理·音视频·腾讯会议·游戏机
Tracy9732 小时前
XMSRC4194_VC1:4通道192KHz ASRC音频采样率转换器产品介绍
嵌入式硬件·音视频·智能硬件·xmos模组固件
xiaotianyun882 小时前
NCP13992 CS 分压计算
单片机·嵌入式硬件·ncp13992
偶像你挑的噻3 小时前
Linux应用开发-17-套接字
linux·网络·stm32·嵌入式硬件
Msshu1234 小时前
PD快充诱骗芯片 XSP15 支持获取快充电压可与外部MCU共用D+D-网络与电脑传输数据
单片机·嵌入式硬件
brave and determined5 小时前
MCU学习Day24——STM32G030多路ADC DMA采集深度解析:完全可配置序列器与不完全可配置序列器的陷阱与抉择
stm32·单片机·嵌入式硬件·dma·adc·hal·多通道采集
d111111111d5 小时前
通过操作地址,来进行STM32的写入GPIO端口值
stm32·单片机·嵌入式硬件
小刘爱玩单片机5 小时前
【stm32简单外设篇】- 土壤湿度传感器
c语言·stm32·单片机·嵌入式硬件
晚秋大魔王5 小时前
基于python的jlink单片机自动化批量烧录工具
前端·python·单片机
d111111111d5 小时前
STM32外设学习--TIM定时器--编码器接口
stm32·嵌入式硬件·学习