系统做延时的方法

不管是单片机还是实时操作系统,在应用中都会有写延时的需求,比如:点亮一个LED,然后以1S频率亮灭;不可能亮了之后delay1S,然后灭,delay1S;那这样系统就浪费了CPU资源;
可以做个系统的滴答时钟,使用定时器做个1ms的滴答,举例stm32上面就有专门的滴答定时器,叫systick;
这个滴答的周期越短,对CPU的开销就越大,这个时间根据系统的负荷调整,比如:电力系统要求遥信的分辨率为2ms,为了满足要求,滴答的周期只能设置为1ms的周期。
初始化操作之后,会1ms进入systick中断一次,但是中断里处理操作不可太多,中断会一直占用CPU的资源,直到执行完中断内容后才会释放CPU,去执行用户应用;还有一点就是中断里面执行的操作时间一定要小于中断周期时间,否则CPU会一直在中断里面运行,无法跳出来了。
中心思想就是获取当前的时间,然后通过后续更新的时间减去时标的差值,作为延时的时长;

1、初始化systick定时器

 1/***************************************************************************************

 2* 函数名称: SysTick_Init

 3* 功能描述: RCC模块配置,为系统其它模块提供一个时基源

 4* 输入参数: Systick_1us = SysTick周期 单位us

 5* 输出参数: 无

 6* 返 回 值: OK=成功 ERR=失败

 7* 作    者: 

 8* 日    期: 

 9* 修改记录:

10* 修改人  : 

11* 修改日期: 

12* 修改内容:

13***************************************************************************************/

14ERR_TYPE SysTick_Init(u32 Systick_1us)

15{

16    u32 systick = 0;

17    RCC_ClocksTypeDef RCC_Clocks;

18

19/* 输入参数有效判断 */

20if(Systick_1us == 0)

21    {

22return ERR;

23    }

24

25/* 计算配置时间对应的计数次数 */

26    RCC_GetClocksFreq(&RCC_Clocks);

27    systick = RCC_Clocks.SYSCLK_Frequency / 1000000;    //单位转为us

28    systick = systick * Systick_1us;

29

30/*SysTick周期配置 */

31if(SysTick_Config(systick))  

32    {

33while(1);

34    }

35

36/* SysTick中断优先级设置 */

37    NVIC_SetPriority(SysTick_IRQn, 0x0);

38

39/* SysTick中断设置 */

40    SysTick->CTRL |= 0x00000002;                //SysTick_ITConfig(ENABLE);   

41

42/* 使能计数器 */

43    SysTick->CTRL |= SysTick_Counter_Enable;

44

45return OK;

46}
2、重定向中断处理函数

 1/***************************************************************************************

 2* 函数名称: SysTick_Handler

 3* 功能描述: SysTick中断函数

 4* 输入参数: 无

 5* 输出参数: 无

 6* 返 回 值: 无

 7* 作    者: 

 8* 日    期: 

 9* 修改记录:

10* 修改人  : 

11* 修改日期: 

12* 修改内容:

13***************************************************************************************/

14void SysTick_Handler(void)

15{

16   gSystickT++;                            //系统心跳ticker计数  

17}

3、延时回绕函数

 1/***************************************************************************************

 2* 函数名称: Get_SysTick

 3* 功能描述: 获取SysTick计数器

 4* 输入参数: 无

 5* 输出参数: 无

 6* 返 回 值: 时间

 7* 作    者: 

 8* 日    期: 

 9* 修改记录:

10* 修改人  : 

11* 修改日期: 

12* 修改内容:

13***************************************************************************************/

14u32 Get_SysTick(void)

15{

16return gSystickT;                  

17}
18/***************************************************************************************

19* 函数名称: BSP_TickerOut

20* 功能描述: 时基 1mS 延时周期判定

21* 输入参数: *pTicker 模块定时器  cnt=0 赋初值  cnt!=0 比较延时周期

22* 输出参数: 无

23* 返 回 值: eFalse,eTrue

24* 作    者:

25* 日    期: 

26* 修改记录:

27* 修改人  : 

28* 修改日期:

29* 修改内容:

30****************************************************************************************/

31E_Bool BSP_TickerOut(u32 *pTicker, u32 cnt)

32{

33    u32 ticks = 0;

34

35/* 输入参数有效判断 */

36if(pTicker == (void *)0)

37    {

38return(eFalse);

39    }

40

41    ticks = Get_SysTick();

42

43if(cnt == 0)

44    {

45        *pTicker = ticks;                   // 开始计时

46    }

47else

48    {

49if(ticks >= *pTicker)

50        {

51            ticks = ticks - *pTicker;

52        }

53else

54        {

55            ticks = (0XFFFFFFFF - *pTicker) + ticks;

56        }

57

58if(ticks >= cnt)                 //计时判断

59        {

60return(eTrue);

61        }

62    }

63

64return eFalse;

65}

4、示例

 1//LED 1S频率亮灭操作

 2void LED_Test(void)

 3{

 4		static u32 LedDelay = 0;

 5

 6/* 判断1S是否到 */

 7if(!TickerOut(&LedDelay, 1000))

 8    {

 9return;

10    }   

11/* 更新LedDelay时间 */

12    TickerOut(&LedDelay, 0);

13

14/* LED进行翻转 */

15    GPIO_ToggleBits(RUN_LED_GPIO_PORT, RUN_LED_PIN);

16}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值