GD32F207开发板SysTick定时器产生ms计时、us计时;GD32与STM32方法通用。

1、系统滴答定时器
参考资料《Cortex M3与M4权威指南.pdf》中的9.5 The SysTick timer小节,里面详细讲解了
1、为什么要用SysTick计时器;
2、SysTick定时器的操作情况;
3、如何使用SysTick定时器;
4、使用SysTick定时器。 

2、简介
系统定时器【SysTick】它挂载在AHB时钟线上,是一个24bit的向下递减的计数器,计数器每计数一次的时间为1/SystemCoreClock,当前我们的开发板选用的是8M的外部晶振,倍频至120M。当重装载数值寄存器的值递减到0的时候,系统定时器就产生一次中断,以此循环往复。 

3、SysTick寄存器

SysTick寄存器:
CTRL:SysTick控制及状态寄存器
LOAD:SysTick重装载数值寄存器
VAL:SysTick当前数值寄存器
CALIB:SysTick校准数值寄存器

SysTick控制及状态寄存器:

COUNTFLAG:如果在上次读取本寄存器后 SysTick已经计到了0,则该位为 1;
CLKSOURCE:时钟源选择位 ,0=AHB/8,1=处理器时钟AHB
TICKINT:1=SysTick倒数计数到 0时产生 SysTick异常请求,0=数到 0 时无动作。也可以通过读取COUNTFLAG标志位来确定计数器是否递减到0
ENABLE:SysTick 定时器的使能位

思路
SysTick->VAL寄存器的值每一个时钟周期就会递减1,当它递减到0时候,SysTick->LOAD的值将会进入SysTick->VAL中,并且SysTick->CTRL的COUNTFLAG位将会置1,如果还使能了中断,将还会进入中断。

延时原理就是通过使能中断,并设定SysTick->LOAD的值以及时钟周期的数值(通常设定为1kHz = 1ms)来实现的。

4、SysTick代码如下:

__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
{
  if ((ticks - 1) > SysTick_LOAD_RELOAD_Msk)  return (1);      /* Reload value impossible */

  SysTick->LOAD  = ticks - 1;                                  /* set reload register */
  NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1);  /* set Priority for Systick Interrupt */
  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 */
}

M4手册解说
如果你只想产生一个周期性的SysTick中断,最简单的方法是使用systick.c中的函数“SysTick_Config”:

SysTick_Config(uint32_t ticks);

该函数将SysTick中断间隔设置为“ticks”,启用使用处理器时钟的计数器,并启用异常优先级最低的SysTick异常。

例如,如果你有一个120MHz的时钟频率,你想要触发一个1KHz的SysTick异常,则ticks=120000;触发一个1MHz的SysTick异常,则ticks=120;

个人理解

AHB为120MHz,则计数周期为(1/120)us,1ms/(1/120)us=10^3*120=120000,也就是计数1ms要递减120000次,也就是SysTick->VAL递减120000次,所以SysTick->LODA是120000,也可以说ticks参数必须是120000;

5、SysTick库函数添加延时函数

先初始化SysTick配置函数:将SysTick函数配置成ms级中断,如果配置成us级中断,中断就会频繁的进入,将会占用cpu的使用资源。

volatile static uint32_t delay;


/*!
    \brief      configure systick
    \param[in]  none
    \param[out] none
    \retval     none
*/
void systick_config(void)
{
    /* setup systick timer for 1000Hz interrupts */
    if(SysTick_Config(SystemCoreClock / 1000U)) {
        /* capture error */
        while(1) {
        }
    }
    /* configure the systick handler priority */
    NVIC_SetPriority(SysTick_IRQn, 0x00U);
	
}

/*!
    \brief      delay a time in milliseconds
    \param[in]  count: count in milliseconds
    \param[out] none
    \retval     none
*/
void delay_1ms(uint32_t count)
{
    delay = count;

    while(0U != delay) {
    }
}

/*!
    \brief      delay decrement
    \param[in]  none
    \param[out] none
    \retval     none
*/
void delay_decrement(void)
{
    if(0U != delay) {
        delay--;
    }
}

其中SystemCoreClock定义为120000000;

在中断函数运行void delay_decrement(void)函数,实现1ms递减一次。

void SysTick_Handler(void)
{
    delay_decrement();

}

us计数器原理:由于SysTick->VAL 的计数范围120000~0就是1ms,递减计数器,每变化120就是1us。

void delay_1us(uint32_t count)
{	
	register uint32_t us_tcnt, cycle_cnt;
	us_tcnt = count*120;				//SysTick->VAL 的计数120~0就是1us,递减计数器,最大值不超过1ms
	cycle_cnt = SysTick->VAL;
	if(cycle_cnt>=us_tcnt)				//在计数到0前,满足计数要求
	{
		while(cycle_cnt-us_tcnt<SysTick->VAL);
	}
	else 								//需要计数到第二次转载值后
	{
		while(cycle_cnt>SysTick->VAL);
		while(cycle_cnt-us_tcnt<SysTick->VAL);
	}					
}

—SystemCoreClock———————————————
版权声明:本文为CSDN博主「极术社区」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_47569031/article/details/128954917

SysTick_Config函数的输入参数不能装进大于24位加载值(大于OxFFFFFF),

否则SysTick_Config函数返回1失败。

/* SysTick Reload Register Definitions */
#define SysTick_LOAD_RELOAD_Pos             0                                             /*!< SysTick LOAD: RELOAD Position */
#define SysTick_LOAD_RELOAD_Msk            (0xFFFFFFUL << SysTick_LOAD_RELOAD_Pos)        /*!< SysTick LOAD: RELOAD Mask */

6、函数测试

示波器测试IO口电平,100us反转一次


500ms反转一次

 
版权声明:本文为CSDN博主「极术社区」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_47569031/article/details/128954917

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值