系统(嘀嗒)定时器

2024-01-08 06:02:01

一.简介

SysTick---系统(嘀嗒定时器内核外设,是一个24位向下递减计数器,计数器每计数一次的时间为 1/SYSCLK

当重装载数值寄存器的值递减到 0 的时候,系统定时器就产生一次中断,以此循环往复。

系统定时器一般用于操作系统,用于产生时基,维持操作系统的心跳。

二.寄存器

校准寄存器一般不用。?

?三.实验(闪光灯)

编程步骤:

  1. 设置重装载寄存器的值;
  2. 清除当前数值寄存器的值;
  3. 配置控制与状态寄存器。
延时思路:
systick counter reload 值往下递减到 0 的时候,CTRL 寄存器的位 16:countflag 会置 1 ,且读取该位的值可清 0 ,所有我们可以使用软件查询的方法来实现延时。

?

systick.c

#include "systick.h"

#if 0
static __INLINE uint32_t SysTick_Config(uint32_t ticks)
{ 
	//  判断 tick 的值是否大于 2^24,如果大于,则不符合规则
  if (ticks > SysTick_LOAD_RELOAD_Msk)  return (1);

  // 初始化reload寄存器的值	
  SysTick->LOAD  = (ticks & SysTick_LOAD_RELOAD_Msk) - 1;
	
  // 配置中断优先级,配置为15,默认为最低的优先级
	NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); 

  // 初始化counter的值为0	
  SysTick->VAL   = 0; 
  
  // 配置 systick 的时钟为 72M
  // 使能中断
	// 使能systick
  SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk | 
                   SysTick_CTRL_TICKINT_Msk   | 
                   SysTick_CTRL_ENABLE_Msk;                    
  return (0);                                                 
}
#endif

void SysTick_Delay_us(uint32_t us)
{
	uint32_t i;
	SysTick_Config(72);
	
	for(i=0; i<us; i++)
	{
        // 当计数器的值减小到 0 的时候,CRTL 寄存器的位 16 会置 1
		while( !((SysTick->CTRL) & (1<<16)) );
	}

	// 关闭 SysTick 定时器
	SysTick->CTRL &= ~ SysTick_CTRL_ENABLE_Msk;
}

void SysTick_Delay_ms(uint32_t ms)
{
	uint32_t i;
	SysTick_Config(72000);
	
	for(i=0; i<ms; i++)
	{
        // 当计数器的值减小到 0 的时候,CRTL 寄存器的位 16 会置 1
        // 当置 1 时,读取该位会清 0
		while( !((SysTick->CTRL) & (1<<16)) );
	}
	
    // 关闭 SysTick 定时器
	SysTick->CTRL &= ~ SysTick_CTRL_ENABLE_Msk;
}


SysTick 中断时间的计算:SysTick_Config(SystemCoreClock / 100000)

SysTick 定时器的计数器是向下递减计数的,计数一次的时间 T DEC =1/CLK AHB ,当重装载寄存器中的值 VALUE LOAD 减到 0 的时候,产生中断,可知中断一次的时间 T INT =VALUE LOAD * T DEC = VALUELOAD /CLK AHB ,其中 CLK AHB =72MHZ 。如果设置 VALUE LOAD 72 ,那中断一次的时间 TINT =72/72M=1us 。不过 1us 的中断没啥意义,整个程序的重心都花在进出中断上了,根本没有时间处理其他的任务。

systick.h

#ifndef _SYSTICK_H
#define _SYSTICK_H

#include "stm32f10x.h"
#include "core_cm3.h"


void SysTick_Delay_us(uint32_t us);
void SysTick_Delay_ms(uint32_t ms);

#endif

led.c

#include "led.h"

void led_gpio_init(void)
{
	GPIO_InitTypeDef GPIO_InitStruct;
	RCC_APB2PeriphClockCmd(LED0_GPIO_CLK,ENABLE);//注意需要用到的总线
	GPIO_InitStruct.GPIO_Pin = LED0_GPIO_PIN;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(LED0_GPIO_PORT,&GPIO_InitStruct);
	GPIO_ResetBits(LED0_GPIO_PORT,LED0_GPIO_PIN);
	
}


led.h

#ifndef _LED_H
#define _LED_H

#include "stm32f10x.h"

#define LED0_GPIO_CLK			RCC_APB2Periph_GPIOB
#define LED0_GPIO_PORT 		GPIOB
#define LED0_GPIO_PIN			GPIO_Pin_5

/******************************************************************************************/
/* LED端口定义 */
#define LED0(x)   do{ x ? \
                      GPIO_SetBits(LED0_GPIO_PORT, LED0_GPIO_PIN) : \
                      GPIO_ResetBits(LED0_GPIO_PORT, LED0_GPIO_PIN); \
                  }while(0)      /* LED0翻转 */

#define digitalToggle(p,i) {p->ODR ^=i;} //输出反转状态

#define LED0_Toggle	digitalToggle(LED0_GPIO_PORT,LED0_GPIO_PIN)

void led_gpio_init(void);


#endif

main.c

#include "stm32f10x.h"
#include "led.h"
#include "systick.h"

int main()
{
	// 来到这里的时候,系统的时钟已经被配置成72M。
	led_gpio_init();

	while(1)
	{
		LED0(1);
		SysTick_Delay_ms(500);
		LED0(0);
		SysTick_Delay_ms(500);
		
	}
}

文章来源:https://blog.csdn.net/m0_58575898/article/details/135347796
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。