Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1485077
  • 博文数量: 129
  • 博客积分: 1449
  • 博客等级: 上尉
  • 技术积分: 3048
  • 用 户 组: 普通用户
  • 注册时间: 2012-07-24 18:36
文章分类

全部博文(129)

文章存档

2015年(3)

2014年(20)

2013年(65)

2012年(41)

分类: C/C++

2013-03-13 16:15:19



  1. /* 外部调用:
  2.     delay_init(72);    //系统主频, 单位为MHZ, 仅对 SYSTICK_DELAY 有效
  3.     delay_ms(1000);
  4. */

  5. #include "stm32f10x.h"

  6. //#define SOFT_DELAY        //纯软件延时
  7. //#define SYSTICK_DELAY    //系统定时器延时
  8. #define TIMER_DELAY            //定时器延时

  9. #ifdef TIMER_DELAY

  10. #define TIMER_DELAY                                    TIM4
  11. #define TIMER_DELAY_PERIOD                    1000
  12. #define TIMER_DELAY_PRESCALER                72
  13. #define TIMER_DELAY_CLOCK                        RCC_APB1Periph_TIM4
  14. #define TIMER_DELAY_IRQ_HANDLER            TIM4_IRQHandler

  15. #define TIMER_DELAY_PREEMPTION_PRIORITY        2
  16. #define TIMER_DELAY_SUB_PRIORITY                    2
  17. #define TIMER_DELAY_IRQ_CHANNEL                        TIM4_IRQn

  18. static __IO u16    counter_delay_ms;
  19. #endif

  20. //-----------------------------------------------------------------
  21. #ifdef SOFT_DELAY

  22. void delay_init(u8 SYSCLK)
  23. {}

  24. #if 1
  25. void delay_us(u32 Number)
  26. {
  27.     u32 i=0;

  28.      while(Number--){
  29.       i=12; while(i--);
  30.      }
  31. }

  32. void delay_ms(u16 Number)
  33. {
  34.     u32 i;

  35.      while(Number--){
  36.       i=12000; while(i--);
  37.     }
  38. }

  39. #else
  40. unsigned char MULTIPLE8M = 9;
  41. void delay_us(u32 usNum)
  42. {
  43.   unsigned short kk, i;

  44.   for(i=usNum; i>0; i--)
  45.   {
  46.     kk = 2*MULTIPLE8M - 1; //0x080003AA 4C06 LDR r4,[pc,#24] ; @0x080003C4 2clk
  47.     do
  48.     { //0x080003AC BF00 NOP 1clk
  49.       kk--; //0x080003AE 1E64 SUBS r4,r4,#1 1clk
  50.     } while(kk); //0x080003B0 2C00 CMP r4,#0x00 1clk
  51.                     //0x080003B2 D1FC BNE 0x080003AE jump:2clk, no jump:1clk
  52.   }
  53. }

  54. void delay_ms(u16 usNum)
  55. {
  56.   unsigned short kk, i;

  57.   for(i=usNum; i>0; i--)
  58.   {
  59.     if (i % 100 == 0) {
  60.         //FEEDDOG;
  61.     }
  62.     kk = 2000*MULTIPLE8M - 1; //0x080003AA 4C06 LDR r4,[pc,#24] ; @0x080003C4 2clk
  63.     do
  64.     { //0x080003AC BF00 NOP 1clk
  65.       kk--; //0x080003AE 1E64 SUBS r4,r4,#1 1clk
  66.     } while(kk); //0x080003B0 2C00 CMP r4,#0x00 1clk
  67.                     //0x080003B2 D1FC BNE 0x080003AE jump:2clk, no jump:1clk
  68.   }
  69. }
  70. #endif
  71. #endif

  72. //---------------------------------------------------------------------------

  73. #ifdef SYSTICK_DELAY
  74. //参考原子的代码. 修正了中断中调用出现死循环的错误, 防止延时不准确,采用do
  75. static u8 fac_us = 0;    //us延时倍乘数
  76. static u16 fac_ms = 0;    //ms延时倍乘数

  77. //初始化延迟函数, SYSTICK的时钟固定为HCLK时钟的1/8, SYSCLK:系统时钟, 单位为MHZ
  78. void delay_init(u8 SYSCLK)
  79. {
  80.     SysTick->CTRL &= 0xfffffffb;    //bit2清空,选择外部时钟 HCLK/8
  81.     fac_us = SYSCLK/8;
  82.     fac_ms = (u16)fac_us*1000;
  83. }

  84. //延时nms, 注意nms的范围
  85. //SysTick->LOAD为24位寄存器,所以,最大延时为:nms<=0xffffff*8*1000/SYSCLK
  86. //SYSCLK单位为Hz,nms单位为ms, 对72M条件下,nms<=1864
  87. void delay_ms(u16 nms)
  88. {
  89.     u32 temp;

  90.     SysTick->LOAD = (u32)nms*fac_ms;//时间加载(SysTick->LOAD为24bit)
  91.     SysTick->VAL = 0x00; //清空计数器
  92.     SysTick->CTRL = 0x01 ; //开始倒数
  93.     do {
  94.         temp = SysTick->CTRL;
  95.     }while(temp&0x01 && !(temp&(1<<16)));//等待时间到达
  96.     SysTick->CTRL = 0x00; //关闭计数器
  97.     SysTick->VAL = 0X00; //清空计数器
  98. }

  99. //延时nus, nus为要延时的us数.
  100. void delay_us(u32 nus)
  101. {
  102.     u32 temp;

  103.     SysTick->LOAD = nus*fac_us; //时间加载
  104.     SysTick->VAL = 0x00; //清空计数器
  105.     SysTick->CTRL = 0x01 ; //开始倒数
  106.     do{
  107.         temp = SysTick->CTRL;
  108.     }while(temp&0x01 && !(temp&(1<<16)));//等待时间到达
  109.     SysTick->CTRL = 0x00; //关闭计数器
  110.     SysTick->VAL = 0X00; //清空计数器
  111. }
  112. #endif
  113. //-------------------------------------------------------------------

  114. #ifdef TIMER_DELAY

  115. void decrement_delay(void)
  116. {
  117.     if(counter_delay_ms != 0)
  118.     {
  119.         /* Decrement the counter */
  120.         counter_delay_ms--;
  121.     }
  122. }

  123. void delay_init(u8 SYSCLK)
  124. {
  125.     TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
  126.     NVIC_InitTypeDef NVIC_InitStructure;

  127.     RCC_APB1PeriphClockCmd(TIMER_DELAY_CLOCK, ENABLE);

  128.     TIM_TimeBaseStructure.TIM_Period                 = TIMER_DELAY_PERIOD;
  129.     TIM_TimeBaseStructure.TIM_Prescaler         = TIMER_DELAY_PRESCALER;
  130.     TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
  131.     TIM_TimeBaseStructure.TIM_CounterMode     = TIM_CounterMode_Up;
  132.     TIM_TimeBaseInit(TIMER_DELAY, &TIM_TimeBaseStructure);

  133.     TIM_UpdateRequestConfig(TIMER_DELAY, TIM_UpdateSource_Global);
  134.     TIM_ClearITPendingBit(TIMER_DELAY, TIM_IT_Update);

  135.     /* Enable TIMER Update interrupt */
  136.     TIM_ITConfig(TIMER_DELAY, TIM_IT_Update, ENABLE);

  137.     // Disable timers
  138.     TIM_Cmd(TIMER_DELAY, DISABLE);

  139.     /* Enable and set TIMER IRQ used for delays */
  140.     NVIC_InitStructure.NVIC_IRQChannel                                          = TIMER_DELAY_IRQ_CHANNEL;
  141.     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority     = TIMER_DELAY_PREEMPTION_PRIORITY;
  142.     NVIC_InitStructure.NVIC_IRQChannelSubPriority                  = TIMER_DELAY_SUB_PRIORITY;
  143.     NVIC_InitStructure.NVIC_IRQChannelCmd                                 = ENABLE;
  144.     NVIC_Init(&NVIC_InitStructure);
  145. }

  146. void delay_ms(uint16_t delay)
  147. {
  148.     counter_delay_ms = delay;

  149.     TIM_SetCounter(TIMER_DELAY, 0);
  150.     /* TIM4 enable counter */
  151.   TIM_Cmd(TIMER_DELAY, ENABLE);
  152.     /* Wait for 'delay' milliseconds */
  153.     while(counter_delay_ms != 0);
  154.     /* TIM4 disable counter */
  155.     TIM_Cmd(TIMER_DELAY, DISABLE);
  156. }

  157. void TIMER_DELAY_IRQ_HANDLER(void)
  158. {
  159.     /* Clear TIMER update interrupt flag */
  160.     TIM_ClearITPendingBit(TIMER_DELAY, TIM_IT_Update);

  161.     decrement_delay();
  162. }

  163. #endif

当然运行RTOS时, 一般系统定时器延时就不能用了. 

阅读(19491) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~