delay.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. #include "delay.h"
  2. #include "sys.h"
  3. //////////////////////////////////////////////////////////////////////////////////
  4. //如果需要使用OS,则包括下面的头文件即可.
  5. #if SYSTEM_SUPPORT_OS
  6. #include "FreeRTOS.h" //FreeRTOS使用
  7. #include "task.h"
  8. #endif
  9. static u8 fac_us=0; //us延时倍乘数
  10. static u16 fac_ms=0; //ms延时倍乘数,在ucos下,代表每个节拍的ms数
  11. extern void xPortSysTickHandler(void);
  12. //systick中断服务函数,使用ucos时用到
  13. //void SysTick_Handler(void)
  14. //{
  15. // if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED)//系统已经运行
  16. //{
  17. // xPortSysTickHandler();
  18. //}
  19. //}
  20. /*static inline void delay_cycles(uint32_t cycles) {
  21. while (cycles-- > 0) {
  22. __NOP(); // NOP指令通常需要1个CPU周期来执行
  23. }
  24. }
  25. void delay_us(uint32_t us) {
  26. uint32_t cycles_per_us = SystemCoreClock / 1000000; // 假设SystemCoreClock已正确配置为CPU时钟频率
  27. delay_cycles(us * cycles_per_us);
  28. }
  29. void delay_ms(uint32_t us) {
  30. for(int i=0;i<us;i++)
  31. delay_us(1000);
  32. }
  33. */
  34. void delay_init(void)
  35. {
  36. systick_clksource_set(SYSTICK_CLKSOURCE_HCLK_DIV8); //选择外部时钟 HCLK/8
  37. fac_us = SystemCoreClock / 8000000; //时钟频率/8得到每微秒需要的时钟数
  38. fac_ms = (u16)fac_us * 1000; //得到每毫秒需要的时钟数
  39. }
  40. void delay_us(u32 nus)
  41. {
  42. u32 temp;
  43. SysTick->LOAD = nus * fac_us; //时间加载
  44. SysTick->VAL = 0x00; //清空计数器
  45. SysTick->CTRL = SysTick_CTRL_ENABLE_Msk ;//开始倒数
  46. do
  47. {
  48. temp = SysTick->CTRL;
  49. }
  50. while(temp & 0x01 && !(temp & (1<<16))); //等待时间到达
  51. SysTick->CTRL &= ~ SysTick_CTRL_ENABLE_Msk; //关闭计数器
  52. SysTick->VAL = 0X00; //清空计数器
  53. }
  54. void delay_ms(u32 nms)
  55. {
  56. u32 temp;
  57. SysTick->LOAD = (u32)nms * fac_ms; //时间加载(SysTick->LOAD为24bit)
  58. SysTick->VAL = 0x00; //清空计数器
  59. SysTick->CTRL = SysTick_CTRL_ENABLE_Msk ;//开始倒数
  60. do
  61. {
  62. temp = SysTick->CTRL;
  63. }
  64. while(temp & 0x01 && !(temp & (1<<16))); //等待时间到达
  65. SysTick->CTRL &= ~ SysTick_CTRL_ENABLE_Msk; //关闭计数器
  66. SysTick->VAL = 0X00; //清空计数器
  67. }
  68. //初始化延迟函数
  69. //SYSTICK的时钟固定为AHB时钟,基础例程里面SYSTICK时钟频率为AHB/8
  70. //这里为了兼容FreeRTOS,所以将SYSTICK的时钟频率改为AHB的频率!
  71. //SYSCLK:系统时钟频率
  72. /*void delay_init()
  73. {
  74. systick_clksource_set(SYSTICK_CLKSOURCE_HCLK_DIV8); //选择外部时钟,HCLK/8
  75. fac_us=SystemCoreClock /8; //为系统时钟的1/8
  76. fac_ms=(uint16_t)fac_us*1000; //代表每个ms需要的systick时钟数
  77. u32 reload;
  78. SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK);//选择外部时钟 HCLK
  79. fac_us=SystemCoreClock/1000000; //不论是否使用OS,fac_us都需要使用
  80. reload=SystemCoreClock/1000000; //每秒钟的计数次数 单位为M
  81. reload*=1000000/configTICK_RATE_HZ; //根据configTICK_RATE_HZ设定溢出时间
  82. //reload为24位寄存器,最大值:16777216,在72M下,约合0.233s左右
  83. fac_ms=1000/configTICK_RATE_HZ; //代表OS可以延时的最少单位
  84. SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk; //开启SYSTICK中断
  85. SysTick->LOAD=reload; //每1/configTICK_RATE_HZ秒中断一次
  86. SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk; //开启SYSTICK
  87. }
  88. //延时nus
  89. //nus:要延时的us数.
  90. //nus:0~204522252(最大值即2^32/fac_us@fac_us=168)
  91. void delay_us(u32 nus)
  92. {
  93. u32 ticks;
  94. u32 told,tnow,tcnt=0;
  95. u32 reload=SysTick->LOAD; //LOAD的值
  96. ticks=nus*fac_us; //需要的节拍数
  97. told=SysTick->VAL; //刚进入时的计数器值
  98. while(1)
  99. {
  100. tnow=SysTick->VAL;
  101. if(tnow!=told)
  102. {
  103. if(tnow<told)tcnt+=told-tnow; //这里注意一下SYSTICK是一个递减的计数器就可以了.
  104. else tcnt+=reload-tnow+told;
  105. told=tnow;
  106. if(tcnt>=ticks)break; //时间超过/等于要延迟的时间,则退出.
  107. }
  108. };
  109. }
  110. //延时nms
  111. //nms:要延时的ms数
  112. //nms:0~65535
  113. void delay_ms(u32 nms)
  114. {
  115. if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED)//系统已经运行
  116. {
  117. if(nms>=fac_ms) //延时的时间大于OS的最少时间周期
  118. {
  119. vTaskDelay(nms/fac_ms); //FreeRTOS延时
  120. }
  121. nms%=fac_ms; //OS已经无法提供这么小的延时了,采用普通方式延时
  122. }
  123. delay_us((u32)(nms*1000)); //普通方式延时
  124. }*/
  125. //延时nms,不会引起任务调度
  126. //nms:要延时的ms数
  127. void delay_xms(u32 nms)
  128. {
  129. u32 i;
  130. for(i=0;i<nms;i++) delay_us(1000);
  131. }