STM32系统滴答_及不可不知的延时技巧 - (下)

下面为你们介绍一个曾见过的在裸机系统中,非阻塞延时的巧妙设计,当时它是被用在一导航影音娱乐系统的MCU驱动软件中,在此我对其做了必定的改动。函数

此章节涉及到STM32内容很少,以软件为主。spa

此延时软件的设计能够直接进行1050100ms1s的查询定时,而且当若需其它时间要求的定时或延时能够很方便的本身编写软件很简单方便设定。设计

 

首先须要设置SysTick 定时中断为10MS进入一次。而后在定时中断函数中做以下处理 code

 

void SysTick_Handler(void)
{
        
        bTemp10Msec = TIMER_SET;
       
        ++gTimer.Tick10Msec;
        if (0 == (gTimer.Tick10Msec % 5))
        {
            bTemp50Msec = TIMER_SET;
        }
       
        if (0 == (gTimer.Tick10Msec % 10))
        {
            bTemp100Msec = TIMER_SET;
        }
       
        if (100 == gTimer.Tick10Msec)
        {
            gTimer.Tick10Msec = 0;
            bTemp1Sec = TIMER_SET;
        }
}

 

gTimer是定义的一全局结构体变量,Timer_Struct  gTimer;it


此软件设计巧妙之处首先在结构体的设计上:io

typedef struct
{
    u8 Tick10Msec;
    Char_Field Status;
} Timer_Struct;

 

其中Char_Field 为一联合体,设计以下:class

typedef union
{
    unsigned char byte;
    Timer_Bit     field;
} Char_Field;

 

而它内部的Timer_Bit是一个可按位访问的结构体变量

typedef struct
{
    unsigned char bit0: 1;
    unsigned char bit1: 1;
    unsigned char bit2: 1;
    unsigned char bit3: 1;
    unsigned char bit4: 1;
    unsigned char bit5: 1;
    unsigned char bit6: 1;
    unsigned char bit7: 1;
} Timer_Bit;

此联合体的这样设计的目的将在后面的代码中体现出来;软件

 

定时中断里的bTempXXX及后面定时或延时查询用的bSystemXXX 是宏定义,以下:循环

#define bSystem10Msec          gTimer.Status.field.bit0
#define bSystem50Msec          gTimer.Status.field.bit1
#define bSystem100Msec         gTimer.Status.field.bit2
#define bSystem1Sec            gTimer.Status.field.bit3
#define bTemp10Msec            gTimer.Status.field.bit4
#define bTemp50Msec            gTimer.Status.field.bit5
#define bTemp100Msec           gTimer.Status.field.bit6
#define bTemp1Sec              gTimer.Status.field.bit7

 

定时中断里的TIMER_SET 为真(1)可用宏定义,也可以下定义:

typedef enum
{
    TIMER_RESET = 0,
    TIMER_SET = 1,
} TimerStatus;

以上即是非阻塞延时软件的总体结构设计。

 

另外还须要在系统运行大的循环中调用设计的控制函数,

void SysTimer _Process(void)
{
    gTimer.Status.byte &= 0xF0;
   
    if (bTemp10Msec)
    {
        bSystem10Msec = TIMER_SET;
    }
   
    if (bTemp50Msec)
    {
        bSystem50Msec = TIMER_SET;
    }
   
    if (bTemp100Msec)
    {
        bSystem100Msec = TIMER_SET;
    }
   
    if (bTemp1Sec)
    {
        bSystem1Sec = TIMER_SET;
    }
   
    gTimer.Status.byte &= 0x0F;
}

此函数开头与结尾两句

gTimer.Status.byte &= 0xF0;
gTimer.Status.byte &= 0x0F;

就巧妙的实现了bSystemXXX  bTempXXX的消除工做,不用再定时到来后手动把计数值消除。此处便用到了联合体中的变量共用一个起始存储空间的特性。

 

下面一个简单的应用举例,好比咱们想让一LED灯每100MS亮或灭一次,就能够这样设计:

 
int main(void)
{
    while(1)
    {
         SysTimer _Process();
         if(TIMER_SET == bSystem100Msec)
         {
             LED = !LED;
         }
    }
}



附此软件的总体代码

#define bSystem10Msec          gTimer.Status.field.bit0
#define bSystem50Msec          gTimer.Status.field.bit1
#define bSystem100Msec         gTimer.Status.field.bit2
#define bSystem1Sec            gTimer.Status.field.bit3
#define bTemp10Msec            gTimer.Status.field.bit4
#define bTemp50Msec            gTimer.Status.field.bit5
#define bTemp100Msec           gTimer.Status.field.bit6
#define bTemp1Sec              gTimer.Status.field.bit7

typedef enum
{
    TIMER_RESET = 0,
    TIMER_SET = 1,
} TimerStatus;


typedef struct
{
    unsigned char bit0: 1;
    unsigned char bit1: 1;
    unsigned char bit2: 1;
    unsigned char bit3: 1;
    unsigned char bit4: 1;
    unsigned char bit5: 1;
    unsigned char bit6: 1;
    unsigned char bit7: 1;
} Timer_Bit;


typedef union
{
    unsigned char byte;
    Timer_Bit     field;
} Char_Field;

typedef struct
{
    u8 Tick10Msec;
    Char_Field Status;
} Timer_Struct;

//定义一全局变量
Timer_Struct gTimer;

void SysTick_Handler(void)
{
    bTemp10Msec = TIMER_SET;

    ++gTimer.Tick10Msec;
    if (0 == (gTimer.Tick10Msec % 5))
    {
        bTemp50Msec = TIMER_SET;
    }
    if (0 == (gTimer.Tick10Msec % 10))
    {
        bTemp100Msec = TIMER_SET;
    }
    if (100 == gTimer.Tick10Msec)
    {
        gTimer.Tick10Msec = 0;
        bTemp1Sec = TIMER_SET;
    }
}


void SysTimer _Process(void)
{
    gTimer.Status.byte &= 0xF0;
    
    if (bTemp10Msec)
    {
        bSystem10Msec = TIMER_SET;
    }
    
    if (bTemp50Msec)
    {
        bSystem50Msec = TIMER_SET;
    }
    
    if (bTemp100Msec)
    {
        bSystem100Msec = TIMER_SET;
    }
    
    if (bTemp1Sec)
    {
        bSystem1Sec = TIMER_SET;
    }
    
    gTimer.Status.byte &= 0x0F;
}

 

 

相关文章
相关标签/搜索