打印
[KungFu32位 MCU]

使用Systick做延时

[复制链接]
1705|6
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
wwppd|  楼主 | 2022-10-27 12:10 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
TI, ck, ic, sy


这个声明函数
void TimingDelay_Decrement(void);
void Systick_Delay(uint32_t delayTime);
void SysTick_Configuration(uint32_t Reload);
配置systick
void SysTick_Configuration(uint32_t Reload)
{
        /*before initializtion,disable systick timer*/
        SYSTICK_Cmd (FALSE);
        SYSTICK_Reload_Config(Reload);
        /*write ST_CV any valer,clear ST_CV*/
        SYSTICK_Counter_Updata();
        /*select SCLK as the clock source of the system tick timer */
        SYSTICK_Clock_Config(SYSTICK_SYS_CLOCK_DIV_1);
        /*enable system timer IRQ&interrupt flag*/
        SYSTICK_Systick_INT_Enable(TRUE);
        /*Configuration system timer Interrupt Priority*/
        INT_Interrupt_Priority_Config(INT_SysTick,2,0);
        /*enable systick timer*/
        SYSTICK_Cmd(TRUE);
        /*enable system timer Interrupt*/
    INT_Interrupt_Enable(INT_SysTick,TRUE);                               
        INT_All_Enable (TRUE);
}
void TimingDelay_Decrement(void)
{
        if (TimingDelay != 0x00)
        {
                TimingDelay--;
        }
}


/**
*  [url=home.php?mod=space&uid=247401]@brief[/url] :Inserts a delay time.
*  @param in :        delayTime: specifies the delay time length, in milliseconds.
*  @param out :None
*  @retval :None
*/
void Systick_Delay(uint32_t delayTime)
{
        TimingDelay = delayTime;
        while(TimingDelay != 0);
}


使用特权

评论回复
沙发
木木guainv| | 2022-11-8 09:49 | 只看该作者
CM3、CM4的内核中都有个24位的SysTick定时器。这两个MCU里边的SysTick大同小异

使用特权

评论回复
板凳
tpgf| | 2022-11-8 10:05 | 只看该作者
//使用中断定时

void SysTick_Init(void)
{
    if (SysTick_Config(SystemCoreClock / 100000)
    {
        while(1);
    }
}


/*
    时钟频率是72MHz,T = 1 / (72 * 1000000),
    SystemCoreClock / 100000 = 720.如果想每10us产生一个中断,则传入的参数是720。
        因为时钟频率是72M,所以T = 1/(72 * 1000000),所以在systick计数器每计数一次的时间是T,所以想要多少个T,直接在SysTick_Config(uint32_t ticks),中给参数ticks即可。假如想每1us中断一次,则ticks = 72,即SystemCoreClock / 1000000.**注意在老版本的系统时钟常数是SystemFrequency。而在以后的版本是SystemCoreClock。移植到ucosii的时候要注意。**
    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 SysTickzz Timer
        return (0);                                                  // Function successful
    }
        #define SysTick_LOAD_RELOAD_Msk            (0xFFFFFFul << SysTick_LOAD_RELOAD_Pos)        // SysTick LOAD: RELOAD Mask
        SysTick->LOAD  = (ticks & SysTick_LOAD_RELOAD_Msk) - 1;这句是systick配置函数的重装值的设置,结合上面可知SysTick_LOAD_RELOAD_Msk这个值和ticks
        是为了对RELOAD寄存器的配置。计数的值就是ticks。

        因为传入的ticks是720,即720计数。而时钟频率是72MHz,所以每次计数的结果是10us。
*/



//中断服务函数
void SysTick_handler(void)
{
    TimeDelay_Decrement();
}


//时钟每10us中断一次,进入中断函数,然后中断函数调用TimeDelay_Decrement()函数。
//其中TimeDelay是全局变量
void TimingDelay_Decrement(void)
{
    if (TimeDelay != 0x00)
    {
        TimeDelay--;
    }
}



//延时函数
void Delay_us(_IO u32 nTime)
{
    TimeDelay = nTime;

    while (TimeDelay != 0);
}


/************************************************************************************
*在主函数中首先调用SysTick_Init()。这个函数作用是配置时钟初始值,即多久中断一次。
*Enable SysTick IRQ and SysTick Timer,这是SysTick_Config函数中的注释。可以看出
*在这个函数最后使能中断和时间计时器。所以不需要我们单独配置CTRL寄存器的TICKINT为去使能中断了。
*TICKINT  类型 RW  复位值 0   描述:当该位是1的时候,SysTick倒数到0的时候产生SysTick异常请求
*,当该位是0 的时候,无动作。也可以通过读取COUNTFLAG标志位来确定计数器是否递减到0。
*
*这样的话,第一种采用中断延时的方式就搞定啦!
************************************************************************************/









/**********************************************************************************
另外一种更加简洁的编程

*systick的counter从reload值往下减的时候,CTRL寄存器位16:countflag会置1,且读取该位的值可清零。
*所以我们使用软件查询的方式实现延时。
*推荐使用方法。
*
************************************************************************************/

//systick微妙级延时

void SysTick_Delay_Us(_IO uint32_t us)
{
    uint32_t i;
    SysTick_Config(SystemCoreClock / 1000000)
    for (i = 0; i < us; ++i)
    {
        //当计数器的值减少到0的时候,CTRL寄存器的位16会置1
        while (!(SysTick ->CTRL) & (1 << 16));
    }
    //关闭SysTick定时器
    SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
}


//systick毫秒级延时
void SysTick_Delay_Ms(_IO uint32_t ms)
{
    uint32_t i;
    SysTick_Config(SystemCoreClock / 1000);
    for(i = 0; i < ms; i++)
    {
        //当计数器的值减少到0的时候,CTRL寄存器的位16会置1
        //当置1的时候,读取该位会清零
        while (!(SysTick->CTRL) & (1 << 16)));
    }
    //关闭SysTick定时器
    SysTick->CTRL &= ~SysTick_CTRL_CLKSOURCE_Msk;
}




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 */
}

使用特权

评论回复
地板
磨砂| | 2022-11-8 10:17 | 只看该作者
Sys-系统,Tick-滴答声,系统滴答滴答很形象地表示了它是一个系统节拍器。SysTick 是一个集成在Cortex内核里的24位的倒计数定时器,当计到0时,将从RELOAD 寄存器中自动重装载定时初值。只要不把它在SysTick 控制及状态寄存器中的使能位清除,就永不停息。

使用特权

评论回复
5
晓伍| | 2022-11-8 10:32 | 只看该作者
SysTick主要有以下几个作用:

1、产生操作系统的时钟节拍;

当RTOS以并行的架构处理任务,单一任务的崩溃并不会牵连到整个系统。这样用户出于可靠性的考虑可能就会基于RTOS来设计自己的应用程序。这样SYSTICK存在的意义就是提供必要的时钟节拍,为RTOS的任务调度提供一个有节奏的“心跳”。

2、便于不同处理器之间程序移植

因为所有的CM3芯片都带有这个定时器,软件在不同 CM3器件间的移植工作得以化简。

3、作为一个闹铃测量时间

可以用作闹钟,作为启动一个特定任务的时间依据。它作为一个闹铃,用于测量时间。要注意的是,当处理器在调试期间被喊停(halt)时,则SysTick定时器亦将暂停运作。

使用特权

评论回复
6
八层楼| | 2022-11-8 11:07 | 只看该作者
SysTick编程用到以下寄存器:

CTRL          SysTick 控制和状态寄存器

LOAD         SysTick 重装载值寄存器

VAL            SysTick 当前值寄存器

CALIB         SysTick 校准值寄存器

使用特权

评论回复
7
观海| | 2022-11-8 11:16 | 只看该作者
SysTick编程步骤。

① 为SysTick设置时钟源


② 为SysTick 装载计数值寄存器设置计数值;

③ 对SysTick当前计数值寄存器置0;

④ 通过对SysTick的CTRL寄存器的位0置位使能SysTick定时器。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

39

主题

2559

帖子

2

粉丝