STM32F103 SysTick系统嘀嗒时钟学习(一)

SysTick

SysTick是Cortex-M3内核中的一个外设,内嵌在NVIC中,是一个24位的系统定时器,它从重装载值向下计数一直计到0后,在下一个时钟边沿将重装载值装载到 LOAD 寄存器后,继续向下计数。

当处理器在调试期间被喊停时,SysTick也将暂停运作。

与SysTick 相关寄存器一共有如下4个:

寄存器描述
CTRLSysTick 控制和状态寄存器
LOADSysTick 重装载值寄存器
VALSysTick 当前值寄存器
CALIBSysTick 校准寄存器(一般不需要校准不常用)

  

CTRL 寄存器

CTRL寄存器可用的一共有4个位

bit 16 : COUNTFLAG  计数标志位,

            如果上次处理器读取到计数器已经计到0,那么将该位置为1。可以该位来得知一轮计数是否完成。

bit 2 : CLKSOURCE   Systick 时钟源选择位,

         为0则为AHB/8,为1则为处理器时钟即AHB。

bit 1 :  Systick 异常请求标志位,

         为0表示VAL计数到0后不会触发Systick异常中断请求,为1表示VAL计数到0后会触发ystick异常中断请求。软件可以通过查询COUNTFLAG来判断SysTick是否计数到0.

bit 0 : ENABLE   计数使能位

          当该位为1时使能计数器,计数器从LOAD寄存器装载reload值,并开始向下计数,当计数到0时,会置位COUNTFLAG,同时根据TICKINT的值来决定是否申请Systick 异常中断,同时计数器重新装载reload值,并开始新一轮的向下计数。

LOAD 寄存器

LOAD 寄存器的值指定了当计数器使能时或计数到0后装载到VAL寄存器的值,即指定Reload 的值.

LOAD 寄存器有效位为24位,故能装载0x000000~0xFFFFFF范围内的值。

VAL 寄存器

VAL寄存器中存放着当前计数值,读该寄存器返回 SysTick计数值,写该寄存器会使该字段清0,同时也会使COUNTFLAG位清0.

CALIB 寄存器(一般不用)

相关库函数

SysTick_Config()

static __INLINE uint32_t SysTick_Config(uint32_t ticks)
{ 
  if (ticks > SysTick_LOAD_RELOAD_Msk)  return (1);            /* Reload value impossible */
                                                               
  SysTick->LOAD  = (ticks & SysTick_LOAD_RELOAD_Msk) - 1;      /* set reload register */
  NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1);  /* set Priority for Cortex-M0 System Interrupts */
  SysTick->VAL   = 0;                                          /* 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 (0);                                                  /* Function successful */
}

使用该函数可以对SysTikc初始化并且赋上重装载寄存器的值,该函数需要一个参数,这个参数就是用来设置重装载计数器的值的。该函数返回值为1时表示失败,为0时表示成功。

if (ticks > SysTick_LOAD_RELOAD_Msk)  return (1);

该语句用来判断重装A载值的合法型,SysTick_LOAD_RELOAD_Msk 为宏定义,值为0xFFFFFFUL,由于LOAD寄存器有效位位24位,故大于0xFFFFFF的设定值均不合法,返回1。

SysTick->LOAD  = (ticks & SysTick_LOAD_RELOAD_Msk) - 1;  

将需要计数的值减1后赋值给LOAD寄存器。SysTick_LOAD_RELOAD_Msk同上表示0xFFFFFFul。

NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1);

设置SysTick 异常中断的优先级,随后研究。

SysTick->VAL   = 0; 

将计数器的值清零。

SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk | 
                   SysTick_CTRL_TICKINT_Msk   | 
                   SysTick_CTRL_ENABLE_Msk;   

配置CTRL寄存器,涉及宏定义如下图:

 配置结果如下:

CLKSOURCE =1,使用系统时钟AHB——72MHz;

TICKINT=1, 开启SysTick异常中断

ENABLE=1,开启计数。

使用 SysTick 实现延时函数

如果想要定义1us,使用系统时钟AHB——72MHz,通过换算可知,重装载值应该为(72-1),如果需要定时1ms,则重装载值为(72000-1),如果需要定时1s,则不能使用上述方法,因为其结果大于0xFFFFFF,可以通过调用1000次毫秒延时来实现。

void Delay_us(uint32_t us)
{
    //SysTick_Config(72000000/1000000);
    SysTick_Config(SystemCoreClock/1000000);//固件库函数初始化,设置重装载值
    while(us--)
    {
        while(!((SysTick->CTRL)&0x00010000));//不断查询计数标志位,等待计数为0
    }
    SysTick->CTRL = 0x00000004; //关闭计数使能   
}


void Delay_ms(uint32_t xms)
{
	while(xms--)
	{
		Delay_us(1000);
	}
}


void Delay_s(uint32_t xs)
{
	while(xs--)
	{
		Delay_ms(1000);
	}
}

实物测试

利用延时函数实现LED间隔1s闪烁

int main(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//配置时钟RCC
	GPIO_InitTypeDef GPIO_InitStructure;                //定义GPIO初始化结构体
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;    //定义GPIO模式为推挽输出
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;           //定义引脚
	GPIO_InitStructure.GPIO_Speed= GPIO_Speed_50MHz;    //定义速度
	GPIO_Init(GPIOA,&GPIO_InitStructure); 	//GPIOA初始化
   
	while(1)
	{
		GPIO_SetBits(GPIOA,GPIO_Pin_0);
		Delay_s(1);
		GPIO_ResetBits(GPIOA,GPIO_Pin_0);
		Delay_s(1);
	}
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值