유용한 시간관련 클래스[MFC/C++]

2021. 1. 10. 14:30장비제어개발관한이야기

반응형

오늘 포스팅할 내용은 타이머관련한 내용입니다.

 

장비제어를 하다 보면 실제로 시간개념이 많이 들어갑니다.

 - 500ms 동안 실린더를 작동하고 다시 실린더 동작을 원래 대로 돌아가라.

 - 3000ms 동안 카메라에서 응답이 없다면 알람을 발생하여라.

 - 200ms 후에 모터구동을 시작하여라

 

꼭 장비제어 뿐만 아니라 알고리즘의 걸리는 시간이 측정 쓰레드의 생성시간 등등 안쓰는데가 많습니다. 

 

간단히는 Sleep(500); 등의 구문으로 대기하는 경우가 많죠. 하지만 장비제어서는 정확한 시간관리가 필요하기 때문에 MFC 개발을 하게 되면 QueryPerformanceFrequency() 이용하여 시간을 파악하여 동작을 시킵니다.

 

다른 분야의 분들도 많이 쓰는 API라 생각됩니다.

 

매번 WINAPI를 호출해서 사용하는것은 소스도 더럽고 그럴리는 없지만 QueryPerformanceFrequency를 대체해야 된다고 했을경우 랩핑클래스로 구현하는것이  유리하다고 생각해서 하나 작성하였습니다. 주로 많이 쓰는 Case 위주로 랩핑클래스를 구성 해보았습니다.

 

 

밑에 소스는 그 랩핑한 클래스 입니다. 윈도우 환경에서는 큰 수정없이 바로 쓸수 있어 파일첨부합니다.

QueryPerformanceFrequency API 하나만을 응용해서 만든 랩핑 클래스로 ms us 100ms 단위로 체크 할수 있는 기능이 특별하다고 하면, 특별한 기능이겠습니다.

 

한번 보시면 알수 있습니다. 소스코드입니다.

* 헤더파일

// Timer.h: interface for the CTimer class.
//
//////////////////////////////////////////////////////////////////////
#pragma once


class CTimer  
{
public:
    CTimer();
    virtual ~CTimer();
    
private:
    int m_QueryInitialized;      
    __int64 m_Frequency;
    double m_100msFrequency;
    double m_msFrequency;
    double m_usFrequency;
    
    __int64 m_Begin;
    
private:
    BOOL    InitTimer();
public:
    void    Delay(int time);
    
    void    StartTimer()  { QueryPerformanceCounter((LARGE_INTEGER *) &m_Begin); }
    
    long    Get_secTime();
    long    Get_usTime();
    long    Get_msTime();
    long    Get_100msTime();
    
    BOOL    TimeOver(long time);
    BOOL    TimeOverus(long time);
    
};​

 

.CPP

// Timer.cpp: implementation of the CTimer class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "MFrequencyTimer.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CTimer::CTimer()
{
    InitTimer();
}

CTimer::~CTimer()
{
    
}

BOOL CTimer::InitTimer()
{
    m_QueryInitialized = QueryPerformanceFrequency((LARGE_INTEGER*)&m_Frequency);
    
    if(!m_QueryInitialized)
    {
        m_Frequency = 1;
    }
    
    m_100msFrequency = m_Frequency / 10.;
    m_msFrequency = m_Frequency / 1000.;
    m_usFrequency = m_Frequency / 1000000.;
    
    if(!m_QueryInitialized) return FALSE;
    else                    return TRUE;
}

void CTimer::Delay(int d)
{
    QueryPerformanceCounter((LARGE_INTEGER*) &m_Begin);
    
    while(Get_msTime() < d);
}

long CTimer::Get_secTime()
{
    __int64  End;
    
    QueryPerformanceCounter((LARGE_INTEGER*) &End);
    
    return (long)((End - m_Begin)/ m_Frequency); 
}

long CTimer::Get_usTime()
{
    __int64  End;
    
    QueryPerformanceCounter((LARGE_INTEGER*) &End);
    
    return (long)((End - m_Begin)/ m_usFrequency); 
}

long CTimer::Get_msTime()
{
    __int64  End;
    
    QueryPerformanceCounter((LARGE_INTEGER*) &End);
    
    return (long)((End - m_Begin)/ m_msFrequency); 
}

long CTimer::Get_100msTime()
{
    __int64  End;
    
    QueryPerformanceCounter((LARGE_INTEGER*) &End);
    
    return (long)((End - m_Begin)/ m_100msFrequency); 
}

BOOL CTimer::TimeOver(long time)
{
    if(Get_msTime() > time) return TRUE;
    else                   return FALSE;
}

BOOL CTimer::TimeOverus(long time)
{
    if(Get_usTime() > time) return TRUE;
    else                   return FALSE;
}
​

 

 

밑에 소스는 실제로 장비개발시에 시간 대기하는 예제 입니다. 

BOOL MCommonStageUnit::SetStageVacuum(BOOL bVacuum, int nTimeOut) 
{
    int ret = SetIOOutPutID(STAGE_OUT_VACUUM_ON,bVacuum);
    if(ret) return ret;

    BOOL b = FALSE;
    
    if(nTimeOut < 0 ) return TRUE;

    CTimer tm;
    tm.StartTimer();
    for(;;)
    {        
        b = IsStageDetectVacuum();
        if(bVacuum)
        {
            if(b) break;        
        }
        else 
        {
            if(!b){
                b = TRUE;
                break;
            }
        }
        if(tm.TimeOver(nTimeOut)) return FALSE;    
        Sleep(1);
    }

    BOOL bCheck = GetIOOutPutOnOff(STAGE_OUT_VACUUM_ON);

    if(bCheck != bVacuum) return FALSE;

    return b;
}
​

TickTimer.zip
다운로드

 

위에 함수는 스테이지 구동에 필요한 기능중 하나로서 진공을 형성한후 실제로 nTimeOut 안에 진공센서의 일정량의 진공 상태를 형성 되었는지 체크하는 함수 입니다.

StartTimer(); 로 시작을 시키고 시작 TimeOver로 시간경과를 체크하고 있습니다. 그리 복잡한 소스는 아니기 때문에 활용하는데 문제는 각자 만들어서 잘 썼으면 합니다.

 

 

나머지 활용은 금방 파악하실거라 생각됩니다. 그럼 오늘도 즐거운 프로그래밍 하세요.

 

 

 

 

 

 

반응형