3.关于延时函数的配置

接下来简单谈下如何配置延时函数(使用SysTick)
参考  http://blog.csdn.net/luodonghuan1/article/details/46573501

关于延时函数有以下几种方案
1.不依赖于硬件,实现软件延时
2.利用SysTick,实现硬件演示,依赖于时钟配置

/***********************************************************************************************/


1.使用这种延时函数的情况大多是对时序要求不严格的情况,大多都是为了让单片机打发一些时间而已,
  然后实现某种功能,比如,初学MCU,第二课,实现延时函数点灯。
  以下是一些相对较准的软件延时函数,从来只有相对准确,而没有绝对准确的东西
  //微秒延时函数,
  void delay_us(u16 time)
  {    
    u16 i=0;  
    while(time--)
    {
      i=10;  //自己定义
      while(i--) ;    
    }
  }

//毫秒延时函数
  void delay_ms(u16 time)
  {    
    u16 i=0;  
    while(time--)
    {
      i=12000;  //自己定义
      while(i--) ;    
    }
  }

/***********************************************************************************************/

2.此种情况大多应对时序比较严格的情况下,比如为了描述某个IC的时序,就必须要用到这种延时函数了,
  当然这并不是绝对的,有些情况下使用SysTick也可能不如软件延时准确,使用软件延时就比较好,一切看需求
  扯了这么多,接下来简单谈下怎么配置MS级的延时函数和US级的延时函数
  首先说一下 ST中文参考手册中对SysTick介绍的很简单,如果不仔细查找,基本你获取不到很多有关他的信息
  以下引用原话
  /*
  1.RCC 向 Cortex 系统定时器 (SysTick) 馈送 8 分频的 AHB 时钟 (HCLK)。 SysTick 可使用
    此时钟作为时钟源,也可使用 HCLK 作为时钟源,具体可在 SysTick 控制和状态寄存器中配置。
  2.SysTick 校准值设置为 18750。当 SysTick 时钟设置为 18.75 MHz(HCLK/8, HCLK 设为
    150 MHz),会产生 1 ms 时间基准。
  */

  好吧,第一句还有点用,看时钟树,意思就是说,SysTick时钟来源于HCLK,可以实现1分频或者8分频,
  可以在SysTic寄存器里面配置.这里再简单提一下系统时钟,
  有HSE (8M)|| HSI (16M)|| LSE (32.768K)|| LSI(32K)  (LSE && LSI 都可以用来做位RTC的时钟,但是LSI只能用来做看门狗时钟)
  然后可以选择使用哪种时钟源(HSE || HSI),一般来说都是选择使用HSE最稳定,然后使用PLL实现倍频,
  就是 PLL / M * N  / P / Q 配置这四个参数,之后就是配置AHB APB1 APB2,
  然后不管是接外设还是使用定时器,时钟都来源于这几个,HCLK是来源于SYSTICK的,AHB分频系数一般设置为1
  因此HCLK = SYSTICK

  其实吧,很多ST官方手册上面都没有介绍,比如SysTick的寄存器,NVIC的寄存器,还有一些其他的东西
  SysTick有四个寄存器

  __IOM uint32_t CTRL;                   /*!< Offset: 0x000 (R/W)  SysTick Control and Status Register */
  __IOM uint32_t LOAD;                   /*!< Offset: 0x004 (R/W)  SysTick Reload Value Register */
  __IOM uint32_t VAL;                    /*!< Offset: 0x008 (R/W)  SysTick Current Value Register */
  __IM  uint32_t CALIB;                  /*!< Offset: 0x00C (R/ )  SysTick Calibration Register */

  第一个是控制和状态寄存器 (16位,一般只用最低位0,使能)
  第二个是重装载寄存器     (24位)
  第三个是存储当前值寄存器 (24位)
  第四个是自校正寄存器(一般用不到)
  以上寄存器具体可以去查下,这里就不给出了
  然后就是配置的问题

  思路很简单
  1.给重装载寄存器装载需要计时的时间
  2.把VAL寄存器中的值清零
  3.CTRL使能计数
  4.等待直到计时完毕
  5.失能CTRL
  6.清零VAL,为下次计时做准备

  是吧,很简单吧,其实我更愿意称呼它为简单的定时器,
  然后就是翻译成寄存器了。但是还是要注意几个问题的,

  1.重装载需要的时间得根据当前HCLK的频率来设置
    其实这一步也不是很懂,看了不管是HAL库还是ATK的配置都是HCLK / 8 * num,num为要延时的时间,
    留一个参数入口,这样,LOAD就配置完成了,看下面这个例子,us级的延时函数,如果是ms的话
    只需要*1000就行了,但是需要注意寄存器是24位的,使用ms的话168M只能延时798.915ms
    然后可参照ATK的代码。
  2.最好8分频(如ST官方手册,可以HCLK 8分频 也可以不分频)

/*******************************************************************************************/

/**
* @brief  : Use SysTick to enable delay_us 
* @param  : MAX num : 2^24 * 8 / 168 = 798915 us
*
* @retval : none
*/
void 
delay_us(uint32_t num)
{

#if   CLK_168         //168MHZ     
  SysTick->LOAD = num * 168 / 8 ;     //Reload    
#elif CLK_160         //160MHZ
  SysTick->LOAD = num * 160 / 8 ;     //Reload 
#elif CLK_80          //80MHZ
  SysTick->LOAD = num * 80  / 8 ;     //Reload 
#elif CLK_72           //72MHZ
  SysTick->LOAD = num * 72  / 8 ;     //Reload 
#endif //<CLK_168> 

  SysTick->VAL = 0;                                            //CE  
  SysTick->CTRL |= 1<<0;                                       //Enable SysTick
  while(!(SysTick->CTRL & 1<<16));                             //Till 0
  SysTick->CTRL &= ~(1<<0);                                    //Disable SysTick
  SysTick->VAL = 0;                                            //CE
}


/**
* @brief  : From ATK
* @param  : MAX num : 65535 ms
*
* @retval : none
*/
void 
delay_ms(uint16_t nms)
{        
  uint16_t repeat=nms / 540;                        
  uint16_t remain=nms % 540;
  while(repeat)
  {
    delay(540);
    repeat--;
  }
  if(remain)
    delay(remain);
} 


//Hide
/**
* @brief  : Use SysTick to enable delay_ms
* @param  : MAX num = 2^24 * 8 / 168 / 1000 = 798.915 ms
*
* @retval : none
*/
static void 
delay(uint32_t num)
{

#if   CLK_168         //168MHZ     
  SysTick->LOAD = num * 168 * 1000 / 8 ;     //Reload    
#elif CLK_160         //160MHZ
  SysTick->LOAD = num * 160 * 1000 / 8 ;     //Reload 
#elif CLK_80          //80MHZ
  SysTick->LOAD = num * 80 *  1000 / 8 ;     //Reload 
#elif CLK_72           //72MHZ
  SysTick->LOAD = num * 72 *  1000 / 8 ;     //Reload 
#endif //<CLK_168> 

  SysTick->VAL = 0;                                            //CE  
  SysTick->CTRL |= 1<<0;                                       //Enable SysTick
  while(!(SysTick->CTRL & 1<<16));                             //Till 0
  SysTick->CTRL &= ~(1<<0);                                    //Disable SysTick
  SysTick->VAL = 0;                                            //CE
}



/***********************************************************************************************/      
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值