[STM32F0] STM32F072 systick 相关疑问

[复制链接]
2066|8
 楼主| huaiqiao 发表于 2016-11-22 12:17 | 显示全部楼层 |阅读模式
最近用到STM32F072 discovery的板子,我在建立工程的时候,想调用delay函数,所以就想到了systick。

我看了下网上说这个systick可以参考正点原子的delay.c写。那么问题来了。

正点原子在F4探索者的delay.c中这个地方。

  1. //延时nms
  2. //nms:0~65535
  3. void delay_ms(u16 nms)
  4. {                  
  5.         u8 repeat=nms/540;        //这里用540,是考虑到某些客户可能超频使用,
  6.                                                 //比如超频到248M的时候,delay_xms最大只能延时541ms左右了
  7.         u16 remain=nms%540;
  8.         while(repeat)
  9.         {
  10.                 delay_xms(540);
  11.                 repeat--;
  12.         }
  13.         if(remain)delay_xms(remain);
  14.         
  15. }
那么我想问下,对于F0的话,这个地方该怎么写啊? 难道F0也要超频??

正点原子的delay.c如附件所示。

delay.rar (2.13 KB, 下载次数: 1)



mmuuss586 发表于 2016-11-22 15:02 | 显示全部楼层
不用超频啊;
改下系数就好了呀;

如果你延时时间特别短,最多延时时间无法满足要求;
 楼主| huaiqiao 发表于 2016-11-22 16:33 | 显示全部楼层
mmuuss586 发表于 2016-11-22 15:02
不用超频啊;
改下系数就好了呀;

我不知道您有看如下这个地方么?

  1. //延时nms
  2. //注意nms的范围
  3. //SysTick->LOAD为24位寄存器,所以,最大延时为:
  4. //nms<=0xffffff*8*1000/SYSCLK
  5. //SYSCLK单位为Hz,nms单位为ms
  6. //对168M条件下,nms<=798ms
  7. void delay_xms(u16 nms)
  8. {                                     
  9.         u32 temp;                  
  10.         SysTick->LOAD=(u32)nms*fac_ms;//时间加载(SysTick->LOAD为24bit)
  11.         SysTick->VAL =0x00;           //清空计数器
  12.         SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ;          //开始倒数  
  13.         do
  14.         {
  15.                 temp=SysTick->CTRL;
  16.         }
  17.         while((temp&0x01)&&!(temp&(1<<16)));//等待时间到达   
  18.         SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk;       //关闭计数器
  19.         SysTick->VAL =0X00;       //清空计数器                      
  20. }
  21. //延时nms
  22. //nms:0~65535
  23. void delay_ms(u16 nms)
  24. {                  
  25.         u8 repeat=nms/540;        //这里用540,是考虑到某些客户可能超频使用,
  26.                                                 //比如超频到248M的时候,delay_xms最大只能延时541ms左右了
  27.         u16 remain=nms%540;
  28.         while(repeat)
  29.         {
  30.                 delay_xms(540);
  31.                 repeat--;
  32.         }
  33.         if(remain)delay_xms(remain);
  34.        
  35. }
如果不写这个delay_ms的这个函数的话,那么紧紧靠void delay_xms(u16 nms)这个函数的话,按照nms<=0xffffff*8*1000/SYSCLK这个注解中的这个公式计算的话,对48M条件下,nms<=0xffffff*8*1000/SYSCLK=2796ms啊。也就是2s。如果是这样的话,后面的这个函数delay_ms(u16 nms)是不是就不要了呢?
flydream0 发表于 2016-11-22 17:34 | 显示全部楼层
如果是毫秒级别,并且只是想利用systick来达到延时效果的话,可以参考这个思路:

1>定义一个全局变量,假如uint32_t DelayCount =0;
2> 在systick中断中 if(DelayCount >0) DelayCount-- ;
3>再写个延时函数
void HAL_Delay(uint32_t time)
{
   DelayCount =time;
   while(DelayCount);
}

以上仅供参考。
 楼主| huaiqiao 发表于 2016-11-22 18:32 | 显示全部楼层
本帖最后由 huaiqiao 于 2016-11-22 18:37 编辑
flydream0 发表于 2016-11-22 17:34
如果是毫秒级别,并且只是想利用systick来达到延时效果的话,可以参考这个思路:

1>定义一个全局变量,假 ...

首先,感谢回帖哈。
其实,您的这种方式,我在青风的一个帖子中也看到过。
  1. 首先建立一个延迟函数,nTime作为定时数。SysTick配置通过设置为1ms,为SystemCoreClock / 1000:
  2.         void Delay_ms(__IO uint32_t nTime)//延迟函数,设置为MS
  3.         {
  4.           TimingDelay = nTime;//时钟滴答数
  5.         
  6.           while(TimingDelay != 0);
  7.         }
  8.          
  9.         
  10.         void Systick_Init(void)
  11.         {
  12.           if (SysTick_Config(SystemCoreClock / 1000))//设置为1毫秒
  13.           {
  14.             /* Capture error */
  15.             while (1);
  16.           }
  17.         }
  1. 并且通过TimingDelay_Decrement调动中断,代码如下:
  2.         void TimingDelay_Decrement(void)
  3.         {
  4.           if (TimingDelay != 0x00)
  5.           {
  6.             TimingDelay--;
  7.           }
  8.         }
  9.    在stm32f0xx_it.c 中定义 SysTick_Handler中断函数,函数调用TimingDelay_Decrement:
  10.         void SysTick_Handler(void)
  11.         {
  12.                      TimingDelay_Decrement();//调动中断函数
  13.         }

他这里跟您的思路是一样的。

但是他这个写得是毫秒级的延时,那么我如果按照这样的方式来的话。怎么实现毫秒,微秒的延时,是不是就有点混乱了呢?


flydream0 发表于 2016-11-23 11:18 | 显示全部楼层
huaiqiao 发表于 2016-11-22 18:32
首先,感谢回帖哈。
其实,您的这种方式,我在青风的一个帖子中也看到过。

如果是毫秒级,使用systick这种方式就可以实现,如果是微妙级,我暂时可以想到:
1 将systick换成timer外设,还是类似方法,尽量提高timer外设所在APB总线时钟频率,配合调整timer外设的预分频系数等等,目的只有一个,就是使timer的中断间隔变成微秒级,这样就可以一样的方法,估计CPU负载也会很大,需要实测验证。
2 使用定时器外设精确为你延时这段微妙级时间。
3 使用代码延时,利用精确计算时钟周期来实现,就是几个for循环,但这个精度无法保证,受其他外设,环境等影响。

。。。
wahahaheihei 发表于 2016-11-23 13:00 | 显示全部楼层
不如直接参考BSP里的程序例子。
 楼主| huaiqiao 发表于 2016-11-23 21:26 | 显示全部楼层
flydream0 发表于 2016-11-23 11:18
如果是毫秒级,使用systick这种方式就可以实现,如果是微妙级,我暂时可以想到:
1 将systick换成timer外 ...

我今天用st的f0的时钟配置工具,仿照原子的形式写了个delay.c

然后把外接的8M晶振也焊接上去了。

延时了1s来点灯,看起来是可以的。

但是这个我要用示波器再看看波形。
 楼主| huaiqiao 发表于 2016-11-23 21:27 | 显示全部楼层
wahahaheihei 发表于 2016-11-23 13:00
不如直接参考BSP里的程序例子。

BSP里面的例子中有么?

我大概看了下,好像没有。。。。。就没有认真再去看
您需要登录后才可以回帖 登录 | 注册

本版积分规则

10

主题

600

帖子

2

粉丝
快速回复 在线客服 返回列表 返回顶部