STM32滴答时钟[直接用寄存器]

生活中,我们通过看表来知道当前时间,知道我们在这个点应该做什么事情,那么芯片呢,就通过各种定时器来记录时间,滴答时钟就是定时器的一种,它可以用来做操作系统的节拍(心跳),可以用来计时,可以用来做闹钟,延时,今天,我们就简单看一下滴答时钟。

void Delay(unsigned int xx)
{
	while(xx--);
}

滴答时钟也是填入一个值,然后倒数到零,然后通知芯片,但是相比上边的粗略延时函数就精确了很多很多,可以精确到微秒、毫秒。
滴答时钟配置有两种

一、滴答时钟在STM32的哪里

在这里插入图片描述
首先我们得知道,ARM公司制造了CortexM3,ST公司以CortexM3为内核,造了STM32,这个滴答时钟就是在CortexM3里,也就是STM32内核中,所以用到的寄存器地址可以在Cortex-权威指南里查找。

二、滴答时钟相关的寄存器

1、SysTick->CTRL(控制和状态寄存器)

在这里插入图片描述
因为是查询式,所以我们不用第1位

  • 0位(打开滴答时钟)
  • 2位(选择时钟源,我们一般选择外部时钟源)
  • 16位(查看是否数到了零)

2、SysTick->RELOAD(重装载数值寄存器)

在这里插入图片描述
这个寄存器就比较简单了,这个就是重新向滴答时钟里加载计时次数,可以看到总共有24位可设置,所以重新加载值最大不能超过24位。

3、SysTick->VAL(当前数值寄存器)

在这里插入图片描述
这个寄存器作用在读取的时候返回当前计数值,在写入的时候就是计数器清零,同时还清除掉了SysTick->CTRL第16位的标志。

4、SysTick->CALIB(校准数值寄存器)

在这里插入图片描述
这个寄存器不常用,所以我们不再讲解。

以上四种寄存器,我们常用的有:

  • SysTick->CTRL(控制和状态寄存器)
  • SysTick->RELOAD(重装载数值寄存器)
  • SysTick->VAL(当前数值寄存器)

三、寄存器地址定义

//----------------GPIOB配置寄存器 ------------------------
#define GPIOB_CRL		*((unsigned volatile int*)0x40010C00)
#define	GPIOB_ODR		*((unsigned volatile int*)0x40010C0C)

寄存器少的时候,我们可以像以上这样定义,那么寄存器多的时候呢?我们就用C语言里学的结构体来定义,比如下边这次我们的滴答时钟寄存器地址

//-----------------SysTick寄存器地址----------------------
#define SysTick_Base	0xE000E010	//这是我们结构体的首地址,也是结构体第一个成员地址
#define SysTick	((SysTick_Typedef*)SysTick_Base)	//转换为指针类型
typedef struct
{
	volatile unsigned int  CTRL;	//控制和状态寄存器	0xE000E010
	volatile unsigned int RELOAD;	//重装载寄存器		0xE000E014
	volatile unsigned int VAL;		//当前值寄存器		0xE000E018
	volatile unsigned int CALIB;	//校准寄存器			0xE000E01C
}SysTick_Typedef;

四、滴答时钟配置步骤

在这里插入图片描述
在时钟树里可以看到,对于Cortex时钟,有两种选择方法,一是选用经过八分频的外部时钟源,二是选用内核时钟,我们一般在设置的时候选用八分频后的外部时钟源,我们之前设置了系统时钟为72MHZ,经过八分频后变为了9MHZ,也就是说,滴答时钟的频率是9MHZ,那让滴答时钟计1次,时间过去了1/9μs,滴答时钟计9次,才是1μs,于是我们有了以下的设计:

  • 计1μs:我们向计数器里放入9
  • 计1ms:我们向计数器里放入9000
    1ms(毫秒)=1μs(微秒)
    配置滴答时钟步骤如下:
  • 1、清空计数器
  • 2、重新装载数值
  • 3、打开定时器
  • 4、等待计时器数到0
  • 5、关闭计数器
  • 6、清空计数器

五、微秒延时和毫秒延时总程序

1、微秒延时

//-----------------SysTick寄存器地址----------------------
#define SysTick_Base	0xE000E010
#define SysTick	((SysTick_Typedef*)SysTick_Base)
//-----------------SysTick寄存器定义----------------------
typedef struct
{
	volatile unsigned int  CTRL;			//控制和状态寄存器
	volatile unsigned int RELOAD;		//重装载寄存器
	volatile unsigned int VAL;				//当前值寄存器
	volatile unsigned int CALIB;			//校准寄存器
}SysTick_Typedef;
//----------------------滴答定时器---------------------------
void SysTick_us(unsigned int time)
{
	unsigned long int num;
	SysTick->VAL=0;						//计数器清零
	SysTick->RELOAD=9*time;				//重装载计数值
	SysTick->CTRL|=1<<0;				//定时器使能,打开定时器
	do
	{
		num=SysTick->CTRL;
	}
	while((num&0x01)&&!(num&(1<<16))); //等待计数器到0
	SysTick->CTRL&=~(1<<0);			   //关闭计数器
	SysTick->VAL=0;					   //计数器清零
}
int main(void)
{
	SysTick_us(10);			//调用滴答定时器,延时10微秒
}

2、毫秒延时

//-----------------SysTick寄存器地址----------------------
#define SysTick_Base	0xE000E010
#define SysTick	((SysTick_Typedef*)SysTick_Base)
//-----------------SysTick寄存器定义----------------------
typedef struct
{
	volatile unsigned int  CTRL;			//控制和状态寄存器
	volatile unsigned int RELOAD;		//重装载寄存器
	volatile unsigned int VAL;				//当前值寄存器
	volatile unsigned int CALIB;			//校准寄存器
}SysTick_Typedef;
//----------------------滴答定时器---------------------------
void SysTick_ms(unsigned int time)
{
	unsigned long int num;
	SysTick->VAL=0;						//计数器清零
	SysTick->RELOAD=9000*time;			//重装载计数值
	SysTick->CTRL|=1<<0;				//定时器使能,打开定时器
	do
	{
		num=SysTick->CTRL;
	}
	while((num&0x01)&&!(num&(1<<16)));//等待计数器到0
	SysTick->CTRL&=~(1<<0);			  //关闭计数器
	SysTick->VAL=0;					  //计数器清零
}
int main(void)
{
	SysTick_ms(10);		 //调用滴答定时器,延时10毫秒
}

/*
     while((num&0x01)&&!(num&(1<<16)));//等待计数器到0
     
     (num&0x01) 这一句是判断用来判断SysTick定时器是否处于开启状态,
     可以防止SysTick被意外关闭导致的死循环。
     
     (num&(1<<16)) 这一句是用来判断SysTick->CTRL第16位是否为1,如
     果为一,说明计数器延时时间已到
     
     定时器正常开启,那么 (num&0x01) 为1,如果倒数时间已到,
     (num&(1<<16)) 为 1,(num&0x01)&&!(num&(1<<16)) ==>(1)&&!(1)
     可以看到后边的1取反为0,那么 (1)&&(0)=0,while(0)循环结束,执行后
     边的语句。
*/
  • 5
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值