中科因仑“3+1”工程特种兵精英论坛

标题: 分享:STM32下的非阻塞延时模块,可以在状态机下使用 [打印本页]

作者: 谭力源    时间: 2016-6-14 18:45
标题: 分享:STM32下的非阻塞延时模块,可以在状态机下使用
     在参考各个开发板的例程的基础上,经过自身编程实践重新构建和修改,编写了以下方便在状态机模块里使用的延时计数模块。延时计数的基础是SYSTICK,设置为1ms.具体代码如下:
softtimer.h:
  • /*
  • *********************************************************************************************************
  • *
  • *                                                SOFTTIMER
  • *
  • *                                     ST Microelectronics STM32
  • *                                              on the
  • *
  • *                                         STM32Fx-DISCOVERY
  • *                                         Evaluation Board
  • *
  • * 文件名      : softtimer.h
  • * 版 本       : V0.1
  • * 作 者       : Lux
  • * 时 间       : 2014/11/27
  • * 编译环境    : D:\Program Files (x86)\IAR Systems\Embedded Workbench 7.0
  • * 摘    要    : SOFTTIMER Drive,软件方式实现的非阻塞方式的超时计时模块
  • *********************************************************************************************************/
  • #ifndef  __SOFT_TIMER_H
  • #define  __SOFT_TIMER_H
  • #ifdef __cplusplus
  • extern "C" {
  • #endif
  •   //-----------------------Include files--------------------------------//
  •   #include <stdbool.h>
  •   #include <stdint.h>
  •   //------------------------Data struct---------------------------------//
  •   typedef enum
  •   {
  •     ONCE_MODE = 0x00,
  •     CIRC_MODE = 0x01
  •   }TIMER_MODE_t;
  •   typedef struct SOFT_TIMER
  •   {
  •     TIMER_MODE_t          mode;
  •     bool                  isActivate;
  •     volatile uint32_t     value;
  •     uint32_t              totvalue;
  •     struct SOFT_TIMER*    next;
  •   }SOFT_TIMER_t;
  •   //------------------------Extern function-----------------------------//
  •   void soft_timer_register(SOFT_TIMER_t *st);
  •   void set_and_star_soft_timer(SOFT_TIMER_t *st, TIMER_MODE_t mode, uint32_t totvalue);
  •   bool is_soft_timer_Out(SOFT_TIMER_t *st);
  •   void soft_timer_release(SOFT_TIMER_t *st);
  • #ifdef __cplusplus
  • }
  • #endif
  • #endif  /*__SOFTTIMER_H*/

[color=rgb(51, 102, 153) !important]复制代码





softtimer.c:
  • #include "softtimer.h"
  • #include <stdlib.h>
  • #include "stm32f10x.h"
  • /* 使能中断 */
  • #define ENABLE_SYSTICK_INT()        __set_PRIMASK(0)
  • #define DISABLE_SYSTICK_INT()        __set_PRIMASK(1)
  • /* 禁止中断 */
  • static struct SOFT_TIMER *head = NULL;
  • /* SoftTimer_ISR中断服务程序,每隔1ms进入1次 ****************************************/
  • void SoftTimer_ISR(void)
  • {
  •   struct SOFT_TIMER *t = head;
  •   if (t == NULL)
  •     return;
  •   while(t != NULL)
  •   {
  •     if (t->isActivate == true)
  •       t->value++;
  •     t = t->next;
  •   }
  • }
  • // 注册软件计时器
  • void soft_timer_register(SOFT_TIMER_t *st)
  • {
  •   struct SOFT_TIMER *t = head;
  •   st->isActivate = false;
  •   st->mode       = ONCE_MODE;
  •   st->value      = 0;
  •   st->totvalue   = 0;
  •   st->next       = NULL;
  •   if (head == NULL)
  •   {
  •     head = st;
  •     return;
  •   }
  •   while(t->next != NULL )
  •   {
  •     if (t == st) return; //此语句排除重复注册的现象
  •     t = t->next;
  •   }
  •   DISABLE_SYSTICK_INT();
  •   t->next = st;
  •   ENABLE_SYSTICK_INT();
  • }
  • // 设置并开始软件计时器,计时单位为ms
  • void set_and_star_soft_timer(SOFT_TIMER_t *st, TIMER_MODE_t mode, uint32_t totvalue)
  • {
  •   st->mode = mode;
  •   st->totvalue = totvalue;
  •   DISABLE_SYSTICK_INT();
  •   st->value = 0;
  •   st->isActivate = true;
  •   ENABLE_SYSTICK_INT();
  • }
  • // 查询软件计时器是否超时
  • bool is_soft_timer_Out(SOFT_TIMER_t *st)
  • {
  •   bool res = false;
  •   if (st->value >= st->totvalue)
  •   {
  •     res = true;
  •     DISABLE_SYSTICK_INT();
  •     if (st->mode == CIRC_MODE)
  •     {
  •       st->value = 0;
  •       st->isActivate = true;
  •     }else
  •       st->isActivate = false;
  •     ENABLE_SYSTICK_INT();
  •   }
  •   return res;
  • }
  • // 注销软件计时器
  • void soft_timer_release(SOFT_TIMER_t *st)
  • {
  •   struct SOFT_TIMER *p = head,*t = head;
  •   if (head == st)
  •   {
  •     head = st->next;
  •     return;
  •   }
  •   while(t->next != NULL )
  •   {
  •     if (t == st)      //从节点删除st
  •     {
  •       DISABLE_SYSTICK_INT();
  •       p->next = st->next;
  •       ENABLE_SYSTICK_INT();
  •       st->next = NULL;
  •       return;
  •     }
  •     else
  •     {
  •       p = t;
  •       t = t->next;
  •     }
  •   }
  • }

[color=rgb(51, 102, 153) !important]复制代码




使用方法如下:
  • // LED模块的状态机
  • void led_module()
  • {
  •   static uint8_t state = 0;
  •   static SOFT_TIMER_t led_st;
  •   switch(state)
  •   {
  •   case 0:// 初始状态
  •     led1.init();
  •     led1.on();
  •     soft_timer_register(&led_st);
  •     set_and_star_soft_timer(&led_st, CIRC_MODE, 500);
  •     state = 1;
  •     //break;
  •   case 1:// led跳变状态
  •     led1.tigger();
  •     state = 2;
  •     break;
  •   case 2:// 延时等待状态
  •     if (is_soft_timer_Out(&led_st) == true)
  •       state = 1;
  •     break;
  •   }
  • }

[color=rgb(51, 102, 153) !important]复制代码

[color=rgb(51, 102, 153) !important]







欢迎光临 中科因仑“3+1”工程特种兵精英论坛 (http://bbs.enlern.com/) Powered by Discuz! X3.4